How To Implement Graphical Feedback?

Published March 08, 2012
Advertisement
tap-tap-tap-taptap-tap-tap-tapHere's a partial screenshot to help explain things:

shot1z.png

First a quick description of the image: You can just about make out the tiles in the wide open floorspace. The gray blob in the middle is the stand-in icon for the player's character. The two monsters nearby are zombies but I know they look more like green men with bandages on their heads.

The multiple blue and red items on the floor are test items and serve no purpose. The grid at the lower right is the floor view screen which displays the items on the tile at the player's feet. For the sake of this post it has no relevance.

Quick explanation of game-play: The player makes a move using the WASD keys then the zombies get a turn to move. Then it's the players move again, and so on. This all happens fairly instantly as you'd expect. No sooner as you've hit the W key the zombies will move too and it's your turn again. This quickness is important and players will expect it. No-one wants to have to wait half a second per tile moving down a long empty corridor. You want tap-tap-tap-tap to work or even holding the key down.

Problem Background: For this kind of movement there is sufficient graphical feedback - you can see the player and monsters move. But what about combat?

The vast majority of rougelike games provide feedback in the form of a message log. So after you make your turn to attack the zombie the following events might appear on the log telling you what happens:
-You miss the zombie
-The zombie bites you

When combat is hectic you can get loads of messages coming out telling you what each monster in range has done. The message log is also used outside combat to provide other feedback:

-You can hear water nearby

It is also used to provide return state for various actions. Eg you could examine a monster on a tile and the message log can provide a detailed description:

-You see a troll. It is wearing leather armor and carrying a hammer and looking very obvious.

It can even provide feedback about UI actions:

-You can't remove the ring. It is cursed.

Also of course it can be used for conversations with NPCs. It can be used for almost all feedback. The other two benefits of a message log are:

  • The player can ignore the log entirely if they want. Feedback in the form of messages does not slow the player down.
  • The log keeps a history of past turns if the player wants to go back and review something they missed.

I will probably have a message log but...

Problem: I want graphical feedback too. It's a graphical game after-all. Perhaps not all actions will have graphical feedback, but I would like it at least for common actions like melee combat. Also it would be nice to do some cool effects for magic and the ability to show the path of projectiles like arrows would be useful.

What kind of graphical feedback do I mean? I don't mean smooth animations of the player swinging their weapon. It's a tile based game and I am not good enough to make good animations. I am thinking an outline round the attacker with the target flashing would be sufficient. Perhaps with little damage numbers rising and fading. Sound could also be used to feedback the impact severity (miss, deflected, or hit). Perhaps the target could flash white if the attacker misses and red if they hit. Perhaps blue if they hit but the strike was repelled by armor. I don't know the specifics yet, the point is just to add this kind of feedback.

The problem is that if the action happens instantly the player won't see the feedback.

Complications:

My game is currently single threaded. Player/Creature turns occur separately (ie not all in one game frame) so that I can already add a pause after each one. But within a single turn itself I am currently in a single frame. I cannot perform an animation mid-way through a turn and then continue the turn.

For why I might want to do this take the following extreme example:

  1. The player fires an arrow at an exploding barrel
  2. The arrow hits and the barrel explodes
  3. The explosion damages a wall
  4. The wall falls down and hits a zombie
  5. The zombie dies

This all happens in a single turn, a single game frame. On the next game frame the zombie has the state of "dead" and is drawn dead, the barrels no longer exist and are not drawn. Of course I could have all the above events in the message log so the player could see what has happened, but not as nice as a graphical feedback for each one is it?

Preferably the following should happen for the turn:

  1. Arrow sound.
  2. An arrow projectile is created and moves from the player to the barrel.
  3. An explosion sound.
  4. Barrel image changes from intact to destroyed. Screen flashes, fire projectiles are emitted.
  5. Wall collapse sound. The wall image changes to collapsed.
  6. The zombie makes "ARRRHHH!" sound and goes from living image to dead image.

