在這個教程裡,我們将學習如何開發一個基于ERC721的妖怪戰鬥小遊戲,它類似于去中心化版本的Pokémon遊戲。教程中使用的開發工具為Truffle,開發語言為Solidity,第三方庫為OpenZeppelin。
用你熟悉的開發語言學習以太坊DApp開發: Java | Php Python .Net / C# Golang Node.JS Flutter / Dart
1、建立ERC721版本的Pokémon遊戲項目
我們使用Truffle開發架構建立這個基于ERC721的Pokemon遊戲項目。
首先建立一個新的檔案夾,然後初始化Truffle項目:
~$ mkdir ethermon
~$ cd ethermon/
~/ethermon$ truffle init
2、使用OpenZeppelin成熟的ERC721合約實作代碼
為了使用OpenZepplin,我們需要利用npm導入這個庫。讓我們先初始化npm,然後擷取正确版本的OpenZeppelin。我們使用的是2.5.0版本的OpenZeppelin,是以你需要使用0.5.5版本的Solidity編譯器:
~/ethermon$ npm init
~/ethermom$ npm install @openzeppelin/[email protected] --save
3、擴充OpenZeppelin的ERC721合約
在我們的contracts/檔案夾,先建立一個新的檔案ethermon.sol。要使用OpenZeppelin代碼中的功能,我們需要引入并擴充ERC721.sol。
下面的代碼展示了目前為止Ethermon.sol的内容:
pragma solidity ^0.5.5;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Ethermon is ERC721 {
}
首先使用
truffle compile
檢查并確定我們的合約可以正确編譯。接下來,我們編寫遷移腳本以便将合約部署到本地區塊鍊。在migrations/目錄
建立一個新的遷移檔案2_deploy_contracts.js,内容如下:
const Ethermon = artifacts.require("Ethermon");
module.exports = function(deployer) {
deployer.deploy(Ethermon);
};
確定你的truffle-config.js的配置可以正确連接配接本地區塊鍊,你可以使用
truffle test
先測試一下。
4、編寫ERC721版Pokemon的實作邏輯
我們需要Ethermon合約實作如下功能:
- 建立新的妖怪
- 将妖怪配置設定給主人
- 主人可以安排妖怪戰鬥
讓我們先實作第一個功能。我們需要在Ethermon合約中用一個數組儲存所有的妖怪。需要儲存的妖怪相關的資料包括名字、級别等。是以我們使用一個結構。
到目前為止Ethermon合約的代碼如下所示:
pragma solidity ^0.5.5;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Ethermon is ERC721 {
struct Monster {
string name;
uint level;
}
Monster[] public monsters;
address public gameOwner;
constructor() public {
gameOwner = msg.sender;
}
function createNewMonster(string memory _name, address _to) public {
require(msg.sender == gameOwner, "Only game owner can create new monsters");
uint id = monsters.length;
monsters.push(Monster(_name, 1));
_safeMint(_to, id);
}
}
Monster結構在第7行定義,數組在第12行定義。我們也添加了一個gameOwner變量來儲存Ethermon合約的部署賬戶。第19行開始是createNewMonster()函數的實作,該函數負責建立新的妖怪。
首先,它會檢查這個函數是否是由合約的部署賬号調用的。然後為新妖怪生成一個ID,并将新妖怪存入數組,最後使用_safeMint()函數将這個新建立的妖怪配置設定給其主人。
_safeMint() 是我們繼承的ERC721合約中實作的函數。它可以安全地将一個ID配置設定給指定的賬号,在配置設定之前會檢查ID是否已經存在。
好了,現在我們已經可以建立新的妖怪并将其配置設定給指定的賬号。該進行第三步了:戰鬥邏輯。
5、ERC721版Pokemon遊戲的戰鬥邏輯實作
正如之前所述,我們的戰鬥邏輯決定了一個妖怪可以晉升多少等級。較高等級的妖怪可以獲勝并升兩級,失敗的妖怪升一級。如果兩個妖怪處于同一等級,那麼進攻者獲勝。下面的代碼展示了合約中戰鬥邏輯的實作:
pragma solidity ^0.5.5;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Ethermon is ERC721 {
struct Monster {
string name;
uint level;
}
Monster[] public monsters;
address public gameOwner;
constructor() public {
gameOwner = msg.sender;
}
function battle(uint _attackingMonster, uint _defendingMonster) public {
Monster storage attacker = monsters[_attackingMonster];
Monster storage defender = monsters[_defendingMonster];
if (attacker.level >= defender.level) {
attacker.level += 2;
defender.level += 1;
}
else{
attacker.level += 1;
attacker.level += 2;
}
}
function createNewMonster(string memory _name, address _to) public {
require(msg.sender == gameOwner, "Only game owner can create new monsters");
uint id = monsters.length;
monsters.push(Monster(_name, 1));
_safeMint(_to, id);
}
}
第19行開始展示了妖怪的戰鬥邏輯。目前任何賬号都可以調用battle()方法。然而我們需要對此加以限制,隻允許發起進攻的妖怪的主人調用該方法。為此,我們可以添加一個修飾符,該修飾符利用ERC721.sol合約中的ownerOf()函數來檢查調用賬号。下面的代碼展示了這部分的修改:
pragma solidity ^0.5.5;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Ethermon is ERC721 {
struct Monster {
string name;
uint level;
}
Monster[] public monsters;
address public gameOwner;
constructor() public {
gameOwner = msg.sender;
}
modifier onlyOwnerOf(uint _monsterId) {
require(ownerOf(_monsterId) == msg.sender, "Must be owner of monster to battle");
_;
}
function battle(uint _attackingMonster, uint _defendingMonster) public onlyOwnerOf(_attackingMonster) {
Monster storage attacker = monsters[_attackingMonster];
Monster storage defender = monsters[_defendingMonster];
if (attacker.level >= defender.level) {
attacker.level += 2;
defender.level += 1;
}
else{
attacker.level += 1;
attacker.level += 2;
}
}
function createNewMonster(string memory _name, address _to) public {
require(msg.sender == gameOwner, "Only game owner can create new monsters");
uint id = monsters.length;
monsters.push(Monster(_name, 1));
_safeMint(_to, id);
}
}
好了!我們完成了一個ERC721版本的類似Pokemon的妖怪戰鬥遊戲,雖然還很粗糙!
原文連結:
ERC721仿Pokémon遊戲開發 — 彙智網