1 // Description:
2 //   Video subsystem.
3 //
4 // Copyright (C) 2001 Frank Becker
5 //
6 // This program is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free Software
8 // Foundation;  either version 2 of the License,  or (at your option) any  later
9 // version.
10 //
11 // This program is distributed in the hope that it will be useful,  but  WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
14 //
15 #include "Video.hpp"
16 
17 #include <math.h>
18 
19 #include <FPS.hpp>
20 
21 #include <PNG.hpp>
22 #include <Trace.hpp>
23 #include <Random.hpp>
24 #include <Config.hpp>
25 #include <Value.hpp>
26 #include <GameState.hpp>
27 #include <Constants.hpp>
28 
29 #include <Hero.hpp>
30 #include <ParticleGroupManager.hpp>
31 #include <Timer.hpp>
32 #include <Camera.hpp>
33 #include <Starfield.hpp>
34 #include <MenuManager.hpp>
35 #include <StageManager.hpp>
36 #include <FontManager.hpp>
37 #include <BitmapManager.hpp>
38 #include <ModelManager.hpp>
39 #include <ScoreKeeper.hpp>
40 #include <TextureManager.hpp>
41 #include <GLExtension.hpp>
42 
43 #include <ResourceManager.hpp>
44 #include <zrwops.hpp>
45 
46 #include "GLee.h"
47 #include "SDL/SDL.h"
48 
49 #include <algorithm>
50 #include <string>
51 #include <locale>
52 
53 using namespace std;
54 
55 //Earlier versions of SDL don't have DISABLE defined
56 #ifndef SDL_DISABLE
57 #define SDL_DISABLE 0
58 #endif
59 
Video()60 Video::Video():
61     _isFullscreen( false),
62     _showStarfield( true),
63     _showNebulas( true),
64     _maxFPS(0),
65     _fpsStepSize(0.0),
66     _bpp( 0),
67     _width( VIDEO_DEFAULT_WIDTH),
68     _height( VIDEO_DEFAULT_HEIGHT),
69     _boardVisible( true),
70     _boardPosX( 0),
71     _titleA( 0),
72     _titleB( 0),
73     _angle(0.0),
74     _prevAngle(0.0)
75 {
76     XTRACE();
77 }
78 
~Video()79 Video::~Video()
80 {
81     XTRACE();
82     LOG_INFO << "Video shutdown..." << endl;
83 
84     BitmapManagerS::cleanup();
85     FontManagerS::cleanup();
86     TextureManagerS::cleanup();
87     GLExtension::close();
88 
89     delete _titleA;
90     delete _titleB;
91 
92     SkillS::cleanup();
93     CameraS::cleanup();
94 
95 #ifdef __APPLE__
96     //Workaround for non-working minimize buttons on exit
97     SDL_SetVideoMode( _width, _height, _bpp, 0);
98 #endif
99 
100     SDL_QuitSubSystem( SDL_INIT_VIDEO);
101     SDL_Quit();
102 }
103 
reload(void)104 void Video::reload( void)
105 {
106     BitmapManagerS::instance()->reload();
107     FontManagerS::instance()->reload();
108 
109     _titleA->reload();
110     _titleB->reload();
111 
112     ModelManagerS::instance()->reload();
113     MenuManagerS::instance()->reload();
114 }
115 
init(void)116 bool Video::init( void)
117 {
118     XTRACE();
119     LOG_INFO << "Initializing Video..." << endl;
120 
121     if( SDL_InitSubSystem( SDL_INIT_VIDEO) < 0 )
122     {
123         LOG_ERROR << "Init Video: failed # " << SDL_GetError() << endl;
124         return false;
125     }
126     LOG_INFO << "Video: OK" << endl;
127 
128     ConfigS::instance()->getInteger( "maxFPS", _maxFPS);
129     if( _maxFPS)
130     {
131 	LOG_INFO << "Video: Restricting FPS to " << _maxFPS << endl;
132 	_fpsStepSize = 1.0f/(float)_maxFPS;
133     }
134 
135     ConfigS::instance()->getBoolean( "fullscreen", _isFullscreen);
136 
137     if( !setVideoMode())
138     {
139 	SDL_QuitSubSystem( SDL_INIT_VIDEO);
140 	return false;
141     }
142 
143     _smallFont = FontManagerS::instance()->getFont( "bitmaps/arial-small");
144     if( !_smallFont)
145     {
146         LOG_ERROR << "Unable to get font... (arial-small)" << endl;
147 	SDL_QuitSubSystem( SDL_INIT_VIDEO);
148         return false;
149     }
150 
151     _scoreFont = FontManagerS::instance()->getFont( "bitmaps/vipnaUpper");
152     if( !_scoreFont)
153     {
154         LOG_ERROR << "Unable to get font... (vipnaUpper)" << endl;
155 	SDL_QuitSubSystem( SDL_INIT_VIDEO);
156         return false;
157     }
158 
159     _gameOFont = FontManagerS::instance()->getFont( "bitmaps/gameover");
160     if( !_gameOFont)
161     {
162         LOG_ERROR << "Unable to get font... (gameover)" << endl;
163 	SDL_QuitSubSystem( SDL_INIT_VIDEO);
164         return false;
165     }
166 
167     _board = BitmapManagerS::instance()->getBitmap( "bitmaps/board");
168     if( !_board)
169     {
170 	LOG_ERROR << "Unable to load CritterBoard" << endl;
171 	SDL_QuitSubSystem( SDL_INIT_VIDEO);
172         return false;
173     }
174     _boardIndex = _board->getIndex( "CritterBoard");
175 
176     if( !ResourceManagerS::instance()->selectResource(
177 	  string("bitmaps/titleA.png")))
178     {
179 	LOG_WARNING << "titleA.png not found." << endl;
180 	return false;
181     }
182     ziStream &bminfile1 = ResourceManagerS::instance()->getInputStream();
183     SDL_RWops *src = RWops_from_ziStream( bminfile1);
184     SDL_Surface *img1 = IMG_LoadPNG_RW( src);
185     SDL_RWclose( src);
186     _titleA = new GLTexture( GL_TEXTURE_2D, img1, false);
187 
188     if( !ResourceManagerS::instance()->selectResource(
189 	  string("bitmaps/titleB.png")))
190     {
191 	LOG_WARNING << "titleB.png not found." << endl;
192 	return false;
193     }
194     ziStream &bminfile2 = ResourceManagerS::instance()->getInputStream();
195     src = RWops_from_ziStream( bminfile2);
196     SDL_Surface *img2 = IMG_LoadPNG_RW( src);
197     SDL_RWclose( src);
198     _titleB = new GLTexture( GL_TEXTURE_2D, img2, false);
199 
200     //hide&grab cursor and warp to centre
201     SDL_ShowCursor( SDL_DISABLE);
202     SDL_WM_GrabInput( SDL_GRAB_ON);
203     SDL_WarpMouse( _width/2,  _height/2);
204 
205     SDL_Event event;
206     while( SDL_PollEvent( &event))
207     {
208 	//remove any queued up events due to warping, etc.
209 	;
210     }
211 
212     LOG_INFO << "OpenGL info follows..." << endl;
213     string vendor = (char*)glGetString( GL_VENDOR);
214     LOG_INFO << "  Vendor  : " << vendor << endl;
215     LOG_INFO << "  Renderer: " <<  glGetString( GL_RENDERER) << endl;
216     LOG_INFO << "  Version : " << glGetString( GL_VERSION) << endl;
217 
218     glViewport(0,0, _width, _height);
219 /*
220     GLfloat mat_ambient[]  = { 0.7, 0.7, 0.7, 0.0 };
221     GLfloat mat_diffuse[]  = { 0.6, 0.6, 0.6, 0.0 };
222     GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 0.0 };
223 */
224 
225     GLfloat mat_ambient[]  = { 0.5f, 0.5f, 0.5f, 0.5f };
226     GLfloat mat_diffuse[]  = { 0.4f, 0.4f, 0.4f, 0.5f };
227     GLfloat mat_specular[] = { 0.6f, 0.6f, 0.6f, 0.5f };
228     GLfloat mat_shininess[] = { 60.0f };
229     glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
230     glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
231     glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
232     glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
233 
234     GLfloat mat_diffuse_b[]  = { 0.5f, 0.5f, 0.5f, 0.5f };
235     GLfloat mat_ambient_b[]  = { 0.3f, 0.3f, 0.3f, 0.5f };
236     GLfloat mat_specular_b[] = { 0.2f, 0.2f, 0.2f, 0.5f };
237     GLfloat mat_shininess_b[] = { 10.0f };
238     glMaterialfv(GL_BACK, GL_SPECULAR, mat_specular_b);
239     glMaterialfv(GL_BACK, GL_SHININESS, mat_shininess_b);
240     glMaterialfv(GL_BACK, GL_AMBIENT, mat_ambient_b);
241     glMaterialfv(GL_BACK, GL_DIFFUSE, mat_diffuse_b);
242 
243     glClearColor(0.0, 0.0, 0.0, 0.0);
244 
245     return true;
246 }
247 
setVideoMode(void)248 bool Video::setVideoMode( void)
249 {
250     int videoFlags = SDL_OPENGL;
251 
252     ConfigS::instance()->getBoolean( "fullscreen", _isFullscreen);
253     if( _isFullscreen)
254     {
255         LOG_INFO << "Fullscreen request." << endl;
256         videoFlags |= SDL_FULLSCREEN;
257     }
258 
259     if( !ConfigS::instance()->getInteger( "width", _width))
260     {
261 	Value *w = new Value( _width);
262 	ConfigS::instance()->updateTransitoryKeyword( "width", w);
263     }
264     if( !ConfigS::instance()->getInteger( "height", _height))
265     {
266 	Value *h = new Value( _height);
267 	ConfigS::instance()->updateTransitoryKeyword( "height", h);
268     }
269 
270     if( SDL_SetVideoMode( _width, _height, _bpp, videoFlags ) == NULL )
271     {
272         LOG_ERROR << "Video Mode: failed #" << SDL_GetError() << endl;
273         return false;
274     }
275     glViewport(0,0, _width, _height);
276 
277     //set title and icon name
278     SDL_WM_SetCaption( "Critical Mass (aka Critter)", "Critical Mass" );
279 
280     SDL_Surface *surf = SDL_GetVideoSurface();
281 
282     LOG_INFO << "Video Mode: OK ("
283              << surf->w << "x"
284 	     << surf->h << "x"
285 	     << (int)surf->format->BitsPerPixel << ")" << endl;
286 
287     return true;
288 }
289 
updateSettings(void)290 bool Video::updateSettings( void)
291 {
292     bool fullscreen = _isFullscreen;
293     ConfigS::instance()->getBoolean( "fullscreen", _isFullscreen);
294     int width = 0;
295     ConfigS::instance()->getInteger( "width", width);
296     int height = 0;
297     ConfigS::instance()->getInteger( "height", height);
298 
299     if( (fullscreen != _isFullscreen) || (width != _width) || (height != _height))
300     {
301 	bool oldFullscreen = _isFullscreen;
302 	int oldWidth = _width;
303 	int oldHeight = _height;
304 	if( !setVideoMode())
305 	{
306 	    //new settings no good, try old
307 	    Value *fs = new Value( oldFullscreen);
308 	    ConfigS::instance()->updateKeyword( "fullscreen", fs);
309 
310 	    Value *w = new Value( oldWidth);
311 	    ConfigS::instance()->updateKeyword( "width", w);
312 
313 	    Value *h = new Value( oldHeight);
314 	    ConfigS::instance()->updateKeyword( "height", h);
315 
316 	    if( !setVideoMode())
317 	    {
318 		//no luck, we are going down!
319 		SDL_QuitSubSystem(SDL_INIT_VIDEO);
320 		GameState::isAlive = false;
321 		return false;
322 	    }
323 	}
324 	reload();
325     }
326 
327     ConfigS::instance()->getBoolean( "showStarfield", _showStarfield);
328     ConfigS::instance()->getBoolean( "showNebulas", _showNebulas);
329 
330     return true;
331 }
332 
updateLogic(void)333 void Video::updateLogic( void)
334 {
335     _prevAngle = _angle;
336     _angle += 5.0f;
337 
338     float boardWidth = (float)_board->getWidth( _boardIndex);
339     if( _boardVisible && (_boardPosX<0))
340     {
341         _boardPosX+=9;
342         if( _boardPosX > 0) _boardPosX = 0;
343     }
344 
345     if( !_boardVisible && (_boardPosX>-boardWidth))
346     {
347         _boardPosX-=9;
348     }
349 }
350 
update(void)351 bool Video::update( void)
352 {
353     //    XTRACE();
354     static float nextTime = Timer::getTime()+0.5f;
355     float thisTime = Timer::getTime();
356     if( thisTime > nextTime)
357     {
358 	if( ! updateSettings()) return false;
359 	nextTime = thisTime+0.5f;
360     }
361 
362     if( _maxFPS)
363     {
364 	static float sTime = Timer::getTime();
365 	if( (thisTime-sTime) < _fpsStepSize)
366 	{
367 	    return true;
368 	}
369 	while(( thisTime-sTime) > _fpsStepSize) sTime+=_fpsStepSize;
370     }
371 
372     FPS::Update();
373 
374     GLBitmapFont &smallFont = *_smallFont;
375     GLBitmapFont &scoreFont = *_scoreFont;
376     GLBitmapFont &gameOFont = *_gameOFont;
377 
378     glEnable( GL_DEPTH_TEST);
379     glEnable( GL_LIGHTING);
380     glEnable( GL_LIGHT0);
381     glShadeModel(GL_SMOOTH);
382 
383     glEnable( GL_NORMALIZE);
384 //    glEnable( GL_RESCALE_NORMAL);
385 
386     glEnable(GL_BLEND);
387     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
388     glEnable( GL_COLOR_MATERIAL );
389 
390     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
391 
392     glMatrixMode(GL_PROJECTION);
393     glLoadIdentity();
394 
395     const float fov = 53.13f;
396     glFrustum(
397         (4.0/3.0)*(-2.0*tan(53.13 * M_PI / 360.0)),  //xmin
398         (4.0/3.0)*( 2.0*tan(53.13 * M_PI / 360.0)),  //xmax
399         -2.0*tan(53.13 * M_PI / 360.0),  //ymin
400          2.0*tan(53.13 * M_PI / 360.0),  //ymax
401          2.0,                            //znear
402          1000.0);                        //zfar
403 
404     glMatrixMode(GL_MODELVIEW);
405     glLoadIdentity();
406 
407     CameraS::instance()->update();
408 
409     //place camera
410     CameraS::instance()->place();
411 
412     GLfloat light_position[] = { 20.0, 0.0, -50.0, 1.0 };
413     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
414     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
415 
416     if( GameState::isDeveloper)
417     {
418 	//highlight the playing field, useful when using mouselook
419 	glDisable( GL_DEPTH_TEST);
420 	glDisable( GL_LIGHTING);
421 	float y = tan(((float)M_PI*fov)/360.0f)*100;
422 	float x = y*4.0f/3.0f;
423 	glColor4f( 1.0f, 1.0f, 1.0f, 0.1f );
424 	glBegin(GL_QUADS);
425 	    glVertex3f( -x, y, -100);
426 	    glVertex3f(  x, y, -100);
427 	    glVertex3f(  x,-y, -100);
428 	    glVertex3f( -x,-y, -100);
429 	glEnd();
430 	glEnable( GL_LIGHTING);
431 	glEnable( GL_DEPTH_TEST);
432     }
433 
434     StarfieldS::instance()->draw( _showStarfield, _showNebulas);
435 
436     if( GameState::context != Context::eMenu)
437     {
438 	if( HeroS::instance()->alive())
439 	{
440 	    glPushMatrix();
441 	    HeroS::instance()->draw();
442 	    glPopMatrix();
443 	}
444 
445 	ParticleGroupManagerS::instance()->draw();
446     }
447 
448     //--- Ortho stuff from here on ---
449     glMatrixMode(GL_PROJECTION);
450     glLoadIdentity();
451     glOrtho(-0.5,VIDEO_ORTHO_WIDTH+0.5,-0.5,VIDEO_ORTHO_HEIGHT+0.5, -1000.0, 1000.0);
452 
453     glMatrixMode(GL_MODELVIEW);
454     glLoadIdentity();
455 
456     glDisable(GL_DEPTH_TEST);
457     glDisable(GL_LIGHTING);
458 
459     glColor4f(1.0,1.0,1.0,1.0);
460     bool showFPS = false;
461     ConfigS::instance()->getBoolean( "showFPS", showFPS);
462     if( showFPS)
463     {
464 	smallFont.DrawString( FPS::GetFPSString(), 0, 0,  0.6f, 0.6f);
465     }
466 
467     if( GameState::context != Context::eMenu)
468     {
469 	if( !HeroS::instance()->alive())
470 	{
471 	    glColor4f(1.0f,1.0f,1.0f,0.8f);
472 	    gameOFont.DrawString( "GAME OVER" , 80, 320, 1.3f, 1.3f);
473 
474 	    glColor4f(1.0f,0.0f,0.0f,0.8f);
475 	    smallFont.DrawString( "Too dangerous for ya? Try again!" ,
476 		215, 260, 1.0f, 1.0f);
477 
478             if( ScoreKeeperS::instance()->currentIsTopTen())
479 	    {
480 		if( !_textInput.isOn())
481 		{
482 		    _textInput.turnOn();
483 		}
484 
485 		glColor4f(1.0f,1.0f,1.0f,1.0f);
486 		smallFont.DrawString( "Top Ten Finish! RIP",215,200, 1.0f, 1.0f);
487 
488 		string pname = "Enter Pilot name: ";
489 		pname += _textInput.getText()+"_";
490 		glColor4f(1.0f,0.852f,0.0f,1.0f);
491 		smallFont.DrawString( pname.c_str() , 215, 140, 1.0f, 1.0f);
492 
493 		ScoreKeeperS::instance()->setName( _textInput.getText());
494 	    }
495 	    else
496 	    {
497 		string moremorequickquick = "Press right mouse button to restart";
498 		glColor4f(1.0f,0.852f,0.0f,1.0f);
499 		smallFont.DrawString( moremorequickquick.c_str() , 215, 140, 1.0f, 1.0f);
500 	    }
501 
502 	    glColor4f(1.0f,1.0f,1.0f,1.0f);
503 	}
504     }
505 
506     char buff[128];
507     if( GameState::isDeveloper)
508     {
509 	static float nextShow = 0;
510 	static int aCount = 0;
511 	float thisTime = Timer::getTime();
512 	if( thisTime > nextShow)
513 	{
514 	    nextShow = thisTime + 0.5f;
515 	    aCount = ParticleGroupManagerS::instance()->getAliveCount();
516 	}
517 	sprintf( buff, "p=%d", aCount);
518 	smallFont.DrawString( buff, 0, 40, 1.0, 1.0);
519     }
520 
521     if( GameState::context == Context::eMenu)
522     {
523 	glEnable(GL_TEXTURE_2D);
524 
525 	float z=-1.0;
526 	float dx= 1.0/512.0;
527 
528 	_titleA->bind();
529 	glBegin(GL_QUADS);
530 	glTexCoord2f( dx     ,dx );   glVertex3f(350,740, z);
531 	glTexCoord2f( 1.0f-dx,dx );   glVertex3f(500,740, z);
532 	glTexCoord2f( 1.0f-dx,1-dx ); glVertex3f(500,560, z);
533 	glTexCoord2f( dx     ,1-dx ); glVertex3f(350,560, z);
534 	glEnd();
535 
536 	_titleB->bind();
537 	glBegin(GL_QUADS);
538 	glTexCoord2f( dx     ,dx );   glVertex3f(500,740, z);
539 	glTexCoord2f( 1.0f-dx,dx );   glVertex3f(650,740, z);
540 	glTexCoord2f( 1.0f-dx,1-dx ); glVertex3f(650,560, z);
541 	glTexCoord2f( dx     ,1-dx ); glVertex3f(500,560, z);
542 	glEnd();
543 
544 	glDisable(GL_TEXTURE_2D);
545 
546 	MenuManagerS::instance()->draw();
547 
548 	glColor4f(1.0,1.0,1.0,0.5);
549 	string gVersion = "v"+GAMEVERSION;
550 	float width = smallFont.GetWidth( gVersion.c_str(), 0.6f);
551 	smallFont.DrawString( gVersion.c_str() , 995.0f-width, 5.0f, 0.6f, 0.4f);
552     }
553     else
554     {
555 	float boardWidth = (float)_board->getWidth( _boardIndex);
556 
557         //draw board if at least partially visible
558         if( _boardPosX > -boardWidth)
559 	{
560 	    float size = 0.48f;
561 	    float tdy = -36.0f;
562 	    float ty = (float)VIDEO_ORTHO_HEIGHT-56.0f;
563 	    float tx = 28.0f+_boardPosX;
564 
565 	    glEnable(GL_TEXTURE_2D);
566 	    _board->bind();
567 	    glColor4f(1.0,1.0,1.0,0.5);
568 	    _board->Draw(_boardIndex,_boardPosX,VIDEO_ORTHO_HEIGHT-256,1.0,1.0);
569 	    glDisable(GL_TEXTURE_2D);
570 
571 	    sprintf( buff, "%d", ScoreKeeperS::instance()->getCurrentScore());
572 	    scoreFont.DrawString( buff, tx, ty, size, size);
573 	    ty+=tdy;
574 
575 	    sprintf( buff, "%d", ScoreKeeperS::instance()->getHighScore());
576 	    scoreFont.DrawString( buff, tx, ty, size, size);
577 	    ty+=tdy;
578 
579 	    float he = HeroS::instance()->getEnergy();
580 	    if( he<0.0) he=0.0;
581 	    glColor4f( 1.0f, 0.1f, 0.1f, 0.5f );
582 	    glBegin(GL_QUADS);
583 		glVertex3f( tx        , ty+2, -1);
584 		glVertex3f( tx+he*.97f, ty+2, -1);
585 		glVertex3f( tx+he*.97f, ty+20, -1);
586 		glVertex3f( tx        , ty+20, -1);
587 	    glEnd();
588 	    glColor4f(1.0,1.0,1.0,0.5);
589 
590 	    sprintf( buff, "%d", (int)he);
591 	    scoreFont.DrawString( buff, tx, ty, size, size);
592 	    ty+=tdy;
593 
594 	    float se = HeroS::instance()->getShieldEnergy();
595 	    glColor4f( 1.0f, 0.8f, 0.0f, 0.5f );
596 	    glBegin(GL_QUADS);
597 		glVertex3f( tx        , ty+2, -1);
598 		glVertex3f( tx+se*.97f, ty+2, -1);
599 		glVertex3f( tx+se*.97f, ty+20, -1);
600 		glVertex3f( tx        , ty+20, -1);
601 	    glEnd();
602 	    glColor4f(1.0,1.0,1.0,0.5);
603 
604 	    sprintf( buff, "%d", (int)se);
605 	    scoreFont.DrawString( buff, tx, ty, size, size);
606 	    ty+=tdy;
607 
608 	    float we = HeroS::instance()->getWeaponEnergy()/(HeroS::instance()->getMaxWeaponEnergy()/100.0);
609 	    glColor4f( 0.2f, 1.0f, 0.2f, 0.5f );
610 	    glBegin(GL_QUADS);
611 		glVertex3f( tx        , ty+2, -1);
612 		glVertex3f( tx+we*.97f, ty+2, -1);
613 		glVertex3f( tx+we*.97f, ty+20, -1);
614 		glVertex3f( tx        , ty+20, -1);
615 	    glEnd();
616 	    glColor4f(1.0,1.0,1.0,0.5);
617 
618 	    sprintf( buff, "%d", (int)HeroS::instance()->getWeaponEnergy());
619 	    scoreFont.DrawString( buff, tx, ty, size, size);
620 	    ty+=tdy;
621 
622             SkillS::instance();
623             string theSkill = Skill::getString(GameState::skill);
624 	    scoreFont.DrawString( theSkill.c_str(), tx, ty, size, size);
625 
626 	    glEnable( GL_LIGHTING);
627 	    glEnable( GL_DEPTH_TEST);
628 
629 	    GLfloat light_position2[] = { 820.0, 620.0, 500.0, 0.0 };
630 	    glLightfv(GL_LIGHT0, GL_POSITION, light_position2);
631 	    glDisable(GL_TEXTURE_2D);
632 
633 	    float iAngle = _prevAngle+(_angle-_prevAngle)*GameState::frameFraction;
634 
635 	    glPushMatrix();
636 	    glTranslatef(154.0+_boardPosX, 675.0, -1.0);
637 	    glRotatef(iAngle, 0.0, 1.0, 0.0);
638 	    HeroS::instance()->drawWeapon(0);
639 	    glPopMatrix();
640 
641 	    glPushMatrix();
642 	    glTranslatef(154.0+_boardPosX, 621.0, -1.0);
643 	    glRotatef(iAngle, 0.0, 1.0, 0.0);
644 	    HeroS::instance()->drawWeapon(1);
645 	    glPopMatrix();
646 
647 	    glPushMatrix();
648 	    glTranslatef(154.0+_boardPosX, 567.0, -1.0);
649 	    glRotatef(iAngle, 0.0, 1.0, 0.0);
650 	    HeroS::instance()->drawWeapon(2);
651 	    glPopMatrix();
652 	}
653     }
654 
655     SDL_GL_SwapBuffers( );
656 
657     return true;
658 }
659 
takeSnapshot(void)660 void Video::takeSnapshot( void)
661 {
662     static int count = 0;
663 
664     int width = VideoS::instance()->getWidth();
665     int height = VideoS::instance()->getHeight();
666     char filename[128];
667     sprintf( filename, "snap%02d.png", count++);
668     SDL_Surface *img;
669 
670     img = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, 24,
671 	    0xFF000000, 0x00FF0000, 0x0000FF00,0);
672 
673     glReadPixels( 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, img->pixels);
674 
675     LOG_INFO << "Writing snapshot: " << filename << endl;
676     if( !PNG::Snapshot( img, filename))
677     {
678 	LOG_ERROR << "Failed to save snapshot." << endl;
679     }
680 
681     SDL_FreeSurface( img);
682 }
683