├── game ├── imgs │ ├── nft.png │ ├── ground.png │ ├── obstacle.png │ ├── playerJumps.png │ ├── playerRuns0.png │ ├── playerRuns1.png │ └── playerStands.png ├── .gitignore ├── updateCustomProperty.js ├── ground.js ├── index.html ├── blockchain.js ├── nft.js ├── player.js ├── styles.css ├── obstacle.js └── script.js ├── contracts ├── runnerCollectionMetadata │ ├── runnerGameImages │ │ ├── 00.png │ │ ├── 11.png │ │ ├── 22.png │ │ ├── 33.png │ │ └── 44.png │ └── runnerGameJsonFiles │ │ ├── 5.json │ │ ├── 1.json │ │ ├── 2.json │ │ ├── 3.json │ │ └── 4.json ├── contracts │ ├── RunToken.sol │ ├── Greeter.sol │ └── RunnerCollection.sol ├── package.json ├── test │ └── sample-test.js ├── hardhat.config.js └── scripts │ ├── sample-script.js │ ├── deployRunToken.js │ └── deployNFTCollection.js ├── .gitignore └── README.md /game/imgs/nft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/nft.png -------------------------------------------------------------------------------- /game/imgs/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/ground.png -------------------------------------------------------------------------------- /game/imgs/obstacle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/obstacle.png -------------------------------------------------------------------------------- /game/imgs/playerJumps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/playerJumps.png -------------------------------------------------------------------------------- /game/imgs/playerRuns0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/playerRuns0.png -------------------------------------------------------------------------------- /game/imgs/playerRuns1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/playerRuns1.png -------------------------------------------------------------------------------- /game/imgs/playerStands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/game/imgs/playerStands.png -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameImages/00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/contracts/runnerCollectionMetadata/runnerGameImages/00.png -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameImages/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/contracts/runnerCollectionMetadata/runnerGameImages/11.png -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameImages/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/contracts/runnerCollectionMetadata/runnerGameImages/22.png -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameImages/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/contracts/runnerCollectionMetadata/runnerGameImages/33.png -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameImages/44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dappuniversity/Runner-blockchain-game-/HEAD/contracts/runnerCollectionMetadata/runnerGameImages/44.png -------------------------------------------------------------------------------- /contracts/contracts/RunToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract RunToken is ERC20 { 7 | constructor() ERC20("RunToken", "Run"){ 8 | _mint(msg.sender, 20*10**6); 9 | } 10 | 11 | function mintTokens(address account, uint256 amount) public { 12 | _mint(account, amount); 13 | } 14 | } -------------------------------------------------------------------------------- /contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hardhat-project", 3 | "devDependencies": { 4 | "@nomiclabs/hardhat-ethers": "^2.0.5", 5 | "@nomiclabs/hardhat-waffle": "^2.0.3", 6 | "chai": "^4.3.6", 7 | "ethereum-waffle": "^3.4.0", 8 | "ethers": "^5.6.1", 9 | "hardhat": "^2.9.1" 10 | }, 11 | "dependencies": { 12 | "@openzeppelin/contracts": "^4.5.0", 13 | "dotenv": "^16.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /game/.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | coverage.json 3 | typechain 4 | 5 | #Hardhat files 6 | cache 7 | artifacts 8 | 9 | # dependencies 10 | /node_modules 11 | /.pnp 12 | .pnp.js 13 | 14 | # testing 15 | /coverage 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | .env 23 | .env.local 24 | .env.development.local 25 | .env.test.local 26 | .env.production.local 27 | 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | coverage.json 3 | typechain 4 | 5 | #Hardhat files 6 | cache 7 | artifacts 8 | 9 | # dependencies 10 | contracts/node_modules 11 | /.pnp 12 | .pnp.js 13 | 14 | # testing 15 | /coverage 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | .env 23 | .env.local 24 | .env.development.local 25 | .env.test.local 26 | .env.production.local 27 | 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | -------------------------------------------------------------------------------- /game/updateCustomProperty.js: -------------------------------------------------------------------------------- 1 | // get css variable into js update it and back into css 2 | export function getCustomProperty(elem, prop) { 3 | // getComputedStyle allows for getting css value 4 | // this returns string we will convert to float 5 | // the default is 0 6 | return parseFloat(getComputedStyle(elem).getPropertyValue(prop)) || 0 7 | } 8 | 9 | export function setCustomProperty(elem, prop, value) { 10 | elem.style.setProperty(prop, value) 11 | } 12 | 13 | export function incrementCustomProperty(elem, prop, inc) { 14 | setCustomProperty(elem, prop, getCustomProperty(elem, prop) + inc) 15 | } 16 | -------------------------------------------------------------------------------- /contracts/contracts/Greeter.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.0; 3 | 4 | import "hardhat/console.sol"; 5 | 6 | contract Greeter { 7 | string private greeting; 8 | 9 | constructor(string memory _greeting) { 10 | console.log("Deploying a Greeter with greeting:", _greeting); 11 | greeting = _greeting; 12 | } 13 | 14 | function greet() public view returns (string memory) { 15 | return greeting; 16 | } 17 | 18 | function setGreeting(string memory _greeting) public { 19 | console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); 20 | greeting = _greeting; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/test/sample-test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require("chai"); 2 | const { ethers } = require("hardhat"); 3 | 4 | describe("Greeter", function () { 5 | it("Should return the new greeting once it's changed", async function () { 6 | const Greeter = await ethers.getContractFactory("Greeter"); 7 | const greeter = await Greeter.deploy("Hello, world!"); 8 | await greeter.deployed(); 9 | 10 | expect(await greeter.greet()).to.equal("Hello, world!"); 11 | 12 | const setGreetingTx = await greeter.setGreeting("Hola, mundo!"); 13 | 14 | // wait until the transaction is mined 15 | await setGreetingTx.wait(); 16 | 17 | expect(await greeter.greet()).to.equal("Hola, mundo!"); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /game/ground.js: -------------------------------------------------------------------------------- 1 | import { 2 | getCustomProperty, 3 | incrementCustomProperty, 4 | setCustomProperty, 5 | } from "./updateCustomProperty.js" 6 | 7 | const SPEED = 0.05 8 | const groundElems = document.querySelectorAll("[data-ground]") 9 | 10 | export function setupGround() { 11 | setCustomProperty(groundElems[0], "--left", 0) 12 | setCustomProperty(groundElems[1], "--left", 300) 13 | } 14 | 15 | export function updateGround(delta, speedScale) { 16 | groundElems.forEach(ground => { 17 | incrementCustomProperty(ground, "--left", delta * speedScale * SPEED * -1) 18 | // reloop - pak pravi loop za da ne run out of space 19 | if (getCustomProperty(ground, "--left") <= -300) { 20 | incrementCustomProperty(ground, "--left", 600) 21 | } 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /contracts/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | require("dotenv").config(); 3 | // This is a sample Hardhat task. To learn how to create your own go to 4 | // https://hardhat.org/guides/create-task.html 5 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 6 | const accounts = await hre.ethers.getSigners(); 7 | 8 | for (const account of accounts) { 9 | console.log(account.address); 10 | } 11 | }); 12 | 13 | // You need to export an object to set up your config 14 | // Go to https://hardhat.org/config/ to learn more 15 | 16 | /** 17 | * @type import('hardhat/config').HardhatUserConfig 18 | */ 19 | module.exports = { 20 | solidity: "0.8.4", 21 | 22 | networks: { 23 | mumbai: { 24 | url: process.env.MUMBAI_RPC, 25 | accounts: [process.env.PRIVATE_KEY], 26 | }, 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameJsonFiles/5.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Dog", 3 | "description": "Mario is a short, pudgy, Italian plumber who sets out to rescue Princess Peach from the evil villain Bowser", 4 | "image" : "https://ipfs.io/ipfs/QmWAjoqy9hxyQX8BZESny6Q4auedFJ5GsGDgdYrsqmUaEe/44.png", 5 | "attributes": [ 6 | { 7 | "trait_type": "Strength", 8 | "value": 7, 9 | "max_value": 10 10 | }, 11 | { 12 | "trait_type": "Speed", 13 | "value": 6, 14 | "max_value": 10 15 | }, 16 | { 17 | "trait_type": "Jump", 18 | "value": 6, 19 | "max_value": 10 20 | }, 21 | { 22 | "trait_type": "Intelligence", 23 | "value": 9, 24 | "max_value": 10 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameJsonFiles/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Gold", 3 | "description": "Mario is a short, pudgy, Italian plumber who sets out to rescue Princess Peach from the evil villain Bowser", 4 | "image" : "https://ipfs.io/ipfs/QmWAjoqy9hxyQX8BZESny6Q4auedFJ5GsGDgdYrsqmUaEe/00.png", 5 | "attributes": [ 6 | { 7 | "trait_type": "Strength", 8 | "value": 7, 9 | "max_value": 10 10 | }, 11 | { 12 | "trait_type": "Speed", 13 | "value": 6, 14 | "max_value": 10 15 | }, 16 | { 17 | "trait_type": "Jump", 18 | "value": 6, 19 | "max_value": 10 20 | }, 21 | { 22 | "trait_type": "Intelligence", 23 | "value": 9, 24 | "max_value": 10 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameJsonFiles/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Monkey", 3 | "description": "Mario is a short, pudgy, Italian plumber who sets out to rescue Princess Peach from the evil villain Bowser", 4 | "image" : "https://ipfs.io/ipfs/QmWAjoqy9hxyQX8BZESny6Q4auedFJ5GsGDgdYrsqmUaEe/11.png", 5 | "attributes": [ 6 | { 7 | "trait_type": "Strength", 8 | "value": 7, 9 | "max_value": 10 10 | }, 11 | { 12 | "trait_type": "Speed", 13 | "value": 6, 14 | "max_value": 10 15 | }, 16 | { 17 | "trait_type": "Jump", 18 | "value": 6, 19 | "max_value": 10 20 | }, 21 | { 22 | "trait_type": "Intelligence", 23 | "value": 9, 24 | "max_value": 10 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameJsonFiles/3.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Rock", 3 | "description": "Mario is a short, pudgy, Italian plumber who sets out to rescue Princess Peach from the evil villain Bowser", 4 | "image" : "https://ipfs.io/ipfs/QmWAjoqy9hxyQX8BZESny6Q4auedFJ5GsGDgdYrsqmUaEe/22.png", 5 | "attributes": [ 6 | { 7 | "trait_type": "Strength", 8 | "value": 7, 9 | "max_value": 10 10 | }, 11 | { 12 | "trait_type": "Speed", 13 | "value": 6, 14 | "max_value": 10 15 | }, 16 | { 17 | "trait_type": "Jump", 18 | "value": 6, 19 | "max_value": 10 20 | }, 21 | { 22 | "trait_type": "Intelligence", 23 | "value": 9, 24 | "max_value": 10 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /contracts/runnerCollectionMetadata/runnerGameJsonFiles/4.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Champion", 3 | "description": "Mario is a short, pudgy, Italian plumber who sets out to rescue Princess Peach from the evil villain Bowser", 4 | "image" : "https://ipfs.io/ipfs/QmWAjoqy9hxyQX8BZESny6Q4auedFJ5GsGDgdYrsqmUaEe/33.png", 5 | "attributes": [ 6 | { 7 | "trait_type": "Strength", 8 | "value": 7, 9 | "max_value": 10 10 | }, 11 | { 12 | "trait_type": "Speed", 13 | "value": 6, 14 | "max_value": 10 15 | }, 16 | { 17 | "trait_type": "Jump", 18 | "value": 6, 19 | "max_value": 10 20 | }, 21 | { 22 | "trait_type": "Intelligence", 23 | "value": 9, 24 | "max_value": 10 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /contracts/contracts/RunnerCollection.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; 5 | import "@openzeppelin/contracts/utils/Strings.sol"; 6 | 7 | contract RunnerCollection is ERC1155 { 8 | 9 | string public name; 10 | string public symbol; 11 | uint256 public tokenCount; 12 | string public baseUri; 13 | 14 | constructor(string memory _name, string memory _symbol, string memory _baseUri) ERC1155(_baseUri) { 15 | name = _name; 16 | symbol = _symbol; 17 | baseUri = _baseUri; 18 | } 19 | 20 | // we need to override the uri function so our nfts are compatible with opensea 21 | function uri(uint256 _tokenId) override public view returns(string memory) { 22 | return string ( 23 | abi.encodePacked( 24 | baseUri, 25 | Strings.toString(_tokenId), 26 | ".json" 27 | ) 28 | ); 29 | } 30 | 31 | function mint(uint256 amount) public { 32 | tokenCount += 1; 33 | _mint(msg.sender, tokenCount, amount, ""); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blockchain game 2 | Build a play to earn blockchain runner game that rewards tokens and NFTs 3 | 4 | ## Technology Stack & Dependencies 5 | 6 | - Solidity (Writing Smart Contract) 7 | - HTML, Css, Javascript For the website 8 | - [Infura](https://infura.io/) Account on Infura as a node provider 9 | - [NodeJS](https://nodejs.org/en/) To install Dependencies 10 | - [Hardhat](https://hardhat.org/) Ethereum development environment 11 | - [Ethers.js](https://docs.ethers.io/v5/) To interact with the blockchain 12 | 13 | ### 1. Clone/Download the Repository 14 | 15 | ### 2. Install Dependencies: 16 | ``` 17 | $ cd contracts 18 | ``` 19 | ``` 20 | $ npm install 21 | ``` 22 | 23 | ### 3. Deploy NFT collection to Polygon Mumbai testnet 24 | - Setup your env file with both private key and mumbai RPC 25 | ``` 26 | $ $ npx hardhat run scripts/deployNFTCollection.js --network mumbai 27 | ``` 28 | 29 | ### 4. Deploy Run token to Polygon Mumbai testnet 30 | - Setup your env file with both private key and mumbai RPC 31 | ``` 32 | $ $ npx hardhat run scripts/deployRunToken.js --network mumbai 33 | ``` 34 | 35 | ### 5. Provide the smart contract addresses in blockchain.js file 36 | 37 | Images in the game are taken from https://www.flaticon.com/ 38 | -------------------------------------------------------------------------------- /contracts/scripts/sample-script.js: -------------------------------------------------------------------------------- 1 | // We require the Hardhat Runtime Environment explicitly here. This is optional 2 | // but useful for running the script in a standalone fashion through `node 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | NFT total score: 0 18 | Gwei total score: 0 19 | 20 | NFT score: 0 21 |
25 |
26 |
27 |