Author Topic: Programming graphical effects with delays  (Read 21696 times)

Tim Saunders

  • Newcomer
  • Posts: 15
  • Karma: +0/-0
    • View Profile
Programming graphical effects with delays
« on: March 19, 2015, 12:10:41 PM »
I'm wondering what is the best way to resolve complex game interactions each having their own graphical effect that takes some time to complete.

For example if you hit a monster, then they get knocked back and then cause an explosion that damages each adjacent tile. I'd want to calculate everything that happens here in one algorithm but then play out the different effects visually one by one.

I could store the original game state then calculate all the interactions and then send them back to be played one by one, but it seems a little bit unwieldy. How do other people do it?

Xan

  • Rogueliker
  • ***
  • Posts: 78
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #1 on: March 19, 2015, 02:38:30 PM »
I think there are three major approaches you can take here, but each accomplishes something a little different, so you have to sure of what you want:

1) Animations are synchronous with game logic: whenever the game logic does something which would start an animation, it waits until the animation is complete and resumes.
Pro: Very simple.
Con: Only one animation can be happening at once (this can result in having to wait a long time between turns).  Hard to distinguish between different kinds of animations and whether some should be skippable, etc.
Examples: ADoM, Dungeonmans (IIRC); a lot of other turn based games use this as well.

2) Animations are fire-and-forget: animations are completely independent of the order of game logic and each other; e.g. the game logic moves a monster and starts the animation for that, and then (almost instantly in real time) starts the explosion animation at the destination tile.
Pro: Simple.  Can have many animations at once.
Con: Animations are independent of each other (they do not necessarily happen in order).  Not clear what should happen when two different animations are related to the same game objects (e.g. if one animation wants to move a monster to one tile, and a different one wants to move it somewhere else).
Examples: ToME.

3) A visual actor system that works with the rest of the visual presentation to the player independently of game logic and data: the visual aspects of the game are maintained separate from any game logic code; the visual actor system simply listens for game events that it is interested in and makes decisions about what animations to start, queue, replace, skip, etc.
Pro: Far more flexible than the alternatives.  Can be much nicer looking.
Con: Much, much more complicated and prone to subtle bugs.  Hard to determine if the visual state accurately represents the logical state of the game.
Examples: none that I know of.

wire_hall_medic

  • Rogueliker
  • ***
  • Posts: 160
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #2 on: March 19, 2015, 05:04:07 PM »
What has worked well for me previously is having two types of animation; locking and non-locking, each with their own list in the animation manager.  Animation can be set to create a new animation upon death (ie, the traveling fireball turns into a blast).

The engine does not iterate while there is anything on the locking list.  If an effect is registered by an actor, the actor waits to actually resolve the action until the locking list is clear.  Animations are processed regardless.

The only real downside is that you have to create a suspension mechanic for NPCs.  But that's easy enough; I move through my initiative list in a "while(true){. . .}" block, and if there's anything on the locking list at the start of an activation, the initiative loop reiterates without incrementing.  Just make sure you only do start of turn stuff once per actor.

sokol815

  • Rogueliker
  • ***
  • Posts: 85
  • Karma: +0/-0
  • Web Developer by Day, still Web Developer by night
    • View Profile
    • Email
Re: Programming graphical effects with delays
« Reply #3 on: March 19, 2015, 09:48:02 PM »
for strife, I ended up doing blocking animations and asynchronous animations. The JS code stops executing and does setInterval() to queue up all the graphics changes that will occur in order. After all graphics are finished, the UI is re-enabled and gameplay continues like normal.

e.g. click on the Strife link (below) and type a name or whatever, then press f to enter firing mode and target a square, then hit f again to see the arrow animation.

As for damage and effect notifications that show in-world (e.g. 5 damage or Stunned!) those are asynchronous and are actually just html with css transitions that move them up the screen.
« Last Edit: March 19, 2015, 09:54:32 PM by sokol815 »

Paul Jeffries

  • 7DRL Reviewer
  • Rogueliker
  • *
  • Posts: 257
  • Karma: +1/-0
    • View Profile
    • Vitruality.com
