/*************************************************************************** * Copyright (C) 2007 by Cyle Riggs * * cyleriggs@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #define WINDOW_WIDTH 1280 #define WINDOW_HEIGHT 1024 #define TARGET_FPS 24 using namespace std; class CSDLError { public: CSDLError( string doingWhat ) { cerr << "SDL error while "+doingWhat+": " << SDL_GetError() << endl; SDL_Quit(); } }; class CShot { public: CShot( float x ) { CShot::x = x; framesDrawn = 0; y = -1.0; } ~CShot() { } void draw() { glLoadIdentity(); glBegin( GL_LINES ); glVertex3f( x, y, -0.1 ); glVertex3f( x, y+0.1, -0.1 ); glEnd(); } float move( float amount ) { y += amount; return y; } static int sdlThread( void* obj ) { CShot* shot = reinterpret_cast(obj); shot->move( 0.1 ); } float x; float y; unsigned long framesDrawn; static SDL_mutex* instanceMutex; static vector instances; }; SDL_mutex* CShot::instanceMutex = NULL; vector CShot::instances; //Global variables GLfloat mousex = 0; GLfloat mousey = 0; void DrawImage(SDL_Surface *srcimg, int sx, int sy, int sw, int sh, SDL_Surface *dstimg, int dx, int dy, int alpha = 255) { if ((srcimg == NULL) || (alpha == 0)) return; //If theres no image, or its 100% transparent. SDL_Rect src, dst; src.x = sx; src.y = sy; src.w = sw; src.h = sh; dst.x = dx; dst.y = dy; dst.w = src.w; dst.h = src.h; if (alpha != 255) SDL_SetAlpha(srcimg, SDL_SRCALPHA, alpha); SDL_BlitSurface(srcimg, &src, dstimg, &dst); } void drawOutline() { glLoadIdentity(); glBegin( GL_LINES ); glColor3f( 0, 0.9, 0 ); //Horizontal line glVertex3f( -1.0, 0, 0 ); glVertex3f( 1.0, 0, 0 ); //Vertical line glVertex3f( 0, 1.0, 0 ); glVertex3f( 0, -1.0, 0 ); float lineLength = 0.015; for( float x = -1.0; x<1.0; x += 0.05 ) { glVertex3f( x, lineLength, 0 ); glVertex3f( x, -lineLength, 0 ); } for( float y = -1.0; y<1.0; y+= 0.05 ) { glVertex3f( lineLength, y, 0 ); glVertex3f( -lineLength, y, 0 ); } glEnd(); } void drawCursor() { static float rotX = 0; static float rotY = 0; static float rotZ = 0; static const float cursorDiameter = 0.05; // rotX -= 0.4; // rotY += 0.1; // rotZ += 0.2; glLoadIdentity(); glTranslatef( mousex, mousey, 0 ); // glRotatef( rotX, 1.0f, 0, 0 ); // glRotatef( rotY, 0, 1.0f, 0 ); // glRotatef( rotZ, 0, 0, 1.0f ); glBegin( GL_LINES ); glColor3f( 1.0, 1.0, 1.0 ); glVertex3f( -cursorDiameter, 0, 0 ); glVertex3f( cursorDiameter, 0, 0 ); glVertex3f( 0, -cursorDiameter, 0 ); glVertex3f( 0, cursorDiameter, 0 ); glVertex3f( 0, 0, -cursorDiameter ); glVertex3f( 0, 0, cursorDiameter ); glEnd(); } void drawShots() { SDL_mutexP( CShot::instanceMutex ); for( vector::iterator it = CShot::instances.begin(); it != CShot::instances.end(); it++ ) { if( (*it) == NULL ) { continue; } (*it)->draw(); (*it)->framesDrawn++; } SDL_mutexV( CShot::instanceMutex ); } void drawFrame() { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); drawOutline(); drawCursor(); drawShots(); //Done drawing SDL_GL_SwapBuffers(); return; } int drawThreadFn(void*) { int frameStart = 0; int frameEnd = 0; int waitTime = 0; const int frameLength = (1000/TARGET_FPS); while( true ) { frameStart = SDL_GetTicks(); drawFrame(); frameEnd = SDL_GetTicks(); waitTime = frameLength - (frameEnd-frameStart); if( waitTime > 0 ) { SDL_Delay(waitTime); } } } int eventThreadFn(void*) { mousex = mousey = 0; SDL_Event event; while( SDL_WaitEvent(&event) >= 0 ) { switch( event.type ) { case SDL_QUIT: return 0; break; case SDL_MOUSEBUTTONDOWN: cout << "Button down!" << endl; // if( event.button.state == SDL_RELEASED ) { cout << "Created shot!" << endl; SDL_mutexP( CShot::instanceMutex ); CShot::instances.push_back( new CShot(mousex) ); SDL_mutexV( CShot::instanceMutex ); // } break; case SDL_MOUSEMOTION: mousex = ((event.motion.x-(WINDOW_WIDTH/2))*(float)(2.0/(float)WINDOW_WIDTH)); mousey = -((event.motion.y-(WINDOW_HEIGHT/2))*(float)(2.0/(float)WINDOW_HEIGHT)); break; } } } int moveShotsThreadFn(void* obj) { while(true) { SDL_mutexP( CShot::instanceMutex ); for( vector::iterator it = CShot::instances.begin(); it != CShot::instances.end(); it++ ) { if( (*it) == NULL ) { cerr << "skipping null shot pointer" << endl; continue; } if( (*it)->framesDrawn > 0 && (*it)->move(0.1) >= 1.0 ) { cerr << "deleting shot" << endl; delete (*it); cerr << "nullifying shot" << endl; (*it) = NULL; } } cerr << "# of shots = " << CShot::instances.size() << endl; SDL_mutexV( CShot::instanceMutex ); SDL_Delay( 1000/50 ); } } void initGL() { glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); glEnable( GL_DEPTH_TEST ); return; } int main(int argc, char *argv[]) { SDL_Surface *screen = NULL; CShot::instanceMutex = SDL_CreateMutex(); cout <<"Initializing SDL." << endl; if(SDL_Init(SDL_INIT_VIDEO)< 0) { CSDLError( "Initializing SDL" ); } SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); screen = SDL_SetVideoMode(WINDOW_WIDTH,WINDOW_HEIGHT,16,SDL_OPENGL); if( screen == NULL ) { CSDLError( "Initializing Video" ); } initGL(); SDL_WarpMouse( WINDOW_WIDTH/2, WINDOW_HEIGHT/2 ); SDL_Thread *eventThread = SDL_CreateThread( &eventThreadFn, NULL ); SDL_Thread *drawThread = SDL_CreateThread( &drawThreadFn, NULL ); SDL_Thread *shotsThread = SDL_CreateThread( &moveShotsThreadFn, NULL ); SDL_WaitThread( eventThread, NULL ); SDL_KillThread( drawThread ); SDL_KillThread( shotsThread ); SDL_DestroyMutex( CShot::instanceMutex ); SDL_Quit(); return 0; }