Much more fun. But each of these effects requires time to display it. The complexity of the chain of events means I can't just process the turn and then perform everything that happens. For one thing my object model is directly altered by the actions so like I said if I process all the events and proceed to the next game frame the zombie will appear dead and the barrels will be drawn destroyed immediately after.

I can't see any other way but to perform the animations as each action unfolds, eg interleaving the actions with the animations. Only performing animations after the actions:

  1. The player fires an arrow at an exploding barrel
  2. An arrow projectile is created and moves from the player to the barrel.
  3. Calculate whether the arrow hits. It does. Unload damage onto the barrel.
  4. The barrel "dies" and triggers an explosion.
  5. An explosion sound is emitted. Barrel image changes from intact to destroyed. Screen flashes, fire projectiles are emitted.
  6. Splash damage from the explosion is calculated. Damage is unloaded on a nearby wall.
  7. The wall "dies" and triggers a collapse animation and sound.
  8. Splash damage from the wall collapse is calculated. Damage is unloaded on a nearby zombie.
  9. The zombie dies and triggers a death animation and sound.

The problem is all the actions occur beneath one call to game.Update(), which is one game frame. Eg in step 5 I can't freeze the code inside barrel.Explode() and then return to it after an animation has happened to calculate splash damage.

Another complexity is that the user must be able to skip all animation if they hit a movement key. Remember they should be able to tap-tap-tap the keys. if they miss stuff doing that it's their own fault. But you really don't want to have situations which I have experienced in so many turn based games where there are 50 ranged units on the screen and each turn you have to sit through a minute of animation as each of them fires with no way to skip it.

I can vaguely envision a solution here involving threading, but any ideas? Perhaps I have missed something obvious. Perhaps I have even screwed up the design to find myself in this situation?

On a side note I have a very rare week coming up in which I will not have access to a computer of any kind, so only thinking progress will be made and if anyone does reply I might not be able to read it/reply for some time, it isn't because I am ignoring it.
0 likes 3 comments

Comments

mixmaster
Sadly buddy, it looks like you need a redesign of you game loop (Timer) which ever you prefer..

Game loop runs at 60fps all the time, inside this loop you might use Game play modes (states) for example :

CAMEPLAY_MODE_ANIMATION
CAMEPLAY_MODE_PLAYER
CAMEPLAY_MODE_ZOMBIE

This is keeping it simple still and you have the added bonus of animation of your tiles etc as the game runs.
Basically the game doesn't really stop it just switched states.

Hope that helps.. Good luck.
March 09, 2012 03:15 AM
JTippetts
These kinds of issues are exactly what have stalled my many various attempts at doing an animation-heavy turn-based graphical roguelike. Traditional turn-based roguelikes 'cheat' by not having to animate, so things can happen concurrently without complication. I still haven't found a 'good' solution for any of it. I typically tend to fall back on sequential simulation of actions which is, of course, not optimal. Some of the annoyance factor can be mitigated by limiting the number of on-screen enemies, but that doesn't always work and doesn't eliminate the annoyance anyway. In other attempts, I have opted for 'battle mode' type scenarios, where outside of battle the player can move smoothly and continuously, but once combat mode is engaged it switches to a sequential simulation. This tends to be less annoying for me, but still locks you into a sequential simulation inside battle mode.

Turn-based simulations can be [i]hard[/i], far more challenging to implement than typical action RPG simulations. If you hack your way through to some good answers, I'd sure like to hear about them. Good luck.
March 09, 2012 07:43 AM
smo97
My compromise between action & turn based is to have each action take a fixed number of frames, where effectively, a frame is a turn. This way, concurrent actions interleave well. Each entity (player, monster, projectile, etc.) has a state that transitions each time a frame elapses. Action pauses for input when any player controlled units are in an idle state. And because actions take multiple frames, you get for free the ability to do things like pre-emptively dodge attacks or interrupt spellcasting.
March 09, 2012 01:39 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement