#include "application.h" #include "config.h" #include "texturesdl.h" #include #include #include #include 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] = 0.5 + sinf(!reverse ? M_PI_2 + i : M_PI - i + M_PI_2) * 0.09; bullets[j*4 + 1] = 0.8 + cosf(M_PI_2 + i) * 0.1; bullets[j*4 + 2] = sinf(!reverse ? M_PI_2 + i : M_PI - i + M_PI_2) / 15000.0; bullets[j*4 + 3] = -0.0001; } }; 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] = 0.5 + sinf(j % 2 ? M_PI_2 + i : M_PI - i + M_PI_2) * 0.09; bullets[k*5 + 1] = 0.8 + cosf(M_PI_2 + i) * 0.1; bullets[k*5 + 2] = sinf(j % 2 ? M_PI_2 + i : M_PI - i + M_PI_2) / 15000; bullets[k*5 + 3] = -0.0001; 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; } } }; Application::Application() { // Initialize SDL if(SDL_Init(SDL_INIT_VIDEO)) { throw(std::runtime_error("SDL initialization failed")); } // Fetch the video info const SDL_VideoInfo *info = SDL_GetVideoInfo(); if(!info) { throw(std::runtime_error("SDL info query failed")); } // The SDL mode-flags int flags = SDL_OPENGL; // OpenGL in SDL flags |= SDL_GL_DOUBLEBUFFER; // Double buffering flags |= SDL_HWPALETTE; // Hardware palette // Check for hardware surface aviability if(info->hw_available) { flags |= SDL_HWSURFACE; } else { flags |= SDL_SWSURFACE; } // Check for hardware blit ability if(info->blit_hw) { flags |= SDL_HWACCEL; } // Setup double buffering SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); // Get our surface surface = SDL_SetVideoMode(Config::window_w, Config::window_h, 32, flags); if(!surface) { throw(std::runtime_error("Video mode set failed")); } // Texturing glEnable(GL_TEXTURE_2D); // Blending glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); // Smooth shading glShadeModel(GL_SMOOTH); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_POINT_SPRITE); glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); glClearColor(0, 0, 0, 0); glClearDepth(1); please_quit = false; } Application::~Application() { } void Application::run() { elapsed = 0; paused = false; font = new FTPixmapFont("fonts/VeraMono.ttf"); font->FaceSize(12); background = new TextureSDL("textures/background.png"); texture = new TextureSDL("textures/shot1.png"); shader = new GLShaderProgram(); player = new Player(); 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)); GLFragmentShader shader1("shaders/bullet_fragment.glsl"); GLVertexShader shader2("shaders/bullet_vertex.glsl"); shader->attach(shader1); shader->attach(shader2); shader->link(); lasttick = SDL_GetTicks(); while(1) { SDL_Event event; while(SDL_PollEvent(&event)) { if(event.type == SDL_QUIT) { break; } else if(event.type == SDL_KEYDOWN) { event_keypress(event.key.keysym.sym); } } if(please_quit) { return; } unsigned int tick = SDL_GetTicks(); unsigned int step = tick - lasttick; lasttick = tick; main_loop(tick, step); //SDL_Delay(10); } } void Application::main_loop(unsigned int tick, unsigned int step) { if(!paused) { elapsed += step; for(std::vector::iterator it = patterns.begin(); it < patterns.end(); it++) { (*it)->update(elapsed, step); } player->update(); } glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, Config::window_w, Config::window_h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float xo = float(Config::window_w)/float(Config::window_h)/2.5 - 0.5; glOrtho(-xo, 1 + xo, 0, 0.8, 0, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D, background->tex()); glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex2f(-1.9/9.0, 0); glTexCoord2f(0, 0); glVertex2f(-1.9/9.0, 0.8); glTexCoord2f(1, 0); glVertex2f(10.9/9.0, 0.8); glTexCoord2f(1, 1); glVertex2f(10.9/9.0, 0); glEnd(); glDisable(GL_TEXTURE_2D); glColor4f(1, 1, 0, 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(Config::fps_x, Config::fps_y); font->Render(s); float v_x = Config::window_w * (Config::viewport_x + xo) / (1 + 2 * xo); float v_y = Config::window_h * Config::viewport_y; float v_w = Config::window_h * Config::viewport_w; float v_h = Config::window_h * Config::viewport_h; glViewport( v_x - Config::viewport_overscan, v_y - Config::viewport_overscan, v_w + Config::viewport_overscan * 2, v_h + Config::viewport_overscan * 2); glScissor(v_x, v_y, v_w, v_h); glEnable(GL_SCISSOR_TEST); glClearColor(0.2, 0.2, 0.2, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, (float)660 / (float)740, 1, 100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float f = elapsed * 0.0005; 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( -float(Config::viewport_overscan) / float(v_w), 1.0 + float(Config::viewport_overscan) / float(v_w), -float(Config::viewport_overscan) / float(v_w), Config::viewport_aspect + float(Config::viewport_overscan) / float(v_w), 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); player->draw(); shader->use(); glPointSize(32.0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture->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(); } glUseProgram(0); glDisable(GL_SCISSOR_TEST); SDL_GL_SwapBuffers(); } void Application::quit() { please_quit = true; } void Application::event_keypress(SDLKey key) { switch(key) { case SDLK_ESCAPE: quit(); break; case SDLK_SPACE: paused = !paused; lasttick = SDL_GetTicks(); break; default: break; } }