SDL:Tutorials:Simple Engine Framework with Delphi
From GPWiki
The wiki is now hosted by GameDev.NET at wiki.gamedev.net. All gpwiki.org content has been moved to the new server. However, the GPWiki forums are still active! Come say hello. [edit] DescriptionThis is a Pascal/Delphi port of engine provided by Anders "Sion" Nissen here. Porting by Jani Mikkonen There are some bugs still left in the code. The delphi code uses JEDI SDL and has been tested and compiled.
[edit] IGameEngine UnitFile: IGameEngine.pas unit IGameEngine; interface uses SDL; type IIGameEngine = class private m_lLastTick : integer; (* Last iteration's tick value *) m_iWidth : integer; (* Window width *) m_iHeight : integer; (* Window height *) m_bQuit : boolean; (* Has quit been called? *) m_czTitle : string; (* The title of the window *) m_pScreen : PSDL_Surface; m_bMinimized : boolean; (* start the window minimized? *) m_iFPSTickCounter : integer; (* TICK/FPS Counter *) m_iFPSCounter : integer; (* Frame rate counter. *) m_iCurrentFPS : integer; (* Stores the last calculated frame rate. *) OldExitHandler:Pointer; public Constructor Create; Destructor DestroyIt; Procedure Init(); Procedure Start(); Procedure AdditionalInit(); virtual; Procedure Think (const iElapsedTime:integer); virtual; Procedure Render( pDestSurface: PSDL_Surface ); virtual; Procedure EndAll(); virtual; Procedure WindowActive (); virtual; Procedure WindowInactive (); virtual; Procedure KeyUp (const iKeyEnum:integer); virtual; Procedure KeyDown (const iKeyEnum:integer); virtual; Procedure MouseMoved (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); virtual; Procedure MouseButtonUp (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); virtual; Procedure MouseButtonDown (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); virtual; Procedure SetTitle (const czTitle:String); Property Title: string read m_czTitle write SetTitle; Property Surface:PSDL_Surface read m_pScreen; property FPS:integer read m_iCurrentFPS; protected Procedure DoThink(); Procedure DoRender(); Procedure SetSize(const iWidth:integer; const iHeight:integer); Procedure HandleInput(); end; (* IGameEngine Class *) implementation constructor IIGameEngine.Create; begin m_lLastTick := 0; m_iWidth := 800; m_iHeight := 600; m_czTitle := ''; m_pScreen := nil; m_iFPSTickCounter := 0; m_iFPSCounter := 0; m_iCurrentFPS := 0; m_bMinimized := false; end; Destructor IIGameEngine.DestroyIt; begin SDL_Quit(); ExitProc := OldExitHandler; end; procedure IIGameEngine.SetSize(const iWidth:integer; const iHeight:integer); begin m_iWidth := iWidth; m_iHeight := iHeight; m_pScreen := SDL_SetVideoMode( iWidth, iHeight, 0, SDL_SWSURFACE ); end; Procedure IIGameEngine.Init(); begin // Register SDL_Quit to be called at exit; makes sure things are cleaned up when we quit. ExitProc := @SDL_Quit; // Initialize SDL's subsystems - in this case, only video. if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then begin WriteLn('Unable to init SDL: '+SDL_GetError()+'\n' ); Halt( 1 ); end; // Attempt to create a window with the specified height and width. Self.SetSize( Self.m_iWidth, Self.m_iHeight ); // If we fail, return error. if ( m_pScreen = nil ) then begin WriteLn('Unable to set up video: '+SDL_GetError()+'\n'); Halt( 1 ); end; AdditionalInit(); end; procedure IIGameEngine.Start(); begin m_lLastTick := SDL_GetTicks(); m_bQuit := false; // Main loop: loop forever. while ( not m_bQuit ) do begin // Handle mouse and keyboard input HandleInput(); if ( m_bMinimized ) then begin // Release some system resources if the app. is minimized. // WaitMessage(); end else begin // Do some thinking DoThink(); // Render stuff DoRender(); end; end; EndAll(); end; Procedure IIGameEngine.HandleInput(); var event : TSDL_Event; begin // Poll for events, and handle the ones we care about. while ( SDL_PollEvent( @event )>0 ) do begin case event.type_ of SDL_KEYDOWN: begin // If escape is pressed set the Quit-flag if (event.key.keysym.sym = SDLK_ESCAPE) then begin m_bQuit := true; break; end; KeyDown( event.key.keysym.sym ); end; SDL_KEYUP: begin KeyUp( event.key.keysym.sym ); end; SDL_QUITEV: begin m_bQuit := true; end; SDL_MOUSEMOTION: MouseMoved(event.button.button,event.motion.x,event.motion.y,event.motion.xrel,event.motion.yrel); SDL_MOUSEBUTTONUP: MouseButtonUp(event.button.button,event.motion.x,event.motion.y,event.motion.xrel,event.motion.yrel); SDL_MOUSEBUTTONDOWN: MouseButtonDown(event.button.button,event.motion.x,event.motion.y,event.motion.xrel,event.motion.yrel); SDL_ACTIVEEVENT: begin if ( (event.active.state and SDL_APPACTIVE)=SDL_APPACTIVE ) then begin if ( event.active.gain = 1 ) then begin m_bMinimized := false; WindowActive(); end else begin m_bMinimized := true; WindowInactive(); end; end; end; end; end; end; Procedure IIGameEngine.DoThink(); var iElapsedTicks : integer; begin iElapsedTicks := SDL_GetTicks() - m_lLastTick; m_lLastTick := SDL_GetTicks(); Think( iElapsedTicks ); m_iFPSTickCounter := m_iFPSTickCounter + iElapsedTicks; end; Procedure IIGameEngine.DoRender(); begin m_iFPSCounter:=m_iFPSCounter+1; if ( m_iFPSTickCounter >= 1000 ) then begin m_iCurrentFPS := m_iFPSCounter; m_iFPSCounter := 0; m_iFPSTickCounter := 0; end; SDL_FillRect( m_pScreen, nil, SDL_MapRGB( m_pScreen.format, 0, 0, 0 ) ); // Lock surface if needed if ( SDL_MUSTLOCK( m_pScreen ) ) then if ( SDL_LockSurface( m_pScreen ) < 0 ) then Exit; Render( Surface ); // Unlock if needed if ( SDL_MUSTLOCK( m_pScreen ) ) then begin SDL_UnlockSurface( m_pScreen ); end; // Tell SDL to update the whole gScreen SDL_Flip( m_pScreen ); end; procedure IIGameEngine.SetTitle(const czTitle:String); begin self.m_czTitle := czTitle; (* Todo: Convert String to PAnciChar *) (* SDL_WM_SetCaption( czTitle, 0 ); *) end; (* Virtual method stubs *) Procedure IIGameEngine.AdditionalInit(); begin end; Procedure IIGameEngine.Think (const iElapsedTime:integer); begin end; Procedure IIGameEngine.Render( pDestSurface: PSDL_Surface ); begin end; Procedure IIGameEngine.EndAll(); begin end; Procedure IIGameEngine.WindowActive (); begin end; Procedure IIGameEngine.WindowInactive (); begin end; Procedure IIGameEngine.KeyUp (const iKeyEnum:integer); begin end; Procedure IIGameEngine.KeyDown (const iKeyEnum:integer); begin end; Procedure IIGameEngine.MouseMoved (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); begin end; Procedure IIGameEngine.MouseButtonUp (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); begin end; Procedure IIGameEngine.MouseButtonDown (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); begin end; end. [edit] Game ApplicationFile: game.pas unit game; interface Uses IGameEngine,SDL; type IEngine = class(IIGameEngine) public Procedure AdditionalInit(); override; Procedure Think(const iElapsedTime:integer ); override; Procedure Render(pDestSurface:PSDL_Surface); override; Procedure KeyUp(const iKeyEnum:Integer); override; Procedure KeyDown(const iKeyEnum:Integer); override; Procedure MouseMoved (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); override; Procedure MouseButtonUp (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); override; Procedure MouseButtonDown(const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); override; Procedure WindowInactive(); override; Procedure WindowActive(); override; Procedure EndAll(); override; end; implementation Procedure IEngine.AdditionalInit(); begin // Load up additional data end; Procedure IEngine.Think( const iElapsedTime:integer); begin // Do time-based calculations end; Procedure IEngine.Render(pDestSurface:PSDL_Surface); begin // Display slick graphics on screen end; Procedure IEngine.KeyDown(const iKeyEnum:integer); begin case iKeyEnum of SDLK_LEFT: begin // Left arrow pressed end; SDLK_RIGHT: begin // Right arrow pressed end; SDLK_UP: begin // Up arrow pressed end; SDLK_DOWN: begin // Down arrow pressed end; end; (* Ends case *) end; Procedure IEngine.KeyUp(const iKeyEnum:Integer); begin case iKeyEnum of SDLK_LEFT: begin // Left arrow released end; SDLK_RIGHT: begin // Right arrow released end; SDLK_UP: begin // Up arrow released end; SDLK_DOWN: begin // Down arrow released end; end; end; Procedure IEngine.MouseMoved(const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); begin // Handle mouse movement // iX and iY are absolute screen positions // iRelX and iRelY are screen position relative to last detected mouse movement end; Procedure IEngine.MouseButtonUp (const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); begin // Handle Events end; Procedure IEngine.MouseButtonDown(const iButton:integer; const iX:integer; const iY:integer; const iRelX:integer; const iRelY:integer); begin // Handle Events end; Procedure IEngine.WindowInactive(); begin // Pause game end; Procedure IEngine.WindowActive(); begin // Un-pause game end; Procedure IEngine.EndAll(); begin // Clean up end; Var Engine:IEngine; begin Engine := IEngine.Create; Engine.Title := 'Loading...'; Engine.Init(); Engine.Title := 'SDL Testing!'; Engine.Start(); Engine.Title := 'Quitting...'; Halt(0); end. |


