#include #include #include "SDL.h" #include "SDL_opengl.h" #include "SDL_image.h" #include "SDL_net.h" #include #include "glpong3d.h" #include "text.h" #include "fps.h" static int GLPong_Init(GLPong_t * GLPong); static int GLPong_HandleEvents(void); static void GLPong_Draw(void); static void GLPong_CleanUp(void); static void GLPong_Move(void); static void SDL_GL_GetMouseState(Paddle_t * paddle); GLuint box; int main(int argc, char * argv[]) { unsigned int frames = 0; int done = 0; int action; if (argc) { if (argv) {} } if (GLPong_Init(&GLPong) < 0) { fprintf(stderr, "Bailing out.\n"); return -1; } GLPong_FPSInit(); while (!done) { action = GLPong_HandleEvents(); switch (action) { case GLPONG_EXIT: /* exit */ done = 1; break; } SDL_GL_GetMouseState(&GLPong.Front); GLPong_Move(); /* begin drawing */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLPong_Draw(); frames++; if (frames == 30) { frames = 0; } GLPong_TextDrawFPS(GLPong_FPSCount()); SDL_GL_SwapBuffers(); /* end drawing */ SDL_Delay(10); } GLPong_CleanUp(); return 0; } static int GLPong_Init(GLPong_t * GLPong) { SDL_Surface * temp = NULL; GLPong->Ball.w = 0.5f; GLPong->Ball.h = 0.5f; GLPong->Ball.coord.x = -(GLPong->Ball.w / 2); GLPong->Ball.coord.y = -(GLPong->Ball.h / 2); GLPong->Ball.coord.z = GLPONG_FRONT_Z; GLPong->Ball.r = 1.0f; GLPong->Ball.g = 0.0f; GLPong->Ball.b = 0.0f; GLPong->Ball.xv = 0.02f; GLPong->Ball.yv = 0.01f; GLPong->Ball.zv = -0.05f; GLPong->Front.w = 0.66f; GLPong->Front.h = 0.5f; GLPong->Front.coord.x = -1.0f; GLPong->Front.coord.y = -1.0f; GLPong->Front.coord.z = GLPONG_FRONT_Z; GLPong->Front.r = 1.0f; GLPong->Front.g = 1.0f; GLPong->Front.b = 1.0f; GLPong->Back.w = 0.66f; GLPong->Back.h = 0.5f; GLPong->Back.coord.x = -(GLPong->Front.w / 2); GLPong->Back.coord.y = -(GLPong->Front.h / 2); GLPong->Back.coord.z = GLPONG_BACK_Z; GLPong->Back.r = 1.0f; GLPong->Back.g = 1.0f; GLPong->Back.b = 1.0f; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); return -1; } atexit(SDL_Quit); SDL_WM_SetCaption("glpong3d", "glpong3d"); /* SDL_ShowCursor(SDL_DISABLE);*/ temp = IMG_Load("ball.png"); if (!temp) { fprintf(stderr, "Unable to open ball.png\n"); return -1; } SDL_WM_SetIcon(temp, NULL); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (GLPong_TextInit() < 0) { fprintf(stderr, "Cannot initialize GLC context: %d\n", glcGetError()); return -1; } atexit(GLPong_TextDeinit); if (SDLNet_Init() < 0) { fprintf(stderr, "Cannot initialize SDL_net: %s\n", SDL_GetError()); return -1; } atexit(SDLNet_Quit); GLPong->Surface = SDL_SetVideoMode(GLPONG_WIDTH, GLPONG_HEIGHT, 32, SDL_OPENGL); glViewport(0, 0, GLPONG_WIDTH, GLPONG_HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, GLPONG_WIDTH / GLPONG_HEIGHT, 0.1f, 50.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glShadeModel(GL_SMOOTH); glEnable(GL_BLEND); /* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/ /* disabled since it causes drawing corruption, but necessary to enable transparency */ glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); printf("OpenGL Vendor: %s\n", glGetString(GL_VENDOR)); printf("OpenGL Renderer: %s\n", glGetString(GL_RENDERER)); printf("OpenGL Version: %s\n", glGetString(GL_VERSION)); printf("OpenGL Extensions: %s\n", glGetString(GL_EXTENSIONS)); /*temp = IMG_Load("ball.png");*/ /* disabled since it's already loaded for the icon */ ball_texture = SDL_GL_SurfaceToTexture(temp); SDL_FreeSurface(temp); temp = IMG_Load("paddle-skyos.png"); paddle_texture = SDL_GL_SurfaceToTexture(temp); SDL_FreeSurface(temp); temp = IMG_Load("paddle-skyos.png"); paddle_texture_hit = SDL_GL_SurfaceToTexture(temp); SDL_FreeSurface(temp); box = glGenLists(1); glNewList(box, GL_COMPILE); glBegin(GL_LINE_LOOP); glVertex3f(-1.5f, -1.0f, 0.0f); /* Lower Left */ glVertex3f( 1.5f, -1.0f, 0.0f); /* Lower Right */ glVertex3f( 1.5f, 1.0f, 0.0f); /* Upper Right */ glVertex3f(-1.5f, 1.0f, 0.0f); /* Upper Left */ glEnd(); glEndList(); glPointSize(10.0f); return 0; } static int GLPong_HandleEvents(void) { SDL_Event Event; if (SDL_PollEvent(&Event) != 0) { if (Event.type == SDL_QUIT) { return GLPONG_EXIT; } if (Event.type == SDL_KEYDOWN) { if (Event.key.keysym.sym == SDLK_ESCAPE) { return GLPONG_EXIT; } else if (Event.key.keysym.sym == SDLK_p) { for (;;) { SDL_Delay(10); if (SDL_PollEvent(&Event) != 0) { if (Event.type == SDL_QUIT) { return GLPONG_EXIT; } else if (Event.type == SDL_KEYDOWN){ if (Event.key.keysym.sym == SDLK_ESCAPE) { return GLPONG_EXIT; } else if (Event.key.keysym.sym == SDLK_p) { break; } } } } } } } return GLPONG_NOACTION; } void GLPong_Move(void) { GLPong.Ball.coord.x += GLPong.Ball.xv; if (GLPong.Ball.coord.x > 1.0f) { GLPong.Ball.coord.x = 1.0f; GLPong.Ball.xv = -GLPong.Ball.xv; } else if (GLPong.Ball.coord.x + GLPong.Ball.w < -1.0f) { GLPong.Ball.coord.x = -1.0f - GLPong.Ball.w; GLPong.Ball.xv = -GLPong.Ball.xv; } GLPong.Ball.coord.y += GLPong.Ball.yv; if (GLPong.Ball.coord.y > 0.5f) { GLPong.Ball.coord.y = 0.5f; GLPong.Ball.yv = -GLPong.Ball.yv; } else if (GLPong.Ball.coord.y + GLPong.Ball.h < -0.5f) { GLPong.Ball.coord.y = -0.5f - GLPong.Ball.h; GLPong.Ball.yv = -GLPong.Ball.yv; } GLPong.Ball.coord.z += GLPong.Ball.zv; if (GLPong.Ball.coord.z < GLPONG_BACK_Z) { GLPong.Ball.coord.z = GLPONG_BACK_Z; GLPong.Ball.zv = -GLPong.Ball.zv; } else if (GLPong.Ball.coord.z > GLPONG_FRONT_Z) { GLPong.Ball.coord.z = GLPONG_FRONT_Z; GLPong.Ball.zv = -GLPong.Ball.zv; } GLPong.Back.coord.x = GLPong.Ball.coord.x; GLPong.Back.coord.y = GLPong.Ball.coord.y; GLPong_Collide(&GLPong.Ball, &GLPong.Front); } void GLPong_Draw(void) { float count; glLoadIdentity(); glColor3f(0.0f, 0.0f, 0.0f); glTranslatef(0.0f, 0.0f, GLPONG_BACK_Z); glBegin(GL_QUADS); glTexCoord2f(0.875f, 0.0f); glVertex2f( 1.5f, 1.0f); /* Upper Right */ glTexCoord2f(0.125f, 0.0f); glVertex2f(-1.5f, 1.0f); /* Upper Left */ glTexCoord2f(0.125f, 1.0f); glVertex2f(-1.5f, -1.0f); /* Lower Left */ glTexCoord2f(0.875f, 1.0f); glVertex2f( 1.5f, -1.0f); /* Lower Right */ glEnd(); glDisable(GL_TEXTURE_2D); glColor3f(0.0f, 1.0f, 0.0f); for (count = GLPONG_FRONT_Z; count >= GLPONG_BACK_Z; count -= 1.0f) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, count); glCallList(box); } glLoadIdentity(); glTranslatef(0.0f, 0.0f, 0.0f); glBegin(GL_LINES); glVertex3f(-1.5f, -1.0f, GLPONG_FRONT_Z); /* Lower Left */ glVertex3f(-1.5f, -1.0f, GLPONG_BACK_Z); glEnd(); glBegin(GL_LINES); glVertex3f( 1.5f, -1.0f, GLPONG_FRONT_Z); /* Lower Right */ glVertex3f( 1.5f, -1.0f, GLPONG_BACK_Z); glEnd(); glBegin(GL_LINES); glVertex3f( 1.5f, 1.0f, GLPONG_FRONT_Z); /* Upper Right */ glVertex3f( 1.5f, 1.0f, GLPONG_BACK_Z); glEnd(); glBegin(GL_LINES); glVertex3f(-1.5f, 1.0f, GLPONG_FRONT_Z); /* Upper Left */ glVertex3f(-1.5f, 1.0f, GLPONG_BACK_Z); glEnd(); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D, paddle_texture); glEnable(GL_TEXTURE_2D); glColor3f(GLPong.Back.r, GLPong.Back.g, GLPong.Back.b); glTranslatef(GLPong.Back.coord.x, GLPong.Back.coord.y, GLPong.Back.coord.z); glBegin(GL_QUADS); glTexCoord2f(0.832f, 1.0f); glVertex2f(GLPong.Back.w / 2, GLPong.Back.h / 2); /* Upper Right */ glTexCoord2f(0.168f, 1.0f); glVertex2f(-GLPong.Back.w / 2, GLPong.Back.h / 2); /* Upper Left */ glTexCoord2f(0.168f, 0.0f); glVertex2f(-GLPong.Back.w / 2, -GLPong.Back.h / 2); /* Lower Left */ glTexCoord2f(0.832f, 0.0f); glVertex2f(GLPong.Back.w / 2, -GLPong.Back.h / 2); /* Lower Right */ glEnd(); glDisable(GL_TEXTURE_2D); glLoadIdentity(); glColor3f(1.0f, 0.0f, 0.0f); glTranslatef(GLPong.Back.coord.x, GLPong.Back.coord.y, GLPong.Back.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D, ball_texture); glEnable(GL_TEXTURE_2D); glColor3f(GLPong.Ball.r, GLPong.Ball.g, GLPong.Ball.b); glTranslatef(GLPong.Ball.coord.x, GLPong.Ball.coord.y, GLPong.Ball.coord.z); glBegin(GL_QUADS); glTexCoord2f(0.0f, 1.0f); glVertex2f(GLPong.Ball.w, GLPong.Ball.h); /* Lower Left */ glTexCoord2f(1.0f, 1.0f); glVertex2f(0.0f, GLPong.Ball.h); /* Lower Right */ glTexCoord2f(1.0f, 0.0f); glVertex2f(0.0f, 0.0f); /* Upper Right */ glTexCoord2f(0.0f, 0.0f); glVertex2f(GLPong.Ball.w, 0.0f); /* Upper Left */ glEnd(); glDisable(GL_TEXTURE_2D); /* Lower Left */ glLoadIdentity(); glColor3f(1.0f, 0.0f, 0.0f); glTranslatef(GLPong.Ball.coord.x, GLPong.Ball.coord.y, GLPong.Ball.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); /* Lower Right */ glLoadIdentity(); glTranslatef(GLPong.Ball.coord.x + GLPong.Ball.w, GLPong.Ball.coord.y, GLPong.Ball.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); /* Top Right */ glLoadIdentity(); glTranslatef(GLPong.Ball.coord.x + GLPong.Ball.w, GLPong.Ball.coord.y + GLPong.Ball.h, GLPong.Ball.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); /* Top Left */ glLoadIdentity(); glTranslatef(GLPong.Ball.coord.x, GLPong.Ball.coord.y + GLPong.Ball.h, GLPong.Ball.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); glLoadIdentity(); glTranslatef(0.0f, 0.0f, GLPong.Ball.coord.z); glCallList(box); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D, paddle_texture); glEnable(GL_TEXTURE_2D); glColor3f(GLPong.Front.r, GLPong.Front.g, GLPong.Front.b); glTranslatef(GLPong.Front.coord.x + (GLPong.Front.w / 2), GLPong.Front.coord.y + (GLPong.Front.h / 2), GLPong.Front.coord.z); glBegin(GL_QUADS); glTexCoord2f(0.168f, 1.0f); glVertex2f(GLPong.Front.w / 2, GLPong.Front.h / 2); /* Upper Right */ glTexCoord2f(0.832f, 1.0f); glVertex2f(-GLPong.Front.w / 2, GLPong.Front.h / 2); /* Upper Left */ glTexCoord2f(0.832f, 0.0f); glVertex2f(-GLPong.Front.w / 2, -GLPong.Front.h / 2); /* Lower Left */ glTexCoord2f(0.168f, 0.0f); glVertex2f(GLPong.Front.w / 2, -GLPong.Front.h / 2); /* Lower Right */ glEnd(); glDisable(GL_TEXTURE_2D); /* Lower Left */ glLoadIdentity(); glColor3f(1.0f, 0.0f, 0.0f); glTranslatef(GLPong.Front.coord.x, GLPong.Front.coord.y, GLPong.Front.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); /* Lower Right */ glLoadIdentity(); glTranslatef(GLPong.Front.coord.x + GLPong.Front.w, GLPong.Front.coord.y, GLPong.Front.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); /* Top Right */ glLoadIdentity(); glTranslatef(GLPong.Front.coord.x + GLPong.Front.w, GLPong.Front.coord.y + GLPong.Front.h, GLPong.Front.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); /* Top Left */ glLoadIdentity(); glTranslatef(GLPong.Front.coord.x, GLPong.Front.coord.y + GLPong.Front.h, GLPong.Front.coord.z); glBegin(GL_POINTS); glVertex3f(0.0f, 0.0f, 0.0f); glEnd(); } void GLPong_Collide(Ball_t * ball, const Paddle_t * paddle) { if (ball->coord.z == paddle->coord.z) { if (ball->coord.x + ball->w < paddle->coord.x) return; /* if ball is left of paddle */ if (ball->coord.x > paddle->coord.x + paddle->w) return; /* if ball is right of paddle */ if (ball->coord.y > paddle->coord.y + paddle->h) return; /* if ball is above paddle */ if (ball->coord.y + ball->h < paddle->coord.y) return; /* if ball is below paddle */ if (ball->zv < 0) { ball->zv -= 0.005f; } else { ball->zv += 0.005f; } printf("x: %.3f, y: %.2f, z: %.2f\n", ball->coord.x, ball->coord.y, ball->coord.z); } } void GLPong_CleanUp(void) { } static __inline__ unsigned int NextPow2(unsigned int value) { #if (defined __i386__ || defined __amd64__ || defined __x86_64__) \ && (defined __GNUC__) unsigned int x; __asm( "dec %1 \n\t" /* so that if the number is a power of * two we don't change it */ "movl $2,%0 \n\t" "bsr %1,%1 \n\t" "shl %b1,%0 \n\t" : "=r" (x) : "c" (value) ); #else unsigned int x = 2; while (x < value) { x *= 2; } #endif return x; } GLuint SDL_GL_SurfaceToTexture(SDL_Surface * surface) { Uint32 rmask, gmask, bmask, amask; GLuint texture; GLenum format = GL_RGB; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif if (surface->format->Rmask & rmask) { format = GL_RGB; if (surface->format->BitsPerPixel == 32) { format = GL_RGBA; } } else if (surface->format->Rmask & bmask) { format = GL_BGR; if (surface->format->BitsPerPixel == 32) { format = GL_BGRA; } } glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); SDL_LockSurface(surface); glTexImage2D(GL_TEXTURE_2D, 0, surface->format->BytesPerPixel, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels); SDL_UnlockSurface(surface); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); return texture; } static void SDL_GL_GetMouseState(Paddle_t * paddle) { int x, y; float temp_x, temp_y; Uint8 * key; key = SDL_GetKeyState(NULL); SDL_GetMouseState(&x, &y); temp_x = ((float) x / GLPONG_WIDTH) * 3.3f - 1.65f; if (temp_x <= -1.5 + (paddle->w / 2)) { temp_x = -1.5 + (paddle->w / 2); } else if (temp_x >= 1.5 - (paddle->w / 2)) { temp_x = 1.5 - (paddle->w / 2); } temp_y = ((float) y / GLPONG_HEIGHT) * 2.5f - 1.25f; if (temp_y <= -1.0 + (paddle->h / 2)) { temp_y = -1.0 + (paddle->h / 2); } else if (temp_y >= 1.0 - (paddle->h / 2)) { temp_y = 1.0 - (paddle->h / 2); } paddle->coord.x = temp_x - paddle->w / 2; paddle->coord.y = -(temp_y + paddle->h / 2); #ifdef DEBUG printf("SDL (x, y): (%d, %d)\tGL (x, y, z): (%.3f, %.3f)\n", x, y, paddle->coord.x, paddle->coord.y); #endif }