On 2013-04-18, Michał Brzozowski <
mi...@extremic.com> wrote:
[...]
> Pretty nice and simple, but doesn't work. The reason is there may be
> many things happening in between player's actions, and the screen needs
> to updated more often. Also, many messages might appear, and the message
> window needs to block if it's filled, and the view must be displaying
> the situation that generated the last message (much like in Nethack,
> maybe other games solve it in a different way). This is typical during
> combat with many monsters. Another thing is displaying animations, for
> example of fired projectiles.
This is actually one of the reasons why turn-based games are so much
simpler to code -- you just process everything for the given turn and then
pause waiting for the player input, and repeat. Part of what makes
roguelikes so appealing to developers too!
So you start with something like this:
while not game over {
update display ($updates)
$input = wait for player input
$happenings = process game logic ($input)
$updates = process game graphics ($happenings)
}
There are several ways you can go from there, for example, you can add
some crude unskippable animations:
while not game over {
while there are unfinished animations {
$updates = update to next frame ($animations)
update display ($updates)
wait to keep constant fps
}
$input = wait for player input
$happenings = process game logic ($input)
$animations = process game graphics ($happenings)
}
Of course this is quite annoying for the players -- they hate unskippable
animations, and for a reason. So we can try and make them skippable, and
add some idle animations for our monsters, water, etc.
while not game over {
while not $input {
$updates = update to next frame ($animations)
update display ($updates)
wait to keep constant fps
$input = check for player input
}
$updates = update to last frame ($animations)
update display ($updates)
$happenings = process game logic ($input)
$animations = process game graphics ($happenings)
}
This is almost what we want, except for this pesky problem with the *more*
prompt, inventory, yes/no prompts and menus in general. But for those,
I have a separate concept: scenes. You can code a nicely working menu (or
more prompt, or yes/no prompt, or inventory screen, whatever) with code
similar to the one above, with its own animations, display updates and
input handling. Then you put all those screens into objects, and make
a stack of them. The main game loop will always loop through the code of
the scene that is at the top of the stack. But when things happen, your
animations can push new scenes on the stack, or pop themselves from it (or
do a combined pop and push, by replacing themselves with a different
scene). As a bonus, you can use this also for the start screen, character
creation, game over screen, high scores, etc.
A little more about those magical "animation" objects, because they do the
bulk of the work there. They are created from the "happenings" (I didn't
want to use the word "events", because it's too common in programming),
and are supposed to represent them. For example, if the player attacked
a monster, that would generate an appropriate happening, which records
that very fact, together with the positions of the player character and
the monster and whether the attack hit or missed, etc. Now, you take the
list of happenings and generate a list of animations from them. In this
case, you have the animation of the player character swinging her sword
at the monster, the (delayed) animation of the monster getting hit, and
the (further delayed) animation of blood splattering the walls. Oh, and
the animations for displaying the right messages in the console, and
perhaps an animation for displaying the *more* prompt, which would, upon
updating it, push a scene onto the scene stack, instead of updating the
display.
Anyways, there are many more ways for organizing your game loops. This is
one that works pretty well for me (by the way, I use iterator generators
in python to represent the animations), but I would be very curious about
other approaches too!
--
Radomir Dopieralski,
sheep.art.pl