├── .gitignore
├── .travis.yml
├── README.md
├── package-lock.json
├── package.json
├── public
├── closed-eyes-1@2x.png
├── eyes-10@2x.png
├── eyes-11@2x.png
├── eyes-1@2x.png
├── eyes-2@2x.png
├── eyes-3@2x.png
├── eyes-4@2x.png
├── eyes-5@2x.png
├── eyes-6@2x.png
├── eyes-7@2x.png
├── eyes-8@2x.png
├── eyes-9@2x.png
├── favicon.ico
├── grenade-1@2x.png
├── hand-2-1@2x.png
├── hand1-1@2x.png
├── head-1@2x.png
├── head-2@2x.png
├── head-3@2x.png
├── head-4@2x.png
├── head-5@2x.png
├── head-6@2x.png
├── head-7@2x.png
├── head-8@2x.png
├── index.html
├── left-feet-1@2x.png
├── left-forearm-1@2x.png
├── left-leg-1@2x.png
├── left-thigh-1@2x.png
├── left-upper-arm-1@2x.png
├── logo192.png
├── logo512.png
├── manifest.json
├── mouth-1@2x.png
├── open-mouth-1@2x.png
├── right-feet-1@2x.png
├── right-forearm-1@2x.png
├── right-leg-1@2x.png
├── right-thigh-1@2x.png
├── right-upper-arm-1@2x.png
├── robots.txt
├── shirt-1@2x.png
├── shirt-2@2x.png
├── shirt-3@2x.png
├── shirt-4@2x.png
├── shirt-5@2x.png
├── shirt-6@2x.png
└── torso-1@2x.png
├── src
├── App.js
├── ContractAddress.json
├── ContractAdmin.js
├── MyWeb3.js
├── MyZombie.js
├── Page.js
├── ZombieArmy.js
├── ZombieAttack.js
├── ZombieCard.js
├── ZombieCore.json
├── ZombieDetail.js
├── ZombieMarket.js
├── ZombiePreview.js
├── ZombieSimulator.js
├── ZombieToggler.js
├── index.js
└── static
│ ├── App.css
│ ├── Btn_Register_Normal.png
│ ├── Btn_Register_Over.png
│ ├── Index.css
│ ├── ZombiePreview.css
│ ├── bg.png
│ ├── catlegs.png
│ ├── get_start_btn.png
│ ├── homecard@2x.png
│ ├── index_bg.png
│ ├── learn_more_btn.png
│ ├── lesson-complete-bg.png
│ ├── lesson_number_completed.png
│ ├── lesson_panel_complete.png
│ ├── start_btn.png
│ ├── tester-bg@2x.png
│ ├── walls.jpg
│ └── zombierun.png
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 | # production
11 | /build
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 | webpack.config.js
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 10
4 | install: yarn install
5 | script:
6 | - yarn build
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 区块链收藏游戏:僵尸之谜
2 | [](https://travis-ci.org/Fankouzu/my-crypto-zombie)
3 | ## Demo
4 | https://fankouzu.github.io/my-crypto-zombie/
5 | `需要使用Chrome浏览器和Metamask钱包插件`
6 |
7 |
8 | ## 背景
9 | - 这是一个真正的区块链去中心化游戏
10 | - 下载运行之后就可以连接到以太坊智能合约
11 | - 所有人的游戏数据都保存在区块链上
12 | - 无论是谁,无论在何地运行的游戏都可以连接到相同的数据
13 |
14 | 这个程序是根据 https://cryptozombies.io/ 这里提供的以太坊智能合约课程开发的。并使用了其中的游戏素材,素材版权归 https://cryptozombies.io/ 所有,本项目仅供学习智能合约使用。
15 |
16 |
17 | ## 安装
18 | 使用yarn安装更为有效
19 | `yarn install`
20 | ## 运行
21 | `yarn start`
22 | ## 使用说明
23 | - 这个项目是使用React开发的,运行之后在Chrome浏览器中打开地址 [http://localhost:3000](http://localhost:3000) 请确认你安装了[Metamask插件](https://metamask.io/)
24 | - 项目中已经在[这个文件](https://github.com/Fankouzu/my-crypto-zombie/blob/master/src/ContractAddress.json)中设置好了智能合约的地址,你也可以修改成你自己部署的智能合约合约地址
25 |
26 | ```json
27 | {
28 | "3":"0x1a3cA7AbE6370D33986b2D2aC6F1F9A656f87b4D",
29 | "4":"0xbca6885699Ee9ae9B2255538B5a3EfB3082bE5ac",
30 | "5":"0x6817c8475Ad33Aa86422160C3d1C673c453A76dE",
31 | "42":"0x6817c8475Ad33Aa86422160C3d1C673c453A76dE",
32 | "5777":"0x8b11Af05bdBB4848b59f2C3A5Bf3E2BB24c744fD"
33 | }
34 | ```
35 | - 你可以在Metamask中切换你的以太坊网络,每个网络都有我部署的合约,不同的合约地址就像不同的数据库,拥有着不同的游戏数据,地址前面的数字是网络的ID,其中(1)主网我没有部署,(2)已经废弃,(5777)是本地的Ganache软件的模拟网络,需要安装Ganache
36 | ```
37 | '1': Ethereum Main Network
38 | '2': Morden Test network
39 | '3': Ropsten Test Network
40 | '4': Rinkeby Test Network
41 | '5': Goerli Test Network
42 | '42': Kovan Test Network
43 | '5777': Ganache localhost:7545
44 | ```
45 | ## 智能合约
46 | 学习智能合约开发,请看[我的B站视频](https://www.bilibili.com/video/av75230620)
47 |
48 | 本项目所使用的[智能合约源码在这里](https://github.com/Fankouzu/smart-contract/tree/master/Solidity%20Lesson%2004)
49 |
50 | ipfs上也有 ipfs://QmTYNvirSHmoHtjCbH77Zc64xNLFUpMq2JSjUmQeDgLvhY
51 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-crypto-zombie",
3 | "version": "0.1.0",
4 | "private": false,
5 | "license": "Apache-2.0",
6 | "homepage": "https://fankouzu.github.io/my-crypto-zombie",
7 | "dependencies": {
8 | "@testing-library/jest-dom": "^4.2.4",
9 | "@testing-library/react": "^9.3.2",
10 | "@testing-library/user-event": "^7.1.2",
11 | "gh-pages": "^2.1.1",
12 | "moment": "^2.24.0",
13 | "react": "^16.12.0",
14 | "react-dom": "^16.12.0",
15 | "react-redux": "^7.1.3",
16 | "react-router-dom": "^5.1.2",
17 | "react-scripts": "3.3.0",
18 | "serialize-javascript": "3.1.0",
19 | "web3": "^1.6.0"
20 | },
21 | "scripts": {
22 | "start": "react-scripts start",
23 | "build": "react-scripts build",
24 | "test": "react-scripts test",
25 | "eject": "react-scripts eject",
26 | "predeploy": "yarn build",
27 | "deploy": "gh-pages -d build"
28 | },
29 | "eslintConfig": {
30 | "extends": "react-app"
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/public/closed-eyes-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/closed-eyes-1@2x.png
--------------------------------------------------------------------------------
/public/eyes-10@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-10@2x.png
--------------------------------------------------------------------------------
/public/eyes-11@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-11@2x.png
--------------------------------------------------------------------------------
/public/eyes-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-1@2x.png
--------------------------------------------------------------------------------
/public/eyes-2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-2@2x.png
--------------------------------------------------------------------------------
/public/eyes-3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-3@2x.png
--------------------------------------------------------------------------------
/public/eyes-4@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-4@2x.png
--------------------------------------------------------------------------------
/public/eyes-5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-5@2x.png
--------------------------------------------------------------------------------
/public/eyes-6@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-6@2x.png
--------------------------------------------------------------------------------
/public/eyes-7@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-7@2x.png
--------------------------------------------------------------------------------
/public/eyes-8@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-8@2x.png
--------------------------------------------------------------------------------
/public/eyes-9@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/eyes-9@2x.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/favicon.ico
--------------------------------------------------------------------------------
/public/grenade-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/grenade-1@2x.png
--------------------------------------------------------------------------------
/public/hand-2-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/hand-2-1@2x.png
--------------------------------------------------------------------------------
/public/hand1-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/hand1-1@2x.png
--------------------------------------------------------------------------------
/public/head-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-1@2x.png
--------------------------------------------------------------------------------
/public/head-2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-2@2x.png
--------------------------------------------------------------------------------
/public/head-3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-3@2x.png
--------------------------------------------------------------------------------
/public/head-4@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-4@2x.png
--------------------------------------------------------------------------------
/public/head-5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-5@2x.png
--------------------------------------------------------------------------------
/public/head-6@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-6@2x.png
--------------------------------------------------------------------------------
/public/head-7@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-7@2x.png
--------------------------------------------------------------------------------
/public/head-8@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/head-8@2x.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 | 僵尸之谜 || 迷恋尸 || 区块链收藏游戏
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/public/left-feet-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/left-feet-1@2x.png
--------------------------------------------------------------------------------
/public/left-forearm-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/left-forearm-1@2x.png
--------------------------------------------------------------------------------
/public/left-leg-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/left-leg-1@2x.png
--------------------------------------------------------------------------------
/public/left-thigh-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/left-thigh-1@2x.png
--------------------------------------------------------------------------------
/public/left-upper-arm-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/left-upper-arm-1@2x.png
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "./favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "./logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "./logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/mouth-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/mouth-1@2x.png
--------------------------------------------------------------------------------
/public/open-mouth-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/open-mouth-1@2x.png
--------------------------------------------------------------------------------
/public/right-feet-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/right-feet-1@2x.png
--------------------------------------------------------------------------------
/public/right-forearm-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/right-forearm-1@2x.png
--------------------------------------------------------------------------------
/public/right-leg-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/right-leg-1@2x.png
--------------------------------------------------------------------------------
/public/right-thigh-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/right-thigh-1@2x.png
--------------------------------------------------------------------------------
/public/right-upper-arm-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/right-upper-arm-1@2x.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 |
--------------------------------------------------------------------------------
/public/shirt-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/shirt-1@2x.png
--------------------------------------------------------------------------------
/public/shirt-2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/shirt-2@2x.png
--------------------------------------------------------------------------------
/public/shirt-3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/shirt-3@2x.png
--------------------------------------------------------------------------------
/public/shirt-4@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/shirt-4@2x.png
--------------------------------------------------------------------------------
/public/shirt-5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/shirt-5@2x.png
--------------------------------------------------------------------------------
/public/shirt-6@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/shirt-6@2x.png
--------------------------------------------------------------------------------
/public/torso-1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/public/torso-1@2x.png
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React,{Component,Fragment} from 'react'
2 | import './static/App.css'
3 | import Page from "./Page";
4 | import {
5 | BrowserRouter as Router,
6 | Route,
7 | Link
8 | } from "react-router-dom"
9 |
10 | class App extends Component {
11 | constructor(props) {
12 | super(props);
13 | this.state = { AdminArea:()=>{return()} }
14 | }
15 |
16 | componentDidMount(){
17 | let ethereum = window.ethereum
18 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
19 | ethereum.on('accountsChanged', function (accounts) {
20 | console.log("accountsChanged:"+accounts)
21 | //window.location.reload()
22 | })
23 | ethereum.on('chainChanged', function (chainId) {
24 | console.log("chainChanged:"+chainId)
25 | //window.location.reload()
26 | })
27 | ethereum.on('networkChanged', function (networkVersion) {
28 | console.log("networkChanged:"+networkVersion)
29 | //window.location.reload()
30 | })
31 | }else {
32 | alert('You have to install MetaMask !')
33 | }
34 | }
35 |
36 | render() {
37 | let AdminArea = this.state.AdminArea
38 | return (
39 |
40 |
41 |
42 |
43 |
44 |
45 | -
46 |
49 |
50 | -
51 |
54 |
55 | -
56 |
59 |
60 | -
61 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
77 |
78 |
79 | );
80 | }
81 | }
82 |
83 |
84 | export default App
85 |
--------------------------------------------------------------------------------
/src/ContractAddress.json:
--------------------------------------------------------------------------------
1 | {
2 | "3":"0x1a3cA7AbE6370D33986b2D2aC6F1F9A656f87b4D",
3 | "4":"0xbca6885699Ee9ae9B2255538B5a3EfB3082bE5ac",
4 | "5":"0x6817c8475Ad33Aa86422160C3d1C673c453A76dE",
5 | "42":"0x6817c8475Ad33Aa86422160C3d1C673c453A76dE",
6 | "5777":"0x8b11Af05bdBB4848b59f2C3A5Bf3E2BB24c744fD",
7 | "8285":"0xa14FcCa92Cb160284287dCe12803f2A1949A8E8B"
8 | }
9 |
--------------------------------------------------------------------------------
/src/ContractAdmin.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import MyWeb3 from './MyWeb3'
3 |
4 | class ContractAdmin extends Component {
5 | constructor(props) {
6 | super(props)
7 | this.state = {
8 | contractAddress:'',
9 | contractOwner:'',
10 | ContractName:'',
11 | ContractSymbol:'',
12 | ContractBalance:'',
13 | attackVictoryProbability:70,
14 | levelUpFee:0,
15 | minPrice:0,
16 | tax:0,
17 | zombiePrice:0
18 | }
19 | this.inputAttackVictoryProbability = this.inputAttackVictoryProbability.bind(this)
20 | this.setAttackVictoryProbability = this.setAttackVictoryProbability.bind(this)
21 | this.inputLevelUpFee = this.inputLevelUpFee.bind(this)
22 | this.setLevelUpFee = this.setLevelUpFee.bind(this)
23 | this.inputMinPrice = this.inputMinPrice.bind(this)
24 | this.setMinPrice = this.setMinPrice.bind(this)
25 | this.inputTax = this.inputTax.bind(this)
26 | this.setTax = this.setTax.bind(this)
27 | this.inputZombiePrice = this.inputZombiePrice.bind(this)
28 | this.setZombiePrice = this.setZombiePrice.bind(this)
29 | this.withdraw = this.withdraw.bind(this)
30 | }
31 |
32 | componentDidMount(){
33 | let that = this
34 | let ethereum = window.ethereum
35 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
36 | MyWeb3.init().then(function(res){
37 | // console.log(window.web3)
38 | // console.log(ethereum)
39 | // console.log(window.MyContract)
40 | MyWeb3.owner().then(function (contractOwner) {
41 | if(window.defaultAccount === contractOwner){
42 | that.setState({contractOwner:contractOwner})
43 | that.getContractName()
44 | that.getContractSymbol()
45 | that.checkBalance()
46 | that.levelUpFee()
47 | that.minPrice()
48 | that.tax()
49 | that.zombiePrice()
50 | that.setState({
51 | contractAddress:window.MyContract._address
52 | })
53 | }
54 | })
55 | })
56 | }else {
57 | alert('You have to install MetaMask !')
58 | }
59 | }
60 | getContractName(){
61 | let that = this
62 | MyWeb3.name().then(function (name) {
63 | that.setState({ContractName:name})
64 | })
65 | }
66 | getContractSymbol(){
67 | let that = this
68 | MyWeb3.symbol().then(function (symbol) {
69 | that.setState({ContractSymbol:symbol})
70 | })
71 | }
72 | checkBalance(){
73 | let that = this
74 | MyWeb3.checkBalance().then(function (balance) {
75 | that.setState({ContractBalance:balance})
76 | })
77 | }
78 | withdraw(){
79 | let that = this
80 | MyWeb3.withdraw().then(function (res) {
81 | that.checkBalance()
82 | })
83 | }
84 | setAttackVictoryProbability(){
85 | MyWeb3.setAttackVictoryProbability(this.state.attackVictoryProbability).then(function (res) {
86 | console.log(res)
87 | window.location.reload()
88 | })
89 | }
90 | inputAttackVictoryProbability(event){
91 | this.setState({
92 | attackVictoryProbability:event.target.value
93 | })
94 | }
95 | levelUpFee(){
96 | let that = this
97 | MyWeb3.levelUpFee().then(function (levelUpFee) {
98 | that.setState({levelUpFee:levelUpFee})
99 | })
100 | }
101 | setLevelUpFee(){
102 | MyWeb3.setLevelUpFee(this.state.levelUpFee).then(function (res) {
103 | console.log(res)
104 | window.location.reload()
105 | })
106 | }
107 | inputLevelUpFee(event){
108 | this.setState({
109 | levelUpFee:event.target.value
110 | })
111 | }
112 | minPrice(){
113 | let that = this
114 | MyWeb3.minPrice().then(function (minPrice) {
115 | that.setState({minPrice:minPrice})
116 | })
117 | }
118 | setMinPrice(){
119 | MyWeb3.setMinPrice(this.state.minPrice).then(function (res) {
120 | console.log(res)
121 | window.location.reload()
122 | })
123 | }
124 | inputMinPrice(event){
125 | this.setState({
126 | minPrice:event.target.value
127 | })
128 | }
129 | tax(){
130 | let that = this
131 | MyWeb3.tax().then(function (tax) {
132 | that.setState({tax:tax})
133 | })
134 | }
135 | setTax(){
136 | MyWeb3.setTax(this.state.tax).then(function (res) {
137 | console.log(res)
138 | window.location.reload()
139 | })
140 | }
141 | inputTax(event){
142 | this.setState({
143 | tax:event.target.value
144 | })
145 | }
146 | zombiePrice(){
147 | let that = this
148 | MyWeb3.zombiePrice().then(function (zombiePrice) {
149 | that.setState({zombiePrice:zombiePrice})
150 | })
151 | }
152 | setZombiePrice(){
153 | MyWeb3.setZombiePrice(this.state.zombiePrice).then(function (res) {
154 | console.log(res)
155 | window.location.reload()
156 | })
157 | }
158 | inputZombiePrice(event){
159 | this.setState({
160 | zombiePrice:event.target.value
161 | })
162 | }
163 |
164 |
165 | render() {
166 | if(window.defaultAccount === this.state.contractOwner){
167 | return (
168 |
259 | )
260 | }else{
261 | return(
262 |
263 | )
264 | }
265 | }
266 | }
267 |
268 | export default ContractAdmin;
--------------------------------------------------------------------------------
/src/MyWeb3.js:
--------------------------------------------------------------------------------
1 | import Web3 from "web3";
2 | import abi from './ZombieCore.json'
3 | import ContractAddress from './ContractAddress'
4 |
5 | const MyWeb3 ={
6 | init() {
7 | /*
8 | '1': Ethereum Main Network
9 | '2': Morden Test network
10 | '3': Ropsten Test Network
11 | '4': Rinkeby Test Network
12 | '5': Goerli Test Network
13 | '42': Kovan Test Network
14 | */
15 | return new Promise((resolve, reject) => {
16 | //let currentChainId = parseInt(window.ethereum.chainId, 16)
17 | let ethereum = window.ethereum
18 | //禁止自动刷新,metamask要求写的
19 | ethereum.autoRefreshOnNetworkChange = false
20 | //开始调用metamask
21 | ethereum.enable().then(function (accounts) {
22 | //初始化provider
23 | let provider = window['ethereum'] || window.web3.currentProvider
24 | //初始化Web3
25 | window.web3 = new Web3(provider)
26 | //获取到当前以太坊网络id
27 | window.web3.eth.net.getId().then(function (result) {
28 | let currentChainId = result
29 | //设置最大监听器数量,否则出现warning
30 | window.web3.currentProvider.setMaxListeners(300)
31 | //从json获取到当前网络id下的合约地址
32 | let currentContractAddress = ContractAddress[currentChainId]
33 | if(currentContractAddress !== undefined){
34 | //实例化合约
35 | window.MyContract = new window.web3.eth.Contract(abi.abi,currentContractAddress)
36 | //获取到当前默认的以太坊地址
37 | window.defaultAccount = accounts[0].toLowerCase()
38 | //that.allEvents(window.MyContract)
39 | resolve(true)
40 | }else{
41 | reject('Unknow Your ChainId:'+currentChainId)
42 | }
43 | })
44 | }).catch(function (error) {
45 | console.log(error)
46 | })
47 | })
48 | },
49 | //僵尸总量
50 | zombieCount() {
51 | return new Promise((resolve, reject) => {
52 | window.MyContract.methods.zombieCount().call().then(function(zombieCount) {
53 | resolve(zombieCount)
54 | })
55 | })
56 | },
57 | //获得单个僵尸数据
58 | zombies(zombieId){
59 | return new Promise((resolve, reject) => {
60 | if(zombieId>=0){
61 | window.MyContract.methods.zombies(zombieId).call().then(function(zombies) {
62 | resolve(zombies)
63 | })
64 | }
65 | })
66 | },
67 | //获得僵尸拥有者地址
68 | zombieToOwner(zombieId){
69 | return new Promise((resolve, reject) => {
70 | if(zombieId>=0){
71 | window.MyContract.methods.zombieToOwner(zombieId).call().then(function(zombies) {
72 | resolve(zombies.toLowerCase())
73 | })
74 | }
75 | })
76 | },
77 | //获得当前用户的所有僵尸id
78 | getZombiesByOwner(){
79 | return new Promise((resolve, reject) => {
80 | window.MyContract.methods.getZombiesByOwner(window.defaultAccount).call().then(function(zombies) {
81 | resolve(zombies)
82 | })
83 | })
84 | },
85 | //创建随机僵尸
86 | createZombie(_name){
87 | return new Promise((resolve, reject) => {
88 | window.MyContract.methods.createZombie(_name).send({from:window.defaultAccount})
89 | .on('transactionHash', function(transactionHash){
90 | resolve(transactionHash)
91 | })
92 | .on('confirmation', function(confirmationNumber, receipt){
93 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
94 | })
95 | .on('receipt', function(receipt){
96 | console.log({receipt:receipt})
97 | window.location.reload()
98 | })
99 | .on('error', function(error,receipt){
100 | console.log({error:error,receipt:receipt})
101 | reject({error:error,receipt:receipt})
102 | })
103 | })
104 | },
105 | //购买僵尸
106 | buyZombie(_name){
107 | return new Promise((resolve, reject) => {
108 | window.MyContract.methods.zombiePrice().call().then(function(zombiePrice) {
109 | window.MyContract.methods.buyZombie(_name).send({from:window.defaultAccount,value:zombiePrice})
110 | .on('transactionHash', function(transactionHash){
111 | resolve(transactionHash)
112 | })
113 | .on('confirmation', function(confirmationNumber, receipt){
114 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
115 | })
116 | .on('receipt', function(receipt){
117 | console.log({receipt:receipt})
118 | window.location.reload()
119 | })
120 | .on('error', function(error,receipt){
121 | console.log({error:error,receipt:receipt})
122 | reject({error:error,receipt:receipt})
123 | })
124 | })
125 | })
126 | },
127 | //僵尸对战
128 | attack(_zombieId,_targetId){
129 | return new Promise((resolve, reject) => {
130 | window.MyContract.methods.attack(_zombieId,_targetId).send({from:window.defaultAccount})
131 | .on('transactionHash', function(transactionHash){
132 | resolve(transactionHash)
133 | })
134 | .on('confirmation', function(confirmationNumber, receipt){
135 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
136 | })
137 | .on('receipt', function(receipt){
138 | console.log({receipt:receipt})
139 | window.location.reload()
140 | })
141 | .on('error', function(error,receipt){
142 | console.log({error:error,receipt:receipt})
143 | reject({error:error,receipt:receipt})
144 | })
145 | })
146 | },
147 | //僵尸改名
148 | changeName(_zombieId,_name){
149 | return new Promise((resolve, reject) => {
150 | window.MyContract.methods.changeName(_zombieId,_name).send({from:window.defaultAccount})
151 | .on('transactionHash', function(transactionHash){
152 | resolve(transactionHash)
153 | })
154 | .on('confirmation', function(confirmationNumber, receipt){
155 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
156 | })
157 | .on('receipt', function(receipt){
158 | console.log({receipt:receipt})
159 | window.location.reload()
160 | })
161 | .on('error', function(error,receipt){
162 | console.log({error:error,receipt:receipt})
163 | reject({error:error,receipt:receipt})
164 | })
165 | })
166 | },
167 | //僵尸喂食
168 | feed(_zombieId){
169 | return new Promise((resolve, reject) => {
170 | window.MyContract.methods.feed(_zombieId).send({from:window.defaultAccount})
171 | .on('transactionHash', function(transactionHash){
172 | resolve(transactionHash)
173 | })
174 | .on('confirmation', function(confirmationNumber, receipt){
175 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
176 | })
177 | .on('receipt', function(receipt){
178 | console.log({receipt:receipt})
179 | window.location.reload()
180 | })
181 | .on('error', function(error,receipt){
182 | console.log({error:error,receipt:receipt})
183 | reject({error:error,receipt:receipt})
184 | })
185 | })
186 | },
187 | //僵尸付费升级
188 | levelUp(_zombieId){
189 | return new Promise((resolve, reject) => {
190 | window.MyContract.methods.levelUpFee().call().then(function(levelUpFee) {
191 | window.MyContract.methods.levelUp(_zombieId).send({from:window.defaultAccount,value:levelUpFee})
192 | .on('transactionHash', function(transactionHash){
193 | resolve(transactionHash)
194 | })
195 | .on('confirmation', function(confirmationNumber, receipt){
196 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
197 | })
198 | .on('receipt', function(receipt){
199 | console.log({receipt:receipt})
200 | window.location.reload()
201 | })
202 | .on('error', function(error,receipt){
203 | console.log({error:error,receipt:receipt})
204 | reject({error:error,receipt:receipt})
205 | })
206 | })
207 | })
208 | },
209 | //获取僵尸喂食次数
210 | zombieFeedTimes(_zombieId){
211 | return new Promise((resolve, reject) => {
212 | window.MyContract.methods.zombieFeedTimes(_zombieId).call().then(function(zombieFeedTimes) {
213 | resolve(zombieFeedTimes)
214 | })
215 | })
216 | },
217 | //获取最低售价
218 | minPrice(){
219 | return new Promise((resolve, reject) => {
220 | window.MyContract.methods.minPrice().call().then(function(minPrice) {
221 | resolve(window.web3.utils.fromWei(minPrice,'ether'))
222 | })
223 | })
224 | },
225 | //获取税金
226 | tax(){
227 | return new Promise((resolve, reject) => {
228 | window.MyContract.methods.tax().call().then(function(tax) {
229 | resolve(window.web3.utils.fromWei(tax,'ether'))
230 | })
231 | })
232 | },
233 | //出售我的僵尸
234 | saleMyZombie(_zombieId,_price){
235 | return new Promise((resolve, reject) => {
236 | window.MyContract.methods.saleMyZombie(_zombieId,window.web3.utils.toWei(_price.toString())).send({from:window.defaultAccount})
237 | .on('transactionHash', function(transactionHash){
238 | resolve(transactionHash)
239 | })
240 | .on('confirmation', function(confirmationNumber, receipt){
241 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
242 | })
243 | .on('receipt', function(receipt){
244 | console.log({receipt:receipt})
245 | window.location.reload()
246 | })
247 | .on('error', function(error,receipt){
248 | console.log({error:error,receipt:receipt})
249 | reject({error:error,receipt:receipt})
250 | })
251 | })
252 | },
253 | //获得商店里僵尸数据
254 | zombieShop(_zombieId){
255 | return new Promise((resolve, reject) => {
256 | window.MyContract.methods.zombieShop(_zombieId).call().then(function(shopInfo) {
257 | shopInfo.price = window.web3.utils.fromWei(shopInfo.price,'ether')
258 | resolve(shopInfo)
259 | })
260 | })
261 | },
262 | //获得商店所有僵尸
263 | getShopZombies(){
264 | return new Promise((resolve, reject) => {
265 | window.MyContract.methods.getShopZombies().call().then(function(zombieIds) {
266 | resolve(zombieIds)
267 | })
268 | })
269 | },
270 | //购买商店里的僵尸
271 | buyShopZombie(_zombieId,_price){
272 | return new Promise((resolve, reject) => {
273 | window.MyContract.methods.buyShopZombie(_zombieId).send({from:window.defaultAccount,value:window.web3.utils.toWei(_price.toString())})
274 | .on('transactionHash', function(transactionHash){
275 | resolve(transactionHash)
276 | })
277 | .on('confirmation', function(confirmationNumber, receipt){
278 | console.log({confirmationNumber:confirmationNumber,receipt:receipt})
279 | })
280 | .on('receipt', function(receipt){
281 | console.log({receipt:receipt})
282 | window.location.reload()
283 | })
284 | .on('error', function(error,receipt){
285 | console.log({error:error,receipt:receipt})
286 | reject({error:error,receipt:receipt})
287 | })
288 | })
289 | },
290 | //获得合约拥有者地址
291 | owner(){
292 | return new Promise((resolve, reject) => {
293 | window.MyContract.methods.owner().call().then(function(owner) {
294 | resolve(owner.toLowerCase())
295 | })
296 | })
297 | },
298 | //获得合约名称
299 | name(){
300 | return new Promise((resolve, reject) => {
301 | window.MyContract.methods.name().call().then(function(name) {
302 | resolve(name)
303 | })
304 | })
305 | },
306 | //获得合约标识
307 | symbol(){
308 | return new Promise((resolve, reject) => {
309 | window.MyContract.methods.symbol().call().then(function(symbol) {
310 | resolve(symbol)
311 | })
312 | })
313 | },
314 | //查询余额
315 | checkBalance(){
316 | return new Promise((resolve, reject) => {
317 | this.owner().then(function (owner) {
318 | if(window.defaultAccount === owner){
319 | window.MyContract.methods.checkBalance().call({from:window.defaultAccount}).then(function(balance) {
320 | resolve(window.web3.utils.fromWei(balance,'ether'))
321 | })
322 | }else{
323 | reject('You are not contract owner')
324 | }
325 | })
326 | })
327 | },
328 | //设置攻击胜率
329 | setAttackVictoryProbability(_attackVictoryProbability){
330 | return new Promise((resolve, reject) => {
331 | window.MyContract.methods.setAttackVictoryProbability(_attackVictoryProbability).send({from:window.defaultAccount})
332 | .then(function(result) {
333 | resolve(result)
334 | })
335 | })
336 | },
337 | //获得升级费
338 | levelUpFee(){
339 | return new Promise((resolve, reject) => {
340 | window.MyContract.methods.levelUpFee().call().then(function(levelUpFee) {
341 | resolve(window.web3.utils.fromWei(levelUpFee,'ether'))
342 | })
343 | })
344 | },
345 | //设置升级费
346 | setLevelUpFee(_fee){
347 | return new Promise((resolve, reject) => {
348 | window.MyContract.methods.setLevelUpFee(window.web3.utils.toWei(_fee.toString())).send({from:window.defaultAccount})
349 | .then(function(result) {
350 | resolve(result)
351 | })
352 | })
353 | },
354 | //设置最低售价
355 | setMinPrice(_value){
356 | return new Promise((resolve, reject) => {
357 | window.MyContract.methods.setMinPrice(window.web3.utils.toWei(_value.toString())).send({from:window.defaultAccount})
358 | .then(function(result) {
359 | resolve(result)
360 | })
361 | })
362 | },
363 | //获得僵尸售价
364 | zombiePrice(){
365 | return new Promise((resolve, reject) => {
366 | window.MyContract.methods.zombiePrice().call().then(function(zombiePrice) {
367 | resolve(window.web3.utils.fromWei(zombiePrice,'ether'))
368 | })
369 | })
370 | },
371 | //设置僵尸售价
372 | setZombiePrice(_value){
373 | return new Promise((resolve, reject) => {
374 | window.MyContract.methods.setZombiePrice(window.web3.utils.toWei(_value.toString())).send({from:window.defaultAccount})
375 | .then(function(result) {
376 | resolve(result)
377 | })
378 | })
379 | },
380 | //设置税金
381 | setTax(_value){
382 | return new Promise((resolve, reject) => {
383 | window.MyContract.methods.setTax(window.web3.utils.toWei(_value.toString())).send({from:window.defaultAccount})
384 | .then(function(result) {
385 | resolve(result)
386 | })
387 | })
388 | },
389 | //提款
390 | withdraw(){
391 | return new Promise((resolve, reject) => {
392 | this.owner().then(function (owner) {
393 | if(window.defaultAccount === owner){
394 | window.MyContract.methods.withdraw().send({from:window.defaultAccount}).then(function(res) {
395 | resolve(res)
396 | })
397 | }else{
398 | reject('You are not contract owner')
399 | }
400 | })
401 | })
402 | },
403 | //新僵尸事件
404 | EventNewZombie(){
405 | return window.MyContract.events.NewZombie({},{fromBlock: 0, toBlock: 'latest'})
406 | },
407 | //出售僵尸事件
408 | EventSaleZombie(){
409 | return new Promise((resolve, reject) => {
410 | window.MyContract.events.SaleZombie({fromBlock: 0, toBlock: 'latest'},function (error, event) {
411 | resolve(event)
412 | })
413 | })
414 | },
415 | //所有事件
416 | allEvents(){
417 | window.MyContract.events.allEvents({fromBlock: 0}, function(error, event){
418 | console.log({allEvents:event})
419 | }).on("connected", function(subscriptionId){
420 | console.log({connected_subscriptionId:subscriptionId})
421 | }).on('data', function(event){
422 | console.log({event_data:event})
423 | }).on('changed', function(event){
424 | console.log({event_changed:event})
425 | }).on('error', function(error, receipt) {
426 | console.log({event_error:error,receipt:receipt})
427 | })
428 | }
429 | }
430 |
431 | export default MyWeb3;
--------------------------------------------------------------------------------
/src/MyZombie.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import ZombieCard from "./ZombieCard"
3 | import './static/ZombiePreview.css'
4 | import Page from "./Page"
5 | import MyWeb3 from './MyWeb3'
6 | import {
7 | BrowserRouter as
8 | Route,
9 | Link
10 | } from "react-router-dom"
11 |
12 | class MyZombie extends Component {
13 | constructor(props) {
14 | super(props);
15 | this.state = {zombieCount:"",zombies:[],zombieName:'',transactionHash:'',buyAreaDisp:1,createAreaDisp:1,txHashDisp:0}
16 | this.createZombie=this.createZombie.bind(this)
17 | this.buyZombie=this.buyZombie.bind(this)
18 | this.inputChange=this.inputChange.bind(this)
19 | }
20 |
21 | componentDidMount(){
22 | let that = this
23 | let ethereum = window.ethereum
24 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
25 | MyWeb3.init().then(function(res){
26 | that.myZombies()
27 | })
28 | }else {
29 | alert('You have to install MetaMask !')
30 | }
31 | }
32 |
33 | myZombies(){
34 | let that = this
35 | MyWeb3.getZombiesByOwner().then(function(zombies){
36 | if(zombies.length > 0){
37 | for(let i=0;i0) {
79 | return (
80 |
81 | {this.state.zombies.map((item,index)=>{
82 | var name = item.name
83 | var level = item.level
84 | return(
85 |
86 |
87 |
88 | )
89 | })}
90 |
91 |
92 |
93 | {this.input=input}}
98 | value={this.state.zombieName}
99 | onChange={this.inputChange}>
100 |
101 |
102 |
103 |
108 |
109 |
110 |
{this.state.transactionHash}
等待确认中...
111 |
112 | )
113 | }else{
114 | return(
115 |
116 |
117 | {this.input=input}}
122 | value={this.state.zombieName}
123 | onChange={this.inputChange}>
124 |
125 |
126 |
127 |
132 |
133 |
134 |
{this.state.transactionHash}
等待确认中...
135 |
)
136 | }
137 | }
138 | }
139 | export default MyZombie;
--------------------------------------------------------------------------------
/src/Page.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import ZombieArmy from "./ZombieArmy"
3 | import MyZombie from "./MyZombie"
4 | import ZombieMarket from "./ZombieMarket"
5 | import ZombieSimulator from "./ZombieSimulator"
6 | import ZombieDetail from "./ZombieDetail";
7 | import ZombieAttack from "./ZombieAttack";
8 | import ContractAdmin from "./ContractAdmin"
9 |
10 | class Page extends Component {
11 | constructor(props) {
12 | super(props)
13 | this.state = {page:'',id:0 }
14 | }
15 | componentDidMount(){
16 | let search = this.props.location.search.replace(/\?/,'').split("&")
17 | let page = search[0]
18 | this.setState({page:page})
19 | }
20 | UNSAFE_componentWillReceiveProps(nextProps){
21 | if(nextProps!==this.props){
22 | this.setState({nextProps})
23 | let search = nextProps.location.search.replace(/\?/,'').split("&")
24 | let page = search[0] === '' ? 'ZombieArmy' : search[0]
25 | this.setState({page:page})
26 | return true
27 | }else{
28 | return false
29 | }
30 | }
31 | render() {
32 | switch (this.state.page){
33 | case 'ZombieArmy':
34 | return()
35 | case 'MyZombie':
36 | return()
37 | case 'ZombieMarket':
38 | return()
39 | case 'ZombieSimulator':
40 | return()
41 | case 'ZombieDetail':
42 | return()
43 | case 'ZombieAttack':
44 | return()
45 | case 'ContractAdmin':
46 | return()
47 | default:
48 | return()
49 | }
50 | }
51 | }
52 |
53 | export default Page;
--------------------------------------------------------------------------------
/src/ZombieArmy.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import ZombieCard from "./ZombieCard";
3 | import './static/ZombiePreview.css';
4 | import MyWeb3 from './MyWeb3'
5 | import {
6 | BrowserRouter as
7 | Route,
8 | Link
9 | } from "react-router-dom"
10 | import Page from "./Page";
11 |
12 | class ZombieArmy extends Component {
13 | constructor(props) {
14 | super(props);
15 | this.state = { zombieCount:"",zombies:[] }
16 | }
17 |
18 | componentDidMount(){
19 | let that = this
20 | let ethereum = window.ethereum
21 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
22 | MyWeb3.init().then(function(res){
23 | that.zombieArmy()
24 | })
25 | }else {
26 | alert('You have to install MetaMask !')
27 | }
28 | }
29 | zombieArmy(){
30 | let that = this
31 | MyWeb3.zombieCount().then(function(result){
32 | if(result > 0){
33 | for(let i=0;i {
46 | return
47 | }
48 | }
49 | render() {
50 | if(this.state.zombies.length>0) {
51 | return (
52 |
53 | {this.state.zombies.map((item,index)=>{
54 | var name = item.name
55 | var level = item.level
56 | return(
57 |
58 |
59 |
60 | )
61 | })}
62 |
63 |
64 | )
65 | }else{
66 | return ( )
67 | }
68 | }
69 | }
70 |
71 | export default ZombieArmy;
--------------------------------------------------------------------------------
/src/ZombieAttack.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import MyWeb3 from './MyWeb3'
3 | import ZombiePreview from "./ZombiePreview"
4 | import './static/ZombiePreview.css'
5 | import moment from "moment"
6 |
7 | class NewZombie extends Component {
8 | constructor(props) {
9 | super(props);
10 | const searchParams = new URLSearchParams(window.location.search)
11 | const id = searchParams.get('id')
12 | this.state = {
13 | targetId:id ,
14 | targetZombie:{},
15 | myZombies:[],
16 | myZombie:{},
17 | myZombieId:'',
18 | active: {},
19 | buttonTxt:'',
20 | modalDisplay:'none',
21 | transactionHash:'',
22 | AttackBtn:()=>{
23 | return(
28 | )
29 | }
30 | }
31 | this.selectZombie = this.selectZombie.bind(this)
32 | this.zombieAttack = this.zombieAttack.bind(this)
33 | }
34 | componentDidMount(){
35 | let that = this
36 | let ethereum = window.ethereum
37 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
38 | MyWeb3.init().then(function(res){
39 | that.getZombie(that.state.targetId)
40 | that.getMyZombies()
41 | })
42 | }else {
43 | alert('You have to install MetaMask !')
44 | }
45 | }
46 |
47 | getZombie(zombieId){
48 | let that = this
49 | MyWeb3.zombies(zombieId).then(function (result) {
50 | that.setState({targetZombie:result})
51 | })
52 | }
53 | getMyZombies(){
54 | let that = this
55 | MyWeb3.getZombiesByOwner().then(function(zombies){
56 | if(zombies.length > 0){
57 | for(let i=0;iresult.readyTime){
62 | _zombies.push(result)
63 | }
64 | that.setState({myZombies:_zombies})
65 | })
66 | }
67 | }
68 | })
69 | }
70 | selectZombie = index => {
71 | var _active = this.state.active
72 | var prev_active = _active[index]
73 | for(var i=0;i{
82 | return(
87 | )
88 | }
89 | })
90 | }
91 |
92 | zombieAttack(){
93 | let that = this
94 | if(this.state.myZombie !== undefined){
95 | this.setState({modalDisplay:''})
96 | MyWeb3.attack(this.state.myZombieId,this.state.targetId)
97 | .then(function(transactionHash){
98 | that.setState({
99 | transactionHash:transactionHash,
100 | AttackBtn : () =>{
101 | return()
102 | }
103 | })
104 | })
105 | }
106 | }
107 | render() {
108 | let AttackBtn = this.state.AttackBtn
109 | if(this.state.myZombies.length>0) {
110 | return (
111 |
112 |
118 |
119 |
120 |
121 |
122 |
123 | VS
124 |
125 |
126 |
127 |
128 |
129 |
{this.state.transactionHash}
130 |
131 |
132 |
137 |
138 |
139 | {this.state.myZombies.map((item,index)=>{
140 | var name = item.name
141 | var level = item.level
142 | return(
143 |
this.selectZombie(index)} >
144 |
145 |
146 |
147 |
148 | {name}
149 |
150 |
CryptoZombie{level}级
151 |
152 |
153 |
154 | )
155 | })}
156 |
157 |
158 |
159 |
160 |
161 | );
162 | }else{
163 | return(
164 | 没有能干它的僵尸
165 | )
166 | }
167 | }
168 | }
169 |
170 | export default NewZombie;
--------------------------------------------------------------------------------
/src/ZombieCard.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import ZombiePreview from "./ZombiePreview"
3 |
4 | class ZombieCard extends Component {
5 | constructor(props) {
6 | super(props)
7 | this.state = { zombie:this.props.zombie,name:this.props.name,level:this.props.level}
8 | }
9 | UNSAFE_componentWillReceiveProps(nextProps){
10 | if(nextProps!==this.props){
11 | this.setState({ _className:nextProps._className,_style:nextProps._style})
12 | return true
13 | }else{
14 | return false
15 | }
16 | }
17 | render() {
18 | return (
19 |
20 |
21 |
22 |
23 |
24 | {this.state.name}
25 |
26 |
CryptoZombie{this.state.level}级
27 |
28 |
29 |
30 | )
31 | }
32 | }
33 |
34 | export default ZombieCard;
--------------------------------------------------------------------------------
/src/ZombieDetail.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import ZombiePreview from "./ZombiePreview"
3 | import './static/ZombiePreview.css'
4 | import MyWeb3 from './MyWeb3'
5 | import moment from "moment"
6 | import {
7 | BrowserRouter as
8 | Route,
9 | Link
10 | } from "react-router-dom"
11 | import Page from "./Page";
12 |
13 | class Zombiedetail extends Component {
14 | constructor(props) {
15 | super(props)
16 | const searchParams = new URLSearchParams(window.location.search)
17 |
18 | const id = searchParams.get('id')
19 | this.state = {
20 | id:id ,
21 | zombie:{},owner:'',
22 | zombieFeedTimes:0,
23 | myPrice:0,
24 | minPrice:0,
25 | AttackBtn: () =>{return()},
26 | RenameArea: () =>{return()},
27 | zombieNewname:'',
28 | FeedArea: () =>{return()},
29 | LevelupArea: () =>{return()},
30 | SaleArea: () =>{return()},
31 | BuyArea: () =>{return()},
32 | onShop:false,
33 | shopInfo:{}
34 | }
35 | this.zombieChangeName = this.zombieChangeName.bind(this)
36 | this.changeName = this.changeName.bind(this)
37 | this.feed = this.feed.bind(this)
38 | this.levelUp = this.levelUp.bind(this)
39 | this.saleZombie = this.saleZombie.bind(this)
40 | this.buyShopZombie = this.buyShopZombie.bind(this)
41 | this.setPrice = this.setPrice.bind(this)
42 | }
43 |
44 | componentDidMount(){
45 | let that = this
46 | let ethereum = window.ethereum
47 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
48 | MyWeb3.init().then(function(res){
49 | that.getZombie(that.state.id)
50 | that.getZombieFeedTimes(that.state.id)
51 | that.getMinPrice()
52 | that.getZombieShop(that.state.id)
53 | })
54 | }else {
55 | alert('You have to install MetaMask !')
56 | }
57 | }
58 | getZombieShop(zombieId){
59 | let that = this
60 | MyWeb3.zombieShop(zombieId).then(function (shopInfo) {
61 | if(shopInfo.price>0){
62 | that.setState({onShop:true,shopInfo:shopInfo})
63 | }
64 | })
65 | }
66 | getMinPrice(){
67 | let that = this
68 | MyWeb3.minPrice().then(function (minPrice) {
69 | if(minPrice>0){
70 | MyWeb3.tax().then(function (tax) {
71 | if(tax>0){
72 | that.setState({myPrice:parseFloat(minPrice)+parseFloat(tax),minPrice:parseFloat(minPrice)+parseFloat(tax)})
73 | }
74 | })
75 | }
76 | })
77 | }
78 | getZombieFeedTimes(zombieId){
79 | let that = this
80 | MyWeb3.zombieFeedTimes(zombieId).then(function (result) {
81 | if(result>0){
82 | that.setState({zombieFeedTimes:result})
83 | }
84 | })
85 | }
86 | setPrice(event){
87 | this.setState({
88 | myPrice:event.target.value
89 | })
90 | }
91 | zombieChangeName(event){
92 | this.setState({
93 | zombieNewname:event.target.value
94 | })
95 | }
96 | changeName(){
97 | let that = this
98 | if(window.defaultAccount !== undefined){
99 | MyWeb3.changeName(this.state.id,this.state.zombieNewname)
100 | .then(function(transactionHash){
101 | that.setState({RenameArea : () =>{
102 | return({transactionHash}
)
103 | }
104 | })
105 | })
106 | }
107 | }
108 | feed(){
109 | let that = this
110 | if(window.defaultAccount !== undefined){
111 | MyWeb3.feed(this.state.id)
112 | .then(function(transactionHash){
113 | that.setState({FeedArea : () =>{
114 | return({transactionHash}
)
115 | }
116 | })
117 | })
118 | }
119 | }
120 | levelUp(){
121 | let that = this
122 | if(window.defaultAccount !== undefined){
123 | MyWeb3.levelUp(this.state.id)
124 | .then(function(transactionHash){
125 | that.setState({LevelupArea : () =>{
126 | return({transactionHash}
)
127 | }
128 | })
129 | })
130 | }
131 | }
132 | saleZombie(){
133 | let that = this
134 | if(window.defaultAccount !== undefined
135 | && this.state.myPrice*this.state.minPrice>0
136 | && this.state.myPrice>=this.state.minPrice){
137 | MyWeb3.saleMyZombie(this.state.id,this.state.myPrice)
138 | .then(function(transactionHash){
139 | that.setState({SaleArea : () =>{
140 | return({transactionHash}
)
141 | }
142 | })
143 | })
144 | }
145 | }
146 | buyShopZombie(){
147 | let that = this
148 | if(window.defaultAccount !== undefined){
149 | MyWeb3.buyShopZombie(this.state.id,this.state.shopInfo.price)
150 | .then(function(transactionHash){
151 | that.setState({BuyArea : () =>{
152 | return({transactionHash}
)
153 | }
154 | })
155 | })
156 | }
157 | }
158 | getZombie(zombieId){
159 | let that = this
160 | MyWeb3.zombies(zombieId).then(function (result) {
161 | that.setState({zombie:result})
162 | that.setState({zombieNewname:result.name})
163 | MyWeb3.zombieToOwner(zombieId).then(function (zombieOwner) {
164 | that.setState({owner:zombieOwner})
165 | if(window.defaultAccount !== undefined &&
166 | zombieOwner !== window.defaultAccount){
167 | that.setState({AttackBtn : () =>{
168 | return(
169 | )
174 | }
175 | })
176 | if(that.state.onShop){
177 | that.setState({BuyArea : () =>{
178 | return(
179 |
180 |
181 | 售价:{that.state.shopInfo.price} ether
182 |
183 |
184 |
189 |
190 |
191 | )
192 | }
193 | })
194 | }
195 | }else{
196 | that.setState({AttackBtn : () =>{return()}})
197 | if(that.state.zombie.level > 1){
198 | that.setState({RenameArea : () =>{
199 | return(
200 |
201 |
202 |
208 |
209 |
210 |
211 |
216 |
217 |
)
218 | }
219 | })
220 | }
221 | if(that.state.zombie.readyTime === 0 || moment().format('X')>that.state.zombie.readyTime){
222 | that.setState({FeedArea : () =>{
223 | return(
224 |
225 |
230 |
)
231 | }
232 | })
233 | }
234 | that.setState({LevelupArea : () =>{
235 | return(
236 |
237 |
242 |
)
243 | }
244 | })
245 | if(!that.state.onShop){
246 | that.setState({SaleArea : () =>{
247 | return(
248 |
249 |
250 |
256 |
257 |
258 |
259 |
264 |
265 |
266 | )
267 | }
268 | })
269 | }
270 | }
271 | })
272 | })
273 | }
274 |
275 | render() {
276 | var readyTime = '已冷却'
277 | if(this.state.zombie.readyTime !== undefined && moment().format('X')
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
CryptoZombie第一级
297 |
298 |
299 |
300 |
301 |
302 | - {this.state.zombie.name}
303 | - 主人
304 | - {this.state.owner}
305 | - 等级
306 | - {this.state.zombie.level}
307 | - 胜利次数
308 | - {this.state.zombie.winCount}
309 | - 失败次数
310 | - {this.state.zombie.lossCount}
311 | - 冷却时间
312 | - {readyTime}
313 | - 喂食次数
314 | - {this.state.zombieFeedTimes}
315 |
316 | -
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 | );
330 | }
331 | }
332 |
333 | export default Zombiedetail;
--------------------------------------------------------------------------------
/src/ZombieMarket.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import MyWeb3 from './MyWeb3'
3 | import ZombieCard from "./ZombieCard";
4 | import {
5 | BrowserRouter as
6 | Route,
7 | Link
8 | } from "react-router-dom"
9 | import Page from "./Page";
10 |
11 | class ZombieMarket extends Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {shopZombies:[] }
15 | }
16 |
17 | componentDidMount(){
18 | //console.log(window.web3._extend.utils)
19 | let that = this
20 | let ethereum = window.ethereum
21 | if (typeof ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
22 | MyWeb3.init().then(function(res){
23 | that.zombieShop()
24 | })
25 | }else {
26 | alert('You have to install MetaMask !')
27 | }
28 | }
29 |
30 | zombieShop(){
31 | let that = this
32 | MyWeb3.getShopZombies().then(function(zombieIds){
33 | if(zombieIds.length>0){
34 | for(var i=0;i=0){
37 | MyWeb3.zombies(zombieId).then(function(zombies) {
38 | let _shopZombies = that.state.shopZombies
39 | zombies.zombieId = zombieId
40 | _shopZombies.push(zombies);
41 | that.setState({shopZombies:_shopZombies})
42 | })
43 | }
44 | }
45 | }
46 | })
47 | }
48 |
49 | render() {
50 | if(this.state.shopZombies.length>0) {
51 | return (
52 |
53 | {this.state.shopZombies.map((item,index)=>{
54 | var name = item.name
55 | var level = item.level
56 | return(
57 |
58 |
59 |
60 | )
61 | })}
62 |
63 |
64 | )
65 | }else{
66 | return ( )
67 | }
68 | }
69 | }
70 |
71 | export default ZombieMarket;
--------------------------------------------------------------------------------
/src/ZombiePreview.js:
--------------------------------------------------------------------------------
1 | import React,{Component} from 'react'
2 |
3 | class ZombiePreview extends Component {
4 | constructor(props){
5 | super(props)
6 | this.state = { zombie:this.props.zombie,_style:this.props._style,_className:this.props._className}
7 | }
8 | UNSAFE_componentWillReceiveProps(nextProps){
9 | if(nextProps!==this.props){
10 | this.setState({
11 | zombie:nextProps.zombie,
12 | _style:nextProps._style,
13 | _className:nextProps._className,
14 | })
15 | return true
16 | }else{
17 | return false
18 | }
19 | }
20 | render(){
21 | var _style = this.state._style || []
22 | var _className = this.state._className
23 | if(this.state.zombie !== undefined){
24 | _style['color'] = {filter:"hue-rotate(0deg)"}
25 | _style['skin'] = {filter:"hue-rotate(0deg)"}
26 | _style['eye_color'] = {filter:"hue-rotate(0deg)"}
27 | _className = "zombie-parts head-visible-1 eye-visible-1 shirt-visible-1"
28 | if(this.state.zombie.dna !== undefined){
29 | var dna = this.state.zombie.dna
30 | var _head = dna.substring(0,2) % 8 +1
31 | var _eye = dna.substring(2,4) % 11 +1
32 | var _shirt = dna.substring(4,6) % 6 +1
33 | _className = "zombie-parts head-visible-"+_head+" eye-visible-"+_eye+" shirt-visible-"+_shirt
34 | _style['color'] = {filter:"hue-rotate("+dna.substring(6,9) % 360 +1+"deg)"}
35 | _style['skin'] = {filter:"hue-rotate("+dna.substring(9,12) % 360 +1+"deg)"}
36 | _style['eye_color'] = {filter:"hue-rotate("+dna.substring(12,15) % 360+"deg)"}
37 | }
38 | }
39 | return (
40 |
41 | {/*

*/}
42 |

43 |

44 |

45 |

46 |

47 |

48 |

49 |

50 |

51 |

52 |

53 |

54 |

55 |

56 |

57 |

58 |

59 |

60 |

61 |

62 |

63 |

64 |

65 |

66 |

67 |

68 |

69 |

70 |

71 |

72 |

73 |

74 |

75 |

76 |

77 |

78 |

79 |

80 |

81 |
82 | );
83 | }
84 | }
85 |
86 |
87 | export default ZombiePreview;
88 |
--------------------------------------------------------------------------------
/src/ZombieSimulator.js:
--------------------------------------------------------------------------------
1 | import React,{Component} from 'react'
2 | import './static/ZombiePreview.css';
3 | import ZombiePreview from "./ZombiePreview";
4 | import ZombieToggler from "./ZombieToggler";
5 |
6 |
7 |
8 | class ZombieSimulator extends Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | _value:{
13 | "head":1,
14 | "eye":1,
15 | "shirt":1
16 | },
17 | _className:"zombie-parts head-visible-1 eye-visible-1 shirt-visible-1",
18 | _style:{
19 | eye_color:{filter:"hue-rotate(0deg)"},
20 | skin:{filter:"hue-rotate(0deg)"},
21 | color:{filter:"hue-rotate(0deg)"},
22 | }
23 | };
24 | this.handleChange = this.handleChange.bind(this);
25 | }
26 |
27 | handleChange(event) {
28 | var _id = event.target.id.replace(/_select/,"");
29 |
30 | var _value = this.state._value
31 | var _className = this.state._className
32 | var _style = this.state._style
33 | _value[_id] = event.target.value;
34 |
35 | if(_id === "head" || _id === "eye" || _id === "shirt"){
36 | _className = "zombie-parts head-visible-"+ _value["head"] +" eye-visible-"+ _value["eye"] +" shirt-visible-" + _value["shirt"];
37 | }else{
38 | _style[_id] = {filter:"hue-rotate("+_value[_id]+"deg)"}
39 | }
40 | this.setState({_className,_style,_value});
41 | }
42 | render() {
43 | return ;
53 | }
54 | }
55 |
56 |
57 |
58 | export default ZombieSimulator
59 |
--------------------------------------------------------------------------------
/src/ZombieToggler.js:
--------------------------------------------------------------------------------
1 | import React,{Component,Fragment} from 'react'
2 |
3 |
4 | class ZombieToggler extends Component {
5 | constructor(props){
6 | super(props)
7 | this.handleChange=this.handleChange.bind(this)
8 | this.state = { list: [
9 | {
10 | "name":"head",
11 | "title":"头部基因",
12 | "max":8
13 | },{
14 | "name":"eye",
15 | "title":"眼部基因",
16 | "max":11
17 | },{
18 | "name":"shirt",
19 | "title":"上衣基因",
20 | "max":6
21 | },{
22 | "name":"skin",
23 | "title":"皮肤颜色",
24 | "max":360
25 | },{
26 | "name":"eye_color",
27 | "title":"眼睛颜色",
28 | "max":360
29 | },{
30 | "name":"color",
31 | "title":"衣服颜色",
32 | "max":360
33 | }
34 | ],inputValue:[]
35 | }
36 | }
37 | handleChange(event){
38 | var id = event.target.id.replace(/_select/,"")
39 | var _list = this.state.inputValue
40 | _list[id] = event.target.value;
41 | this.setState({
42 | inputValue:_list
43 | })
44 | this.props.handleChange(event);
45 | }
46 | render() {
47 | return (
48 |
49 |
59 |
60 | );
61 | }
62 | }
63 |
64 | export default ZombieToggler;
65 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './static/Index.css'
4 | import App from './App';
5 | require('events').EventEmitter.prototype._maxListeners = 100;
6 | ReactDOM.render(, document.getElementById('root'));
--------------------------------------------------------------------------------
/src/static/App.css:
--------------------------------------------------------------------------------
1 |
2 | @media (min-width: 576px){
3 | .block {
4 | padding: 120px 1rem;
5 | }
6 | }
7 | .block {
8 | position: relative;
9 | padding: 60px 30px;
10 | color: inherit;
11 | background-position: 50%;
12 | background-size: cover;
13 | background-repeat: no-repeat;
14 | }
15 | .zombies-hero.no-webp {
16 | background-image: url(./index_bg.png);
17 | }
18 | .zombies-hero {
19 | background-repeat: no-repeat;
20 | background-position: center top;
21 | background-size: cover;
22 | background-size: 100% auto;
23 | }
24 | .pt-5 {
25 | padding-top: 3rem!important;
26 | }
27 | .pb-0 {
28 | padding-bottom: 0!important;
29 | }
30 | article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {
31 | display: block;
32 | }
33 | *, :after, :before {
34 | box-sizing: inherit;
35 | }
36 | .zombies-hero .container {
37 | padding-top: 35%;
38 | text-align: center;
39 | max-width: 1260px;
40 | overflow: auto;
41 | display: -webkit-box;
42 | }
43 | .container {
44 | margin-right: auto;
45 | margin-left: auto;
46 | padding-right: 10px;
47 | padding-left: 10px;
48 | width: 100%;
49 | }
50 | .zombies-hero .menu {
51 | background-color: rgba(0,0,0,.5);
52 | padding-top: 20px;
53 | height: min-content;
54 | display: flex;
55 | width: 100%;
56 | }
57 | .zombies-hero .menu ul {
58 | width: 100%;
59 | display: flex;
60 | }
61 | .zombies-hero a {
62 | color: #fff;
63 | }
64 | .zombies-hero a:hover {
65 | color: #fff;
66 | text-decoration: none;
67 | }
68 | .zombies-hero .menu li {
69 | width: 33%;
70 | }
71 |
72 | .start-course-btn:active {
73 | background: url(./Btn_Register_Normal.png);
74 | background-size: 100% 100%;
75 | }
76 | .start-course-btn:hover {
77 | background: url(./Btn_Register_Over.png);
78 | background-size: 100% 100%;
79 | }
80 | .start-course-btn {
81 | cursor: pointer;
82 | background: url(./Btn_Register_Normal.png);
83 | background-position: top;
84 | background-size: 100% 100%;
85 | background-color: transparent;
86 | border: none;
87 | outline: none;
88 | font-family: soleil,sans-serif;
89 | font-size: 20px;
90 | text-shadow: 0 2px 7px #000;
91 | color: #fff;
92 | padding: 40px 65px;
93 | }
94 |
95 | [type=reset], [type=submit], button, html [type=button] {
96 | -webkit-appearance: button;
97 | }
98 | #root{
99 | background: url(./walls.jpg);
100 | background-size: cover;
101 | background-position: 50%;
102 | }
103 | .zombie-container {
104 | padding-top: 0px;
105 | }
106 | .zombie-container .container{
107 | text-align: center;
108 | max-width: 1260px;
109 | }
110 |
111 | .zombie-container .area{
112 | background-color: rgba(0,0,0,0.5);
113 | padding: 20px;
114 | height: min-content;
115 | }
116 |
117 | .start-admin-btn:hover {
118 | -webkit-transition: all .6s ease 0s;
119 | transition: all .6s ease 0s;
120 | -webkit-filter: brightness(130%);
121 | filter: brightness(130%);
122 | }
123 | .start-admin-btn {
124 | cursor: pointer;
125 | background: url(./learn_more_btn.png);
126 | background-position: 50% 20px;
127 | background-size: 90%;
128 | background-color: transparent;
129 | background-repeat: no-repeat;
130 | border: none;
131 | outline: none;
132 | font-family: soleil,sans-serif;
133 | font-size: 20px;
134 | text-shadow: 0 2px 7px #000;
135 | color: #fff;
136 | padding: 40px 65px;
137 | }
138 |
139 | .home-card{
140 | background-image: url(./homecard@2x.png);
141 | background-repeat: no-repeat;
142 | }
143 | .game-card {
144 | height: 42vh;
145 | width: 29vh;
146 | margin: -1rem;
147 | background-size: 100%;
148 | position: relative;
149 | transform: scale(.8);
150 | cursor: pointer;
151 | transition: transform 0.5s;
152 | }
153 | .cards{
154 | justify-content: space-around!important;
155 | flex-wrap: wrap!important;
156 | display: flex!important;
157 | }
158 | .cards a{
159 | display: flex!important;
160 | color: unset;
161 | }
162 | .game-card .zombie-parts{
163 | margin-left: 0vh;
164 | margin-top: 38vh;
165 | transform: scale(1.5);
166 | }
167 | .zombie-card {
168 | position: absolute;
169 | left: 50%;
170 | top: 51vh;
171 | font-size: 40px;
172 | width: 48vh;
173 | margin-left: -8vh;
174 | text-align: center;
175 | transform: scale(1);
176 | background-color: rgba(0,0,0,.2)!important;
177 | }
178 | .card-header:first-child {
179 | border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0;
180 | }
181 | .hide-overflow-text {
182 | text-overflow: ellipsis;
183 | white-space: nowrap;
184 | overflow: hidden;
185 | }
186 | .bg-dark {
187 | background-color: rgba(0,0,0,.7)!important;
188 | }
189 | .game-card[active='1'] {
190 | transform: rotate(5deg);
191 | }
192 | .game-card[active='0'] {
193 | transform: rotate(0deg);
194 | transform: scale(.8);
195 | }
196 | .game-card:hover {
197 | transform: rotate(5deg);
198 | }
199 | .zombie-detail{
200 | padding-top: 1.5rem !important;
201 | position: relative;
202 | width: 70%;
203 | min-height: 1px;
204 | padding-right: 10px;
205 | padding-left: 10px;
206 | flex-basis: 0px;
207 | flex-grow: 1;
208 | max-width: 100%;
209 | margin-top: 20vh;
210 | }
211 | .zombie-detail dl{
212 | display: inline-block;
213 | background-color: rgba(0,0,0,.3)!important;
214 | padding: 30px 0px;
215 | }
216 | .zombie-detail dt,dd{
217 | float:left;
218 | padding: 10px 0px;
219 | }
220 | .zombie-detail dt{
221 | width: 30%;
222 | }
223 | .zombie-detail dd{
224 | width: 70%;
225 | }
226 | .zombie-detail dl>:first-child,.zombie-detail dl>:last-child{
227 |
228 | width: 100%;
229 | }
230 | .zombie-detail dl>:last-child{
231 | margin-top: 30px;
232 | }
233 |
234 | .attack-btn:hover {
235 | -webkit-transition: all .6s ease 0s;
236 | transition: all .6s ease 0s;
237 | -webkit-filter: brightness(130%);
238 | filter: brightness(130%);
239 | }
240 | .attack-btn {
241 | cursor: pointer;
242 | background: url(./start_btn.png);
243 | background-position: top;
244 | background-size: 100%;
245 | background-color: transparent;
246 | border: none;
247 | outline: none;
248 | font-family: soleil,sans-serif;
249 | font-size: 20px;
250 | text-shadow: 0 2px 7px #000;
251 | color: #fff;
252 | height: 77px;
253 | width: 528px;
254 | margin-top: 50px;
255 | }
256 | .attack-btn span{
257 | margin-top: 10px;
258 | display: block;
259 |
260 | }
261 | .zombieInput{
262 | margin: 30px 0px;
263 | width: 100%;
264 | }
265 | .zombieInput input{
266 | width: 300px;
267 | line-height: 30px;
268 | font-size: 28px;
269 | text-align: center;
270 | background-color: #000;
271 | color: #fff;
272 | padding: 10px;
273 | border: 1px solid #999;
274 | }
275 | button a,button a:hover{
276 | color: unset!important;
277 | text-decoration: none!important;
278 | background: none;
279 | }
280 | .flex{
281 | display: flex!important;
282 | }
283 |
284 | .zombie-attack .zombie-preview {
285 | transform: scale(0.5);
286 | }
287 | .zombie-attack .zombie-detail{
288 | margin-top: 0px;
289 | padding-top: 0px;
290 | }
291 | .target-card{
292 | transform: none;
293 | background-image: url(./tester-bg@2x.png);
294 | background-size: 85%;
295 | background-repeat: no-repeat;
296 | background-position: center;
297 | }
298 | .target-card:hover{
299 | transform: none;
300 | }
301 | .modal{
302 | position: absolute;
303 | background: rgba(0,0,0,.8);
304 | top: 25px;
305 | left: 10%;
306 | right: 10%;
307 | padding: 15px;
308 | z-index: 999;
309 | }
310 | .battelArea{
311 | display: flex;
312 | min-height: 300px;
313 | }
314 | .battelArea .targetZombie,.battelArea .myZombie{
315 | width: 33%;
316 | margin-top: -200px;
317 | transform: scale(0.5);
318 | }
319 | .battelArea .myZombie{
320 | transform: rotateY(180deg) scale(0.5);
321 | }
322 | .battelArea .vs{
323 | width: 33%;
324 | font-size: 100px;
325 | color: #fff;
326 | font-weight: bolder;
327 | line-height: 300px;
328 | }
329 | .pay-btn:hover {
330 | -webkit-transition: all .6s ease 0s;
331 | transition: all .6s ease 0s;
332 | -webkit-filter: brightness(130%);
333 | filter: brightness(130%);
334 | }
335 | .pay-btn {
336 | cursor: pointer;
337 | background: url(./learn_more_btn.png);
338 | background-position: top;
339 | background-size: 100%;
340 | background-color: transparent;
341 | border: none;
342 | outline: none;
343 | font-family: soleil,sans-serif;
344 | font-size: 20px;
345 | text-shadow: 0 2px 7px #000;
346 | color: #fff;
347 | height: 66px;
348 | width: 210px;
349 | margin-top: 50px;
350 | }
351 | .pay-btn-last {
352 | margin-top: 0px;
353 | }
354 | .pay-btn span{
355 | margin-top: 10px;
356 | display: block;
357 |
358 | }
359 | .zombie-simulator .zombie-parts{
360 | width: 50%;
361 | margin-top: 16vh;
362 | }
363 | .zombie-simulator .zombie-preview{
364 | background-repeat: no-repeat;
365 | background-size: 70%;
366 | background-position: center top;
367 | }
368 | .transactionHash{
369 | display: none;
370 | }
371 | .transactionHash[display='1']{
372 | display: block;
373 | }
374 | .buyArea[display='0'],.createArea[display='0']{
375 | display: none;
376 | }
377 | .buyArea[display='1'],.createArea[display='1']{
378 | display: block;
379 | }
380 | .contract-admin dl{
381 | display: flex;
382 | flex-wrap: wrap;
383 | }
384 | .contract-admin dt{
385 | width: 30%;
386 | padding: 10px 0px;
387 | }
388 | .contract-admin dd{
389 | width: 70%;
390 | font-family: auto;
391 | font-size: 16px;
392 | letter-spacing: 1px;
393 | }
394 | .contract-admin .pay-btn{
395 | height: 40px;
396 | width: 105px;
397 | font-size: 14px;
398 | background-position: 0px 8px;
399 | background-repeat: no-repeat;
400 | margin-left: 20px;
401 | }
402 | .contract-admin .pay-btn span{
403 | margin-top: 15px;
404 | }
405 | .lowcase{
406 | text-transform: lowercase;
407 | }
--------------------------------------------------------------------------------
/src/static/Btn_Register_Normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/Btn_Register_Normal.png
--------------------------------------------------------------------------------
/src/static/Btn_Register_Over.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/Btn_Register_Over.png
--------------------------------------------------------------------------------
/src/static/Index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | font-size: 1rem;
9 | font-weight: 400;
10 | line-height: 1.5;
11 | color: rgb(207, 210, 218);
12 | text-align: left;
13 | }
14 | code {
15 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
16 | monospace;
17 | }
18 | ul,li{
19 | list-style: none;
20 | margin: 0px!important;
21 | padding: 0px;
22 | }
23 |
24 | :root {
25 | --blue: #007bff;
26 | --indigo: #6610f2;
27 | --purple: #6f42c1;
28 | --pink: #e83e8c;
29 | --red: #dc3545;
30 | --orange: #fd7e14;
31 | --yellow: #ffc107;
32 | --green: #28a745;
33 | --teal: #20c997;
34 | --cyan: #17a2b8;
35 | --white: #fff;
36 | --gray: #6c757d;
37 | --gray-dark: #343a40;
38 | --primary: #1997c6;
39 | --secondary: #6c757d;
40 | --success: #1bc98e;
41 | --info: #9f86ff;
42 | --warning: #e4d836;
43 | --danger: #e64759;
44 | --light: #f8f9fa;
45 | --dark: #1a1c22;
46 | --black: #000;
47 | --light-grey: #30343e;
48 | --shaded: rgba(0, 0, 0, 0.2);
49 | --breakpoint-xs: 0;
50 | --breakpoint-sm: 576px;
51 | --breakpoint-md: 768px;
52 | --breakpoint-lg: 992px;
53 | --breakpoint-xl: 1200px;
54 | --font-family-sans-serif: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif;
55 | --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
56 | }
57 |
58 | *,
59 | ::after,
60 | ::before {
61 | box-sizing: border-box;
62 | }
63 |
64 | html {
65 | font-family: sans-serif;
66 | line-height: 1.15;
67 | text-size-adjust: 100%;
68 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
69 | }
70 |
71 | article,
72 | aside,
73 | figcaption,
74 | figure,
75 | footer,
76 | header,
77 | hgroup,
78 | main,
79 | nav,
80 | section {
81 | display: block;
82 | }
83 |
84 | [tabindex="-1"]:focus {
85 | outline: 0px !important;
86 | }
87 |
88 | hr {
89 | box-sizing: content-box;
90 | height: 0px;
91 | overflow: visible;
92 | }
93 |
94 | h1,
95 | h2,
96 | h3,
97 | h4,
98 | h5,
99 | h6 {
100 | margin-top: 0px;
101 | margin-bottom: 0.5rem;
102 | }
103 |
104 | p {
105 | margin-top: 0px;
106 | margin-bottom: 1rem;
107 | }
108 |
109 | abbr[data-original-title],
110 | abbr[title] {
111 | text-decoration: underline dotted;
112 | cursor: help;
113 | border-bottom: 0px;
114 | }
115 |
116 | address {
117 | font-style: normal;
118 | line-height: inherit;
119 | }
120 |
121 | address,
122 | dl,
123 | ol,
124 | ul {
125 | margin-bottom: 1rem;
126 | }
127 |
128 | dl,
129 | ol,
130 | ul {
131 | margin-top: 0px;
132 | }
133 |
134 | ol ol,
135 | ol ul,
136 | ul ol,
137 | ul ul {
138 | margin-bottom: 0px;
139 | }
140 |
141 | dt {
142 | font-weight: 700;
143 | }
144 |
145 | dd {
146 | margin-bottom: 0.5rem;
147 | margin-left: 0px;
148 | }
149 |
150 | blockquote {
151 | margin: 0px 0px 1rem;
152 | }
153 |
154 | dfn {
155 | font-style: italic;
156 | }
157 |
158 | b,
159 | strong {
160 | font-weight: bolder;
161 | }
162 |
163 | small {
164 | font-size: 80%;
165 | }
166 |
167 | sub,
168 | sup {
169 | position: relative;
170 | font-size: 75%;
171 | line-height: 0;
172 | vertical-align: baseline;
173 | }
174 |
175 | sub {
176 | bottom: -0.25em;
177 | }
178 |
179 | sup {
180 | top: -0.5em;
181 | }
182 |
183 | a {
184 | color: rgb(0, 123, 255);
185 | text-decoration: none;
186 | background-color: transparent;
187 | }
188 |
189 | a:hover {
190 | color: rgb(0, 86, 179);
191 | text-decoration: underline;
192 | }
193 |
194 | a:not([href]):not([tabindex]),
195 | a:not([href]):not([tabindex]):focus,
196 | a:not([href]):not([tabindex]):hover {
197 | color: inherit;
198 | text-decoration: none;
199 | }
200 |
201 | a:not([href]):not([tabindex]):focus {
202 | outline: 0px;
203 | }
204 |
205 | code,
206 | kbd,
207 | pre,
208 | samp {
209 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
210 | font-size: 1em;
211 | }
212 |
213 | figure {
214 | margin: 0px 0px 1rem;
215 | }
216 |
217 | img {
218 | border-style: none;
219 | }
220 |
221 | img,
222 | svg {
223 | vertical-align: middle;
224 | }
225 |
226 | svg {
227 | overflow: hidden;
228 | }
229 |
230 | table {
231 | border-collapse: collapse;
232 | }
233 |
234 | caption {
235 | padding-top: 0.75rem;
236 | padding-bottom: 0.75rem;
237 | color: rgb(108, 117, 125);
238 | text-align: left;
239 | caption-side: bottom;
240 | }
241 |
242 | th {
243 | text-align: inherit;
244 | }
245 |
246 | label {
247 | display: inline-block;
248 | margin-bottom: 0.5rem;
249 | }
250 |
251 | button {
252 | border-radius: 0px;
253 | }
254 |
255 |
256 | button,
257 | input,
258 | optgroup,
259 | select,
260 | textarea {
261 | margin: 0px;
262 | font-family: inherit;
263 | font-size: inherit;
264 | line-height: inherit;
265 | }
266 |
267 | button,
268 | input {
269 | overflow: visible;
270 | }
271 |
272 | button,
273 | select {
274 | text-transform: none;
275 | }
276 |
277 | [type="reset"],
278 | [type="submit"],
279 | button,
280 | html [type="button"] {
281 | -webkit-appearance: button;
282 | }
283 |
284 | input[type="checkbox"],
285 | input[type="radio"] {
286 | box-sizing: border-box;
287 | padding: 0px;
288 | }
289 |
290 | input[type="date"],
291 | input[type="datetime-local"],
292 | input[type="month"],
293 | input[type="time"] {
294 | -webkit-appearance: listbox;
295 | }
296 |
297 | textarea {
298 | overflow: auto;
299 | resize: vertical;
300 | }
301 |
302 | fieldset {
303 | min-width: 0px;
304 | padding: 0px;
305 | margin: 0px;
306 | border: 0px;
307 | }
308 |
309 | legend {
310 | display: block;
311 | width: 100%;
312 | max-width: 100%;
313 | padding: 0px;
314 | margin-bottom: 0.5rem;
315 | font-size: 1.5rem;
316 | line-height: inherit;
317 | color: inherit;
318 | white-space: normal;
319 | }
320 |
321 | progress {
322 | vertical-align: baseline;
323 | }
324 |
325 | [type="number"]::-webkit-inner-spin-button,
326 | [type="number"]::-webkit-outer-spin-button {
327 | height: auto;
328 | }
329 |
330 | [type="search"] {
331 | outline-offset: -2px;
332 | -webkit-appearance: none;
333 | }
334 |
335 | [type="search"]::-webkit-search-cancel-button,
336 | [type="search"]::-webkit-search-decoration {
337 | -webkit-appearance: none;
338 | }
339 |
340 | ::-webkit-file-upload-button {
341 | font: inherit;
342 | -webkit-appearance: button;
343 | }
344 |
345 | output {
346 | display: inline-block;
347 | }
348 |
349 | summary {
350 | display: list-item;
351 | cursor: pointer;
352 | }
353 |
354 | template {
355 | display: none;
356 | }
357 |
358 | [hidden] {
359 | display: none !important;
360 | }
361 |
362 | hr {
363 | margin-top: 1rem;
364 | margin-bottom: 1rem;
365 | border-width: 1px 0px 0px;
366 | border-right-style: initial;
367 | border-bottom-style: initial;
368 | border-left-style: initial;
369 | border-right-color: initial;
370 | border-bottom-color: initial;
371 | border-left-color: initial;
372 | border-image: initial;
373 | border-top-style: solid;
374 | border-top-color: rgb(67, 72, 87);
375 | }
376 |
377 | code {
378 | font-size: 87.5%;
379 | color: rgb(232, 62, 140);
380 | word-break: break-word;
381 | }
382 |
383 | a>code {
384 | color: inherit;
385 | }
386 |
387 | kbd {
388 | padding: 0.2rem 0.4rem;
389 | font-size: 87.5%;
390 | color: rgb(255, 255, 255);
391 | background-color: rgb(33, 37, 41);
392 | border-radius: 0.2rem;
393 | }
394 |
395 | kbd kbd {
396 | padding: 0px;
397 | font-size: 100%;
398 | font-weight: 700;
399 | }
400 |
401 | pre {
402 | display: block;
403 | font-size: 87.5%;
404 | color: rgb(33, 37, 41);
405 | }
406 |
407 | pre code {
408 | font-size: inherit;
409 | color: inherit;
410 | word-break: normal;
411 | }
--------------------------------------------------------------------------------
/src/static/ZombiePreview.css:
--------------------------------------------------------------------------------
1 |
2 | .zombie-parts-bin-component {
3 | min-height: 100%;
4 | }
5 |
6 | .zombie-preview {
7 | height: 84vh;
8 | width: 47vh;
9 | background-size: cover;
10 | background-image: url(./tester-bg@2x.png)
11 | }
12 |
13 | .zombie-char {
14 | position: relative;
15 | }
16 |
17 | .zombie-parts {
18 | position: relative;
19 | margin-left: -2vh;
20 | margin-top: 31vh;
21 | }
22 |
23 | .zombie-loading {
24 | background: url(./zombierun.png) 0;
25 | background-size: cover;
26 | height: 287px;
27 | width: 192px;
28 | position: absolute;
29 | left: 16vh;
30 | animation: play-data-v-3614808b .7s steps(24) infinite;
31 | }
32 |
33 | @keyframes play-data-v-3614808b {
34 | to {
35 | background-position: -4608px
36 | }
37 | }
38 |
39 | .zombie-parts {
40 | position: relative;
41 | margin-left: -2vh;
42 | margin-top: 31vh
43 | }
44 |
45 | .zombie-parts .head {
46 | width: 28vh;
47 | position: absolute;
48 | left: 13vh;
49 | top: -4vh
50 | }
51 |
52 | .zombie-parts .eye {
53 | width: 13vh;
54 | position: absolute;
55 | left: 23vh;
56 | top: 8vh;
57 | }
58 |
59 | .zombie-parts .shirt {
60 | width: 13vh;
61 | position: absolute;
62 | left: 15.6vh;
63 | top: 13vh
64 | }
65 |
66 | .mouth {
67 | width: 6vh;
68 | position: absolute;
69 | left: 26.6vh;
70 | top: 15vh
71 | }
72 |
73 | .torso {
74 | width: 13vh;
75 | position: absolute;
76 | left: 15.6vh;
77 | top: 13vh
78 | }
79 |
80 | .left-thigh {
81 | width: 6vh;
82 | position: absolute;
83 | left: 17.3vh;
84 | top: 22vh
85 | }
86 |
87 | .right-thigh {
88 | width: 6vh;
89 | position: absolute;
90 | left: 20.4vh;
91 | top: 22vh
92 | }
93 |
94 | .cat-legs {
95 | width: 10vh;
96 | position: absolute;
97 | left: 15.4vh;
98 | top: 18vh
99 | }
100 |
101 | .left-hand {
102 | width: 4vh;
103 | position: absolute;
104 | left: 24.3vh;
105 | top: 19vh
106 | }
107 |
108 | .right-hand {
109 | width: 4vh;
110 | position: absolute;
111 | left: 28.4vh;
112 | top: 19vh
113 | }
114 |
115 | .left-forearm {
116 | width: 4vh;
117 | position: absolute;
118 | left: 22.3vh;
119 | top: 20vh
120 | }
121 |
122 | .right-forearm {
123 | width: 4vh;
124 | position: absolute;
125 | left: 26.4vh;
126 | top: 20vh
127 | }
128 |
129 | .left-upper-arm {
130 | width: 6vh;
131 | position: absolute;
132 | left: 19.3vh;
133 | top: 16vh
134 | }
135 |
136 | .right-upper-arm {
137 | width: 6vh;
138 | position: absolute;
139 | left: 23.4vh;
140 | top: 16vh
141 | }
142 |
143 | .left-leg {
144 | width: 4vh;
145 | position: absolute;
146 | left: 18.3vh;
147 | top: 27vh
148 | }
149 |
150 | .right-leg {
151 | width: 3.3vh;
152 | position: absolute;
153 | left: 22.3vh;
154 | top: 27.6vh
155 | }
156 |
157 | .left-feet {
158 | width: 4vh;
159 | position: absolute;
160 | left: 18.3vh;
161 | top: 30vh
162 | }
163 |
164 | .right-feet {
165 | width: 3.3vh;
166 | position: absolute;
167 | left: 22.3vh;
168 | top: 30.3vh
169 | }
170 |
171 | .zombie-name {
172 | text-transform: uppercase;
173 | text-shadow: 5px 5px 5px rgba(0, 0, 0, .2)
174 | }
175 |
176 |
177 | .zombie-name {
178 | font-weight: 700
179 | }
180 |
181 | .home-card .zombie-char {
182 | left: -6vh;
183 | top: -27vh;
184 | transform: scale(0.4);
185 | }
186 |
187 |
188 | .card[data-v-ab64d37c] .card-header {
189 | background: transparent;
190 | }
191 |
192 | input[type="range"] {
193 | width: 100%;
194 | }
195 |
196 | a[data-v-2133ad68] {
197 | text-decoration: none;
198 | }
199 |
200 | ul[data-v-4a0b5f72] {
201 | overflow-y: scroll;
202 | }
203 |
204 | ul[data-v-4a0b5f72]::-webkit-scrollbar {
205 | display: none;
206 | }
207 |
208 | .form-control.is-invalid,
209 | .form-control.is-valid,
210 | .was-validated .form-control:invalid,
211 | .was-validated .form-control:valid {
212 | background-position: right calc(0.375em + 0.1875rem) center;
213 | }
214 |
215 | input[type="color"].form-control {
216 | height: calc((1.5em + 0.75rem) + 2px);
217 | padding: 0.125rem 0.25rem;
218 | }
219 |
220 | .input-group-sm input[type="color"].form-control,
221 | input[type="color"].form-control.form-control-sm {
222 | height: calc((1.5em + 0.5rem) + 2px);
223 | padding: 0.125rem 0.25rem;
224 | }
225 |
226 | .input-group-lg input[type="color"].form-control,
227 | input[type="color"].form-control.form-control-lg {
228 | height: calc((1.5em + 1rem) + 2px);
229 | padding: 0.125rem 0.25rem;
230 | }
231 |
232 | input[type="color"].form-control:disabled {
233 | background-color: rgb(173, 181, 189);
234 | opacity: 0.65;
235 | }
236 |
237 | .input-group>.custom-range {
238 | position: relative;
239 | flex: 1 1 auto;
240 | width: 1%;
241 | margin-bottom: 0px;
242 | }
243 |
244 | .input-group>.custom-file+.custom-range,
245 | .input-group>.custom-range+.custom-file,
246 | .input-group>.custom-range+.custom-range,
247 | .input-group>.custom-range+.custom-select,
248 | .input-group>.custom-range+.form-control,
249 | .input-group>.custom-range+.form-control-plaintext,
250 | .input-group>.custom-select+.custom-range,
251 | .input-group>.form-control+.custom-range,
252 | .input-group>.form-control-plaintext+.custom-range {
253 | margin-left: -1px;
254 | }
255 |
256 | .input-group>.custom-range:focus {
257 | z-index: 3;
258 | }
259 |
260 | .input-group>.custom-range:not(:last-child) {
261 | border-top-right-radius: 0px;
262 | border-bottom-right-radius: 0px;
263 | }
264 |
265 | .input-group>.custom-range:not(:first-child) {
266 | border-top-left-radius: 0px;
267 | border-bottom-left-radius: 0px;
268 | }
269 |
270 | .input-group>.custom-range {
271 | padding: 0px 0.75rem;
272 | background-color: rgb(255, 255, 255);
273 | background-clip: padding-box;
274 | border: 1px solid rgb(206, 212, 218);
275 | height: calc((1.5em + 0.75rem) + 2px);
276 | border-radius: 0.25rem;
277 | transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;
278 | }
279 |
280 | .input-group>.custom-range:focus {
281 | color: rgb(73, 80, 87);
282 | background-color: rgb(255, 255, 255);
283 | border-color: rgb(128, 189, 255);
284 | outline: 0px;
285 | box-shadow: rgba(0, 123, 255, 0.25) 0px 0px 0px 0.2rem;
286 | }
287 |
288 | .input-group>.custom-range:disabled,
289 | .input-group>.custom-range[readonly] {
290 | background-color: rgb(233, 236, 239);
291 | }
292 |
293 | .input-group-lg>.custom-range {
294 | height: calc((1.5em + 1rem) + 2px);
295 | padding: 0px 1rem;
296 | border-radius: 0.3rem;
297 | }
298 |
299 | .input-group-sm>.custom-range {
300 | height: calc((1.5em + 0.5rem) + 2px);
301 | padding: 0px 0.5rem;
302 | border-radius: 0.2rem;
303 | }
304 |
305 | .input-group .custom-range.is-valid,
306 | .was-validated .input-group .custom-range:valid {
307 | border-color: rgb(40, 167, 69);
308 | }
309 |
310 | .input-group .custom-range.is-valid:focus,
311 | .was-validated .input-group .custom-range:valid:focus {
312 | border-color: rgb(40, 167, 69);
313 | box-shadow: rgba(40, 167, 69, 0.25) 0px 0px 0px 0.2rem;
314 | }
315 |
316 | .custom-range.is-valid:focus::-webkit-slider-thumb,
317 | .was-validated .custom-range:valid:focus::-webkit-slider-thumb {
318 | box-shadow: rgb(255, 255, 255) 0px 0px 0px 1px, rgb(155, 231, 172) 0px 0px 0px 0.2rem;
319 | }
320 |
321 | .custom-range.is-valid::-webkit-slider-thumb,
322 | .was-validated .custom-range:valid::-webkit-slider-thumb {
323 | background-color: rgb(40, 167, 69);
324 | background-image: none;
325 | }
326 |
327 | .custom-range.is-valid::-webkit-slider-thumb:active,
328 | .was-validated .custom-range:valid::-webkit-slider-thumb:active {
329 | background-color: rgb(155, 231, 172);
330 | background-image: none;
331 | }
332 |
333 | .custom-range.is-valid::-webkit-slider-runnable-track,
334 | .was-validated .custom-range:valid::-webkit-slider-runnable-track {
335 | background-color: rgba(40, 167, 69, 0.35);
336 | }
337 |
338 | .custom-range.is-valid~.valid-feedback,
339 | .custom-range.is-valid~.valid-tooltip,
340 | .was-validated .custom-range:valid~.valid-feedback,
341 | .was-validated .custom-range:valid~.valid-tooltip {
342 | display: block;
343 | }
344 |
345 | .input-group .custom-range.is-invalid,
346 | .was-validated .input-group .custom-range:invalid {
347 | border-color: rgb(220, 53, 69);
348 | }
349 |
350 | .input-group .custom-range.is-invalid:focus,
351 | .was-validated .input-group .custom-range:invalid:focus {
352 | border-color: rgb(220, 53, 69);
353 | box-shadow: rgba(220, 53, 69, 0.25) 0px 0px 0px 0.2rem;
354 | }
355 |
356 | .custom-range.is-invalid:focus::-webkit-slider-thumb,
357 | .was-validated .custom-range:invalid:focus::-webkit-slider-thumb {
358 | box-shadow: rgb(255, 255, 255) 0px 0px 0px 1px, rgb(246, 205, 209) 0px 0px 0px 0.2rem;
359 | }
360 |
361 | .custom-range.is-invalid::-webkit-slider-thumb,
362 | .was-validated .custom-range:invalid::-webkit-slider-thumb {
363 | background-color: rgb(220, 53, 69);
364 | background-image: none;
365 | }
366 |
367 | .custom-range.is-invalid::-webkit-slider-thumb:active,
368 | .was-validated .custom-range:invalid::-webkit-slider-thumb:active {
369 | background-color: rgb(246, 205, 209);
370 | background-image: none;
371 | }
372 |
373 | .custom-range.is-invalid::-webkit-slider-runnable-track,
374 | .was-validated .custom-range:invalid::-webkit-slider-runnable-track {
375 | background-color: rgba(220, 53, 69, 0.35);
376 | }
377 |
378 | .custom-range.is-invalid~.invalid-feedback,
379 | .custom-range.is-invalid~.invalid-tooltip,
380 | .was-validated .custom-range:invalid~.invalid-feedback,
381 | .was-validated .custom-range:invalid~.invalid-tooltip {
382 | display: block;
383 | }
384 |
385 |
386 | .row {
387 | display: flex;
388 | flex-wrap: wrap;
389 | padding: 10px 30px;
390 | }
391 |
392 | .col {
393 | position: relative;
394 | width: 100%;
395 | min-height: 1px;
396 | padding-right: 10px;
397 | padding-left: 10px;
398 | flex-basis: 0px;
399 | flex-grow: 1;
400 | max-width: 100%;
401 | }
402 |
403 | .form-control {
404 | display: block;
405 | width: 100%;
406 | height: calc(2.25rem + 2px);
407 | padding: 0.375rem 0.75rem;
408 | font-size: 1rem;
409 | line-height: 1.5;
410 | color: rgb(255, 255, 255);
411 | background-color: rgb(67, 72, 87);
412 | background-clip: padding-box;
413 | border: 1px solid rgb(67, 72, 87);
414 | border-radius: 0.25rem;
415 | transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;
416 | }
417 |
418 | .form-control:focus {
419 | color: rgb(73, 80, 87);
420 | background-color: rgb(255, 255, 255);
421 | border-color: rgb(128, 189, 255);
422 | outline: 0px;
423 | box-shadow: rgba(0, 123, 255, 0.25) 0px 0px 0px 0.2rem;
424 | }
425 |
426 | .form-control::-webkit-input-placeholder {
427 | color: rgb(108, 117, 125);
428 | opacity: 1;
429 | }
430 |
431 | .form-control::placeholder {
432 | color: rgb(108, 117, 125);
433 | opacity: 1;
434 | }
435 |
436 | .form-control:disabled,
437 | .form-control[readonly] {
438 | background-color: rgb(48, 52, 62);
439 | opacity: 1;
440 | }
441 |
442 | select.form-control[multiple],
443 | select.form-control[size],
444 | textarea.form-control {
445 | height: auto;
446 | }
447 |
448 | .form-group {
449 | margin-bottom: 1rem;
450 | }
451 |
452 | .form-row>.col,
453 | .form-row>[class*="col-"] {
454 | padding-right: 5px;
455 | padding-left: 5px;
456 | }
457 |
458 | .custom-select.is-valid,
459 | .form-control.is-valid,
460 | .was-validated .custom-select:valid,
461 | .was-validated .form-control:valid {
462 | border-color: rgb(40, 167, 69);
463 | }
464 |
465 | .custom-select.is-valid:focus,
466 | .form-control.is-valid:focus,
467 | .was-validated .custom-select:valid:focus,
468 | .was-validated .form-control:valid:focus {
469 | border-color: rgb(40, 167, 69);
470 | box-shadow: rgba(40, 167, 69, 0.25) 0px 0px 0px 0.2rem;
471 | }
472 |
473 | .custom-select.is-valid~.valid-feedback,
474 | .custom-select.is-valid~.valid-tooltip,
475 | .form-control-file.is-valid~.valid-feedback,
476 | .form-control-file.is-valid~.valid-tooltip,
477 | .form-control.is-valid~.valid-feedback,
478 | .form-control.is-valid~.valid-tooltip,
479 | .was-validated .custom-select:valid~.valid-feedback,
480 | .was-validated .custom-select:valid~.valid-tooltip,
481 | .was-validated .form-control-file:valid~.valid-feedback,
482 | .was-validated .form-control-file:valid~.valid-tooltip,
483 | .was-validated .form-control:valid~.valid-feedback,
484 | .was-validated .form-control:valid~.valid-tooltip {
485 | display: block;
486 | }
487 |
488 | .custom-select.is-invalid,
489 | .form-control.is-invalid,
490 | .was-validated .custom-select:invalid,
491 | .was-validated .form-control:invalid {
492 | border-color: rgb(220, 53, 69);
493 | }
494 |
495 | .custom-select.is-invalid:focus,
496 | .form-control.is-invalid:focus,
497 | .was-validated .custom-select:invalid:focus,
498 | .was-validated .form-control:invalid:focus {
499 | border-color: rgb(220, 53, 69);
500 | box-shadow: rgba(220, 53, 69, 0.25) 0px 0px 0px 0.2rem;
501 | }
502 |
503 | .custom-select.is-invalid~.invalid-feedback,
504 | .custom-select.is-invalid~.invalid-tooltip,
505 | .form-control-file.is-invalid~.invalid-feedback,
506 | .form-control-file.is-invalid~.invalid-tooltip,
507 | .form-control.is-invalid~.invalid-feedback,
508 | .form-control.is-invalid~.invalid-tooltip,
509 | .was-validated .custom-select:invalid~.invalid-feedback,
510 | .was-validated .custom-select:invalid~.invalid-tooltip,
511 | .was-validated .form-control-file:invalid~.invalid-feedback,
512 | .was-validated .form-control-file:invalid~.invalid-tooltip,
513 | .was-validated .form-control:invalid~.invalid-feedback,
514 | .was-validated .form-control:invalid~.invalid-tooltip {
515 | display: block;
516 | }
517 |
518 | .input-group>.custom-file,
519 | .input-group>.custom-select,
520 | .input-group>.form-control {
521 | position: relative;
522 | flex: 1 1 auto;
523 | width: 1%;
524 | margin-bottom: 0px;
525 | }
526 |
527 | .input-group>.custom-file+.custom-file,
528 | .input-group>.custom-file+.custom-select,
529 | .input-group>.custom-file+.form-control,
530 | .input-group>.custom-select+.custom-file,
531 | .input-group>.custom-select+.custom-select,
532 | .input-group>.custom-select+.form-control,
533 | .input-group>.form-control+.custom-file,
534 | .input-group>.form-control+.custom-select,
535 | .input-group>.form-control+.form-control {
536 | margin-left: -1px;
537 | }
538 |
539 | .input-group>.custom-file .custom-file-input:focus~.custom-file-label,
540 | .input-group>.custom-select:focus,
541 | .input-group>.form-control:focus {
542 | z-index: 3;
543 | }
544 |
545 | .input-group>.custom-select:not(:last-child),
546 | .input-group>.form-control:not(:last-child) {
547 | border-top-right-radius: 0px;
548 | border-bottom-right-radius: 0px;
549 | }
550 |
551 | .input-group>.custom-select:not(:first-child),
552 | .input-group>.form-control:not(:first-child) {
553 | border-top-left-radius: 0px;
554 | border-bottom-left-radius: 0px;
555 | }
556 |
557 | .input-group-lg>.form-control,
558 | .input-group-lg>.input-group-append>.btn,
559 | .input-group-lg>.input-group-append>.input-group-text,
560 | .input-group-lg>.input-group-prepend>.btn,
561 | .input-group-lg>.input-group-prepend>.input-group-text {
562 | height: calc(2.875rem + 2px);
563 | padding: 0.5rem 1rem;
564 | font-size: 1.25rem;
565 | line-height: 1.5;
566 | border-radius: 0.3rem;
567 | }
568 |
569 | .input-group-sm>.form-control,
570 | .input-group-sm>.input-group-append>.btn,
571 | .input-group-sm>.input-group-append>.input-group-text,
572 | .input-group-sm>.input-group-prepend>.btn,
573 | .input-group-sm>.input-group-prepend>.input-group-text {
574 | height: calc(1.8125rem + 2px);
575 | padding: 0.25rem 0.5rem;
576 | font-size: 0.875rem;
577 | line-height: 1.5;
578 | border-radius: 0.2rem;
579 | }
580 |
581 | .custom-range {
582 | width: 100%;
583 | padding-left: 0px;
584 | background-color: transparent;
585 | -webkit-appearance: none;
586 | }
587 |
588 | .custom-range:focus {
589 | outline: none;
590 | }
591 |
592 | .custom-range:focus::-webkit-slider-thumb {
593 | box-shadow: rgb(255, 255, 255) 0px 0px 0px 1px, rgba(0, 123, 255, 0.25) 0px 0px 0px 0.2rem;
594 | }
595 |
596 | .custom-range::-webkit-slider-thumb {
597 | width: 1rem;
598 | height: 1rem;
599 | margin-top: -0.25rem;
600 | background-color: rgb(0, 123, 255);
601 | border: 0px;
602 | border-radius: 1rem;
603 | transition: background-color 0.15s ease-in-out 0s, border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;
604 | -webkit-appearance: none;
605 | }
606 |
607 | .custom-range::-webkit-slider-thumb:active {
608 | background-color: rgb(179, 215, 255);
609 | }
610 |
611 | .custom-range::-webkit-slider-runnable-track {
612 | width: 100%;
613 | height: 0.5rem;
614 | color: transparent;
615 | cursor: pointer;
616 | background-color: rgb(222, 226, 230);
617 | border-color: transparent;
618 | border-radius: 1rem;
619 | }
620 |
621 | .card-header {
622 | padding: 0.75rem 1.25rem;
623 | margin-bottom: 0px;
624 | background-color: rgba(0, 0, 0, 0.03);
625 | border-bottom: 1px solid rgba(0, 0, 0, 0.125);
626 | }
627 |
628 | .card-header:first-child {
629 | border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0px 0px;
630 | }
631 |
632 | .card-header+.list-group .list-group-item:first-child {
633 | border-top: 0px;
634 | }
635 |
636 | .accordion .card:not(:first-of-type) .card-header:first-child {
637 | border-radius: 0px;
638 | }
639 |
640 | .bg-dark {
641 | background-color: rgb(26, 28, 34) !important;
642 | }
643 |
644 | a.bg-dark:focus,
645 | a.bg-dark:hover,
646 | button.bg-dark:focus,
647 | button.bg-dark:hover {
648 | background-color: rgb(4, 4, 5) !important;
649 | }
650 |
651 | .mt-2,
652 | .my-2 {
653 | margin-top: 0.5rem !important;
654 | }
655 |
656 | .pt-4,
657 | .py-4 {
658 | padding-top: 1.5rem !important;
659 | }
660 |
661 | html {
662 | position: relative;
663 | min-height: 100%;
664 | }
665 |
666 | h1,
667 | h2 {
668 | line-height: 1.5;
669 | margin-top: 10px;
670 | margin-bottom: 10px;
671 | }
672 |
673 | h2,
674 | h3,
675 | h4,
676 | h5 {
677 | margin-top: 30px;
678 | }
679 |
680 | .hide {
681 | visibility: hidden;
682 | }
683 |
684 | .zombie-preview {
685 | position: relative;
686 | }
687 |
688 | .share-page .name-input {
689 | background-color: rgb(255, 255, 255);
690 | color: rgb(51, 51, 51);
691 | max-width: 500px;
692 | }
693 |
694 | .zombie-parts .eye,
695 | .zombie-parts .head,
696 | .zombie-parts .shirt {
697 | display: none;
698 | }
699 |
700 | .zombie-parts.eye-visible-1 .eye-part-1,
701 | .zombie-parts.eye-visible-2 .eye-part-2,
702 | .zombie-parts.eye-visible-3 .eye-part-3,
703 | .zombie-parts.eye-visible-4 .eye-part-4,
704 | .zombie-parts.eye-visible-5 .eye-part-5,
705 | .zombie-parts.eye-visible-6 .eye-part-6,
706 | .zombie-parts.eye-visible-7 .eye-part-7,
707 | .zombie-parts.eye-visible-8 .eye-part-8,
708 | .zombie-parts.eye-visible-9 .eye-part-9,
709 | .zombie-parts.eye-visible-10 .eye-part-10,
710 | .zombie-parts.eye-visible-11 .eye-part-11,
711 | .zombie-parts.head-visible-1 .head-part-1,
712 | .zombie-parts.head-visible-2 .head-part-2,
713 | .zombie-parts.head-visible-3 .head-part-3,
714 | .zombie-parts.head-visible-4 .head-part-4,
715 | .zombie-parts.head-visible-5 .head-part-5,
716 | .zombie-parts.head-visible-6 .head-part-6,
717 | .zombie-parts.head-visible-7 .head-part-7,
718 | .zombie-parts.head-visible-8 .head-part-8,
719 | .zombie-parts.shirt-visible-1 .shirt-part-1,
720 | .zombie-parts.shirt-visible-2 .shirt-part-2,
721 | .zombie-parts.shirt-visible-3 .shirt-part-3,
722 | .zombie-parts.shirt-visible-4 .shirt-part-4,
723 | .zombie-parts.shirt-visible-5 .shirt-part-5,
724 | .zombie-parts.shirt-visible-6 .shirt-part-6 {
725 | display: inherit;
726 | }
727 |
728 | .head-part-8 {
729 | z-index: 9;
730 | }
731 |
732 | .vb>.vb-dragger {
733 | z-index: 5;
734 | width: 12px;
735 | right: 0px;
736 | }
737 |
738 | .form-control {
739 | box-shadow: none;
740 | }
741 |
742 | .has-error .form-control,
743 | .has-error .form-control:focus,
744 | .has-success .form-control,
745 | .has-success .form-control:focus,
746 | .has-warning .form-control,
747 | .has-warning .form-control:focus {
748 | border-color: rgb(67, 72, 87);
749 | box-shadow: none;
750 | }
751 |
752 | @media (min-width: 992px) {
753 | .mt-lg-5,
754 | .my-lg-5 {
755 | margin-top: 3rem!important;
756 | }
757 | .pt-lg-5,
758 | .py-lg-5 {
759 | padding-top: 3rem!important;
760 | }
761 | }
--------------------------------------------------------------------------------
/src/static/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/bg.png
--------------------------------------------------------------------------------
/src/static/catlegs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/catlegs.png
--------------------------------------------------------------------------------
/src/static/get_start_btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/get_start_btn.png
--------------------------------------------------------------------------------
/src/static/homecard@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/homecard@2x.png
--------------------------------------------------------------------------------
/src/static/index_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/index_bg.png
--------------------------------------------------------------------------------
/src/static/learn_more_btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/learn_more_btn.png
--------------------------------------------------------------------------------
/src/static/lesson-complete-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/lesson-complete-bg.png
--------------------------------------------------------------------------------
/src/static/lesson_number_completed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/lesson_number_completed.png
--------------------------------------------------------------------------------
/src/static/lesson_panel_complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/lesson_panel_complete.png
--------------------------------------------------------------------------------
/src/static/start_btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/start_btn.png
--------------------------------------------------------------------------------
/src/static/tester-bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/tester-bg@2x.png
--------------------------------------------------------------------------------
/src/static/walls.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/walls.jpg
--------------------------------------------------------------------------------
/src/static/zombierun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fankouzu/my-crypto-zombie/79ede64adf382ac861897f1631599f4242db932c/src/static/zombierun.png
--------------------------------------------------------------------------------