Re: Programming graphical effects with delays
« Reply #4 on: March 19, 2015, 11:07:43 PM »
3) A visual actor system that works with the rest of the visual presentation to the player independently of game logic and data: the visual aspects of the game are maintained separate from any game logic code; the visual actor system simply listens for game events that it is interested in and makes decisions about what animations to start, queue, replace, skip, etc.
Pro: Far more flexible than the alternatives.  Can be much nicer looking.
Con: Much, much more complicated and prone to subtle bugs.  Hard to determine if the visual state accurately represents the logical state of the game.
Examples: none that I know of.

I do something a bit like this, which is essentially my own simplified version of the MVVM pattern used by WPF.  This allows me to 'bind' properties of two different objects together.  The way it is implemented is something a bit like this:

- Each game object has getter and setter functions for all of its properties.
- In the setter function, I raise a 'propertyChanged' event, passing the property name as an argument
- Other objects can then subscribe to that event.  These maintain a list of bound property pairs.  When a 'propertyChanged' event gets raised, I use reflection to get the new value of the source property and apply it to the target one.

So, for example, let's say I have a game object A and a visual object B that I want to represent the position of A.  I just call:

Code: [Select]
B.dataContext(A);
B.addDataBinding("position","position");

Then, whenever the 'position' property of A is changed, the 'position' property of B is automatically updated.  Where animation comes in is that rather than immediately setting the property on B, I can instead set it up to automatically apply an animation that tweens from the old value to the new one.

Advantages of this system:
- It's super-flexible.
- My game logic and display logic can be completely separate.  If I want to move A from X to Y I just set its position to Y.  The visual representation B takes care of the tweening - I don't need to pollute my game code to deal with it.
- It's very easy and fast to set up new property bindings, or to completely change the way existing ones work.
- I can easily have multiple visual objects attached to the same game object.  For instance in Hellion, every game object has a 3D sprite in the main view and a top-down sprite in the 2D map.

Disadvantages:
- It was very complicated and took a lot of work to set up in the first place (although now it's there it doesn't give me much trouble).
- Because it uses reflection, it is relatively inefficient.  (Although not so much that it's had a noticeable effect in any of the scenarios I've used it in so far.)

Trystan

  • Rogueliker
  • ***
  • Posts: 164
  • Karma: +0/-0
    • View Profile
    • my blog
Re: Programming graphical effects with delays
« Reply #5 on: March 20, 2015, 12:30:54 AM »
What I've done a couple times is have different queues that animations and effects can go in. Then, during the timer callback, if there's anything in the first queue, update them and refresh, else if anything is in the second queue, update them and refresh, etc. If all the queues are empty and the player has taken their turn, update the monsters and let the player take their next turn. I can put visual effects in the first queue, projectile effects in the second queue, and creatures being knocked back in a third queue. So far it's been simple, flexible, and easy to use and understand.

Xan

  • Rogueliker
  • ***
  • Posts: 78
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #6 on: March 20, 2015, 01:18:12 AM »
I do something a bit like this, which is essentially my own simplified version of the MVVM pattern used by WPF.  This allows me to 'bind' properties of two different objects together.  The way it is implemented is something a bit like this:

- Each game object has getter and setter functions for all of its properties.
- In the setter function, I raise a 'propertyChanged' event, passing the property name as an argument
- Other objects can then subscribe to that event.  These maintain a list of bound property pairs.  When a 'propertyChanged' event gets raised, I use reflection to get the new value of the source property and apply it to the target one.

Very interesting.  I haven't implemented this in my own RL yet, and I didn't know of any others that had before.  The last time I did this was with a multi-player turn based game, and there I had the visual system receive the same data from the server that the game logic does, so in effect it sounds very similar to what you did, but at the level of game commands rather than class properties.  (The server was completely authoritative; nothing ever changed the game state on the client except at the request of the server.)

stefoid

  • Newcomer
  • Posts: 46
  • Karma: +0/-0
    • View Profile
    • Email
Re: Programming graphical effects with delays
« Reply #7 on: March 21, 2015, 05:52:04 AM »
I'm wondering what is the best way to resolve complex game interactions each having their own graphical effect that takes some time to complete.

