In this tutorial, we will expand upon the previous multiplayer UI by introducing an inventory page that displays the items owned by the player.
Additionally, we’ll enhance the existing Express server by adding new API endpoints that will fetch the player’s items so they can be displayed in the UI.
Source location
You can find the complete sample source within the ${Gameface package}/Samples/uiresources/UITutorials/MultiplayerUI directory.
src folder contains the UI source code.
api folder contains the Express server source code.
Ensure to run npm i before testing the sample.
Refer to the README.md file in this directory for information on running the sample locally or previewing it without building or starting any processes.
Getting started - Backend
We’ll begin by updating the backend to include new API endpoints that return data for the player’s items, which will be shown in the UI.
New items collection schema
To store player items in the database, we’ll define a new schema for the item collection. The schema will include details such as the item name, image, type, rarity, and stats.
Extending user schema to include items
To allow users to own items, we’ll extend the user schema in the database by adding an array of item IDs.
Creating an API to retrieve user items
When the inventory page is accessed, the player’s items will be retrieved from the server. We’ll add a new route to fetch the user’s items.
getUserItems method
This method retrieves the items owned by the user. We use the items collection to pull data such as the item name, image, and ID.
Creating an API to retrieve item data
When players interact with their inventory and select an item, we’ll fetch detailed data about that item. A new route and controller will be created to retrieve item data by its ID.
And the controller:
We also need to ensure these routes are added to the router in our Express server.
Adding random items to the users
Since our UI isn’t connected to a live game, we need to generate items when a new user registers or logs in and doesn’t have any items.
We’ve already developed a simple item generator that creates objects filled with randomly generated data. You can review this generator in the ${Gameface package}/Samples/uiresources/UITutorials/MultiplayerUI/api/itemsGenerator.js file. This file exports the generateRandomItemObject method by default, which returns a random item object that follows the schema in the database.
Once we have this generator, we can use it to create random items for users.
We’ll add a new method in the items controller, which was created earlier, to generate a random item and save it to the database:
Next, we can integrate the generateRandomItem method into the usersController to add items when the user logs in and has no items yet.
Here’s how we can add items for the user when they log in:
The generateUserItems method will create 7 new items for the user and add them to the database:
Similarly, we will ensure items are generated for new users during registration.
We’ll refactor the register method to include the item generation, by combining the user stats data and item data generation under a new generateUserData method:
The generateUserData method will create mock stats and generate random items for the new user:
This ensures that users will have items generated both upon login and registration.
Serving the items icons
Since the item icons will be loaded from the server, we need to configure the server to serve them properly.
We’ll start by creating a new folder within the api directory, named public, and inside it, we will add another folder to store the item icons, called items.
The full path will be: /api/public/items.
Next, we need to serve this folder statically in our Express app:
Once the folder is set up, we’ll store the item icons inside, and to load an icon in the frontend, we can use the image name from the item data. The URL format will be: ${server-host}/api/items/${item-image-name}.png.
Getting started - Frontend
For the inventory page, we’ll create a new interface that displays a grid with all the items the user owns. On the right-hand side, the selected item’s stats will be shown.
Inventory page
We’ll begin by building the inventory page, which will have a layout similar to the leaderboard, with a scrollable container displaying previews of the user-owned items. On the right side, the stats of the selected item will be visible.
To enable scrolling through the list of items, we will use the gameface-scrollable-container component. Additionally, we’ll leverage the useFetch custom hook for fetching data from the server and the useLocalStorage custom hook to retrieve the currently logged-in user’s ID.
Let’s start by setting up the necessary states and hooks:
When the page is mounted, we’ll fetch the items for the currently logged-in user using the useEffect hook with no dependencies:
Now that we have the data, let’s render the items. We’ll use the Loader component to display a loading indicator until the data is fetched.
Inside the gameface-scrollable-container, we’ll map through the fetched items and render each one using the ItemPreview component, which we will create later:
Display item stats in the inventory
On the inventory page, we will display item stats on the right side. To achieve this, we will create a method that toggles the stats based on the selected item’s ID from the inventory and renders the stats within the inventory interface.
For this, we’ll use the ItemStats component, which we will build later.
Adding spatial navigation to the inventory
To enhance the user experience, we will add spatial navigation to the inventory, allowing users to navigate items using arrow keys.
First, install the interaction manager by running the command: npm i coherent-gameface-interaction-manager.
Next, initialize spatial navigation:
Now, integrate spatial navigation into the Inventory page:
Whenever the items data changes, we clear any existing items in the spatial navigation with the remove method, then add items identified by the .item-preview CSS class to it, and focus on the first item.
ItemPreview component
The ItemPreview component is designed to display the name and icon of the item. When focused, it triggers the display of item stats on the right side of the inventory.
To display the item icon, we use the background-image CSS property, loading the image based on the provided item data. The image URL follows this template: ${server-host}/items/${image-name}.
ItemStats component
To display item stats on the right side of the inventory, we’ll show the item’s name, image, and its stats below.
In this tutorial, we will use the gameface-progress-bar component to present some of the stats for a more well-looking UI.
We’ll begin by fetching the complete item data using the item ID passed from the inventory to our ItemStats component:
Next, we can render a loader while the data is being fetched, and display the item stats once ready:
As you can see, different UI elements are used to represent various stats. For instance, the item name is displayed as text, the image is set as a background image, and the remaining stats are presented using the StatItem component.
For the StatItem children, we utilize either RarityStatItem, ProgressStatItem, or plain text, depending on the type of stat.
These components are simple and can be defined within the ItemStats.jsx file:
The StatItem component uses the showStat prop to conditionally render only if the stat exists. This ensures that only relevant stats are displayed. The ProgressStatItem utilizes the gameface-progress-bar to visually represent the stat’s value.
Wrapping the inventory page
Now when the inventory page is complete, it’s time to integrate it into the UI.
First, we need to define a route for it in App.jsx:
Next, we need to add a button for it in the navigation menu at the top of the UI:
Now, you’re all set to navigate to the newly added inventory page.
Resources
For the item icons, we used the free Basic RPG Item Icons from this resource.