4

使用 Solidity、Web3 和 Vue.js 创建区块链游戏

 2 years ago
source link: https://xie.infoq.cn/article/5705d51884aeaefac253016c6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Solidity

对于 Solidity 的初学者,可以关注 buildspace 上的教程。



这里智能合约需要完成用户角色创建,铸造选择的角色,然后用它来对抗 BOSS。

打开一个终端并使用以下命令在项目文件夹中创建一个文件夹:



mkdir vue-game-dapp



进入创建的项目文件夹:



cd vue-game-dapp



运行以下命令来初始化项目信息:



npm init



填写项目信息,并安装相关依赖:



npm install @openzeppelin/contracts --savenpm install hardhat chai @nomiclabs/hardhat-waffle @nomiclabs/hardhat-ethers ethers ethereum-waffle --save-dev 



现在编写智能合约,在项目根目录下创建智能合约文件夹 contracts



mkdir contracts



contracts 文件夹中创建一个新文件并将其命名为 EpicGame.sol,并在其中写入以下代码:



// SPDX-License-Identifier: MITpragma solidity >=0.4.22 <0.9.0;



这始终是智能合约文件中的第一行,用来指定 solidity 的版本。现在来编写代码制作完整的游戏智能合约 EpicGame



// SPDX-License-Identifier: MITpragma solidity >=0.4.22 <0.9.0;import "@openzeppelin/contracts/token/ERC721/ERC721.sol";import "@openzeppelin/contracts/utils/Counters.sol";import "@openzeppelin/contracts/utils/Strings.sol";import "./libraries/Base64.sol";import "hardhat/console.sol";contract EpicGame is ERC721 {    struct CharacterAttributes {        uint256 characterIndex;        string name;        string imageURI;        uint256 hp;        uint256 maxHp;        uint256 attackDamage;    }    struct BigBoss {        string name;        string imageURI;        uint256 hp;        uint256 maxHp;        uint256 attackDamage;    }    BigBoss public bigBoss;    using Counters for Counters.Counter;    Counters.Counter private _tokenIds;    CharacterAttributes[] defaultCharacters;    mapping(uint256 => CharacterAttributes) public nftHolderAttributes;    mapping(address => uint256) public nftHolders;    event CharacterNFTMinted(        address sender,        uint256 tokenId,        uint256 characterIndex    );    event AttackComplete(uint256 newBossHp, uint256 newPlayerHp);    constructor(        string[] memory characterNames,        string[] memory characterImageURIs,        uint256[] memory characterHp,        uint256[] memory characterAttackDmg,        string memory bossName,        string memory bossImageURI,        uint256 bossHp,        uint256 bossAttackDamage    ) ERC721("Heroes", "HERO") {        for (uint256 i = 0; i < characterNames.length; i += 1) {            defaultCharacters.push(                CharacterAttributes({                    characterIndex: i,                    name: characterNames[i],                    imageURI: characterImageURIs[i],                    hp: characterHp[i],                    maxHp: characterHp[i],                    attackDamage: characterAttackDmg[i]                })            );            CharacterAttributes memory c = defaultCharacters[i];            console.log(                "Done initializing %s w/ HP %s, img %s",                c.name,                c.hp,                c.imageURI            );        }        bigBoss = BigBoss({            name: bossName,            imageURI: bossImageURI,            hp: bossHp,            maxHp: bossHp,            attackDamage: bossAttackDamage        });        console.log(            "Done initializing boss %s w/ HP %s, img %s",            bigBoss.name,            bigBoss.hp,            bigBoss.imageURI        );        _tokenIds.increment();    }    function mintCharacterNFT(uint256 _characterIndex) external {        uint256 newItemId = _tokenIds.current();        _safeMint(msg.sender, newItemId);        nftHolderAttributes[newItemId] = CharacterAttributes({            characterIndex: _characterIndex,            name: defaultCharacters[_characterIndex].name,            imageURI: defaultCharacters[_characterIndex].imageURI,            hp: defaultCharacters[_characterIndex].hp,            maxHp: defaultCharacters[_characterIndex].hp,            attackDamage: defaultCharacters[_characterIndex].attackDamage        });        console.log(            "Minted NFT w/ tokenId %s and characterIndex %s",            newItemId,            _characterIndex        );        nftHolders[msg.sender] = newItemId;        _tokenIds.increment();        emit CharacterNFTMinted(msg.sender, newItemId, _characterIndex);    }    function attackBoss() public {        uint256 nftTokenIdOfPlayer = nftHolders[msg.sender];        CharacterAttributes storage player = nftHolderAttributes[            nftTokenIdOfPlayer        ];        console.log(            "\nPlayer w/ character %s about to attack. Has %s HP and %s AD",            player.name,            player.hp,            player.attackDamage        );        console.log(            "Boss %s has %s HP and %s AD",            bigBoss.name,            bigBoss.hp,            bigBoss.attackDamage        );        require(player.hp > 0, "Error: character must have HP to attack boss.");        require(bigBoss.hp > 0, "Error: boss must have HP to attack boss.");        if (bigBoss.hp < player.attackDamage) {            bigBoss.hp = 0;        } else {            bigBoss.hp = bigBoss.hp - player.attackDamage;        }        if (player.hp < bigBoss.attackDamage) {            player.hp = 0;        } else {            player.hp = player.hp - bigBoss.attackDamage;        }        console.log("Boss attacked player. New player hp: %s\n", player.hp);        emit AttackComplete(bigBoss.hp, player.hp);    }    function checkIfUserHasNFT()        public        view        returns (CharacterAttributes memory)    {        uint256 userNftTokenId = nftHolders[msg.sender];        if (userNftTokenId > 0) {            return nftHolderAttributes[userNftTokenId];        } else {            CharacterAttributes memory emptyStruct;            return emptyStruct;        }    }    function getAllDefaultCharacters()        public        view        returns (CharacterAttributes[] memory)    {        return defaultCharacters;    }    function getBigBoss() public view returns (BigBoss memory) {        return bigBoss;    }    function tokenURI(uint256 _tokenId)        public        view        override        returns (string memory)    {        CharacterAttributes memory charAttributes = nftHolderAttributes[            _tokenId        ];        string memory strHp = Strings.toString(charAttributes.hp);        string memory strMaxHp = Strings.toString(charAttributes.maxHp);        string memory strAttackDamage = Strings.toString(            charAttributes.attackDamage        );        string memory json = Base64.encode(            bytes(                string(                    abi.encodePacked(                        '{"name": "',                        charAttributes.name,                        " -- NFT #: ",                        Strings.toString(_tokenId),                        '", "description": "This is an NFT that lets people play in the game", "image": "',                        charAttributes.imageURI,                        '", "attributes": [ { "trait_type": "Health Points", "value": ',                        strHp,                        ', "max_value":',                        strMaxHp,                        '}, { "trait_type": "Attack Damage", "value": ',                        strAttackDamage,                        "} ]}"                    )                )            )        );        string memory output = string(            abi.encodePacked("data:application/json;base64,", json)        );        return output;    }}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK