Handling logic and animation

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Handling logic and animation

      I am developing a quite simple turn based board game and face different problems. The game flow is like that:
      Player performs a move, after that I need to find all the objects that match a pattern and all of such objects considered scored. Depending on their health they either destoryed or just damaged. For all of them I need to perform some animation. After that goes second phase. Since I have scored objects, they could affect other objects on the board. And they have to change their state too, as well as animation for every one of them should be taken. Some of them may be destroyed too. After all that I need to refresh the board, adding new objects.
      I explicitly decouple one phase from another, so we have three phases or states and maybe I did it wrong.

      First of all, I don't know, when and where I should dispatch "actorDestroyed" event.
      Because, after finding all that scored objects and sending event for everyone of them:

      Source Code

      1. function Logic:onMoveDone(event) local scoredActors = findScoredActors(self._actors)
      2. for k in pairs(scoredActors) do
      3. local event = {name = "actorScored", actor = scoredActors[k]}
      4. QueueEvent(actorScored)
      5. end
      6. QueueEvent(doneScoring)
      7. end


      Animation system receives these events and plan animation. Also, all the other objects can receive those and react accordingly, whether they were affected, if so they also send events, that again animation system receives and so on.

      Having written that I suddenly understood that I have first two phases merged together.
      Thank you for your suggestions!

      Seconldy, I don't know who to detect that second phase ended and I can start updating and refreshing the board. Because i have to wait for all those animations to end.

      I had some thougths of wrapping all of it into processes, but right now I am not very clear how it would look like.

      As a matter of fact, I have got so many questions that make me feel like a kid.

      The post was edited 3 times, last by George ().

    • I don't really understand the question, probably because I can't picture what's happening in my head. Can you talk more about the game itself and the problem this is trying to solve? What is the design? Screenshots can help too.

      -Rez
    • I will try to outline the idea. I have a board with boxes of different color. And I have a goals. Goals are the cells on the board that also have a color.
      I can move line of boxes.

      [IMG:http://i.imgur.com/QOlki2j.png?1]

      But when you move a line and one of its boxes turns up to be on the goal of the same color, that box is considered «scored». It means, that all boxes of that color get destroyed. Excepts for ones, that have health on them and health > 1(You can see such boxes with a number on them). For those I should decrease their health.

      [IMG:http://i.imgur.com/Su1k2rG.png?1]

      There could be different objects on board, that can be affected by the scored boxes. Like, for example, a spot on the cell (2, 1). It also has to be destroyed, because one of the scored boxes was on it.
      Or I can have a bomb that explodes if one of scored boxes is near it. If bomb explodes, it should affect by the blast all the objects of the bomb’s column and row.

      [IMG:http://i.imgur.com/hpJnAFj.png?1]

      After all that I just add new objects on the board and if they appear to be on the goals, process starts again. If none of new actors are on the goals we just wait the player to take his turn.

      For all scored objects I have animation. They disappear or explode in a sequence but not exactly one after another. For example, time of explosion of the first object is 300ms, then second object starts playing its animation on 200ms time. To handle such an animation, I have an animation system, that receives a message «startScoringAnimation» and it contains all the scored actors. Animation system plans that animation.

      The aforementioned spot or bomb should also be affected and animated. But they have to be animated by the actual time animation plays for the nearby actor.

      And, of course, I have to know, when I can start stage of putting new actors on the board. For that I should know that all animations of that scoring process are executed. Animation system are called from different places and components.

      The main problem is that I don't know how to orginize all that flow.

      First of all, my input system tells game logic that move has been done.
      Game logic finds all the scored actors, for every one of them it sends message and after that it sends message to start animation with the list of all scored actors:

      Source Code

      1. function Logic:onMoveDone()
      2. local scoredList = findAllScored()
      3. for i in pairs(scoredList) do
      4. QueueEvent({name = "actorScored", actor = scoredList[i]})
      5. end
      6. QueueEvent({name = "scoringAnimation", actors = scoredList})
      7. end


      All the actors or systems interested get "actorScored" message. Spots receive that message and detect, if the actor affects them.

      Source Code

      1. function SpotSystem:onActorScored(actor)
      2. for i in pairs(spots) do
      3. if samePosition(spots[i], actor) then
      4. spots[i]:animation()
      5. end
      6. end
      7. end


      Animation system receives "scoringAnimation":

      Source Code

      1. function AnimationSystem:onScoringAnimation(actors)
      2. for i in pairs(actors) do
      3. local ActorAnimation = actors[i]:getComponent("AnimationComponent"):get("scoreAnimation")
      4. AnimationSystem:plan(delay, ActorAnimation)
      5. end
      6. end


      I just feel all that unsynchronized logic from animation to be very weak. I try to picture the design in processes but I can't. For example, I start process "scoring", where onInit() find all scored actors, plans animation and so on; then it can start other processes from itself and all that goes until all the child processes are done. After that I can start process "adding new elements".

      The post was edited 5 times, last by George ().

    • Ok. Just after playes's performed his turn I start to identify all the actors(colored boxes) that considered scored. For every such an actor I send a message, which different subsystems receive and handle. For example, the health component of that same actor receives it and decreases its health; the bomb component of any other actor that has it detects if the event's actor is nearby and send message if it blows. Then other systems gets that blow message and so on. Make sense?
      The problem is that architecture becomes very individualized - so, for example, I can't control the overall process of animation, if I want all the scored boxes animated in the specified sequence.
    • Not really. I still can't play the game in my head. One of the things that would help a lot is if you had a key or something to show me what tiles are what on the board. You talk about goal tiles, boxes, etc. but it's not clear what they are. I'm looking more for an example of play. Teach me the game first, then the problem will become more clear.

      It sounds like you're trying to control things like animation order so that when I make a move, it can set off a chain reaction. First these things go away, then this happen, then another thing happens. My initial hit for solving this is with a Process that acts like a state machine. You can either have a single process that keeps track of the state or you can have a real chain by attaching them as children to a parent process.

      So it would work something like this:
      1. Player does something.
      2. This spins up the process chain.
      3. In the OnInit() function, an event is fired (probably synchronously) which probably contains a pointer to this process.
      4. Everyone who receives the event can add themselves to some particular phase.
      5. Once the events are handled, the process now has all the information it needs. It runs, handling the order of animation, etc.
      I think something like that would work, if I understand the problem you're having.

      Either way, if you want to have complete control over the order of something, using only events isn't going to work well. One of the disadvantages of events is that it's harder to control the exact order of things. Using a process is a great way to manage something over multiple frames. It can just sit there in the background, processing every frame. You can choose to disable input while it's happening or just let it run, triggering a separate process if the player moves again (though you'll have to handle the case where the same object is being dealt with by multiple processes).

      -Rez
    • I will try to explain it in parts.
      For now in my explanation I get rid of bombs, spots, etc so you could unerstand a basic idea.
      Let's say, we have two main objects - colored box and the goal:
      There is a board, and there are colored boxes on that board. We also have goals - special kind of tiles on the board that just have a color. Goals don't move, they are static components of the board. For example, on the board I can have 14 boxes of 4 different colors(red, green, blue, yellow) and 4 tiles “goal” of those colors(r, g, b, y). The player can move lines of boxes either horizontally or vertically. They move in a kind of simultaneous way so if you move a line, all the boxes that that line contains all are moved proportionally. And when you make a move resulting that one of colored boxes places itself on one of those colored tiles I call goals, magic happens. Say, for example, the red box gets on the red tile, all red tiles should go away from the board. If the board has 8 red boxes, you get score 8. Or, if the blue box gets on the red tile, then only blue box goes away, because it’s not match the goal tile and you got only 1 score.
      And your target is to score as much as you can.

      And, Rez, you are absolutely right about the problem I’m trying to solve.

      The post was edited 4 times, last by George ().

    • Cool, thanks for explaining. I have a better idea of the core game loop and what you're trying to achieve. I think my suggestion of the process that manages this is the direction you should explore.

      Let me know how it goes!

      -Rez
    • So now I will try to describe as I see the flow now.

      1. Player does something.
      2. This spins up the process ReactionProcess.
      3. In the OnInit() function we identify all the colored boxes that have been scored. After that an event is fired, which contains a pointer to the process and the list of the scored boxes.
      4. HealthComponent of the boxes receives that event and finds itself in the list. After that it decides what process it should create, depending on the health of the box and attaches to ReactionProcess:
      ReactionProcess:addToPhase(“scoring”, BoxProcess)
      or
      ReactionProcess:attach(BoxProcess)(if we want that process to be immediately started.

      After that HealthComponent sends an event with BoxProcess.
      5. BombComponent receives BoxProcess event, and if the box is nearby that bomb, it attaches BlowProcess to the parent of the BoxProcess:
      BoxProcess:getParent():add(BlowProcess)

      And then it fires an event with BlowProcess.
      6. And so on and so on.
      7. After all these processes are done, OnSuccess() function calls new process UpdateProcess.

      OR
      1, 2, 3 - the same.
      4. HealthComponent of the box receives that event and finds itself in the list. After that it decides what process it should create, depending on the health of the box and attaches to ReactionProcess. BUT it doesn't send an event with created BoxProcess. Instead of that in OnInit() function of BoxProcess we actually send an event with itself and every system takes care of it and attaches new processes if needed.
      5. Any of the later created processes fire an event with themselves in OnInit() function.

      And as far as I understand, all processes should have names, so they could be identified in event listener of systems to decide what actions to do.
      In the model I described process may have multiple child processes as well, not only one. And, of course, I have to keep chains from going into infinite loop. As for object being dealt with by multiple processes, I am not exactly sure how I will handle that, if of course the model is appropriate at all.

      The post was edited 4 times, last by George ().

    • Rez, I would like to sincerely thank you. There are very few people who combine such qualities as being professional and a good teacher. You have got a very rich experience and you are the one who can give an excellent answer and explanation! I personally think that without such great people like you and Mike it would be practically impossible to start in еру game development industry.

      The post was edited 1 time, last by George ().

    • I like how you both thinking.

      To create a workflow from an idea, is like building an pyramide,
      First you got an impossible idea, but can't see the details, the end, the result etc
      and than you begin to struggle with a plan of actually how to do it, wich means you
      breaking things apart, doing a structured and logic list of actions
      and you realize in the end how easy it was to build the pyramide.
      I find that process as the most challenging, interesting and important part of creating a game.
      The rest is details, meaning actually following the plan and coding.

      /F
    • utopiafx wrote:

      I like how you both thinking.

      To create a workflow from an idea, is like building an pyramide,
      First you got an impossible idea, but can't see the details, the end, the result etc
      and than you begin to struggle with a plan of actually how to do it, wich means you
      breaking things apart, doing a structured and logic list of actions
      and you realize in the end how easy it was to build the pyramide.
      I find that process as the most challenging, interesting and important part of creating a game.
      The rest is details, meaning actually following the plan and coding.

      /F


      Welcome to software engineering. :)

      -Rez