Over the past month, I participated in the ThirdWeb hackathon in which I set myself the challenge of building a web3 clone of The Hill Climb game using both ThirdWeb GamingKit and ContractKit. I was so excited about the opportunity to explore the different ways in which the Ethereum blockchain can be utilized to create games with unique features.
In this post, I will analyze the different parts of the game I built over the past month. I'll explain how I used ThirdWeb GamingKit and ContractKit to customize different game parts. Finally, I'll show you how you can customize this game to build your own decentralized version of The Hill Climb.
Model Analysis
Model Analysis is a method that allows us to comprehend the prerequisites of specific software, in this case, a game, and how they interact with one another. This technique gives us a high-level overview of what must be done to build the game and a plan for developing it.
Use Case Diagram
The Use Case Diagram outlines the interactions between a user and the software. It illustrates the user's activities and how they are interconnected. A player progresses through the game by completing a series of activities represented by modules/panels. Each panel signifies a different game stage, and the player must complete all tasks within each panel to move on to the next one.
This use case diagram begins when a user playing the game triggers the server to run and the game has loaded. A user connects their wallet, selects a car and level, and then begins playing the game. As they play, they may upgrade their vehicle.
- Steps:
- Go to the dashboard.
- Claim an NFT to grant access to the game.
- Go to the main menu of the game.
- Connect the wallet.
- Select a level.
- Select a car.
- Upgrade your car.
- The game is loaded.
Activity Diagram
An activity Diagram is a great tool to understand better the order of activities that need to be performed to complete a task and the relationships between them. It is mainly used to identify potential areas for improvement.
You can comprehensively understand the project by reading the above activity diagram from the top right corner.
Architecture
ThirdWeb Integration
This section describes how ThirdWeb was integrated into this game.
Smart Contract
Using the ThirdWeb ContractKit CLI, we can quickly write and deploy secure contracts by only focusing on the smart contract itself. The code snippet below represents a custom ERC721 Drop contract.
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/base/ERC721Drop.sol";
import "@thirdweb-dev/contracts/extension/Permissions.sol";
contract Contract is ERC721Drop, Permissions {
// An array of notes.
mapping(uint256 => string) public notes;
constructor(
string memory _name,
string memory _symbol,
address _royaltyRecipient,
uint128 _royaltyBps,
address _primarySaleRecipient
)
ERC721Drop(
_name,
_symbol,
_royaltyRecipient,
_royaltyBps,
_primarySaleRecipient
)
{
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/**
* A function that allows writing notes to the owner of the NFT.
*/
function writeNote(uint256 _tokenId, string memory _msg) public {
require(
msg.sender == ownerOf(_tokenId),
"You are not the token owner."
);
notes[_tokenId] = _msg;
}
/**
* A function that allows notes update only to holders of the NFT that has the `DEFAULT_ADMIN_ROLE` permission.
*/
function updateNote(
uint256 _tokenId,
string memory _msg
) public onlyRole(DEFAULT_ADMIN_ROLE) {
notes[_tokenId] = _msg;
}
}
The code shows that only the owner of a given NFT has permission to write, update, and read notes for a given token.
The reason why I chose the ERC721 Drop contract is because of the following features:
- Batch uploading because it saves time and gas fees on the upload process.
- Set up robust claiming options for claiming these tokens from users, like setting up an allow list, etc.
- Great for PFP projects like our game in this case.
For more info on how to build and deploy this contract, you can refer to the following repo:
hill-climb / smart-contract
A custom ERC721 Drop smart contract.
Getting Started
Create a project using this example:
npx thirdweb create --contract --template hardhat-javascript-starter
You can start editing the page by modifying contracts/Contract.sol
.
To add functionality to your contracts, you can use the @thirdweb-dev/contracts
package which provides base contracts and extensions to inherit. The package is already installed with this project. Head to our Contracts Extensions Docs to learn more.
Building the project
After any changes to the contract, run:
npm run build
# or
yarn build
to compile your contracts. This will also detect the Contracts Extensions Docs detected on your contract.
Deploying Contracts
When you're ready to deploy your contracts, just run one of the following command to deploy you're contracts:
npm run deploy
# or
yarn deploy
Releasing Contracts
If you want to release a version of your contracts publicly, you can use one of the followings command:
npm run release
# or
yarn release
Join
…The Game
The game utilizes Unity and the ThirdWeb GamingKit to create a powerful unique web3 gaming experience. This game was developed in Unity version 2021.15.1f
because it is the only existing version on my PC. So, make sure to have this version to build and deploy the game. For more info on how to build and deploy the game, please refer to the following repo:
hill-climb / game
A web3 clone of Hill Climb powered by Unity, ThirdWeb GamingKit and ContractKit
Hill Climb ThirdWeb
A web3 clone of Hill Climb powered by Unity, ThirdWeb GamingKit and ContractKit.
Features
- Four levels.
- Four cars.
Requirements
- Unity version
2021.3.15f1
.
Build
- Create a new unity project.
- Import
Assets
,packages
andProjectSettings
folders into your project. - Deploy your smart contract using this repo.
- Change the smart contract address under
ContractAddress
of the MainMenu Scene component.
- Set the player build settings to the following:
Demos
Resources
Feedback
Have questions? Hit me up on twitter: @wiseaidev.
Fixes or feature additions? Send a pull request, happy to integrate them!
License
This project and the accompanying materials are made available under the terms and conditions of the MIT LICENSE
.
Unity
Scenes
At the moment of writing this guide, there are four playable levels and menu scenes. Double-click on a scene to start your edit.
Levels
When developing a game, you must consider the different levels a player will progress through. Each level can have similar game objects and components to maintain continuity throughout the game. However, you will also need to customize the terrain heights for each level; this is where the 2D Terrain Editor comes in handy.
To create a new level, you only need to customize terrain heights for each level. You can use the 2D Terrain Editor for this purpose. This tool can spawn coins, fuels, and other items randomly.
The Input component is attached to the Canvas and automatically switches between the keyboard and touch buttons on each platform.
Menus
The main menu system is a crucial part of the game, providing access to all necessary features and allowing us to navigate easily through the game. This system is based on activating and deactivating menu panels, which are stored under empty game objects.
As you can notice, the main menu consists of five different panels. If you want to switch to a particular menu panel, it can be activated or deactivated accordingly by right-clicking on the intended panel and clicking Toggle Active State
.
Similarly, you can click on a particular panel and check the box that is left aligned with the panel's name in the inspector.
The components of each panel are fully customizable; you can customize different properties of objects (e.g., color, width, height, script, etc.) under the currently activated panel.
1. Main Menu
The Main Menu is the first thing you see when you open the MainMenu game scene. It's activated by default, so you can connect your wallet and start playing. The Main Menu is where you'll find all the options and settings for the game.
This panel has two primary components: Connected
and Disconnected
. These components are programmatically activated and deactivated based on the wallet connection status. On a successful attempt, the Connected
component will be activated, and the Disconnected
component will be deactivated. This provides us with an easy way to check the wallet connection status.
Creating a new input component is pretty straightforward. To create a new input component, you can copy, paste, and customize it to your liking.
2. Settings Menu
The settings menu is where you gain complete control over the gaming experience. It provides access to various features and settings so that you can tailor their game as much as possible.
For example, if you want to use a particular feature in the game, you can find it in the settings menu and activate it with just a few clicks. Similarly, you can customize your experience by enabling or disabling certain graphics options from here too. Using this menu system, you can control your gaming experience and customize it according to your needs and preferences.
Another example is changing the background music's volume by sliding the indicator left or right like a sliding window. You can turn off the music and sound effects to enjoy a more peaceful atmosphere while playing. You also have the opportunity to adjust the quality of each pixel displayed on the screen.
Creating a new component is pretty straightforward. To create a new component, you can copy, paste, and customize it.
3. Level Select Menu
The level select menu is easy to use and navigate. You click the LevelSelect GameObject
icon on your screen and scroll down to the item icons in the inspector, where you can choose from four available levels. These levels are ordered from left to right according to their length, price, and terrain difficulty.
If you want to add a new level, you can click the plus
icon in the inspector and drag and drop a level sprite onto your screen. After that, you can change its animation, sound, and icons as needed.
4. Car Select Menu
This panel is a powerful tool that allows you to add new cars, control animation, and more. This Menu is similar to the previous one.
5. Upgrade Menu
The upgrade menu is where you can customize the recently selected car. You can adjust the engine, fuel, wheels, and speed levels.
Creating A New Menu Panel
You can also create a new panel using the built-in Empty GameObject in Unity. To do so, select GameObject > Create Empty
under the canvas.
This will create a new empty GameObject that you can rename to whatever you like, YourCustomPanelName
.
As the object is invisible, you will need to add a Canvas Renderer to it so that we can see something in the scene view that lives inside the canvas. This is not, however, related to the animation states. It simply gives us an on-screen representation of the panel.
After adding the Canvas Renderer component, you can add an Image component. The Image component provides many options for customizing the look and feel of your image. You can choose from a variety of presets or customize the settings yourself.
The image component is now visible in the scene. To attach a sprite to that component, drag the image from the Project window into the inspector.
If you want to take your panel user experience to the next level, you can even attach a script to the component that controls its behavior based on custom logic. This means you have complete control over how your panel looks and behaves.
Now, you can start adding your custom panel components children. You can take inspiration from existing panels.
Switch between panels
You can attach a button to the current panel to switch between panels. To make that button switch to the next one, you can add a runtime event under the OnClick
header by clicking on the plus icon. Now, you must drag and drop the canvas into the GameObject
placeholder.
Now you can attach a custom function available in the game, which is true
in this case, that accepts a GameObject.
The game object represents the next panel. This function will display the next panel. Similarly, to hide the current panel, drag and drop the current panel as an argument to setFalse
.
Initial State
When you first open the canvas, all of the values for the game's initial states are present there. You can control the game variables' initial values under the inspector's canvas script. The initial states are important because they set the starting point for the player's actions. If you want to change how the game plays, you can do so by altering the initial states.
Create A New Car
Creating a new car is relatively easy. To create a new one, copy and paste a car prefab, and change its objects under the Hierarchy tab. To enhance your car's performance, open the Body
object in the Hierarchy tab. Then select any of these components from the list to customize them to your car body.
To change the car body image, Click the VehicleSprite
object in the Hierarchy tab. Now you need to specify a car image.
Now, you need to change the bounding volume of the car body collider. To do so, click the Collider
object in the Hierarchy tab. Now you need to click edit collider in the inspector to match the car sprite recently added.
The Dead trigger component controls when the lost state is set. If the top of the car touches the ground,
you will lose the game.
Similarly, you can customize the remaining components of the car. After changing all these properties to your liking, your new vehicle is ready to be used in your game!
Top comments (5)
Really interesting and in-depth post. Nice work! :)
Thanks for your feedback; it is much appreciated.
nice work!
Thanks!