For example if you hit a monster, then they get knocked back and then cause an explosion that damages each adjacent tile. I'd want to calculate everything that happens here in one algorithm but then play out the different effects visually one by one.

I could store the original game state then calculate all the interactions and then send them back to be played one by one, but it seems a little bit unwieldy. How do other people do it?

Hi.  My game is www.dungeonbash.com  and I implemented it the exact wrong way.  For whatever reason , it was decided that the game model or engine would be turn based, and these events and their completion callbacks would be communicated to the presentaton layer as a stream of events and let the presentation layer queue them in an animation queue to play out. 

I cant stress strongly enough that this was a bad idea and if you have started down this path, pull our now before its too late.

It means you have a bunch of state that is turn based in your model and another bunch of state that is realtime in your presentation layer (making it much more complicated than it needs to be), and these two systems have to communicate in a more complex way than needs be, and there is quite an impedance mismatch there there as well between these two complex systems.

If you have a game with realtime animations and such then make a real time model.  Sure, the player and creatures might take turns, but in this context, they are real time turns where an action just happens to be walking from one tile to another, or making an attack or whatever. 

If I wrote DungeonBash again, it would be so much easier to construct and maintain if I:

1) made each and every entity in the game model (creatures, explosions, whatever) its own rigourous formal state machine that independently and asynchronously responds to events from other entities in real time.  the fact that a lot of these events tend to happen on what the player perceives as 'turn' boundaries is irrelevent to the model.  The model is a collection of indepdent entities that communicate with each other via realtime events no concept of turns at this level.

(consider the pros and cons of using an event bus which is another discussion in itself)

2) make the presentation layer as thin and dumb as possible.  Each presenter just reflects the state of the entity it represents in realtime with as little state in itself as you can get away with.  None would be ideal.

3) state transitions in the entities in your model that require time to play out are timed in the model - it doesnt require a callback from the UI to tell it that an animation has completed.  Rather, the UI dumbly mirrors the state of the entity and configures the animations to complete at the specified time.  i.e.  the model fires an event for its UI that says - I have transitioned to this state, and I will be in it for exactly 800ms.  The UI then dumbly takes that event, and starts playing the appropriate animation to complete in 800ms
My squad-based tactical roguelike for mobiles:
http://www.dungeonbash.com

Tim Saunders

  • Newcomer
  • Posts: 15
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #8 on: March 21, 2015, 07:07:35 AM »
Thanks for the replies, very interesting.

I have indeed started down the path of queueing in animation, but it isn't too late for a rethink. It does seem quite silly to calculate everything once and then send it back to be recreated and hope that everything matches up correctly in the end. I hadn't thought of making it a real time model and I'm going to stop and reconsider whether to change to that type of model instead, it might make things much easier in the long run.

By the way Dungeon Bash looks great, I'll have to check it out.

stefoid

  • Newcomer
  • Posts: 46
  • Karma: +0/-0
    • View Profile
    • Email
Re: Programming graphical effects with delays
« Reply #9 on: March 21, 2015, 08:01:44 AM »
I would highly recommend it - a turn based model that queues and waits on real time animations is one of those 'how hard can it be" things that  seems simple at first, and then the further  you go and the more things you want to do , the more it drags you down into the mud, and you curse yourself for not taking the time to get it right in the first place.
My squad-based tactical roguelike for mobiles:
http://www.dungeonbash.com

Omnivore

  • Rogueliker
  • ***
  • Posts: 154
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #10 on: March 21, 2015, 11:38:20 AM »
3) A visual actor system that works with the rest of the visual presentation to the player independently of game logic and data: the visual aspects of the game are maintained separate from any game logic code; the visual actor system simply listens for game events that it is interested in and makes decisions about what animations to start, queue, replace, skip, etc.
Pro: Far more flexible than the alternatives.  Can be much nicer looking.
Con: Much, much more complicated and prone to subtle bugs.  Hard to determine if the visual state accurately represents the logical state of the game.
Examples: none that I know of.

Another name for this is the client server model.  There are quite a few examples out there, whether or not any qualify as roguelikes by today's definitions I have no idea.  I'm not aware of any that are called roguelikes.  The primary advantage of this approach is clean separation.  SOLID, SRP, encapsulation, all 'best practices' in industry, at least according to some, are all satisfied in this model.   

