Share on facebook
Share on twitter
Share on linkedin

NFT Game Development – The 2022 Guide

One of the drivers for the recent hype regarding NFTs (non-fungible tokens) comes from these tokens’ dynamic nature. Specifically, NFTs have the potential to represent virtually anything ranging from digital to physical assets. The dynamic element of NFTs provides various use cases, making them attractive assets in several different development areas, one of which is games. However, game development is also one of the most demanding sectors as it’s relatively taxing. To alleviate some of the hardship, we will dive deeper into NFT game development in this article and provide a clear overview of how to create an NFT game quickly. 

Depending on how familiar you are with the blockchain industry, you might already be familiar with NFTs. However, for the uninitiated, we will start this article by explaining NFTs and NFT game development. Following this, we’ll continue by creating a simple NFT game to give you an example of what the process might look like. To help in our development endeavors, we’ll be utilizing the Moralis operating system as this provides a solid foundation for our development needs. 

So, let’s kick off this article with a brief explanation of NFTs and NFT game development! Moreover, are you looking for additional NFT content? If so, you can read up on lazy minting here at NFTCoders for a great tutorial on how to create NFTs for free!  

NFTs and NFT Game Development Explained

NFT is an abbreviation for non-fungible tokens, and they are, as the name suggests, ”non-fungible”. However, what does this actually mean? To answer the question, we need to understand the concept of ”fungibility”.

”Fungible” refers to an asset being interchangeable, which means assets are of the same type and value. This suggests that one asset can be traded for another as they share the same properties. An example within the crypto industry is Ether. One Ether is valued exactly the same as another Ether, meaning that it is possible to swap one for the other without any compensation.

NFTs are instead ”non-fungible”, meaning they aren’t of the same type and value. An example of a non-fungible asset from traditional economics is property. All houses are different, meaning that they aren’t directly interchangeable. Similarly, NFTs are simple tokens that lack fungibility elements. In turn, they are unique and irreplaceable. 

Moreover, their uniqueness is what makes them valuable, as they can represent ownership of both digital and physical assets. Further, this also makes them flexible, meaning that there are numerous use cases for these tokens. For example, it is possible to integrate them when developing games. However, what is NFT game development? 

Well, the answer to this question is pretty simple; NFT game development revolves around creating games based on NFTs. As NFTs can represent anything, they can act as avatars, weapons, armor, and other items within a game. As such, it becomes possible to create completely unique elements and items, providing an exciting game experience. 

However, as a relatively new development sector, it is uncharted territory for many. So, to make life easier for you, we’re going to show you how to create an NFT game quickly! 

NFT Game Development – How to Create an NFT Game Quickly

So, with a better understating of what NFTs are and what NFT game development is all about, we can move on to the main topic of this article. In this section, we’ll take you through the process of how to create your very own NFT game quickly.

To exemplify, we’ll be making a game based on Aavegotchi NFTs, and we’re going to keep it simple. We’re going to create a 2D environment where avatars can move around freely, and the avatars, in this case, will be represented by Aavegotchi NFTs. However, even though this tutorial is about an Aavegotchi NFT game, the logic will remain the same for other NFTs alike.

To aid in the development process, we will be utilizing the Moralis platform. With Moralis, we have access to an already existing backend infrastructure which allows us to develop dApps and NFT games much quicker. In fact, according to Polygon, it’s possible to reduce the average development time by around 87%, making this a given in most situations! Moreover, in NFT game development, we need two essential features; 1) real-time alerts and 2) the users’ NFT balances, which the Moralis platform provides easy access to. 

To make it more understandable, we’ll break down the process into three sections: 1) setting up a Moralis server and database, 2) frontend development, and 3) backend development. Moreover, at the end of the tutorial, we’ll present a link to the GitHub page for the complete game so that you have full access to the code. 

So, with no further delay, let’s dig deeper and take a closer look at how to build an NFT game quickly! 

NFT Game Development: Part 1 – Moralis Server

