1 /* 2 * JLib - Jacob's Library. 3 * Copyright (C) 2003, 2004 Juan Carlos Seijo P�rez 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 * Juan Carlos Seijo P�rez 20 * jacob@mainreactor.net 21 */ 22 23 /** Base application class. Allows to init SDL and the other subsystems as sound. 24 * @file JApp.h 25 * @author Juan Carlos Seijo P�rez 26 * @date 01/04/2003 27 * @version 0.0.1 - First version - 01/04/2003 28 */ 29 30 #ifndef _JAPP_INCLUDED 31 #define _JAPP_INCLUDED 32 33 #include <JLib/Util/JTypes.h> 34 #include <JLib/Util/JString.h> 35 #include <JLib/Util/JTimer.h> 36 #include <JLib/Graphics/JFont.h> 37 #include <JLib/Sound/JMixer.h> 38 #include <SDL.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 42 #ifdef _WIN32 43 #else 44 #include <unistd.h> 45 #define _sleep sleep 46 #endif 47 48 /** Application base class. You should inherit from this class and override 49 * the Update and Draw methods to create an application. The following example 50 * creates a 400x300 window and fills the window with a diferent color each frame: 51 * You can try to execute it with the '-h' option to see what standard parameters a JApp 52 * accepts by default. 53 * <pre> 54 * 55 * #include <JLib/Util/JApp.h> 56 * #include <SDL_keysym.h> 57 * #include <stdio.h> 58 * 59 * class MyApp : public JApp 60 * { 61 * int myData; 62 * 63 * public: 64 * MyApp() : JApp("App window title", 400, 300, false, 16), myData(0) 65 * {} 66 * 67 * bool Update() 68 * { 69 * UpdateEvents(); 70 * 71 * ++myData; 72 * if (Keys()[SDLK_ESCAPE] != 0) 73 * { 74 * Exit(); 75 * } 76 * } 77 * 78 * bool Draw() {SDL_FillRect(screen, 0, myData); Flip();} 79 * }; 80 * 81 * int main(int argc, char **argv) 82 * { 83 * MyApp app; 84 * 85 * // Optionally, parses the command line 86 * app.ParseArgs(argc, argv); 87 * 88 * // Initializes SDL. 89 * if (!app.Init()) 90 * { 91 * printf("Error initializing app.\n"); 92 * return -1; 93 * } 94 * 95 * // The aplication stays here until Exit() is called. 96 * return app.MainLoop(); 97 * } 98 * 99 * </pre> 100 */ 101 class JApp 102 { 103 protected: 104 bool active; /**< Is the application active (first plane)? */ 105 bool paused; /**< Is paused the application? */ 106 bool endLoop; /**< Must exit the app? */ 107 JString title; /**< Window title */ 108 s32 width; /**< Window width */ 109 s32 height; /**< Window height */ 110 s32 depth; /**< Color depth */ 111 bool fullScreen; /**< Fullscreen flag */ 112 bool doInput; /**< Must capture events (keyboard, mouse, WM)? */ 113 u32 flags; /**< SDL additional flags */ 114 u32 appPauseTime; /**< Time at which the application is paused */ 115 u8 *keys; /**< Keyboard state */ 116 SDLMod keyMods; /**< Key modifiers state (Shift, Ctrl, etc.) */ 117 s32 numKeys; /**< Number of keyboard keys */ 118 s32 mouseX; /**< Mouse X position */ 119 s32 mouseY; /**< Mouse Y position */ 120 u8 mouseBt; /**< Mouse button mask */ 121 s32 mouseRelX; /**< Mouse X relative increment */ 122 s32 mouseRelY; /**< Mouse Y relative increment */ 123 s16 joyAxisX; /**< Joystick X offset */ 124 s16 joyAxisY; /**< Joystick Y offset */ 125 u8 joyButton; /**< Joystick button */ 126 JTimer timer; /**< Application timer */ 127 s32 fps; /**< Frames per second */ 128 bool dumpVideoInfo; /**< Must dump video info at init? */ 129 130 JMixer mixer; /**< Audio mixer */ 131 bool soundEnabled; /**< Is sound enabled? */ 132 133 char *iconName; /**< Application icon filename */ 134 135 static JApp* thisApp; /**< Pointer to this application */ 136 137 void (*__OnActive)(bool active, s32 state); /**< Active event callback */ 138 void (*__OnKeyUp )(SDL_keysym key); /**< Key up event callback */ 139 void (*__OnKeyDown)(SDL_keysym key); /**< Key down event callback */ 140 void (*__OnMouseMove)(s32 x, s32 y, s32 bt, s32 xRel, s32 yRel); /**< Mouse move event callback */ 141 void (*__OnMouseDown)(s32 bt, s32 x, s32 y); /**< Mouse button down event callback */ 142 void (*__OnMouseUp)(s32 bt, s32 x, s32 y); /**< Mouse button up event callback */ 143 void (*__OnJoyMove)(s32 joyNum, s32 axis, s32 value); /**< Joystick move event callback */ 144 void (*__OnJoyBall)(s32 joyNum, s32 ballIndex, s32 xRel, s32 yRel); /**< Joystick ball event callback */ 145 void (*__OnJoyHat)(s32 joyNum, s32 hatIndex, s32 value); /**< Joystick hat event callback */ 146 void (*__OnJoyUp)(s32 joyNum, s32 btIndex); /**< Joystick button up event callback */ 147 void (*__OnJoyDown)(s32 joyNum, s32 btIndex); /**< Joystick button down event callback */ 148 void (*__OnQuit)(); /**< Quit event callback */ 149 void (*__OnSysWM)(); /**< Window manager event callback */ 150 void (*__OnResize)(s32 w, s32 h); /**< Resize event callback */ 151 void (*__OnExpose)(); /**< Window exposure (unhide) event callback */ 152 void (*__OnUser)(s32 code, void *data1, void *data2); /**< User event callback */ 153 154 SDL_Surface *screen; /**< Primary surface as of SDL_GetVideoSurface() */ 155 SDL_Joystick *joystick; /**< Joystick device */ 156 157 public: 158 /** Creates the application. The audio mixer must be initialized in the child class. 159 * @param strTitle Window title. 160 * @param w Window width. 161 * @param h Window height. 162 * @param fullScr Fullscreen flag. 163 * @param _depth Bits per pixel (color depth, 8, 16, 24, 32, etc.) 164 * @param otherFlags SDL Additional flags 165 */ 166 JApp(const JString& strTitle, s32 w = 1024, s32 h = 768, bool fullScr = true, s32 _depth = 16, u32 otherFlags = 0); 167 168 /** Checks for events to process. In case the associated callback is registered, calls it. 169 * @return <b>true</b> if event polling succeded, <b>false</b> if not. 170 */ 171 virtual bool UpdateEvents(); 172 173 /** Initializes the app. Creates the window with the paraameters given at construction time. 174 * Normally the child application class overrides this method to initialize its objects and calls the parent (this class) 175 * to do the SDL initialization stuff. 176 * @return <b>true</b> if the creation succeded <b>false</b> if not. 177 */ 178 virtual bool Init(); 179 180 /** Updates the application objects (graphics, sounds, A.I., etc.). Must be implemented in the child class. 181 * JApp will call this method before Draw in the child class (by means of MainLoop(). 182 * @return <b>true</b> if success, <b>false</b> else. 183 */ 184 virtual bool Update() = 0; 185 186 /** Draws the application. As Update(), must be implemented in the child class. 187 * @return <b>true</b> if ok, <b>false</b> else. 188 */ 189 virtual bool Draw() = 0; 190 191 /** Main loop. The default implementation calls Update() and if it succeded then calls Draw. The application remains 192 * here until Exit() is called or Update() or Draw() fail. 193 * @return Application exit code. 194 */ 195 virtual s32 MainLoop(); 196 197 /** Returns the window width. 198 * @return Window width. 199 */ Width()200 s32 Width() {return width;} 201 202 /** Returns the window height. 203 * @return Window Height. 204 */ Height()205 s32 Height() {return height;} 206 207 /** Changes the window size. 208 * @param w New width. 209 * @param h New height. 210 * @param _fullScreen <b>true</b> if the app must be fullscreen, <b>false</b> if windowed. 211 */ 212 void Resize(s32 w, s32 h, bool _fullScreen); 213 214 /** Returns the fullscreen flag. 215 * @return <b>true</b> if fullscreen, <b>false</b> if windowed. 216 */ IsFullscreen()217 bool IsFullscreen() {return fullScreen;} 218 219 /** Returns the color depth. 220 * @return Color depth in bits (normally 8, 16, 24 or 32). 221 */ Depth()222 s32 Depth() {return depth;} 223 224 /** Ends the application, exiting from the main loop. 225 */ Exit()226 void Exit() {endLoop = true;} 227 228 /** Returns the active flag. 229 * @return <b>true</b> if the application is active (foreground) <b>false</b> if not. 230 */ IsActive()231 bool IsActive() {return active;} 232 233 /** Returns the pause state of the application. 234 * @return <b>true</b> if paused <b>false</b> otherwise. 235 */ IsPaused()236 bool IsPaused() {return paused;} 237 238 /** Pauses or resumes the application. 239 * @param doPause <b>true</b> pauses the application, <b>false</b> resumes. 240 * @return if pausing (doPause is <b>true</b>), returns the number 241 * of milliseconds from the start of the application. If resuming, 242 * (doPause <b>false</b>), returns the number of milliseconds 243 * during pause mode. 244 */ 245 u32 Pause(bool doPause); 246 247 /** Returns the window title. 248 * @return Window title. 249 */ Title()250 const JString &Title() {return title;} 251 252 /** Sets the window title. 253 * @param newTitle New window title.. 254 */ Title(JString & newTitle)255 void Title(JString &newTitle) {title = newTitle; SDL_WM_SetCaption(title, 0);} 256 257 /** Returns the execution time in milliseconds. 258 * @return Execution time in milliseconds. 259 */ AppTime()260 u32 AppTime() {return SDL_GetTicks();} 261 262 /** Returns the main SDL surface. The surface is created after Init() 263 * @return SDL main surface. 264 */ Screen()265 SDL_Surface * Screen() {return screen;} 266 267 /** Establishes if events must be captured. 268 * @param b <b>true</b> if they must be <b>false</b> otherwise. 269 */ DoInput(bool b)270 void DoInput(bool b) {doInput = b;} 271 272 /** Determines if events must be captured. 273 * @return <b>true</b> if so <b>false</b> if not. 274 */ DoInput()275 bool DoInput() {return doInput;} 276 277 /** Sets the active event callback. 278 * @param _OnActive Callback. 279 */ SetOnActive(void (* _OnActive)(bool active,s32 state))280 void SetOnActive (void (*_OnActive)(bool active, s32 state)) 281 {__OnActive = _OnActive;} 282 283 /** Sets the kay up event callback. 284 * @param _OnKeyUp Callback. 285 */ SetOnKeyUp(void (* _OnKeyUp)(SDL_keysym key))286 void SetOnKeyUp (void (*_OnKeyUp )(SDL_keysym key)) 287 {__OnKeyUp = _OnKeyUp ;} 288 289 /** Sets the key down event callback. 290 * @param _OnKeyDown Callback. 291 */ SetOnKeyDown(void (* _OnKeyDown)(SDL_keysym key))292 void SetOnKeyDown (void (*_OnKeyDown)(SDL_keysym key)) 293 {__OnKeyDown = _OnKeyDown;} 294 295 /** Sets the mouse move event callback. 296 * @param _OnMouseMove Callback. 297 */ SetOnMouseMove(void (* _OnMouseMove)(s32 x,s32 y,s32 bt,s32 xRel,s32 yRel))298 void SetOnMouseMove (void (*_OnMouseMove)(s32 x, s32 y, s32 bt, s32 xRel, s32 yRel)) 299 {__OnMouseMove = _OnMouseMove;} 300 301 /** Sets the mouse button down event callback. 302 * @param _OnMouseDown Callback. 303 */ SetOnMouseDown(void (* _OnMouseDown)(s32 bt,s32 x,s32 y))304 void SetOnMouseDown (void (*_OnMouseDown)(s32 bt, s32 x, s32 y)) 305 {__OnMouseDown = _OnMouseDown;} 306 307 /** Sets the mouse button up event callback. 308 * @param _OnMouseUp Callback. 309 */ SetOnMouseUp(void (* _OnMouseUp)(s32 bt,s32 x,s32 y))310 void SetOnMouseUp (void (*_OnMouseUp)(s32 bt, s32 x, s32 y)) 311 {__OnMouseUp = _OnMouseUp;} 312 313 /** Sets the joystick move event callback. 314 * @param _OnJoyMove Callback. 315 */ SetOnJoyMove(void (* _OnJoyMove)(s32 joyNum,s32 axis,s32 value))316 void SetOnJoyMove (void (*_OnJoyMove)(s32 joyNum, s32 axis, s32 value)) 317 {__OnJoyMove = _OnJoyMove;} 318 319 /** Sets the joystick ball event callback. 320 * @param _OnJoyBall Callback. 321 */ SetOnJoyBall(void (* _OnJoyBall)(s32 joyNum,s32 ballIndex,s32 xRel,s32 yRel))322 void SetOnJoyBall (void (*_OnJoyBall)(s32 joyNum, s32 ballIndex, s32 xRel, s32 yRel)) 323 {__OnJoyBall = _OnJoyBall;} 324 325 /** Sets the joystick hat event callback. 326 * @param _OnJoyHat Callback. 327 */ SetOnJoyHat(void (* _OnJoyHat)(s32 joyNum,s32 hatIndex,s32 value))328 void SetOnJoyHat (void (*_OnJoyHat)(s32 joyNum, s32 hatIndex, s32 value)) 329 {__OnJoyHat = _OnJoyHat;} 330 331 /** Sets the joystick button up event callback. 332 * @param _OnJoyUp Callback. 333 */ SetOnJoyUp(void (* _OnJoyUp)(s32 joyNum,s32 btIndex))334 void SetOnJoyUp (void (*_OnJoyUp)(s32 joyNum, s32 btIndex)) 335 {__OnJoyUp = _OnJoyUp;} 336 337 /** Sets the joystick button down event callback. 338 * @param _OnJoyDown Callback. 339 */ SetOnJoyDown(void (* _OnJoyDown)(s32 joyNum,s32 btIndex))340 void SetOnJoyDown (void (*_OnJoyDown)(s32 joyNum, s32 btIndex)) 341 {__OnJoyDown = _OnJoyDown;} 342 343 /** Sets the quit event callback. 344 * @param _OnQuit Callback. 345 */ SetOnQuit(void (* _OnQuit)())346 void SetOnQuit (void (*_OnQuit)()) 347 {__OnQuit = _OnQuit;} 348 349 /** Sets the window manager event callback. 350 * @param _OnSysWM Callback. 351 */ SetOnSysWM(void (* _OnSysWM)())352 void SetOnSysWM (void (*_OnSysWM)()) 353 {__OnSysWM = _OnSysWM;} 354 355 /** Sets the resize event callback. 356 * @param _OnResize Callback. 357 */ SetOnResize(void (* _OnResize)(s32 w,s32 h))358 void SetOnResize (void (*_OnResize)(s32 w, s32 h)) 359 {__OnResize = _OnResize;} 360 361 /** Sets the video expose event callback. 362 * @param _OnExpose Callback. 363 */ SetOnExpose(void (* _OnExpose)())364 void SetOnExpose (void (*_OnExpose)()) 365 {__OnExpose = _OnExpose;} 366 367 /** Sets the user event callback. 368 * @param _OnUser Callback. 369 */ SetOnUser(void (* _OnUser)(s32 code,void * data1,void * data2))370 void SetOnUser(void (*_OnUser)(s32 code, void *data1, void *data2)) 371 {__OnUser = _OnUser;} 372 373 /** Returns mouse X position. 374 * @return Mouse X position. 375 */ MouseX()376 s32 MouseX() {return mouseX;} 377 378 /** Returns mouse Y position. 379 * @return Mouse Y position. 380 */ MouseY()381 s32 MouseY() {return mouseY;} 382 383 /** Returns the relative X mouse position (since the last move). 384 * @return Relative X mouse position. 385 */ MouseRelX()386 s32 MouseRelX() {return mouseRelX;} 387 388 /** Returns the relative Y mouse position (since the last move). 389 * @return Relative Y mouse position. 390 */ MouseRelY()391 s32 MouseRelY() {return mouseRelY;} 392 393 /** Returns the mouse button press mask. 394 * @return Mouse button state mask. 395 */ MouseBt()396 u8 MouseBt() {return mouseBt;} 397 398 /** Returns the keyboard key state. The state for a certain key is determined 399 * with Keys()[SDLK_XXX], where SDLK_XXX is the key to query. 400 * If the value is 0, the key is not pressed, else, it is pressed. 401 * @return Key state array. 402 */ Keys()403 u8 * Keys() {return keys;} 404 405 /** Returns the key modifier mask. The bits of this mask are those for SDL 406 * KMOD_XXX, with XXX=LCTRL, LSHIFT, etc. 407 * @return Key modifiers bit mask. 408 */ KeyMods()409 SDLMod KeyMods() {return keyMods;} 410 411 /** Returns the joystick X axis 412 * @return joystick X axis 413 */ JoystickX()414 s16 JoystickX() {return joyAxisX;} 415 416 /** Returns the joystick Y axis 417 * @return joystick Y axis 418 */ JoystickY()419 s16 JoystickY() {return joyAxisY;} 420 421 /** Returns the joystick buttonstate. Note: It does not differentiate between buttons. 422 * @return joystick button 423 */ JoystickButton()424 u8 JoystickButton() {return joyButton;} 425 426 /** Updates the given region of the primary surface. If all parameters are 0, 427 * the whole window is updated. This is simply a wrapper for SDL_UpdateRect(...). 428 * @param x X position of the rectangle to update. 429 * @param y Y position of the rectangle to update. 430 * @param w Width of the rectangle to update. 431 * @param h Height of the rectangle to update.. 432 */ UpdateRect(s32 x,s32 y,s32 w,s32 h)433 void UpdateRect(s32 x, s32 y, s32 w, s32 h) {SDL_UpdateRect(screen, x, y, w, h);} 434 435 /** Update the given rects. As UpdateRect() is only a wrapper for SDL_UpdateRects(). 436 * @param num Number of rects to update. 437 * @param rc Array with the rects to update. 438 */ UpdateRects(s32 num,SDL_Rect * rc)439 void UpdateRects(s32 num, SDL_Rect *rc) {SDL_UpdateRects(screen, num, rc);} 440 441 /** Swaps front and back buffer (if SDL_DOUBLEBUF is used as flag during SDL initializacion) 442 * or updates the whole screen. This is a wrapper for SDL_Flip(). 443 * @return <b>true</b> if ok, <b>false</b> if an error ocurred.. 444 */ Flip()445 bool Flip() {return -1 != SDL_Flip(screen);} 446 447 /** Returns the audio mixer. Must be initialized in the child class. 448 * @return Audio mixer. 449 */ Mixer()450 JMixer & Mixer() {return mixer;} 451 452 /** Returns this application instance. 453 * @return Pointer to this application. 454 */ App()455 static JApp * App() {return thisApp;} 456 457 /** Sets the number of frames per second (FPS). Its the maximum number of times Draw() is called per second. 458 * @param newFPS New FPS value. 459 */ 460 void FPS(s32 newFPS); 461 462 /** Returns the FPS (frames per second). Its the maximum number of times Draw() is called per second. 463 * @return FPS value. 464 */ FPS()465 s32 FPS() {return fps;} 466 467 /** Returns a pointer to the current video mode video info. Is Exactly a wrapper for SDL_GetVideoInfo(). 468 * If called before Init() or Resize() it contains the 'best' intended video mode. 469 * @return Information about the current video mode or about the video system in general. 470 */ VideoInfo()471 const SDL_VideoInfo *VideoInfo() {return SDL_GetVideoInfo();} 472 473 /** Show the video info in the standard output. 474 */ 475 void DumpVideoInfo(); 476 477 /** Parses the application argument. 478 * @param args Command line arguments. 479 * @param argc Arguments left. 480 * @return Number of parameters used. 481 */ 482 virtual int ParseArg(char *args[], int argc); 483 484 /** Shows the usage string. It contains the default arguments a JApp can be passed. 485 * @param program Program's name. 486 */ 487 virtual void PrintUsage(char *program); 488 489 /** Parses the application arguments. 490 * @param argc Command line argument count. 491 * @param argv Command line arguments. 492 */ 493 void ParseArgs(s32 argc, char **argv); 494 495 /** Enables or disables sound playback. 496 * @param enable <b>true</b> if it must be enabled, <b>false</b> if not. 497 */ SoundEnabled(bool enable)498 void SoundEnabled(bool enable) {soundEnabled = (enable && mixer.Valid());} 499 500 /** Shows or hides the mouse cursor. 501 * @param b <b>true</b> to show, <b>false</b> to hide. 502 */ MouseCursor(bool b)503 void MouseCursor(bool b) {SDL_ShowCursor(b ? SDL_ENABLE : SDL_DISABLE);} 504 505 /** Returns the viewing state of the mouse cursor. 506 * @param b <b>true</b> if showing, <b>false</b> if not. 507 */ MouseCursor()508 bool MouseCursor() {return SDL_ENABLE == SDL_ShowCursor(SDL_QUERY);} 509 510 /** Sets the file name of the icon to be used for the window. Must be called before init. 511 * In Windows must have exactly 32x32 pixels. 512 * @param filename Filename of the icon, 0 to use the default icon. 513 */ 514 void Icon(const char *filename); 515 516 /** Returns the sound mixer state. 517 * @return <b>true</b> if active, <b>false</b> if not or the mixer couldn't be initialized properly. 518 * @see JMixer::Valid(), Mixer(). 519 */ SoundEnabled()520 bool SoundEnabled() {return soundEnabled;} 521 522 /** Destroys this application, frees resources and quits the SDL subsystems initialized. 523 */ 524 void Destroy(); 525 526 /** Destroys the object. 527 */ 528 virtual ~JApp(); 529 }; 530 531 #endif // JAPP_INCLUDED 532