lesson-5_ボスとのバトルフィールドを作ろう
💥 ボスと戦う
前回のレッスンで、シナリオの1と2を実装しました。
✅ シナリオ 1. ユーザーが Web アプリケーションにログインしていない場合
👉 WEBアプリ上に、"Connect Wallet to Get Started" ボタンを表示します。
✅ シナリオ 2. ユーザーは Web アプリケーションにログインしており、かつ NFT キャラクターを持っていない場合
👉 WEBアプリ上に、SelectCharacter
コンポーネントを表示します。
これから、ボスとのバトルフィールド「Arena
」を作成し、シナリオ3を実装していきます。
🔥 シナリオ 3. ユーザーは Web アプリケーションにログインしており、かつ NFT キャラクターを持っている場合
👉 WEBアプリ上に、「Arena Component」を表示します。
- 「Arena Component」は、プレイヤーがボスと戦う場所です。
まず、ターミナル上でclient/src/Components/Arena
フォルダに移動して、index.js
という名前の新しいファイルを作成しましょう。
Arena
フォルダにはArena.css
ファイルが含まれています。
Webアプリケーションの構築が完了したら、CSSのスタイリングを楽しんでください ✨
🏰 Arena
を作成する
次に、client/src/Components/Arena/index.js
を開き、下記のコードを貼り付けましょう。
import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import { CONTRACT_ADDRESS, transformCharacterData } from "../../constants";
import myEpicGame from "../../utils/MyEpicGame.json";
import "./Arena.css";
// フロントエンドにNFTキャラクターを表示するため、characterNFTのメタデータを渡します。
const Arena = ({ characterNFT }) => {
// コントラクトのデータを保有する状態変数を初期化します。
const [gameContract, setGameContract] = useState(null);
// ページがロードされると下記が実行されます。
useEffect(() => {
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const gameContract = new ethers.Contract(
CONTRACT_ADDRESS,
myEpicGame.abi,
signer
);
setGameContract(gameContract);
} else {
console.log("Ethereum object not found");
}
}, []);
return (
<div className="arena-container">
{/* ボス */}
<p>ボスを表示します。</p>
{/* NFT キャラクター */}
<p>NFT キャラクターを表示します。</p>
</div>
);
};
export default Arena;
Arena
コンポーネント準備ができたので、App.js
に戻って、シナリオ3を実装していきます。
シナリオ 3. ユーザーは Web アプリケーションにログインしており、かつ NFT キャラクターを持っている場合
👉 WEBアプリ上に、「Arena Component」を表示します。
- 「Arena Component」は、プレイヤーがボスと戦う場所です。
まず、Arena
をインポートするため、App.js
の先頭に、下記を追加しましょう。
import Arena from "./Components/Arena";
次に、renderContent
関数を下記のように更新しましょう。
// レンダリングメソッド
const renderContent = () => {
// シナリオ1.
// ユーザーがWEBアプリにログインしていない場合、WEBアプリ上に、"Connect Wallet to Get Started" ボタンを表示します。
if (!currentAccount) {
return (
<div className="connect-wallet-container">
<img src="https://i.imgur.com/TXBQ4cC.png" alt="LUFFY" />
<button
className="cta-button connect-wallet-button"
onClick={connectWalletAction}
>
Connect Wallet to Get Started
</button>
</div>
);
// シナリオ2.
// ユーザーはWEBアプリにログインしており、かつ NFT キャラクターを持っていない場合、WEBアプリ上に、"SelectCharacter Component" を表示します。
} else if (currentAccount && !characterNFT) {
return <SelectCharacter setCharacterNFT={setCharacterNFT} />;
// シナリオ3.
// ユーザーはWEBアプリにログインしており、かつ NFT キャラクターを持っている場合、
// Arena でボスと戦います。
} else if (currentAccount && characterNFT) {
return <Arena characterNFT={characterNFT} />;
}
};
Webアプリケーションを更新すると、「アリーナ」コンポーネントに直接移 動します。
フロントエンドが下記のように表示されていれば、ここまでの実装は成功です。
😈 スマートコントラクトからボスを取得する
それでは、Arena
コンポーネントに、ボスのデータを取得していきましょう。
SelectCharacter
コンポーネントで、NFTキャラクターのデータを取得した方法と同じ要領で進めていきます。
まず、Arena
コンポーネントの中のconst [gameContract, setGameContract] = useState(null);
の直下に下記を追記してください。
// ボスのメタデータを保存する状態変数を初期化します。
const [boss, setBoss] = useState(null);
// ページがロードされると下記が実行されます。
useEffect(() => {
// コントラクトからボスのメタデータを取得し、bossを設定する非同期関数 fetchBoss を設定します。
const fetchBoss = async () => {
const bossTxn = await gameContract.getBigBoss();
console.log("Boss:", bossTxn);
setBoss(transformCharacterData(bossTxn));
};
if (gameContract) {
// コントラクトの準備ができたら、ボスのメタデータを取得します。
fetchBoss();
}
}, [gameContract]);
上記の実装が完了したら、Webアプリケーション上でConsoleを開いて、ボスのデータが読み込まれていることを確認しましょう。