不知道多少人和营长一样,在结束一天的工作后,就想瘫在沙发上玩玩游戏,一扫一天的疲惫。不过现在的游戏都越来越氪金了,就像玩家们常说的:不充钱你怎么能变强!!!
但要说氪金,很少有哪个游戏能比得上区块链游戏,因为区块链上的游戏都建立在一笔笔真实的加密货币交易之上。
就拿最火的去中心化游戏加密猫来说,其刚上线时一只加密猫能卖到上千元人民币,最贵的一只竟卖到了 125673 个以太币,在当时约合人民币 2.6 亿元(太可怕了)。
当时最贵的一只加密猫
不禁让人直呼:玩不起,玩不起。
玩不起又想玩怎么办?
手把手开发一款区块链游戏,不就OK了,何况又那么简单,10分钟就够了
这是一款怎样的 DApp?
从现在开始,我们将构建一个类似于加密猫的简单 DApp,我们称之为加密毒蛇
你可能会问为什么是蛇呢,但为什么不能是蛇呢?Python 翻译过来也是蛇呀。
在这个 DApp 中,你可以购买毒蛇和养殖毒蛇,应用页面是这样的:
加密毒蛇程序的页面
其功能列表如下:
-
创造毒蛇 – 用户能够通过购买或让两条毒蛇交配来创造新的毒蛇。
-
查看毒蛇的详细信息 – 用户应该能够查看自己拥有的毒蛇的详细信息并进行显示。
创建加密毒蛇,你至少需要用到以下工具
-
智能合约相关:
-
智能合约编程语言 Solidity
-
开源智能合约开发环境 Remix
-
用于调试和测试智能合约的 Metamask
-
前端技术相关:
-
用于与本地以太坊节点进行通信的 js 库 Web3.js
-
构建用户界面的渐进式框架 Vue.js
-
用于创建 vue 项目的 Vue-cli
-
前端框架 Boostrap-vue
此外,你还需要使用 Git 来克隆一些代码模板。
在进行编程之前,这里先假定你已经对以下的知识有了基本的了解。
-
了解智能合约及其编程语言 Solidity 。
-
了解使用 MetaMask 进行智能合约的调试和测试。
-
了解使用 Remix IDE 进行智能合约的编译和部署。
当然了,如果你对这一些知识还有欠缺,也不用担心,本文会详细介绍每一个细节。
深入了解 ERC-721 标准
ERC-721 是一个用来描述如何在以太坊区块链上制造不可替代 token 的标准。满足 ERC-721 标准的每个 token 或其他数字资产都是唯一的,这意味着它不等同于任何其他 token。你可以把它们想象成一种特殊的,独一无二的收藏品。(如果你已了解 ERC-721,可选择跳过这一部分)
ERC-721 标准的接口
根据标准的官方文档,ERC-721 规定了智能合约用以管理、持有和交易唯一 token 必须实现的最小接口:
-
balanceOf(_owner) - 返回特定所有者 _owner 钱包中的 token 余额。
-
ownerOf(_tokenId) - 返回特定 token 所有者的钱包地址。
-
totalSupply() - 返回创建的 token 总数。
-
transfer(_to,_tokenId) - 将 _tokenId 标记的 token 从发送者的钱包转移到指定接收者的钱包。
-
takeOwnership(_tokenId) - 声明给定 ID 的 token 的所有权。
-
approve(_to,_tokenId) - 批准另一个地址来声明给定 ID 的 token 所有权。
此外,它还定义了两个事件:Transfer 和 Approval。当 token 从一个钱包转移到另一个钱包时,会触发转移事件。另一方面,当一个账户批准另一个账户声明他拥有的某个 token 的所有权时,会触发批准事件。
OpenZeppelin 的 ERC-721 token 实现
OpenZeppelin 是一款开源智能合约开发框架,它提供了可重复使用的智能合约模板,包括 ERC-20 和 ERC-721 等标准 token 的实现模板。在这里,我们将导入他们的 ERC-721 token 实现,这样我们就不必从头开始编写它,避免了重复造轮子。
创建智能合约
此 DApp 是基于以太坊平台开发,所以需要使用 Solidity 语言发行 token。
首先,在开源智能合约开发环境 Remix 中,创建一个名为 ViperToken.sol 的新文件并在其中添加以下代码:
1// We will be using Solidity version 0.5.3
2pragma solidity 0.5.3;
3// Importing OpenZeppelin's ERC-721 Implementation
4import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
5// Importing OpenZeppelin's SafeMath Implementation
6import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol";
7
8
9contract ViperToken is ERC721Full {
10 using SafeMath for uint256;
11 // This struct will be used to represent one viper
12 struct Viper {
13 uint8 genes;
14 uint256 matronId;
15 uint256 sireId;
16 }
17
18 // List of existing vipers
19 Viper[] public vipers;
20
21 // Event that will be emitted whenever a new viper is created
22 event Birth(
23 address owner,
24 uint256 viperId,
25 uint256 matronId,
26 uint256 sireId,
27 uint8 genes
28 );
29
30 // Initializing an ERC-721 Token named 'Vipers' with a symbol 'VPR'
31 constructor() ERC721Full("Vipers", "VPR") public {
32 }
33
34 // Fallback function
35 function() external payable {
36 }
37
38 /** @dev Function to determine a viper's characteristics.
39 * @param matron ID of viper's matron (one parent)
40 * @param sire ID of viper's sire (other parent)
41 * @return The viper's genes in the form of uint8
42 */
43 function generateViperGenes(
44 uint256 matron,
45 uint256 sire
46 )
47 internal
48 pure
49 returns (uint8)
50 {
51 return uint8(matron.add(sire)) % 6 + 1;
52 }
53
54 /** @dev Function to create a new viper
55 * @param matron ID of new viper's matron (one parent)
56 * @param sire ID of new viper's sire (other parent)
57 * @param viperOwner Address of new viper's owner
58 * @return The new viper's ID
59 */
60 function createViper(
61 uint256 matron,
62 uint256 sire,
63 address viperOwner
64 )
65 internal
66 returns (uint)
67 {
68 require(viperOwner != address(0));
69 uint8 newGenes = generateViperGenes(matron, sire);
70 Viper memory newViper = Viper({
71 genes: newGenes,
72 matronId: matron,
73 sireId: sire
74 });
75 uint256 newViperId = vipers.push(newViper).sub(1);
76 super._mint(viperOwner, newViperId);
77 emit Birth(
78 viperOwner,
79 newViperId,
80 newViper.matronId,
81 newViper.sireId,
82 newViper.genes
83 );
84 return newViperId;
85 }
86
87 /** @dev Function to allow user to buy a new viper (calls createViper())
88 * @return The new viper's ID
89 */
90 function buyViper() external payable returns (uint256) {
91 require(msg.value == 0.02 ether);
92 return createViper(0, 0, msg.sender);
93 }
94
95 /** @dev Function to breed 2 vipers to create a new one
96 * @param matronId ID of new viper's matron (one parent)
97 * @param sireId ID of new viper's sire (other parent)
98 * @return The new viper's ID
99 */
100 function breedVipers(uint256 matronId, uint256 sireId) external payable returns (uint256) {
101 require(msg.value == 0.05 ether);
102 return createViper(matronId, sireId, msg.sender);
103 }
104
105 /** @dev Function to retrieve a specific viper's details.
106 * @param viperId ID of the viper who's details will be retrieved
107 * @return An array, [viper's ID, viper's genes, matron's ID, sire's ID]
108 */
109 function getViperDetails(uint256 viperId) external view returns (uint256, uint8, uint256, uint256) {
110 Viper storage viper = vipers[viperId];
111 return (viperId, viper.genes, viper.matronId, viper.sireId);
112 }
113
114 /** @dev Function to get a list of owned vipers' IDs
115 * @return A uint array which contains IDs of all owned vipers
116 */
117 function ownedVipers() external view returns(uint256[] memory) {
118 uint256 viperCount = balanceOf(msg.sender);
119 if (viperCount == 0) {
120 return
本文来自,仅作分享,存在异议请联系平台删除。本文观点不代表刺猬财经 - 刺猬区块链资讯站立场。