First things first, we need a server and database before we create an NFT game. To get these components, we need a Moralis account. As such, the first step is to create a Moralis account, which only takes a couple of seconds and is completely free. With a Moralis account at our disposal, we can continue by creating our own server.  

To create a server, you can log in to your account and navigate to the ”Servers” tab at the far left of the Moralis interface. After this, you can go ahead and create a server by clicking on ”+ Create a new Server” at the top right of the admin panel. 

Once you click this button, a drop-down menu will appear with three alternatives. We’re going to pick a testnet server for this tutorial as we aren’t planning on launching the game on a blockchains’ mainnet. However, once either alternative is chosen, you can go ahead and enter the required information and simply click on ”Add Instance” to spin up the server. 

Now, with a server at hand, we also have access to the server’s database. To access the database, click on the ”Dashboard” button for the server in question. Clicking this button will take you to the following page: 

As you can see, we have a few options here, such as ”Browser”, ”Webhooks”, etc. In this menu, we’ll be able to access all sorts of information once users authenticate themselves. For example, once a user signs in with their Web3 wallet, we have the opportunity to access everything from their crypto addresses to their tokens. As such, we can view their NFTs and use this information when developing the game to, for example, display their NFTs as in-game avatars.

NFT Game Development: Part 2 – Frontend

The NFT game application that we’re about to create quickly will consist of two main files, ”index.html” and ”cloud.js”. This section will delve deeper into the ”index.html” file, which covers all the frontend logic.

To begin with, we’re going to import the Moralis SDK (software development kit) and then initialize Moralis. Following this, we’ll also take a closer look at the necessary functions needed to make the game function properly. Nonetheless, let’s begin by importing the Moralis SDK and initializing Moralis. 

The Moralis SDK is an essential part of this tutorial, as importing this kit will allow us to access and utilize some of the libraries and valuable tools of the platform. So, to import the SDK, we need to input the following at the top of our ”index.html” file: 

<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js></script>
<script src="https://npmcdn.com/moralis@0.0.6/dist/moralis.js"></script>
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js"></script>

As you can see from the code above, some additional components are imported alike to make the development of this game more accessible. With the SDK imported, we can continue by initializing Moralis. To do so, you’ll need to input the following into the code:

