The Engine and the Game Loop

A number of actions must happen in the engine and game loop, and these actions should correspond to a codeable function. You must have a function to remove any sprites that aren't being used and add any new ones, a function to render the screen and background, a function that keeps track of time and updates the game state, a function that does the blitting, and a function that listens for player keystrokes:

• render_frame. Updates and redraws.

• engine_init. Sets screen and video.

• engine_loop. Main engine loop.

• gameloop_iteration. Tracks time and call other functions.

• update_tick. Updates any game actors.

• handle_event. Listens for any events caused by the player.

• handle_collision. Handles any actor collisions.

The first step is to initialize the engine.

The engine_init function is used to set the screen width and height and the video mode and to start the game ticking, so to speak. It does all this through common-sense local variables, a few SDL calls, and calling gamestate:

function engine init(argv)

local width, height; local video bpp; local videoflags;

videoflags = SDL.bit_or(SDL.SDL_HWSURFACE, SDL.SDL_ANYFORMAT)

height = 600

video bpp = 16

-- Set video mode gamestate.screen = SDL.SDL SetVideoMode(width, height, video bpp, videoflags);

gamestate.background = SDL.SDL MapRGB(gamestate.screen.format, 0, 0, 0);

SDL.SDL_ShowCursor(0 )

-- initialize the timer/ticks gamestate.begin time = SDL.SDL GetTicks();

gamestate.last update ticks = gamestate.begin time;

Removing any actors that are no longer used and adding any new actors is handled by an update_tick function. Two Lua for loops iterate through each actor in the game. The first removes any actors that aren't active and adds any new ones:

for i = 1, getn(gamestate.actors) do if gamestate.actors[i].active then -- add the actors tinsert(gamestate.new actors, gamestate.actors[i]) end end

The former gamestate. actor table is then replaced with the new table in a quick swap:

gamestate.actors = gamestate.new actors gamestate.new actors = {}

Then a second for loop calls an update for each actor in the table:

— call update for each actor for i = 1, getn(gamestate.actors) do gamestate.actors[i]:update(gamestate)

After the actors have been updated, each needs to be redrawn, as does the screen. A quick render_f rame function does this work, first clearing the current screen and then redrawing each actor rect () within gamestate . actors:

function render frame(screen, background)

— When called renders a new frame.

-- First clears the screen

SDL.SDL_FillRect(screen, NULL, background); -- re-draws each actor in gamestate.actors for i = 1, getn(gamestate.actors) do gamestate.actors[i]:render(screen)

-- updates

Most of the actual game-engine work is done by this next little function, called gameloop_iteration. It is called each time the engine loops, and is responsible for calling all the other rendering functions and keeping track of time. First gameloop_iteration calls handle_event on any pending events in the gamestate's event_buff er (checking first that the buffer exists):

function gameloop iteration()

— call this to update the game state. Runs update ticks and renders

— according to elapsed time.

-- if buffer doesnt exist make it so if gamestate.event buffer == nil then gamestate.event buffer = SDL.SDL Event new()

-- run handle even on any pending events while SDL.SDL PollEvent(gamestate.event buffer) ~= 0 do handle event(gamestate.event buffer)

end gameloop_iteration then uses sdl_getticks () to set the local time variable and compares this with the gamestate to see if an update needs to occur. If the engine needs to update, then update_tick is called and the time count is updated:

— run any necessary updates local time = SDL.SDL_GetTicks();

local delta ticks = time - gamestate.last update ticks local update count = 0

while delta ticks > gamestate.update period do update tick();

delta ticks = delta ticks - gamestate.update period gamestate.last update ticks = gamestate.last update ticks + gamestate.update period update count = update count + 1

Finally, render_f rame has to be called to redraw any actors and the screen background if an update has occurred:

— if we did any updates, then render a frame if update count > 0 then render frame(gamestate.screen, gamestate.background) gamestate.frames = gamestate.frames + 1

The actual engine game loop (engine_loop) runs while the gamestate is active. The engine_loop calls gameloop_iteration each time its own while loop fires. The engine_loop then cleans out the buffer. If the gamestate is no longer active, then engine_loop calls SDL_QUIT:

function engine loop ()

— While loop calls gameloop iteration while gamestate.active do gameloop iteration()

-- clean up if event buffer then

SDL.SDL Event delete(event)

0 0

Post a comment