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
] );
86 delete m_python_input
;
92 if ( m_thumbnailMode
) {
93 for ( int i
=0; i
<m_files
.size(); i
++ ) {
94 renderThumbnail( m_files
[i
], m_width
, m_height
);
97 m_window
= new Window(m_width
,m_height
,"Numpty Physics","NPhysics", m_fullscreen
),
98 runGame( m_files
, m_width
, m_height
);
106 if ( m_thumbnailMode
) {
107 putenv((char*)"SDL_VIDEODRIVER=dummy");
109 putenv((char*)"SDL_VIDEO_X11_WMCLASS=NPhysics");
111 if ( mkdir( (std::string(getenv("HOME"))+"/"USER_BASE_PATH
).c_str(),
113 fprintf(stderr
,"failed to create user dir\n");
117 if (SDL_Init(SDL_INIT_VIDEO
|SDL_INIT_TIMER
) < 0) {
118 throw "Couldn't initialize SDL";
122 m_python_input
= new PythonInput(m_width
, m_height
);
127 void renderThumbnail( const char* file
, int width
, int height
)
129 configureScreenTransform( width
, height
);
131 if ( scene
.load( file
) ) {
132 printf("generating bmp %s\n", file
);
133 Canvas
temp( width
, height
);
134 scene
.draw( temp
, FULLSCREEN_RECT
);
135 std::string
bmp( file
);
137 temp
.writeBMP( bmp
.c_str() );
142 void add( Widget
* w
)
144 m_layers
.append( w
);
145 w
->setParent( this );
148 void remove( Widget
* w
)
150 if ( m_layers
.indexOf( w
) >= 0 ) {
151 m_layers
.erase( m_layers
.indexOf( w
) );
152 w
->setParent( NULL
);
157 void runGame( Array
<const char*>& files
, int width
, int height
)
159 Levels
* levels
= new Levels();
161 if ( files
.size() > 0 ) {
162 for ( int i
=0; i
<files
.size(); i
++ ) {
163 levels
->addPath( files
[i
] );
167 if ( stat("Game.cpp",&st
)==0 ) {
168 levels
->addPath( "data" );
170 levels
->addPath( DEFAULT_LEVEL_PATH
);
172 levels
->addPath( Config::userDataDir().c_str() );
175 add( createGameLayer( levels
, width
, height
) );
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
);