From 86611c5beec296c6c27525c859259d9aab418885 Mon Sep 17 00:00:00 2001 From: Joe Adams Date: Thu, 7 Dec 2017 17:13:16 +0000 Subject: [PATCH] Added pongy code --- glboilerplate/makefile | 16 ++ glboilerplate/pongy.c | 378 +++++++++++++++++++++++++++++ glboilerplate/pongy_modified.c | 418 +++++++++++++++++++++++++++++++++ glboilerplate/readme.md | 20 ++ 4 files changed, 832 insertions(+) create mode 100644 glboilerplate/makefile create mode 100644 glboilerplate/pongy.c create mode 100644 glboilerplate/pongy_modified.c create mode 100644 glboilerplate/readme.md diff --git a/glboilerplate/makefile b/glboilerplate/makefile new file mode 100644 index 0000000..5f85907 --- /dev/null +++ b/glboilerplate/makefile @@ -0,0 +1,16 @@ +unspecified: + cat readme.md + +pongy_s = pongy.c +pongy_c = pongy +pongy: $(pongy_s) + clang $(pongy_s) -l SDL2 -l GLU -l GL -o $(pongy_c) + chmod +x $(pongy_c) + ./$(pongy_c) + +pongymod_s = pongy_modified.c +pongymod_c = pongy_modified +pongymod: $(pongymod_s) + clang $(pongymod_s) -l SDL2 -l GLU -l GL -o $(pongymod_c) + chmod +x $(pongymod_c) + ./$(pongymod_c) diff --git a/glboilerplate/pongy.c b/glboilerplate/pongy.c new file mode 100644 index 0000000..5e17c41 --- /dev/null +++ b/glboilerplate/pongy.c @@ -0,0 +1,378 @@ +// This is the main SDL include file +#include +#include +#include +#include +#include + +/* data structures */ +typedef struct paddle +{ + double x; + double y; + double width; + double height; + char side; /* left: 1; right -1 */ + double speed; +} paddle; + +typedef struct ball +{ + double x; + double y; + double radius; + double speedX; + double speedY; +} ball; + +void initializePaddle(paddle *p,double x,double y,double w,double h,char sd,double sp) +{ + p->x=x; + p->y=y; + p->width=w; + p->height=h; + p->side=sd; + p->speed=sp; +} + +void initializeBall(ball *b,double x,double y, double r,double sx,double sy) +{ + b->x=x; + b->y=y; + b->radius=r; + b->speedX=sx; + b->speedY=sy; +} + +void updatePaddle(paddle *p,double f,int d,int h) +{ + p->y+=p->speed*f*(double)d; /* calculate next position */ + + /* ensure the paddle does not go beyond the boundaries */ + if(p->y+(p->height/2.0)>=(double)(h/2)) p->y=(double)(h/2)-(p->height/2.0); + if(p->y-(p->height/2.0)<=(double)(h/-2)) p->y=(double)(h/-2)+(p->height/2.0); +} + +char ballXpaddle(ball *b,paddle *p) /* collision detection */ +{ /* return if the ball has collided with the side of the paddle that faces the centre of the screen */ + if((b->y <= p->y+(p->height/2.0))&&(b->y >= p->y-(p->height/2.0))) /* ball y matches the paddle */ + { + /* check what the x coordinate of the correct side of the paddle is */ + double colX=p->x+(p->width/2.0*(double)p->side); + + /* now check if the ball has collided with this side */ + if(p->side==1) /* left - so <= */ + { + if(b->x-b->radius<=colX) return 1; /* return 1 if colliding */ + } + else /* right - so >= */ + { + if(b->x+b->radius>=colX) return 1; /* return 1 if colliding */ + } + } + return 0; /* clearly no collision */ +} + +void updateBall(ball *b,double f,paddle *p1,paddle *p2,int w,int h) +{ + /* collision detection & resolution with scene boundaries */ + if((b->x-b->radius)<=-1.0*(double)(w/2)) + { + b->x=-1.0*(double)(w/2)+b->radius; /* ensure the ball does not go beyond the boundaries */ + b->speedX*=-1.0; + } + if((b->x+b->radius)>=(double)(w/2)) + { + b->x=(double)(w/2)-b->radius; /* ensure the ball does not go beyond the boundaries */ + b->speedX*=-1.0; + } + if((b->y-b->radius)<=-1.0*(double)(h/2)) + { + b->y=-1.0*(double)(h/2)+b->radius; /* ensure the ball does not go beyond the boundaries */ + b->speedY*=-1.0; + } + if((b->y+b->radius)>=(double)(h/2)) + { + b->y=(double)(h/2)-b->radius; /* ensure the ball does not go beyond the boundaries */ + b->speedY*=-1.0; + } + + /* collision detection with paddles - incomplete */ + /* paddle 1 - not quite enough - paddle 2 todo */ + if(ballXpaddle(b,p1)) + { + printf("ping\n");fflush(stdout); + /* something should happen here */ + } + + /* update position */ + b->x+=f*b->speedX; + b->y+=f*b->speedY; +} + +void drawBall(ball *b) +{ + GLint matrixmode=0; + glGetIntegerv(GL_MATRIX_MODE,&matrixmode); /* get current matrix mode */ + + glMatrixMode(GL_MODELVIEW); /* set the modelview matrix */ + glPushMatrix(); /* store current modelview matrix */ + glTranslated(b->x,b->y,0.0); /* move the ball to its correct position */ + + glBegin(GL_QUADS); /* draw ball */ + glColor3f(1.0,1.0,1.0); + glVertex3d(b->radius/-2.0,b->radius/2.0,0.0); + glVertex3d(b->radius/2.0,b->radius/2.0,0.0); + glVertex3d(b->radius/2.0,b->radius/-2.0,0.0); + glVertex3d(b->radius/-2.0,b->radius/-2.0,0.0); + glEnd(); + + glPopMatrix(); /* restore previous modelview matrix */ + glMatrixMode(matrixmode); /* set the previous matrix mode */ +} + +void drawPaddle(paddle *p) +{ + GLint matrixmode=0; + glGetIntegerv(GL_MATRIX_MODE,&matrixmode); /* get current matrix mode */ + + glMatrixMode(GL_MODELVIEW); /* set the modelview matrix */ + glPushMatrix(); /* store current modelview matrix */ + glTranslated(p->x,p->y,0.0); /* move the ball to its correct position */ + + glBegin(GL_QUADS); /* draw paddle */ + glColor3f(1.0,1.0,1.0); + glVertex3d(p->width/-2.0,p->height/2.0,0.0); + glVertex3d(p->width/2.0,p->height/2.0,0.0); + glVertex3d(p->width/2.0,p->height/-2.0,0.0); + glVertex3d(p->width/-2.0,p->height/-2.0,0.0); + glEnd(); + + glPopMatrix(); /* restore previous modelview matrix */ + glMatrixMode(matrixmode); /* set the previous matrix mode */ +} + +void render(ball *b,paddle *p1, paddle *p2) +{ + /* Start by clearing the framebuffer (what was drawn before) */ + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + /* Set the scene transformations */ + glMatrixMode(GL_MODELVIEW); /* set the modelview matrix */ + glLoadIdentity(); /* Set it to the identity (no transformations) */ + + /* draw the objects */ + drawBall(b); + drawPaddle(p1); + drawPaddle(p2); + + /* now draw the background */ + glBegin(GL_LINES); + glVertex3f(0.0f,220.0f,0.0f); + glVertex3f(0.0f,-220.0f,0.0f); + glEnd(); + + glFlush(); +} + +int main(void) +{ + /* These are some variables to help show you what the parameters are for the initialisation function. + You can experiment with the numbers to see what they do. */ + int winPosX = 100; + int winPosY = 100; + int winWidth = 640; + int winHeight = 480; + int go; + + Uint32 timer; /* animation timer (in milliseconds) */ + + paddle p1,p2; + ball myB; + int p1dir=0,p2dir=0; + + /* This is our initialisation phase + + SDL_Init is the main initialisation function for SDL + It takes a 'flag' parameter which we use to tell SDL what systems we are going to use + Here, we want to initialise everything, so we give it the flag for this. + This function also returns an error value if something goes wrong, + so we can put this straight in an 'if' statement to check and exit if need be */ + if( SDL_Init( SDL_INIT_EVERYTHING ) != 0 ) + { + /* Something went very wrong in the initialisation, all we can do is exit */ + perror("Whoops! Something went very wrong, cannot initialise SDL :("); + return -1; + } + + /* Now we have got SDL initialised, we are ready to create an OpenGL window! */ + SDL_Window *window = SDL_CreateWindow("My Pongy Game!!!", /* The first parameter is the window title */ + winPosX, winPosY, + winWidth, winHeight, + SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); /* ensure that OpenGL gets enabled here */ + /* The last parameter lets us specify a number of options. + Here, we tell SDL that we want the window to be shown and that it can be resized. + You can learn more about SDL_CreateWindow here: https://wiki.libsdl.org/SDL_CreateWindow?highlight=%28\bCategoryVideo\b%29|%28CategoryEnum%29|%28CategoryStruct%29 + The flags you can pass in for the last parameter are listed here: https://wiki.libsdl.org/SDL_WindowFlags + + The SDL_CreateWindow function returns an SDL_Window. + This is a structure which contains all the data about our window (size, position, etc). + We will also need this when we want to draw things to the window. + This is therefore quite important we do not lose it! */ + + + if( window == NULL ) + { + printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() ); + exit(EXIT_FAILURE); /* crash out if there has been an error */ + } + + /* Use OpenGL 1.5 compatibility */ + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 1 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 5 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); /* set up Z-Buffer */ + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); /* enable double buffering */ + + + /* SDL_GLContext is the OpenGL rendering context - this is the equivalent to the SDL_Renderer when drawing pixels to the window */ + SDL_GLContext context = SDL_GL_CreateContext( window ); + if( context == NULL ) + { + printf( "OpenGL Rendering Context could not be created! SDL Error: %s\n", SDL_GetError() ); + exit(EXIT_FAILURE); /* crash out if there has been an error */ + } + + /* Set up the parts of the scene that will stay the same for every frame. */ + + glFrontFace(GL_CCW); /* Enforce counter clockwise face ordering (to determine front and back side) */ + glEnable(GL_NORMALIZE); + glShadeModel(GL_FLAT); /* enable flat shading - Gouraud shading would be GL_SMOOTH */ + + + glEnable(GL_DEPTH_TEST); + + /* Set the clear (background) colour */ + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + /* Set up the camera/viewing volume (projection matrix) */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(-1.0*(GLdouble)(winWidth/2), (GLdouble)(winWidth/2),-1.0*(GLdouble)(winHeight/2),(GLdouble)(winHeight/2)); + + glViewport(0,0,winWidth,winHeight); + + /* initialize the timer */ + timer = SDL_GetTicks(); + + /* initialize objects */ + initializeBall(&myB,0.0,0.0,8.0,70.0,30.0); + initializePaddle(&p1,-295.0,0.0,6,30,1,50.0); + initializePaddle(&p2,295.0,0.0,6,30,-1,50.0); + + /* We are now preparing for our main loop. + This loop will keep going round until we exit from our program by changing the int 'go' to the value false (0). + This loop is an important concept and forms the basis of most SDL programs you will be writing. + Within this loop we generally do the following things: + * Check for input from the user (and do something about it!) + * Update our graphics (if necessary, e.g. for animation) + * Draw our graphics + */ + go = 1; + while( go ) + { + /* Here we are going to check for any input events. + Basically when you press the keyboard or move the mouse, the parameters are stored as something called an 'event' or 'message'. + SDL has a queue of events. We need to check for each event and then do something about it (called 'event handling'). + The SDL_Event is the data type for the event. */ + SDL_Event incomingEvent; + + double fraction=0.0; + + /* SDL_PollEvent will check if there is an event in the queue - this is the program's 'message pump'. + If there is nothing in the queue it will not sit and wait around for an event to come along (there are functions which do this, + and that can be useful too!). Instead for an empty queue it will simply return 'false' (0). + If there is an event, the function will return 'true' (!=0) and it will fill the 'incomingEvent' we have given it as a parameter with the event data */ + while( SDL_PollEvent( &incomingEvent ) ) + { + /* If we get in here, we have an event and need to figure out what to do with it. + For now, we will just use a switch based on the event's type */ + switch( incomingEvent.type ) + { + case SDL_QUIT: + /* The event type is SDL_QUIT. + This means we have been asked to quit - probably the user clicked on the 'x' at the top right corner of the window. + To quit we need to set our 'go' variable to false (0) so that we can escape out of the main loop. */ + go = 0; + break; + case SDL_KEYDOWN: + switch( incomingEvent.key.keysym.sym ) + { + case SDLK_UP: + p2dir=1; + break; + case SDLK_DOWN: + p2dir=-1; + break; + case SDLK_w: + p1dir=1; + break; + case SDLK_s: + p1dir=-1; + break; + } + break; + case SDL_KEYUP: + switch( incomingEvent.key.keysym.sym ) + { + case SDLK_UP: + case SDLK_DOWN: + p2dir=0; + break; + case SDLK_w: + case SDLK_s: + p1dir=0; + break; + case SDLK_ESCAPE: go = 0; + break; + } + break; + + /* If you want to learn more about event handling and different SDL event types, see: + https://wiki.libsdl.org/SDL_Event + and also: https://wiki.libsdl.org/SDL_EventType */ + } + } + + /* update timer */ + { + Uint32 old=timer; + timer = SDL_GetTicks(); + fraction = (double) (timer-old)/1000.0; /* calculate the frametime by finding the difference in ms from the last update/frame and divide by 1000 to get to the fraction of a second */ + } + + /* update positions */ + updatePaddle(&p1,fraction,p1dir,winHeight); /* move paddle 1 */ + /* move paddle 2 - todo */ + + updateBall(&myB,fraction,&p1,&p2,winWidth,winHeight); /* move ball and check collisions with the paddles */ + + + /* Render our scene. */ + render(&myB,&p1,&p2); + + /* This does the double-buffering page-flip, drawing the scene onto the screen. */ + SDL_GL_SwapWindow( window ); + + } + + /* If we get outside the main loop, it means our user has requested we exit. */ + + + /* Our cleanup phase, hopefully fairly self-explanatory ;) */ + SDL_GL_DeleteContext(context); + SDL_DestroyWindow( window ); + SDL_Quit(); + + return 0; +} diff --git a/glboilerplate/pongy_modified.c b/glboilerplate/pongy_modified.c new file mode 100644 index 0000000..5800c40 --- /dev/null +++ b/glboilerplate/pongy_modified.c @@ -0,0 +1,418 @@ +// This is the main SDL include file +#include +#include +#include +#include +#include + +/* data structures */ +typedef struct paddle +{ + double x; + double y; + double width; + double height; + char side; /* left: 1; right -1 */ + double speed; +} paddle; + +typedef struct ball +{ + double x; + double y; + double radius; + double speedX; + double speedY; +} ball; + +void initializePaddle(paddle *p,double x,double y,double w,double h,char sd,double sp) +{ + p->x=x; + p->y=y; + p->width=w; + p->height=h; + p->side=sd; + p->speed=sp; +} + +void initializeBall(ball *b,double x,double y, double r,double sx,double sy) +{ + b->x=x; + b->y=y; + b->radius=r; + b->speedX=sx; + b->speedY=sy; +} + +void updatePaddle(paddle *p,double f,int d,int h) +{ + p->y+=p->speed*f*(double)d; /* calculate next position */ + + /* ensure the paddle does not go beyond the boundaries */ + if(p->y+(p->height/2.0)>=(double)(h/2)) p->y=(double)(h/2)-(p->height/2.0); + if(p->y-(p->height/2.0)<=(double)(h/-2)) p->y=(double)(h/-2)+(p->height/2.0); +} + +void printscore(int *p1s, int *p2s) { + printf("P1: %d, P2: %d\r",*p1s,*p2s); fflush(stdout); +} + +char ballXpaddle(ball *b,paddle *p) /* collision detection */ +{ /* return if the ball has collided with the side of the paddle that faces the centre of the screen */ + if((b->y <= p->y+(p->height/2.0))&&(b->y >= p->y-(p->height/2.0))) /* ball y matches the paddle */ + { + /* check what the x coordinate of the correct side of the paddle is */ + double colX=p->x+(p->width/2.0*(double)p->side); + + /* now check if the ball has collided with this side */ + if(p->side==1) /* left - so <= */ + { + if((b->x-b->radius<=colX)&&(b->x-b->radius>=p->x)) return 1; /* return 1 if colliding */ + } + else /* right - so >= */ + { + if((b->x+b->radius>=colX)&&(b->x+b->radius<=p->x)) return 1; /* return 1 if colliding */ + } + } + return 0; /* clearly no collision */ +} + +void updateBall(ball *b,double f,paddle *p1,paddle *p2,int w,int h, int *p1s, int *p2s) +{ + /* collision detection & resolution with scene boundaries */ + if((b->x-b->radius)<=-1.0*(double)(w/2)) + { + //b->x=-1.0*(double)(w/2)+b->radius; /* ensure the ball does not go beyond the boundaries */ + //b->speedX*=-1.0; + *p1s-=1; + printscore(p1s,p2s); + initializeBall(b,0.0,0.0,8.0,70.0,30.0); +// b->x=0.0; +// b->y=0.0; +// b->speedX=70.0; +// b->speedY=30.0; + } + if((b->x+b->radius)>=(double)(w/2)) + { + //b->x=(double)(w/2)-b->radius; /* ensure the ball does not go beyond the boundaries */ + //b->speedX*=-1.0; + *p2s-=1; + printscore(p1s,p2s); + b->x=0.0; + b->y=0.0; + b->speedX=-70.0; + b->speedY=30.0; + } + if((b->y-b->radius)<=-1.0*(double)(h/2)) + { + b->y=-1.0*(double)(h/2)+b->radius; /* ensure the ball does not go beyond the boundaries */ + b->speedY*=-1.0; + } + if((b->y+b->radius)>=(double)(h/2)) + { + b->y=(double)(h/2)-b->radius; /* ensure the ball does not go beyond the boundaries */ + b->speedY*=-1.0; + } + + /* collision detection with paddles - incomplete */ + /* paddle 1 - not quite enough - paddle 2 todo */ + if(ballXpaddle(b,p1)) + { + //printf("ping\n");fflush(stdout); + b->speedX*=-1.0; + *p1s+=1; + printscore(p1s,p2s); + } + if(ballXpaddle(b,p2)) { + b->speedX*=-1.0; + *p2s+=1; + printscore(p1s,p2s); + } + + /* update position */ + b->x+=f*b->speedX; + b->y+=f*b->speedY; + if(b->speedX<0.0) b->speedX-=0.05; + else b->speedX+=0.05; + if(b->speedY<0.0)b->speedY-=0.05; + else b->speedY+=0.05; + p1->speed+=0.1; + p2->speed+=0.1; +} + +void drawBall(ball *b) +{ + GLint matrixmode=0; + glGetIntegerv(GL_MATRIX_MODE,&matrixmode); /* get current matrix mode */ + + glMatrixMode(GL_MODELVIEW); /* set the modelview matrix */ + glPushMatrix(); /* store current modelview matrix */ + glTranslated(b->x,b->y,0.0); /* move the ball to its correct position */ + + glBegin(GL_QUADS); /* draw ball */ + glColor3f(1.0,1.0,1.0); + glVertex3d(b->radius/-2.0,b->radius/2.0,0.0); + glVertex3d(b->radius/2.0,b->radius/2.0,0.0); + glVertex3d(b->radius/2.0,b->radius/-2.0,0.0); + glVertex3d(b->radius/-2.0,b->radius/-2.0,0.0); + glEnd(); + + glPopMatrix(); /* restore previous modelview matrix */ + glMatrixMode(matrixmode); /* set the previous matrix mode */ +} + +void drawPaddle(paddle *p) +{ + GLint matrixmode=0; + glGetIntegerv(GL_MATRIX_MODE,&matrixmode); /* get current matrix mode */ + + glMatrixMode(GL_MODELVIEW); /* set the modelview matrix */ + glPushMatrix(); /* store current modelview matrix */ + glTranslated(p->x,p->y,0.0); /* move the ball to its correct position */ + + glBegin(GL_QUADS); /* draw paddle */ + glColor3f(1.0,1.0,1.0); + glVertex3d(p->width/-2.0,p->height/2.0,0.0); + glVertex3d(p->width/2.0,p->height/2.0,0.0); + glVertex3d(p->width/2.0,p->height/-2.0,0.0); + glVertex3d(p->width/-2.0,p->height/-2.0,0.0); + glEnd(); + + glPopMatrix(); /* restore previous modelview matrix */ + glMatrixMode(matrixmode); /* set the previous matrix mode */ +} + +void render(ball *b,paddle *p1, paddle *p2) +{ + /* Start by clearing the framebuffer (what was drawn before) */ + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + /* Set the scene transformations */ + glMatrixMode(GL_MODELVIEW); /* set the modelview matrix */ + glLoadIdentity(); /* Set it to the identity (no transformations) */ + + /* draw the objects */ + drawBall(b); + drawPaddle(p1); + drawPaddle(p2); + + /* now draw the background */ + glBegin(GL_LINES); + glVertex3f(0.0f,220.0f,0.0f); + glVertex3f(0.0f,-220.0f,0.0f); + glEnd(); + + glFlush(); +} + +int main(void) +{ + /* These are some variables to help show you what the parameters are for the initialisation function. + You can experiment with the numbers to see what they do. */ + int winPosX = 100; + int winPosY = 100; + int winWidth = 640; + int winHeight = 480; + int go; + + int p1s=0; // Player 1 score + int p2s=0; // Player 2 score + + Uint32 timer; /* animation timer (in milliseconds) */ + + paddle p1,p2; + ball myB; + int p1dir=0,p2dir=0; + + /* This is our initialisation phase + + SDL_Init is the main initialisation function for SDL + It takes a 'flag' parameter which we use to tell SDL what systems we are going to use + Here, we want to initialise everything, so we give it the flag for this. + This function also returns an error value if something goes wrong, + so we can put this straight in an 'if' statement to check and exit if need be */ + if( SDL_Init( SDL_INIT_EVERYTHING ) != 0 ) + { + /* Something went very wrong in the initialisation, all we can do is exit */ + perror("Whoops! Something went very wrong, cannot initialise SDL :("); + return -1; + } + + /* Now we have got SDL initialised, we are ready to create an OpenGL window! */ + SDL_Window *window = SDL_CreateWindow("My Pongy Game!!!", /* The first parameter is the window title */ + winPosX, winPosY, + winWidth, winHeight, + SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); /* ensure that OpenGL gets enabled here */ + /* The last parameter lets us specify a number of options. + Here, we tell SDL that we want the window to be shown and that it can be resized. + You can learn more about SDL_CreateWindow here: https://wiki.libsdl.org/SDL_CreateWindow?highlight=%28\bCategoryVideo\b%29|%28CategoryEnum%29|%28CategoryStruct%29 + The flags you can pass in for the last parameter are listed here: https://wiki.libsdl.org/SDL_WindowFlags + + The SDL_CreateWindow function returns an SDL_Window. + This is a structure which contains all the data about our window (size, position, etc). + We will also need this when we want to draw things to the window. + This is therefore quite important we do not lose it! */ + + + if( window == NULL ) + { + printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() ); + exit(EXIT_FAILURE); /* crash out if there has been an error */ + } + + /* Use OpenGL 1.5 compatibility */ + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 1 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 5 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); /* set up Z-Buffer */ + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); /* enable double buffering */ + + + /* SDL_GLContext is the OpenGL rendering context - this is the equivalent to the SDL_Renderer when drawing pixels to the window */ + SDL_GLContext context = SDL_GL_CreateContext( window ); + if( context == NULL ) + { + printf( "OpenGL Rendering Context could not be created! SDL Error: %s\n", SDL_GetError() ); + exit(EXIT_FAILURE); /* crash out if there has been an error */ + } + + /* Set up the parts of the scene that will stay the same for every frame. */ + + glFrontFace(GL_CCW); /* Enforce counter clockwise face ordering (to determine front and back side) */ + glEnable(GL_NORMALIZE); + glShadeModel(GL_FLAT); /* enable flat shading - Gouraud shading would be GL_SMOOTH */ + + + glEnable(GL_DEPTH_TEST); + + /* Set the clear (background) colour */ + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + /* Set up the camera/viewing volume (projection matrix) */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(-1.0*(GLdouble)(winWidth/2), (GLdouble)(winWidth/2),-1.0*(GLdouble)(winHeight/2),(GLdouble)(winHeight/2)); + + glViewport(0,0,winWidth,winHeight); + + /* initialize the timer */ + timer = SDL_GetTicks(); + + /* initialize objects */ + initializeBall(&myB,0.0,0.0,8.0,70.0,30.0); + initializePaddle(&p1,-295.0,0.0,6,30,1,50.0); + initializePaddle(&p2,295.0,0.0,6,30,-1,50.0); + + /* We are now preparing for our main loop. + This loop will keep going round until we exit from our program by changing the int 'go' to the value false (0). + This loop is an important concept and forms the basis of most SDL programs you will be writing. + Within this loop we generally do the following things: + * Check for input from the user (and do something about it!) + * Update our graphics (if necessary, e.g. for animation) + * Draw our graphics + */ + go = 1; + while( go ) + { + /* Here we are going to check for any input events. + Basically when you press the keyboard or move the mouse, the parameters are stored as something called an 'event' or 'message'. + SDL has a queue of events. We need to check for each event and then do something about it (called 'event handling'). + The SDL_Event is the data type for the event. */ + SDL_Event incomingEvent; + + double fraction=0.0; + + /* SDL_PollEvent will check if there is an event in the queue - this is the program's 'message pump'. + If there is nothing in the queue it will not sit and wait around for an event to come along (there are functions which do this, + and that can be useful too!). Instead for an empty queue it will simply return 'false' (0). + If there is an event, the function will return 'true' (!=0) and it will fill the 'incomingEvent' we have given it as a parameter with the event data */ + while( SDL_PollEvent( &incomingEvent ) ) + { + /* If we get in here, we have an event and need to figure out what to do with it. + For now, we will just use a switch based on the event's type */ + switch( incomingEvent.type ) + { + case SDL_QUIT: + /* The event type is SDL_QUIT. + This means we have been asked to quit - probably the user clicked on the 'x' at the top right corner of the window. + To quit we need to set our 'go' variable to false (0) so that we can escape out of the main loop. */ + go = 0; + break; + case SDL_KEYDOWN: + switch( incomingEvent.key.keysym.sym ) + { + case SDLK_UP: + p2dir=1; + break; + case SDLK_DOWN: + p2dir=-1; + break; + case SDLK_w: + p1dir=1; + break; + case SDLK_s: + p1dir=-1; + break; + } + break; + case SDL_KEYUP: + switch( incomingEvent.key.keysym.sym ) + { + case SDLK_UP: + case SDLK_DOWN: + p2dir=0; + break; + case SDLK_w: + case SDLK_s: + p1dir=0; + break; + case SDLK_ESCAPE: go = 0; + break; + } + break; + + /* If you want to learn more about event handling and different SDL event types, see: + https://wiki.libsdl.org/SDL_Event + and also: https://wiki.libsdl.org/SDL_EventType */ + } + } + + /* update timer */ + { + Uint32 old=timer; + timer = SDL_GetTicks(); + fraction = (double) (timer-old)/1000.0; /* calculate the frametime by finding the difference in ms from the last update/frame and divide by 1000 to get to the fraction of a second */ + } + + /* update positions */ + updatePaddle(&p1,fraction,p1dir,winHeight); /* move paddle 1 */ + /* move paddle 2 */ + updatePaddle(&p2,fraction,p2dir,winHeight); + + updateBall(&myB,fraction,&p1,&p2,winWidth,winHeight,&p1s,&p2s); /* move ball and check collisions with the paddles */ + + char windowTitle[100]; + + sprintf(windowTitle, "P1: %d | P2: %d", p1s, p2s); + + SDL_SetWindowTitle(window, windowTitle); + + + /* Render our scene. */ + render(&myB,&p1,&p2); + + /* This does the double-buffering page-flip, drawing the scene onto the screen. */ + SDL_GL_SwapWindow( window ); + + } + + /* If we get outside the main loop, it means our user has requested we exit. */ + + + /* Our cleanup phase, hopefully fairly self-explanatory ;) */ + SDL_GL_DeleteContext(context); + SDL_DestroyWindow( window ); + SDL_Quit(); + + return 0; +} diff --git a/glboilerplate/readme.md b/glboilerplate/readme.md new file mode 100644 index 0000000..4287b39 --- /dev/null +++ b/glboilerplate/readme.md @@ -0,0 +1,20 @@ + + +# Boilerplate Code + +Creating a bare-minimum C file for setting up SDL and OpenGL with a single window and renderer (result is **glboilerplate.c**) + +## pongy.c + +> Compile using `make pongy` + +Original file provided by Eike Anderson as part of an exercise to introduce OpenGL/SDL + +## pongy_modified.c + +> Compile using `make pongymod` + +Completed pongy.c file (collisions, paddle movement and scoring system) + +## sdlboilerplate.c +