Not sure if the extra work involved is worth it for a roguelike game.  Depends on whether you plan on doing a single game, a series of games, or a series of enhancements to an initial release.  The longer the lifecycle, the more you benefit from lower maintenance costs.  Its definitely not worth it for a 7DRL, or for a 'throwaway' that is released once and never significantly enhanced.

In this issue, you're probably best served by forgetting that you're doing a roguelike and looking to modern turn based graphical games for examples.  It basically isn't a roguelike problem.

Xan

  • Rogueliker
  • ***
  • Posts: 78
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #11 on: March 21, 2015, 05:30:30 PM »
In this issue, you're probably best served by forgetting that you're doing a roguelike and looking to modern turn based graphical games for examples.  It basically isn't a roguelike problem.

I agree.  In fact, many turn-based games will be more demanding of the animations required than a roguelike will.  The third model I mentioned is also used in real-time games as well; Starcraft 2, for example.  But it is a lot harder to implement correctly than the other two.

stefoid

  • Newcomer
  • Posts: 46
  • Karma: +0/-0
    • View Profile
    • Email
Re: Programming graphical effects with delays
« Reply #12 on: March 22, 2015, 11:45:43 PM »
3) A visual actor system that works with the rest of the visual presentation to the player independently of game logic and data: the visual aspects of the game are maintained separate from any game logic code; the visual actor system simply listens for game events that it is interested in and makes decisions about what animations to start, queue, replace, skip, etc.
Pro: Far more flexible than the alternatives.  Can be much nicer looking.
Con: Much, much more complicated and prone to subtle bugs.  Hard to determine if the visual state accurately represents the logical state of the game.
Examples: none that I know of.

Another name for this is the client server model.  There are quite a few examples out there, whether or not any qualify as roguelikes by today's definitions I have no idea.  I'm not aware of any that are called roguelikes.  The primary advantage of this approach is clean separation.  SOLID, SRP, encapsulation, all 'best practices' in industry, at least according to some, are all satisfied in this model.   

Not sure if the extra work involved is worth it for a roguelike game.  Depends on whether you plan on doing a single game, a series of games, or a series of enhancements to an initial release.  The longer the lifecycle, the more you benefit from lower maintenance costs.  Its definitely not worth it for a 7DRL, or for a 'throwaway' that is released once and never significantly enhanced.

In this issue, you're probably best served by forgetting that you're doing a roguelike and looking to modern turn based graphical games for examples.  It basically isn't a roguelike problem.

Hi.     In terms of this discussion, I reckon separation of UI from game logic/data is a given.   The UI listens for changes from the model that it needs to reflect on the screen.  Gievn that, whats the basic difference of 3. from 1. and 2.   then?  Is it simply that option 3 does neither of the things that option 1 or 2 does?
My squad-based tactical roguelike for mobiles:
http://www.dungeonbash.com

Omnivore

  • Rogueliker
  • ***
  • Posts: 154
  • Karma: +0/-0
    • View Profile
Re: Programming graphical effects with delays
« Reply #13 on: March 23, 2015, 01:47:42 AM »
Hi.     In terms of this discussion, I reckon separation of UI from game logic/data is a given.   The UI listens for changes from the model that it needs to reflect on the screen.  Gievn that, whats the basic difference of 3. from 1. and 2.   then?  Is it simply that option 3 does neither of the things that option 1 or 2 does?

I'm not quite so sure it is a given.  At least, there is a substantial difference of degree.  In case 1, the simulation halts, not for lack of input, but for display purposes - that is tight coupling.  Case 2 is much better, but.. it evidently does not give the view enough information to work with and/or the view itself contains insufficient logic.  There's been a few other methods pointed out in this thread and some of them have a significant degree of coupling.  When I say coupling I mean, can you change the model's simulation without breaking the view, and vice versa (if you can't it is tight coupling). 

A client server or similar approach (strict MVC/Visual Actor/perhaps MVVM), delivers a restricted snapshot of the simulation state to the client/view in some intermediate form (interface) that does not expose the inner workings or details of the simulation.  The view then decides what to display and how to display it.  The model neither knows nor cares about animations, nor any visual effects that do not change the state of the simulation.  As far as the model is concerned it could just as well be feeding a telnet client or an AI bot. 

