avatarAlex Roan

Summary

The article discusses the development of an Ethereum simulation game, focusing on the implementation of player training and resting features, and the integration of real-time account change detection with Metamask.

Abstract

The fourth part of the Ethereum simulation game development series introduces new functionalities that allow users to train and rest their players, impacting attributes and condition. The author details the process of retrieving training costs and gains from the Smart Contract, using React, Redux, and web3 to manage the user interface and interactions. The article also addresses a reader's question about real-time detection of account changes in Metamask, providing a solution that enhances the user experience by updating the DApp's interface without page refreshes. The author emphasizes the importance of listening for account changes and discusses the use of events and subscriptions to ensure the DApp reflects the most current state. The development includes the use of dropdowns for attribute selection and the emission of events upon successful player training, which triggers a reload of the player's data. The article concludes with the current state of the DApp, future interface improvements, and the intention to test on a public testnet.

Opinions

  • The author values user experience, as evidenced by the implementation of real-time account change detection and the emphasis on updating the DApp interface without requiring page refreshes.
  • The author is open to community engagement, shown by addressing a reader's question and providing a detailed solution.
  • There is a recognition of the need for further improvements in the game's interface, indicating a commitment to both functional and aesthetic aspects of the DApp.
  • The author acknowledges the challenges of event listening on public testnets compared to local blockchain environments, highlighting the importance of thorough testing.
  • The author expresses satisfaction with the progress of the DApp's functionality, despite its current aesthetic shortcomings, and plans to revisit the gameplay logic to enhance the game's appeal.

Let’s Make An Ethereum Simulation Game — Part 4

Training and resting players

Image by composita from Pixabay

Recap

Part three saw the introduction of the last Smart Contract jigsaw piece being put into place, and from there, the beginnings of a rudimentary interface using React and Redux.

I’ve added a few cool little features since then and got the interface to a state where users can add new players, train them to increase attributes, and rest them to increase condition.

Here’s how I did it.

The Interface

Recently, I got asked a question from one of my readers. They asked how their DApp could listen for account changes within Metamask in real-time without refreshing the page.

Message from @SolidityDev on Twitter

Metamask users can change account at any time, but the DApp won’t know about it unless it’s listening for it. It doesn’t do it by default. An error will occur if the DApp thinks the current account is sending a transaction, but it comes from another.

This prompted an article I wrote which explains listening for accounts changing and updating the in-app data accordingly.

Example of account changing and the DApp updates (green button on the page)

This was the first small change I made to the front-end to make the UX a little smoother.

Training

The largest bit of functionality added was the ability to train each player. Training doesn’t come free. Each player needs XP (which is gained through playing matches with other players) and reduces their condition. As long as the player’s attributes are equal to or greater than the cost of those, they can train.

The first step was to retrieve those costs and gains, which are stored in the TrainableTennisPlayer contract as public state variables. This is likely to change in future. Ideally, the higher an attribute gets, the more it would cost to train it higher, making it more and more expensive as the player gets better. For now, however, all these values are static.

Retrieving Costs and Gains

Note: I’m using the IARS project code structure. Don’t google that, I made the acronym up.

Public state variables in Solidity are accessed as if they are methods, so calling them from web3 requires the same syntax.

When a player is loaded, I have a function in my interactions.js file called loadTrainingCosts() which calls all of the public state variables representing costs and gains for training and resting.

loadTrainingCosts() in interactions.js

Training costs XP and condition (retrieved on lines 86 and 87), whilst increases an attribute (retrieved on line 88); Resting costs XP (retrieved on line 89) but increases condition (retrieved on line 90).

The final line in that method is a call to dispatch. I haven’t yet gone through what this looks like in the previous articles in the series, so I’ll walk through what happens here.

Dispatch on line 91 kicks off an action in actions.js called trainingDetailsLoaded() with all of the information retrieved from the Smart Contract. This is telling Redux that an action has just occurred and this information is the result. It’s the responsibility of the trainingDetailsLoaded() function to direct the information on to the correct reducer so that the state of the DApp can be updated.

trainingDetailsLoaded() in actions.js

The action-type here is TRAINING_DETAILS_LOADED which the dispatcher directs to the following reducer:

Snippet from reducers.js

The state is updated with all of the new information retrieved from the Smart Contract. The interface can then retrieve this data using a selector, which looks like this:

Snippet from selectors.js

All that the component needs to do is import each of these selectors and it now has full access to all costs and gains for training and resting!

Dropdown

We need users to be able to select which attribute they want to train on their player. React-bootstrap provides a nice component for us here called Dropdown.

Snippet from Train.js component

When clicked, the attributeSelected() function is called with dispatch, the name of the attribute and the id of the attribute. This is important because Solidity enums are externalised in the form of digit arrays. Even though the enum declaration in Solidity looks like this:

enum Attribute { agility, power, stamina, technique }

Interacting with it requires us to use integers 0, 1, 2 and 3.

The attributeSelected() function calls an interaction which follows the same sequence described in Retrieving Costs and Gains to update the currently selected attribute to train.

Training

Once the player is loaded and the desired attribute is selected, submitting the result uses all of this information to send a transaction to the ledger to train the player. The interaction function looks like this:

Snippet from interactions.js for training a player

tennisPlayer is a reference to the Smart Contract instance. At the moment, the DApp logs to the console at each stage of the transaction. I use subscriptions to the Train event instead of acting on receipt or confirmation events for now, but this may need to change in future.

The call on line 95 sends a transaction to this function in our Smart Contract:

train() function in TrainableTennisPlayer.sol

The Train() event is emitted when the player is successfully trained. To ensure the page is reloaded when this event is emitted, the DApp listens out for it using this subscription function:

Subscribing to Train event

When the player is successfully trained, this fires, causing the player to be reloaded and the information on the screen to be updated.

Result

I used the same workflow for resting players, without the ability to select an attribute through a dropdown, since resting only ever increases condition.

I added a few front-end features like badges to display the attribute values and colour coded them depending on the value. The current state of the DApp looks like this:

Here’s what happens:

  1. DApp is connected
  2. A new player is created
  3. The new player with ID: 0 is selected and details are displayed
  4. Several attributes are selected and trained, resulting in updates to the attributes of the player
  5. The player is rested, increasing the condition.

Next Steps

The interface is gross at the moment. I need to have a think and jiggle some things around before adding the match playing functionality anyway, so that’s next.

I also want to try the DApp out on a public testnet, to make sure event listening is working correctly. I’ve had issues with this in the past where events are fired and caught successfully using Ganache local blockchain, but never caught the same way on public testnets.

Regardless, I’m really glad it’s moving towards the point where the interface is fully functional, even though it’s gross to look at right now. Once all features have been implemented I can revisit the gameplay logic in the Smart Contracts to make the game more enticing.

Get Best Software Deals Directly In Your Inbox

Further Reading

If you’re interested in Blockchain Development, I write tutorials, walkthroughs, hints, and tips on how to get started and build a portfolio. Check out some of my resources:

Blockchain
Ethereum
Dapps
Smart Contracts
JavaScript
Recommended from ReadMedium