It is possible to relay most game-related information to the player using a console. However, it's a very basic form of communication. Modern players often expect more graphical ways of receiving information. In this recipe, we'll explore one way of doing this using Nifty. We'll create a dynamic message queue with messages moving in from the right of the screen and fading out once clicked.
It actually doesn't require that many lines of code.
The XML for this recipe can be completed by performing the following five steps:
<controlDefinition name="gameMessage">
.panel
element, and inside this panel
element, add two <control name="label">
elements with the ID #title
and other contents.onShow
trigger and one onHide
trigger with move and fade effects respectively, as shown in the following code:<onShow name="move" mode="fromOffset" offsetX="1500" length="100" inherit="true"/> <onHide name="fade" start="#ff" end="#00" length="100" inherit="true"/>
gameMessage
control, we can define another control to be our messageQueue
element. It just needs a horizontally aligned panel, spanning the whole screen.messageQueue
control is added to the mainScreen.xml
file inside the same layer as the console.Inside MainScreenController
, we need to do the following changes:
int
field called messageIndex
.addMessage
that should take a string as an input.addMessage
method, we define a ControlBuilder
method called messageBuilder
. This will create gameMessage
controls:messageBuilder = new ControlBuilder("gameMessage") {{ id("message"+messageIndex); interactOnClick("removeMessage("+messageIndex+")"); }};
build
method on this and supplying the messageQueue
element as the parent, we can call element.findNiftyControl
to set the title and the text on the labels inside the gameMessage
control.element.show()
and increase messageIndex
for the next message.removeMessage
. It takes a string called id
as the input.screen.findElementByName
to find the message, and call hide
.EndNotify
object, which in its perform
message should call markForRemoval()
on the message and also layoutElements()
on the parent messageQueue
control.Once the addMessage
method is called in the Controller
class, ControlBuilder
creates a new gameMessage
instance. The interactOnClick
element tells gameMessage
to call removeMessage
when clicked, supplying its index as id
.
After its built and added to messageQueue
, we populate the title and content elements of the message. Using #
in the ID of these elements is preferred by Nifty for non-unique IDs.
The gameMessage
instance is not visible upon creation, and we call show()
to make it play the onShow
effect we defined.
The Move
effect is set up to have offsetX
, which is outside of the screen. If it's too low, there will be a pop effect as it comes into existence. It's set to reach the target position in 100 ms. Messages will stack up nicely without any additional work when they are added.
The messages are set to disappear when clicked, as defined in the builder, through the interactOnClick
method. Instead of just removing them, we want to play a short fade effect to make the transition smoother. Simply hiding them won't be enough in this case either. Since they still occupy a position in the messageQueue
panel, the remaining messages won't align properly.
Hence, we want to call markForRemoval
on the gameMessage
element. Doing this instantly, however, would remove it before our hide effect is played. This why we supply an EndNotify
object that is handled once the hide effect is done with playing; then, we add the markForRemoval
call in here instead.
Let's say we would like to be able to show messages in a window, either when clicking the message in the queue, or any time. In that case, we can use Nifty's window control.
We can define a new controlDefinition
in our gameMessageControls.xml
file and call it messageWindow
. Inside this, we'll add <control name="window">
, inside which we can add any content we'd like. For now, we can settle with <control name="label">
for text content and a short fade effect when showing or hiding the window.
Then, we can copy the addMessage
method to MainScreenController
, and instead of having ControlBuilder
make gameMessage
, we can tell it to build a messageWindow
window instead.
We don't need an interactOnClick
element, as the window can be closed by default. Instead, we can use it to set the title of the window:
set("title", "Window"+windowIndex);
Windows are also draggable by default, but the parent element must have childLayout="absolute"
for it to work, as it lets the element decide its position itself.
3.129.22.164