This puts a substantial burden on the view (or client), it needs to run its own simulation, granted of a greatly reduced scope, in order to make acceptable, desirable, decisions as to what  to display, where, when, and how.  It is quite a bit of work and as far as I am aware, only a few AAA's go to the extremes.  If done right it does pay off over the long haul. 

Honestly, for roguelike games, I'm in favor of Xan's #2 'fire and forget' solution, perhaps with a bit more 'smarts' built into the view.  It is basically a 'dumber' version of a full fledged client-server or separate actor model.  Otherwise you're headed where a friend of mine, a professional indie dev is - spending 99% of your time and effort on graphics, 1% on game logic.  I guess that's what rogue lites are trying to be though so it depends on what you are aiming at.
« Last Edit: March 23, 2015, 01:53:00 AM by Omnivore »

stefoid

  • Newcomer
  • Posts: 46
  • Karma: +0/-0
    • View Profile
    • Email
Re: Programming graphical effects with delays
« Reply #14 on: March 23, 2015, 04:42:42 AM »
Hi.     In terms of this discussion, I reckon separation of UI from game logic/data is a given.   The UI listens for changes from the model that it needs to reflect on the screen.  Gievn that, whats the basic difference of 3. from 1. and 2.   then?  Is it simply that option 3 does neither of the things that option 1 or 2 does?

I'm not quite so sure it is a given.  At least, there is a substantial difference of degree.  In case 1, the simulation halts, not for lack of input, but for display purposes - that is tight coupling.  Case 2 is much better, but.. it evidently does not give the view enough information to work with and/or the view itself contains insufficient logic.  There's been a few other methods pointed out in this thread and some of them have a significant degree of coupling.  When I say coupling I mean, can you change the model's simulation without breaking the view, and vice versa (if you can't it is tight coupling). 

A client server or similar approach (strict MVC/Visual Actor/perhaps MVVM), delivers a restricted snapshot of the simulation state to the client/view in some intermediate form (interface) that does not expose the inner workings or details of the simulation.  The view then decides what to display and how to display it.  The model neither knows nor cares about animations, nor any visual effects that do not change the state of the simulation.  As far as the model is concerned it could just as well be feeding a telnet client or an AI bot. 

This puts a substantial burden on the view (or client), it needs to run its own simulation, granted of a greatly reduced scope, in order to make acceptable, desirable, decisions as to what  to display, where, when, and how.  It is quite a bit of work and as far as I am aware, only a few AAA's go to the extremes.  If done right it does pay off over the long haul. 

Honestly, for roguelike games, I'm in favor of Xan's #2 'fire and forget' solution, perhaps with a bit more 'smarts' built into the view.  It is basically a 'dumber' version of a full fledged client-server or separate actor model.  Otherwise you're headed where a friend of mine, a professional indie dev is - spending 99% of your time and effort on graphics, 1% on game logic.  I guess that's what rogue lites are trying to be though so it depends on what you are aiming at.

OK, I understand.  I think the main concern with model/ui separation is that there is no UI code in the model, no model logic in the UI, and the model is not directly dependent on the UI.   (i.e. the UI observes the model).  All of the options in that previous post can still accomplish that.  In option 1) the model fires an event that a listening UI can turn into some animation or other, and the model then waits for an event to come in that says its OK to continue.  That callback event comes from the UI, but the model isnt aware of that.

But anyway, each of those 3 options seems to assume that the model is turn-based and its the job of the UI to turn a stream of turn-based events, by scheduling and queueing, into a sensible-looking UI in real time.  Which is exactly what I did and much regret.  That bolded part is doable, but difficult.  I guess its basically writing a synchronous system (turn-based model) and an asynchronous system (realtime UI) and trying to moosh them together. 

If you make your model inherently asyncronous and event-driven in the first place, as you would for any realtime game, then it isnt going to be too much more complex than a turn-based model anyway, and the pay-off is it lets you get away with a very simple UI layer that jsust dumbly reflects the current state of the model at all times. 



My squad-based tactical roguelike for mobiles:
http://www.dungeonbash.com