Moralis.initialize(”applicationID"); 
Moralis.serverURL = ”serverURL”;

However, in the snippets above, you’ll need to input the application ID and server URL from your own server. You can find this information by clicking on the ”View Details” button for the server in question.

With Moralis initialized, we can move on to the next part of the file, where we implement a function for authenticating users with MetaMask

”login()” Function

The first function of the ”index.html” file is ”login()”. The function is relatively straightforward, and we also use the ”Moralis.Web3.authenticate()” function, allowing us to authenticate users easily. Once users authenticate themselves, they’ll be automatically added to our database. This provides us with access to all sorts of information vital for making this game work. Nonetheless, this is what the function looks like: 

async function login(){
   console.log("login clicked");
   var user = await Moralis.Web3.authenticate();
   if(user){
    console.log(user);
   }
  }

Graphics – The ”preload()” and ”ping()” Functions

Next up, we’re going to take a closer look at adding the graphics to the game. As you might have noticed initially, we also added the Phaser game library when importing the Moralis SDK. This is an excellent library for adding simple graphics to any game, and to do so, we need to initialize the Phaser library through the following code:

var config = {
      type: Phaser.AUTO,
      width: 1200,
      height: 700,
      scene: {
        preload: preload,
        create: create,
        update: update
      },
      physics: {
        default: 'arcade',
        arcade: { debug: true }
      }
    };

Moreover, to show you what it might look like, this is a print screen from the game: 

With Phaser initialized, we must add a couple of functions to go with it, and let’s begin with ”preload()”. All games have something known as a ”game lifecycle”, where the game loads a bunch of different things. So, in our case, we’re simply going to load the background. To do this, we’re going to upload an image through the ”preload()” function: 

function preload ()
    {
      ping();
      context = this;
      context.load.image('background', 'bg.jpg');
    }

As you can see from the code above, we are only preloading the background as this is all we need to do. However, we also initiate ”preload()” by calling an additional function, which is called ”ping()”. 

The ”ping()” function starts pinging the game’s server. The reason for this is allowing the server to know which players are playing the game at any given moment. As such, a ping is sent to the server every second, and this is what the function looks like: 

async function ping(){
      setTimeout(ping,1000)
      await Moralis.Cloud.run("ping");
    }

Controls and Subscription – The ”create()”, ”update()”, and ”drawState()” Functions

With all the graphics for the game setup, we require some controls and a subscription to the ”GameState”. To add controls and the subscription, we’re going to add the ”create()” function:

”create()”: 

async function create ()
    {
      this.wKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
      this.aKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
      this.sKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
      this.dKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);

      // wait for game state update
      let query = new Moralis.Query("GameState");
      let subscription = await query.subscribe();
      query.equalTo("stateType", "globalGameState");
      subscription.on('update', (object) => {
        state = object.get("state");
        console.log(state)
      });

First, we add the controls for the game, allowing players to move around with their keys. After this, we also add the subscription to the GameState. The GameState tells us other players’ locations on the map. We can find the “GameState” tab in our database, and it simply ensures that all clients are updated as soon as anything changes. As such, every client is alerted every time someone else moves on the map. 

With the subscription and the controls added to our game, the next part is to create the ”update()” function. This function listens to what keys the players press and then sends a request to the Moralis server to move their character in the game. We will not include the complete function as it is quite extensive; however, this is a short part for moving the avatar upwards: 

”update()”: 

async function  update ()
    {
      cursors = this.input.keyboard.createCursorKeys();
      const params =  { cursors: cursors };

      if (this.wKey.isDown) {

        if(!buttonsLocked["up"]){
          console.log('W is pressed');

          buttonsLocked["up"]=true;
          await Moralis.Cloud.run("move", {direction:"up"});
          buttonsLocked["up"]=false;
        }

Finally, we also have to create the ”drawState()” function, consisting of two parts. First, if the player just logged in, the function fetches the player’s SVG from the Moralis server, which the server acquires directly from the blockchain. However, how this works will be detailed in the application’s backend. Second, if it isn’t a new player, this function simply moves around the avatar within the game environment: 

”drawState()”: 

function drawState(){

      for (let userId in state) {

        // new player that we haven't seen - need to load image, create sprite
        if(!sprites[userId]){

          sprites[userId] = {loading:true}

          const svgBlob = new Blob([state[userId].svg], {type:"image/svg+xml;charset=utf-8"})
          const url = URL.createObjectURL(svgBlob)

          context.load.image('player'+userId,url).on('filecomplete', function(){
            if(sprites[userId].loading)
            {
              sprites[userId].loading = false
              setTimeout(function(){ //had to add this delay for images to always show
                sprites[userId] =  context.physics.add.image(state[userId].x, state[userId].y, 'player'+userId).setScale(0.5,0.5).setOrigin(0,0);
              },1000)
            }
          }, context);
          context.load.start()
        }
        // existing player - just move around existing sprite
        else{

          if(sprites[userId].x<state[userId].x)
            sprites[userId].x+=5;

          else if(sprites[userId].x>state[userId].x)
              sprites[userId].x-=5;



          if(sprites[userId].y<state[userId].y)
              sprites[userId].y+=5;

          else if(sprites[userId].y>state[userId].y)
              sprites[userId].y-=5;

        }
      }

Now, that’s it for the frontend of this simple NFT game; however, this is only the first half, and next up, we’re going to take a closer look at the ”cloud.js” file where we find the backend. 

NFT Game Development: Part 3 – Backend

With the frontend explained, we can move on to the ”cloud.js” file, which takes care of the backend code. We will in this section go over the three main functions of the backend, which are: ”move”, ”persistState()”, and ”ping”. However, these functions, in turn, call other functions, but we’ll cover those as we go along. 

“move” Function

The first function is ”move”, which the frontend can call. Once a user moves within the game by pressing a key, the frontend registers this and calls the function. As such, the ”move” function registers the direction in which the players want to go and then, in turn, calls the ”updateState()” function:

Moralis.Cloud.define("move", async (request) => {
  logger.info("Move called!");
  logger.info(JSON.stringify(request));

  const userId = request.user.get("username");

  // create and write to DB new version of the state
  const direction = request.params.direction;
  updateState(userId,direction);
  await persistState();
});

The ”updateState()” function takes two arguments, the user ID and a direction. This function then simply moves the avatar depending on these parameters, and this is what the ”updateState()” function looks like:

function updateState(userId,direction){

  logger.info("updateState ", userId, "direction ", direction);

  // TODO - add server-side logic to restrict movements, add pickup items etc

  if(direction == "up"){
    state[userId].y-=5;
  }
  else if(direction == "down"){
    state[userId].y+=5;
  }
  else if(direction == "left"){
    state[userId].x-=5;
  }
  else if(direction == "right"){
    state[userId].x+=5;
  }


}

”persistState()” function

The second function is ”persistState()”, which saves the GameState to the database. Once it saves the state, all clients will be updated, which is how all clients communicate in real-time. It is a simple solution – in combination with the subscription from the frontend code – to allow for real-time communication between multiple clients. Here is the complete code for this function: 

async function persistState(){

  var gameState = await stateDBReference();

  // upload the state
  gameState.set("state",state)
  await gameState.save(null,{useMasterKey:true})
}

“ping” Function

Finally, we have the ”ping” function. The ”ping” function is relatively straightforward as the function simply checks whenever a user pings the server and then updates the state of the game. Here is the first part of the function: 

Moralis.Cloud.define("ping", async (request) => {

  // either add the user to current game state, or update last ping
  const userId = request.user.get("username");
  const ethAddress = request.user.get("authData").moralisEth.id;

  if(!state[userId])
  {
    state[userId] = {x:0,y:0,lastPing:Date.now(), displayAddress: ethAddress}
  }
  else{
    state[userId].lastPing = Date.now()
  }

Moreover, this function additionally fetches the players’ SVGs. Initially, we query the users’ NFTs which we then use to acquire their SVGs directly from the blockchain. Moreover, as you can see from the following code, this function calls an additional function called ”getSVGString()”:

  if(!state[userId].svg){
    //get aavegochi owned
    const EthNFTOwners = Moralis.Object.extend("EthNFTOwners");
    const query = new Moralis.Query(EthNFTOwners);
    query.equalTo("owner_of", ethAddress);
    query.equalTo("token_address", "0x07543db60f19b9b48a69a7435b5648b46d4bb58e");
    const results = await query.find();
    if(results.length>0){
      const token_id = results[0].get("token_id")
      const svg = await getSVGString(token_id);
      state[userId].svg = svg;
    }
  }

  persistState();

});

The ”getSVGString()” function might look a bit confusing in the GitHub code as it is quite extensive; however, the long part of the code is simply the ABI fetched from the Aavegotchi contracts, which we merely copied and pasted into the code. Nonetheless, this is what the function looks like: 

async function getSVGString(tokenId){

  let web3 = Moralis.web3ByChain("0x2a"); // kovan
  const CONTRACT_ADDRESS = "0x07543dB60F19b9B48A69a7435B5648b46d4Bb58E";

    const CONTRACT_ABI = [{INSERT ABI}];

    const contract = new web3.eth.Contract(CONTRACT_ABI,CONTRACT_ADDRESS);
    const svgString = await contract.methods.getAavegotchiSvg(tokenId).call();

    return svgString;


}

Summary of the 2022 Guide to NFT Game Development

Now that’s it! This is essentially all we need to create a fully functioning NFT game quickly. However, if questions remain related to the code itself, we’re going to link to the GitHub page for this NFT game.

Moreover, if you have further interest in NFTs, make sure to read additional articles here at NFTCoders to get the most significant and hottest tips on NFT development! A great start is the following tutorial on how to build an NFT marketplace, an article that you don’t want to miss! 

January 17, 2022
Become a Moralis Mage
Get the latest information about Moralis Web3 in your email
Get Loved BY
the Web3 community

Related Articles