2 * This file is part of NumptyPhysics
3 * Copyright (C) 2008 Tim Edmonds
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 3 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
26 #include "PythonInput.h"
34 class App
: private WidgetParent
42 Array
<const char*> m_files
;
43 Array
<Widget
*> m_layers
;
46 PythonInput
*m_python_input
;
49 App(int argc
, char** argv
)
50 : m_width(SCREEN_WIDTH
),
51 m_height(SCREEN_HEIGHT
),
54 m_thumbnailMode(false),
58 , m_python_input(NULL
)
61 for ( int i
=1; i
<argc
; i
++ ) {
62 if ( strcmp(argv
[i
],"-bmp")==0 ) {
63 m_thumbnailMode
= true;
64 } else if ( strcmp(argv
[i
],"-rotate")==0 ) {
66 } else if ( strcmp(argv
[i
],"-fullscreen")==0 ) {
68 } else if ( strcmp(argv
[i
],"-geometry")==0 && i
<argc
-1) {
70 if ( sscanf(argv
[i
+1],"%dx%d",&ww
,&hh
) ==2 ) {
76 m_files
.append( argv
[i
] );
85 delete m_python_input
;
91 if ( m_thumbnailMode
) {
92 for ( int i
=0; i
<m_files
.size(); i
++ ) {
93 renderThumbnail( m_files
[i
], m_width
, m_height
);
96 runGame( m_files
, m_width
, m_height
, m_fullscreen
);
104 if ( m_thumbnailMode
) {
105 putenv((char*)"SDL_VIDEODRIVER=dummy");
107 putenv((char*)"SDL_VIDEO_X11_WMCLASS=NPhysics");
109 if ( mkdir( (std::string(getenv("HOME"))+"/"USER_BASE_PATH
).c_str(),
111 fprintf(stderr
,"failed to create user dir\n");
115 if (SDL_Init(SDL_INIT_VIDEO
|SDL_INIT_TIMER
) < 0) {
116 throw "Couldn't initialize SDL";
120 m_python_input
= new PythonInput(m_width
, m_height
);
125 void renderThumbnail( const char* file
, int width
, int height
)
127 configureScreenTransform( width
, height
);
129 if ( scene
.load( file
) ) {
130 printf("generating bmp %s\n", file
);
131 Canvas
temp( width
, height
);
132 scene
.draw( temp
, FULLSCREEN_RECT
);
133 std::string
bmp( file
);
135 temp
.writeBMP( bmp
.c_str() );
140 void add( Widget
* w
)
142 m_layers
.append( w
);
143 w
->setParent( this );
146 void remove( Widget
* w
)
148 if ( m_layers
.indexOf( w
) >= 0 ) {
149 m_layers
.erase( m_layers
.indexOf( w
) );
150 w
->setParent( NULL
);
155 void runGame( Array
<const char*>& files
, int width
, int height
, bool fullscreen
)
157 Levels
* levels
= new Levels();
159 if ( files
.size() > 0 ) {
160 for ( int i
=0; i
<files
.size(); i
++ ) {
161 levels
->addPath( files
[i
] );
165 if ( stat("Game.cpp",&st
)==0 ) {
166 levels
->addPath( "data" );
168 levels
->addPath( DEFAULT_LEVEL_PATH
);
170 levels
->addPath( Config::userDataDir().c_str() );
173 Widget
* game
= createGameLayer(levels
, width
, height
, fullscreen
);
174 m_window
= game
->getWindow();
181 Rect area
= m_layers
[0]->dirtyArea();
183 for ( int i
=1; i
<m_layers
.size(); i
++ ) {
184 Rect dirt
= m_layers
[i
]->dirtyArea();
185 if ( !dirt
.isEmpty() ) {
186 if ( area
.isEmpty() ) {
193 for ( int i
=0; i
<m_layers
.size(); i
++ ) {
194 m_layers
[i
]->draw( *m_window
, area
);
196 //m_window->drawRect( area, 0x00ff00, false );
197 m_window
->update( area
);
201 bool handleGameEvent( SDL_Event
&ev
)
208 if ( ev
.key
.keysym
.sym
== SDLK_q
) {
216 void dispatchEvents( int lastTick
)
218 for ( int i
=0; i
<m_layers
.size(); i
++ ) {
219 m_layers
[i
]->onTick( lastTick
);
223 while ( SDL_PollEvent(&ev
) ) {
224 if ( !handleGameEvent(ev
) ) {
225 for ( int i
=m_layers
.size()-1; i
>=0; i
-- ) {
226 if ( m_layers
[i
]->handleEvent(ev
) ) {
238 int renderRate
= (MIN_RENDER_RATE
+MAX_RENDER_RATE
)/2;
239 int iterationRate
= ITERATION_RATE
;
240 int iterateCounter
= 0;
241 int lastTick
= SDL_GetTicks();
242 bool isComplete
= false;
246 //assumes RENDER_RATE <= ITERATION_RATE
247 //TODO dynamic tick scaling for improved sleep
248 while ( iterateCounter
< iterationRate
) {
249 dispatchEvents( lastTick
);
250 if ( m_quit
) return;
251 iterateCounter
+= renderRate
;
253 iterateCounter
-= iterationRate
;
257 int sleepMs
= lastTick
+ 1000/renderRate
- SDL_GetTicks();
259 if ( sleepMs
> 1 && renderRate
< MAX_RENDER_RATE
) {
261 // printf("increasing render rate to %dfps\n",renderRate);
262 sleepMs
= lastTick
+ 1000/renderRate
- SDL_GetTicks();
266 SDL_Delay( sleepMs
);
268 // printf("overrun %dms\n",-sleepMs);
269 if ( renderRate
> MIN_RENDER_RATE
) {
271 // printf("decreasing render rate to %dfps\n",renderRate);
272 } else if ( iterationRate
> 30 ) {
273 //slow down simulation time to maintain fps??
276 lastTick
= SDL_GetTicks();
286 int npmain(int argc
, char** argv
)
291 } catch ( const char* e
) {
292 fprintf(stderr
,"*** CAUGHT: %s",e
);