Mapping Scenes

Keep track of current scene

Now let’s move the spotlight on the Duck game! We want to be able to substitute the Duck with the user’s selected NFT, so let’s keep this in mind. To switch to the game, we should split the MainMenu into two main states. The first state will be the MainMenu we had until now. The second one will be the Game itself. To switch between these two, we will use a state inside MainMenu component to contain the current state:

const [menuPage, setMenuPage] = useState('MainMenu');

Change current scene

Initially, it has the 'MainMenu' value and we will switch it to 'Game' using a PlayGame button inside MainMenu. This will help us moving forward to the game using the selected NFT. This button will need an event handler, too. Initially, we want the PlayGame button’s onClick to console.log() the selected NFT which is going to pass through to the game and saving it using localstorage.

const handlePlayGame = (id) => {
  console.log('selectedNFT', id);
  localStorage.setItem('selectedNFT', id);
  setMenuPage('Game');
};

We will insert the button right after the MainMenu NFTs interface.

<button className="Connect" disabled={selectedNFT == ''} onClick={() => handlePlayGame(selectedNFT)}>
  {`Play with NFT#${selectedNFT}`}
</button>

Initialize Play Game Component

Now we are set. Let’s create a PlayGame component inside components directory:

export const PlayGame = (props) =>{
  return(
    <div>Game State</div>
  )
}

Map the scene using a dictionary

At this point, we have a constant menuPage which memorizes the state. Let’s use it to literally map these two states. As said, we will use a dictionary and name it menuPageMapping that should look like this:

const menuPageMapping = {
  MainMenu: (
    <div>
      <header className="App-header">
        <h1>Integrate NFTs Into GameFi</h1>
        <h6>{`Current user address: ${userAddress}`}</h6>
        {!hasRespondedNFTs && <h1> Loading NFTs... </h1>}
        {hasRespondedNFTs && NFTsOwned.length == 0 && <h1> No NFTs available </h1>}
        {hasRespondedNFTs && NFTsOwned.length > 0 && (
          <div>
            <h2>Pick your NFT!</h2>
            {NFTsOwned.map((nftId) => (
              <span id={`nft${nftId}`} key={nftId} className="characterContainer">
                <img
                  className="characterImg"
                  src={`https://stacksgamefi.mypinata.cloud/ipfs/QmNz74TN66hgi9X4wZ1ch9hXKxaywG5soEQPMfDqEMLVsd/${nftId}.png`}
                  alt={`character ${nftId}`}
                  onClick={() => handleClickNFT(nftId)}
                ></img>
                {`NFT#${nftId}`}
              </span>
            ))}
          </div>
        )}
        <br />
        <br />
        <button className="Connect" disabled={selectedNFT == ''} onClick={() => handlePlayGame(selectedNFT)}>
          {`Play with NFT#${selectedNFT}`}
        </button>
        <br />
        <button className="Connect" onClick={disconnect}>
          Disconnect Wallet
        </button>
        <br />
        <a className="App-link" href="<https://stacksdegens.com/>" target="_blank">
          Build by Stacks Degens
        </a>
      </header>
    </div>
  ),
  Game: <PlayGame menuPage={menuPage} setMenuPage={setMenuPage} />,
};

As it is clear to observe, for the MainMenu state it returns the content we used to return until now inside MainMenu, but for the Game it returns the PlayGame component. Let’s make menuPageMapping useful and return it instead of the previous returned content:

return menuPageMapping[menuPage];

Now, when the user clicks the Play button, you can see the state was switched and now we can see the message from the <div> returned inside PlayGame component previously implemented.

This is the branch with the changes done:

You can check the exact changes in this commit referring to them

Last updated