|
Page 6 of 6
Since it has such a diverse range of uses, I'd like to give you a feel for some of the other places we harness the Scripted Event System. Hopefully you'll be able to see how you might be able to apply it to totally new cases in your own games.
MadStone AI
The computer in MadStone does a few things: moves the cursor, waits, strikes a block, and shakes. Every time it moves or strikes a block, it waits at least a fraction of a second afterward so that it doesn't play at superhuman speeds. Sometimes the situation calls for it to do a short series of moving, waiting, and striking.
Even though the application of the Scripted Event System is simple here, it works really well for what it does. The idea is that since the computer's actions are performed in a specific order, it made sense to just throw the computer's actions into a script as it played. At any given moment, the script would be tiny: maybe just a strike command then a wait action. But when the script was over, the computer would hear the script's callback and know that it needed to decide what to do next.
Execution example
Let's say the AI script starts empty. Here's basically what the computer is thinking while it plays, and what is going on with the script:
[Computer decides what to do next]
script.enqueue(MoveCommand(UP))
script.enqueue(Timer(0.4))
[script finishes, invokes AI.callback()]
[Computer decides what to do next]
script.enqueue(StrikeCommand())
script.enqueue(Timer(0.4))
script.enqueue(MoveCommand(LEFT))
script.enqueue(Timer(0.4))
[script finishes, invokes AI.callback()]
[Computer decides what to do next]
...
The advantage of using scripts here is that you get an easy way to execute short segments of planned activity in order, without any additional control structures. But unlike a cinema, you can't build the whole script at once. This is for two reasons: 1. The script is potentially endless, depending on the length of the game, and 2. The AI must adapt to changing conditions every couple of actions. Luckily, it's no problem to build the script over time.
The computer builds up the script again each time the current script finishes running (which is when it hears the script's callback). In a cinema, the script's listener only hears the callback() from the script once, meaning the cinema is over. Here the callback can occur several times a second, each time pushing a few more items into the (newly empty) script, and telling it to run again.
More examples
All of these examples should be similar enough to ones we've already looked at for you to have the basic idea of how the Scripted Event System would apply:
-Use scripts for extended scene and gui transition effects
-Use a persistant ActionList, managed by the scene, to run effects in game.
-Combine a script and a simple state machine inside Game Objects to manage their actions.
-Use an ActionList in a Game Object to run ongoing behaviors and animation effects.
Common Commands
At first I thought that since Commands could execute any arbitrary code, I would probably end up writing dozens of them to create a good cinema. This turned out to be wrong in both MadStone and Primate Panic. I actually only needed a few important commands with 1 or 2 parameters each. Here are some of the main ones:
-Play music or a sound effect
-Change an image reference (such as the background)
-Add an ActionEvent to an ActionList/ActionQueue
-Enable/disable an ActionEvent
---
Ever since I invented the Scripted Event System, we've used it in dozens of different places throughout each of our games. Combined with the Behavior System and Robot Functions, it has saved me countless weeks of programming and allowed me to take on tasks that I had previously thought were way beyond my reach. I like the system so much that I plan to use it in every game that we make in the future.
I hope you enjoyed this article, thank you for reading!
Newsletter
Was this article helpful to you? Subscribe to our newsletter to keep up with our latest games, articles, and other projects. You can unsubscribe at any time.
|
Good job!
Thanks for sharing this nice iformation. I have implemented the ideo on c# but there's something I can´t find out to do it in a clean way. Imagine this script (Each step is one EventAction):
1) Play Anim
2) Create Particle system
3) Animate with a robot the Particle system position.
How do you handle the third point? You need the particle system instance the robot funcion needs to animate?
Thanks in advance,
HexDump.
The easiest way to do this is basically what you said: instantiate the particle system while you are creating the script and pass it to the command (or behavior, or whatever) that is responsible for the animation. You can organize the particle system's code so that it doesn't load any data just for instantiating it. That way, it isn't taking up much memory until it is supposed to actually run, at which point some item in the script can call particleSystem.load(), and start things running. I almost always use this approach because it is the simplest.
If you really don't want to instantiate the particle system before hand, there are a few options. One is to set up a "global" variable somewhere and pass a reference of it to the parts of the scripts in step 2 and 3. That way, when step 2 creates the system, it's already ready for step 3, which knows to look at the same object. The particle system could be placed into any kind of data structure, as long as both parts of the script know how to access the particle system once its created.
Option 3 would be to create a special command that encompasses steps 2 and 3, generating a particle system and passing to the animation. Again there are quite a few choices for how to do this, but probably the easiest way would be to create a step 2.5 command that facilitates communication between steps 2 and 3, making sure that both have the same data. You could make the input parameters for this communication command general enough so that you can reuse it in other situations (it doesn't have to be completely specific to this problem).
Would any of those solutions work in your case?
Well, I solved the problem more ore less, I have to rethink about it, thanks for the options you offered.
I´m noticing that things are getting complicated. I for example waht to create an effect that is like a meteor rain. This leads me to think that I will need something to do loops, and if you add to this that you want to listen to collisions in the script things get more and more complicated.
For the collision thing I managed to create a WatColliison action that could do the job, but for the loop thing (because you need to create lota of balls that are particle system and do same for all, it is like having 1 script thread per particle system) I can´t get a good solution.
My game is something like Robot Wars where cinematics are really important.
Thanks in advance,
HexDump.
Usually for complicated cinematics, I have an ActionList that encompasses and runs the main script (because scripts can be added to ActionLists, and vice-versa). The script adds ongoing effects (such as a meteor rain) to the list when necessary, and then the script tells it to stop when it is supposed to be done.