User Input – First Steps

What I have so far with React and Kotlin is entirely passive; the game just runs and there is no way to control it. Today I thought it was time to get the first bit of user input – selecting the current player action.

Design

The first step here was a simple design: I wanted to be able to pick only the basic actions, gather herbs, mushrooms and flowers, and to forage. These would appear in a list and some text (like a hyperlink) would allow me to select available actions. Rendering this wasn’t too difficult, and is pretty much covered in previous posts – I didn’t do any styling this time, but I did add an icon in for fun.

This is all in the “player window” – a react component that renders things related to the player that is used by the main window.

Adding a Click Event

Next we needed to use an event handler for the click event on my select link. I had a read of a few tutorials (eg this one for react and this example for kotlin-react) and it seems like there’s simple steps to get started – we create the handler and add it to the attributes for the parent tag using the following syntax:

a(classes = "Player-action", href = "#") {
attrs {
onClickFunction = fun(e: Event) {
onSelectAction(e, action)
}
}
+"Start"
}

I did get caught out here initially that attrs takes a code block, not an assignment! Strictly I could have done this without the parameters, but I want to prevent the default action on the event (so we don’t go to the top of the page after clicking on the link). “action” in the code above contains a data structure that contains information about the action.

Writing the Click Handler

This is enough to get a the onSelectAction called for this player window, but we need to get the message up to the main window in order to send the message to the worker to change the action. For this we need to extend our player window to include a handler for the select action event, which is then called by the onSelectAction above. So, firstly, we need to add a new property to the props structure, for the event handler:

typealias ActionSelectHandler = (ActionType, ResourceType) -> Unit

interface PlayerWindowProps : RProps {
var player: Actor
var selectActionEvent: ActionSelectHandler
}

fun RBuilder.playerWindow(player: Actor, selectActionEvent: ActionSelectHandler) = child(PlayerWindow::class) {
attrs.player = player
attrs.selectActionEvent = selectActionEvent
}

Then we call this even handler from our onSelectAction function

private fun onSelectAction(event: Event, action: PlayerActionSelection) {
this.props.selectActionEvent(action.type, action.resource)
event.preventDefault()
}

Passing on the message

The final step is we need to get the message to the worker. This we had already done, so we simply need to create a handler in the main window that will pass the message to the worker.

fun handleSelectGatherAction(type: ActionType, resource: ResourceType) {
this.sendMessage(SetPlayerActionMessage(type, resource))
}

One final piece of the puzzle is needed; when we create our player window we need to pass this function. We can’t simply use the name however, as Kotlin would expect that to be invoked. Instead we use a callable reference by adding a :: to the front, as follows:

div("Main-window") {
playerWindow(player, ::handleSelectGatherAction)
}

And finally all the pieces are in place; we have a link in a child object which has an onClick event, and this child object is given an event handler in a parent object which is the only place that can send the message to the worker.

Conclusions

This wasn’t really too difficult, but there were a few things that caught me out – it took me quite some time to find the callable reference syntax. I think now I’ve got a reasonable architecture; I can use the same event handlers in other child objects and this will allow me to build a modular window system.

I can only set the basic repeatable actions so far, however. The next steps in this particular path will involve setting up a whole new window for rituals, which are where you will be able to use resources to cast spells that will make your gardens and other constructions more productive. These use the same action system, so should be able to be handled with the same style of events.


Leave a Reply

Your email address will not be published. Required fields are marked *