Wednesday, January 6, 2016

LibGDX game jam - dev log #2

The next big addition to my LibGDX game jam project has been the addition of character dialog menus, inspired by those from the early Final Fantasy games.

To support this feature, the main additions have been:
  • a DialogSequence object, which contains an ArrayList of Strings to store the lines of text that appear, and an Iterator and some basic access methods for convenience (add, next, hasNext)
  • a DialogTrigger object, which extends the Box2DActor class and contains:
    • a DialogSequence object
    • a boolean variable called displayOnce that, as the name suggests, determines if the dialog displays only once, or will appear repeatedly
  • a set of corresponding user interface elements: the text is displayed in a Label (with a NinePatch background) on the Stage containing the user interface elements. The alignment is managed with a Table. To continue, the user needs to press the C key. Thus, in addition, there is an Image of the keyboard C key overlayed on the lower right corner of the Label, with is accomplished using a Stack object.

When the player comes into contact with a DialogTrigger object (as determined by a Box2D ContactListener object), the text is displayed on the dialog Label and the Stack containing the objects discussed above is set to visible. While the dialog text is visible, the program automatically returns from the update method, which means that the physics simulation does not run and continuous user inputs are not polled (thus none of the game world entities move). However, Actions are still processed, and discrete user input is still processed - this enables a subtle animated "pulsing" effect on the keyboard key image to take place, and also allows the user to press the key to cycle through the text contained in the DialogSequence object.

Some of the DialogTrigger data can be set up in Tiled; this is particularly useful for situations where dialog should be triggered when the player walks over a certain area that doesn't correspond to a pre-existing game world object. This is accomplished by creating a Rectangle on the Object layer, named "DialogTrigger", and then by adding a set of properties whose names contain the letters "Text" (Text0, Text1, Text2, etc.) and whose data are the strings to be displayed. By including a property called "Once", the DialogTrigger object will be configured (a boolean value will be set) so that the dialog sequence only displays once. Other dialog sequences can be configured in the code itself to be displayed when a pre-existing object should trigger a dialog sequence -- for example, when obtaining a key, you may want to display the message "You obtained a key!"

Finally, if the DialogTrigger field displayOnce is set to true, then when the message is complete, it gets added to removeList, which removes the corresponding body (that triggered the interaction) from the physics world, and also removes the object from its previously set "parentList", the ArrayList of DialogTrigger objects contained in the room, so even if the room is reloaded again later, the dialog will not display again.

The code that implements these features is currently posted on GitHub.