#ifdef _WIN32 #include #include #define _ #else #include #endif #include #include #include #include typedef struct colour { double r; double g; double b; double a; } colour; typedef struct paddle { int width; int height; double x; } paddle; typedef struct ball { double x; double y; double vX; double vY; double initVX; double initVY; double radius; } ball; void updatePaddle(Uint32 tickrate, paddle *thePaddle, char moveX, int winWidth, int winHeight); void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth, int winHeight); void drawPaddle(paddle *thePaddle, int winWidth, int winHeight, colour *c); void drawBall(ball *theBall, colour *c); void drawBg(int winWidth, int winHeight, colour *c1, colour *c2); int main(void) { /* * RETURN CODES * 0: Success * 1: SDL init fail * 2: Error creating Window * 3: Error creating context * */ /* ---------------- * SDL Init * ---------------- */ if (SDL_Init(SDL_INIT_EVERYTHING)!=0) { perror("[FAILED] Initialising SDL: "); return 1; } int go; //Var for loop control /* ---------------- * Main Window * ---------------- * Create the main output Window for SDL */ // Window vars int winPosX = 100; int winPosY = 100; int winWidth = 480; int winHeight = 720; Uint32 timer; SDL_Window *window1 = SDL_CreateWindow( "Main Window", winPosX, winPosY, winWidth, winHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL ); if (window1==NULL) { fprintf(stderr, "[FAILED] Creating Window window1"); return 2; //Error creating Window } /* * ---------------- * Renderer * ---------------- * Creates the main renderer (tied to main window) */ //SDL_Renderer * renderer1 = SDL_CreateRenderer(window1, -1, 0); //if (renderer1==NULL) { // fprintf(stderr, "[FAILED] Creating renderer renderer1 for window1"); // return 3; //} SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); // Specifies the version of the OpenGL context SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); // (here, 1.5) -- hello, 2003! SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); // Allows deprecated functions to be used SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); // Set depth buffer to 16 bits, if OpenGL agrees (see below) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Enable double buffering SDL_GLContext context1 = SDL_GL_CreateContext(window1); // Use SDL_GL_MakeCurrent function to switch contexts if (context1 == NULL) { fprintf(stderr, "[FAILED] Creating render context context1 for window1"); return 3; } glFrontFace(GL_CCW); // Counter-clockwise winding glEnable(GL_NORMALIZE); // Vectors normalized after transforming to keep units consistent for lighting glShadeModel(GL_SMOOTH); // GL_FLAT for flat shading instead glEnable(GL_DEPTH_TEST); // Enables depth comparisons glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glMatrixMode(GL_PROJECTION); // Sets our matrix mode (initially) to work with the projection stack glLoadIdentity(); // Projection matrix is now the identity matrix, so we can work in 2D space gluOrtho2D( -1.0*(GLdouble)(winWidth / 2), // Left (GLdouble)(winWidth / 2), // Right -1.0*(GLdouble)(winHeight / 2), // Bottom (GLdouble)(winHeight / 2) // Top ); glViewport(0, 0, winWidth, winHeight); // Set the viewport to fill the window timer = SDL_GetTicks(); /* * ---------------- * Game variables * ---------------- */ char moveX=0; ball theBall = { .x = 0, .y = 0, .vX = 0.4f, .vY = -1.5f, .initVX = theBall.vX, .initVY = theBall.vY, .radius = 4 }; paddle thePaddle = { .width = 50, .height = 10, .x = (winWidth/2)-(thePaddle.width/2) }; /* * ---------------- * Let's go! * ---------------- */ go=1; while(go) { /* ---------------- * Timing control * ---------------- * */ Uint32 tickrate=SDL_GetTicks()-timer; timer=SDL_GetTicks(); int fps=1000/(tickrate+1); printf("Time to draw: %u, fps: %i \r", tickrate, fps); fflush(stdout); /* * ---------------- * Event handling * ---------------- */ SDL_Event incomingEvent; while (SDL_PollEvent(&incomingEvent)) { switch (incomingEvent.type) { case SDL_QUIT: // User requested program quit - e.g. window close go=0; break; case SDL_KEYDOWN: switch(incomingEvent.key.keysym.sym) { case SDLK_ESCAPE: go=0; break; case SDLK_LEFT: moveX=-1; break; case SDLK_RIGHT: moveX=1; break; } break; case SDL_KEYUP: switch(incomingEvent.key.keysym.sym) { case SDLK_LEFT: moveX=0; break; case SDLK_RIGHT: moveX=0; break; } break; } } /* * ---------------- * Update elements * ---------------- */ updatePaddle(tickrate, &thePaddle, moveX, winWidth, winHeight); updateBall(tickrate, &theBall, &thePaddle, winWidth, winHeight); /* * ---------------- * Draw to buffer * ---------------- */ SDL_GL_MakeCurrent(window1, context1); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); colour paddleCol; paddleCol.r = 1.0; paddleCol.g = 1.0; paddleCol.b = 1.0; paddleCol.a = 1.0; colour bgcol1; colour bgcol2; bgcol1.r = 0.0824; /*21*/ bgcol2.r = 0.7216; /*184*/ bgcol1.g = 0.0901; /*23*/ bgcol2.g = 0.2471; /*63*/ bgcol1.b = 0.4431; /*113*/ bgcol2.b = 0.6078; /*155*/ bgcol1.a = 1.0000; /*255*/ bgcol2.a = 1.0000; /*255*/ drawPaddle(&thePaddle, winWidth, winHeight, &paddleCol); drawBall(&theBall, &paddleCol); drawBg(winWidth, winHeight, &bgcol1, &bgcol2); glFlush(); /* * -------------------------------- * Output to Window * -------------------------------- */ SDL_GL_SwapWindow(window1); } /* * -------------------------------- * Clean up after ourselves * -------------------------------- */ SDL_GL_DeleteContext(context1); SDL_DestroyWindow(window1); SDL_Quit(); return 0; } void updatePaddle(Uint32 tickrate, paddle *thePaddle, char moveX, int winWidth, int winHeight) { thePaddle->x += moveX * 0.5 * tickrate; if (thePaddle->x < 0-(thePaddle->width/2)) thePaddle->x = 0-(thePaddle->width/2); if (thePaddle->x > winWidth-(thePaddle->width/2)) thePaddle->x = winWidth-(thePaddle->width/2); } void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth, int winHeight) { double ballNX = theBall->x + theBall->vX; // Calculates the position of the ball on the next step double ballNY = theBall->y + theBall->vY; double paddleRX = thePaddle->x - (double)(winWidth / 2); double paddleRY = 20 - (double)(winHeight / 2); if (ballNX > paddleRX && ballNYwidth) { // ...and to the left of the right side of the paddle (i.e. about to go inside inside the paddle) theBall->vY *= -1.0; theBall->vX = ((ballNX - paddleRX - (double)(thePaddle->width/2))/((double)thePaddle->width/2))*0.5; // Sets X velocity to be proportional to the relative position of the ball and the paddle on collision } } if (ballNX > winWidth / 2 || ballNX < (-1.0*winWidth/2)) { // Collision with walls theBall->vX *= -1.0; } if (ballNY > winHeight / 2) { // Collision with ceiling theBall->vY *= -1.0; } if (ballNY < (-1.0*winHeight/2)) { // Collision with floor theBall->x = 0; theBall->y = 0; theBall->vX = theBall->initVX; theBall->vY = theBall->initVY; } theBall->x += theBall->vX * 0.1 * tickrate; theBall->y += theBall->vY * 0.1 * tickrate; } void drawBg(int winWidth, int winHeight, colour *c1, colour *c2) { GLint matrixmode = 0; glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glPushMatrix(); glTranslated((GLdouble)(-1*winWidth/2), (GLdouble)(-1*winHeight/2), 0.0); glBegin(GL_QUADS); //Top colour glColor3f(c1->r, c1->g, c1->b); glVertex2f(winWidth, 0.0); glVertex2f(0.0,0.0); //Bottom colour glColor3f(c2->r, c2->g, c2->b); glVertex2f(0.0,winHeight); glVertex2f(winWidth, winHeight); glEnd(); } void drawPaddle(paddle *thePaddle, int winWidth, int winHeight, colour *c) { GLint matrixmode = 0; glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glPushMatrix(); glTranslated((GLdouble)(thePaddle->x)-winWidth/2, (GLdouble)(20-winHeight/2), 0.0); glBegin(GL_QUADS); glColor3f(c->r, c->g, c->b); glVertex3d(0.0, 0.0, 0.0); glVertex3d(0.0, (double)thePaddle->height, 0.0); glVertex3d((double)thePaddle->width, (double)thePaddle->height, 0.0); glVertex3d((double)thePaddle->width, 0.0, 0.0); glEnd(); glPopMatrix(); glMatrixMode(matrixmode); } void drawBall(ball *theBall, colour *c) { GLint matrixmode = 0; glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glPushMatrix(); glTranslated(theBall->x, theBall->y, 0.0); glBegin(GL_QUADS); glColor3f(c->r, c->g, c->b); glVertex3d(0.0, 0.0, 0.0); glVertex3d(0.0, 8.0, 0.0); glVertex3d(8.0, 8.0, 0.0); glVertex3d(8.0, 0.0, 0.0); glEnd(); glPopMatrix(); glMatrixMode(matrixmode); }