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