Wednesday, November 21, 2012

Flash Game Programming: Treating Game Messages Similarly to Particles with a Life Timer

I love particle engines. We can accomplish so many interesting graphical effects using particles with relatively minimal code. This is because the class definition for the behavior of a particle is minimal but we leverage the power of object oriented design principles to create a complex system. The behavior of any one particle is easy to predict, but the behavior of hundreds of these objects acting at the same time is difficult to predict.

On the other hand, we can also use design patterns similar to particle engines to create a remarkably simple device to manage lots of data.One element that is present in most particle designs is a timer that keeps track of how long a particle has to live before it is released from memory. I will use this design technique in order to simplify the adding and removing of game messages in the game engine for Salvager: A Dredger's Tale.

In the game, one of my classes that I created manages in-game messages. The title of the class is MessageBoxManager. The class holds a standard text-box, a TextFormat object alter the appearance of the text, a variable to keep track of how long the message should be displayed if on a timer, a variable to keep track of how long since the message was created, and a Boolean flag that marks whether or not the message box should acknowledge the timer and just stay visible until the player wishes to close the messages.

What use is this class? In order to script in-game events, one of the issues that needs to be dealt with is to create a mechanism to easily display game messages. These messages can be hints, data from the game engine such as damage dealt on each successful hit, or even dialogue from a non-player character. This mechanism will accept strings that need to be displayed to the player and put them in the game environment on the stage.

The last post outlined how to add display objects to the main stage from a class that is a child of the class that directly references the stage. I have used a similar technique here. The constructor initializes the variables and sets an event listener to execute a method as soon as the object is added to the stage. The main class adds the object to the stage, and the method within the child class executes to add all relevant display objects to the stage by referencing its parent. I know that sounds confusing, so check out my previous post for clarification on how to do this and why we have to do this: Flash Game Programming: Adding objects to the main stage from a child object.

The class creates a text box and edits the display attributes in order to make it match the game content. The visual style is simple retro-style vector graphics. Everything is typically green or white on a black background. A method is created in order to accept a string and then append this string to the text box. We also accept various arguments to this method. One such argument is the number of seconds that the message box should be displayed for. For most quick messages, 3 seconds is the standard time. Since the project is set to run in the Flash environment at 60 fps, we simply assign the timer variable the argument value multiplied by 60.

How do we get the message box to go away without losing any data contained within? The Flash environment makes this very easy. Every display object has an alpha property which determines transparency. This value can be any value from 0 to 1. 0 means the object is entirely transparent and 1 means the object is entirely opaque. I treat the message box like one big particle here. On every frame, when the method that handles updating the message box is called, we set the alpha property of the message box itself. I use a simple formula.


          displayTimer--;

          thisTextField.alpha = displayTimer / 60;

What happens here? We set the alpha property of the text box based on how long the display timer has left. Remember, when we created a message, we passed in a value that told the manager how long we wanted it to be visible by. If the value passed was 3 seconds, then timeToLive was set to 180. Since 180 divided by 60 is 3, the alpha property of the box is set to 1. That means it is opaque. Every frame, that variable is decreased by 1. For two seconds, the box is completely opaque. Then, during the last second that it's to be shown, the box slowly fades until it becomes invisible on the main stage. For example, let's say that timeToLive is equal to 30 frames. It has half a second to live. It will also be at half transparency, since 30 divided by 60 is one half. The alpha property will always be set to 1 if the value of timeToLive divided by 60 is 1 or greater than 1. Once we get below 1 second of life left, it will start to fade as the alpha property is set to the appropriate decimal between 0 and 1.

Notice how easy this technique is. We don't add a new text box each time we create a message. We also don't have to worry about removing old text boxes from the stage and deallocating the memory. The text box inside the manager class is added once and only once. It is never removed. We simple remove it from sight, but the other display properties such as the text inside that container as well as the on-screen position do not change.

When we have an event, such as the player pressing the console key to bring up a history of recent messages, we can set the Boolean flag to display the message box constantly to true. Here, we simply have to add an additional line of code.

            if (permaDisplay) {displayTimer = 60;}

Each frame, the timer will be given 1 second to live. This will keep the alpha property of the text box at 1. We have to make sure that this line comes after the line that decrements the displayTimer variable so that the alpha property of the text box is always set to 1. One the flag is set back to false, the message box will fade out over the course of 1 second.

The full code to the MessageBoxManager class is posted here: Code Examples: MessageBoxManager Class.

No comments:

Post a Comment