#include #include #define GL_GLEXT_PROTOTYPES #ifndef __APPLE__ #include #include #else #include #include #endif #include #include #include #include #include #include #include "texturesdl.h" #include "shader.h" #include "vector.h" #include "bullet.h" #include "bulletpattern.h" const int width = 1280, height = 720; class BulletPattern1 : public BulletPattern { unsigned int base; public: BulletPattern1(bool reverse, unsigned int base) { num_bullets = 0; color_r = 1; color_g = 0; color_b = 1; bullets = new float[128]; this->base = base; int j = 0; for(float i = 0; i < M_PI; i += 0.1, j++) { bullets[j*4] = 50.0 + sinf(!reverse ? M_PI_2 + i : M_PI - i + M_PI_2) * 9; bullets[j*4 + 1] = 80 + cosf(M_PI_2 + i) * 10; bullets[j*4 + 2] = sinf(!reverse ? M_PI_2 + i : M_PI - i + M_PI_2) / 150.0; bullets[j*4 + 3] = -0.01; } }; void update(unsigned int time, unsigned int step) { if(num_bullets < 32 && base + num_bullets * 10 < time) { num_bullets += time / 10 - num_bullets - base / 10; if(num_bullets > 32) num_bullets = 32; } for(int i = 0; i < num_bullets; i++) { bullets[i*4] += bullets[i*4 + 2] * step; bullets[i*4 + 1] += bullets[i*4 + 3] * step; } } }; class BulletPattern2 : public BulletPattern { public: BulletPattern2(unsigned int base) { num_bullets = 0; color_r = 0; color_g = 1; color_b = 0; stride = sizeof(float); bullets = new float[8*32*5]; int k = 0; for(int j = 0; j < 8; j++) { for(float i = 0; i < M_PI; i += 0.1, k++) { bullets[k*5] = 50.0 + sinf(j % 2 ? M_PI_2 + i : M_PI - i + M_PI_2) * 9; bullets[k*5 + 1] = 80 + cosf(M_PI_2 + i) * 10; bullets[k*5 + 2] = sinf(j % 2 ? M_PI_2 + i : M_PI - i + M_PI_2) / 150.0; bullets[k*5 + 3] = -0.01; bullets[k*5 + 4] = base + j * 400 + i * 100; } } }; void update(unsigned int time, unsigned int step) { while(num_bullets < 256 && (unsigned int)(bullets[num_bullets*5 + 4]) < time) { num_bullets++; } for(int i = 0; i < num_bullets; i++) { bullets[i*5] += bullets[i*5 + 2] * step; bullets[i*5 + 1] += bullets[i*5 + 3] * step; } } }; bool fullscreen = false; void toggle_fullscreen() { fullscreen = !fullscreen; SDL_SetVideoMode(width, height, 0, SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_HWSURFACE | (fullscreen ? SDL_FULLSCREEN : 0)); } int main(int, char**) { if(SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError()); return 1; } SDL_Surface *surface = SDL_SetVideoMode(width, height, 0, SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_HWSURFACE); if(surface == NULL) { fprintf(stderr, "Failed to set video mode: %s\n", SDL_GetError()); return 1; } SDL_Event event; bool running = true; bool paused = false; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_POINT_SPRITE); glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); glClearColor(0, 0, 0, 0); glClearDepth(1); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glShadeModel(GL_SMOOTH); std::vector patterns; patterns.push_back(new BulletPattern()); for(int i = 0; i < 8; i++) { patterns.push_back(new BulletPattern1(i % 2 == 1, 5000 + i * 400)); } patterns.push_back(new BulletPattern2(9000)); TextureSDL texture1("foo.png"); TextureSDL texture2("foo4.png"); GLFragmentShader shader1("bullet_fragment.glsl"); GLVertexShader shader2("bullet_vertex.glsl"); GLShaderProgram program; program.attach(shader1); program.attach(shader2); program.link(); FTPixmapFont font("VeraMono.ttf"); font.FaceSize(12); float f = 0.0; float fps = 0.0; unsigned int lasttick = SDL_GetTicks(); unsigned int elapsed = 0; unsigned int lastframes = 0, frames = 0; while(running) { while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: running = false; break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_ESCAPE: running = false; break; case SDLK_SPACE: paused = !paused; lasttick = SDL_GetTicks(); break; case 'f': toggle_fullscreen(); break; default: break; } break; } } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(-10, -10, 660, 740); glScissor(0, 0, 640, 720); glEnable(GL_SCISSOR_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, (float)width / (float)height, 1, 100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); unsigned int tick = SDL_GetTicks(); unsigned int step = tick - lasttick; lasttick = tick; if(!paused) { f += 0.0005 * step; elapsed += step; for(std::vector::iterator it = patterns.begin(); it < patterns.end(); it++) { (*it)->update(elapsed, step); } } gluLookAt( 5 * sinf(f), 1, 5 * cosf(f), 0, 0, 0, 5 * sinf(f), 2, 5 * cosf(f)); glBegin(GL_LINES); for(int i = -10; i < 11; i++) { if(i % 5 == 0) glColor3f(1, 1, 1); else glColor3f(.5, .5, .5); glVertex3f(i, 0, -10); glVertex3f(i, 0, 10); glVertex3f(-10, 0, i); glVertex3f(10, 0, i); } glEnd(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-10, 110, -10, 110, 0, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); program.use(); std::list::iterator it; glPointSize(16.0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture2.tex()); glColor4f(1, 0, 0, 1); for(std::vector::iterator it = patterns.begin(); it < patterns.end(); it++) { BulletPattern *bp = (*it); glColor3f(bp->color_r, bp->color_g, bp->color_b); bp->draw(); } glDisable(GL_TEXTURE_2D); glUseProgram(0); glDisable(GL_SCISSOR_TEST); glViewport(640, 0, 640, 720); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 100, 0, 100, 0, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor4f(1, 1, 1, 1); char s[0xff]; if(tick - lastframes >= 1000) { fps = (float)frames * ((float)(tick - lastframes) / 1000.0f); frames = 1; lastframes = tick; } else { frames++; } snprintf(s, 0xff, "FPS: %.2f", fps); glRasterPos2f(1, 1); font.Render(s); SDL_GL_SwapBuffers(); SDL_Delay(10); } SDL_Quit(); }