1. Basic introduction to the game

1.1 Game Introduction

The theme of this game is an RPG game of exploration and collection. There is not much design for plot tasks, and it is a game with high degree of free exploration.

Characters can gain treasure chests through free exploration on the map, level up in the wild by grinding monsters to gain experience, and get corresponding rewards. The game features that after being defeated, the player will lose all the items picked up, but will retain the current Hero level.

The programming language adopted is JavaScript script language, which is suitable for interaction with the engine. Cocos Creator game engine is used to realize the overall appearance of the game, and the inner logic is controlled by the script written.

1.2 Game Ideas

The main character is set as Hero, and the game layout is a big maze map. Through exploring and collecting equipment on a map, beating monsters to gain experience and upgrade; NPCS are static, talking to the Hero as he approaches, getting information about the maze or general conversation;

Monster and NPCS have the same set of rules, but the only interaction with hero is combat.

When the Hero is close to the teleport point of the game map, the game will be teleported, but the hero level will be detected. If the corresponding level requirements are not met, the map cannot be transmitted, which is called the completion of the game.

There are walls around the map so hero can’t cross the map boundary to prevent mold penetration.

When passing through a particular scene or monster, the sound Settings of the scene will be turned on, including the character’s release skills, interaction with NPCS, and so on.

2. Game planning

Step 1: After determining the direction of the whole process of the game, I start to design the properties and behaviors for Hero, Monster, NPC, etc. (there may be some conflicts between the pre-planning and the later implementation, and the final effect is subject to the later improvement). After the completion of the property design, I start to look for the relevant material maps.

The second step: a processing of game materials, such as a type of material packaging to prevent, prevent internal resources access disorder. Determine the main characters of walking, attack action, all sorts of the UI interface of the map, the response of the key animation, the enemy’s movement, the map is gaming background, and design associated with NPC plot design, finding the right background music, sound effects, etc., the game most of the material at this stage to complete the preparation, the late need specific material and then to separate processing. Image preprocessing is carried out by ShoeBox, TexturePackerGUI and other image processing tools, including splitting sequences of dynamic actions, repackaging into collections of images and so on.

Step 3: Set up the main scene of the game and make prefabricated characters, including skills, monsters and other animation.

The fourth step: according to the game design planning, the game script writing, gradually realize the production of the whole game.

Step 5: Test the game as a whole, improve logic, fix bugs, package and release.

3. Game function design

3.1 Map Design

As an exploratory collection game, the map takes a big picture approach, and the view window moves across the entire background map as the Hero moves. To avoid the phenomenon of model breaking in the game, collision detection should be added to the solid objects such as houses, walls and trees. All the objects are designed as static floor level. When colliding with the hero level objects, the static hero will be shifted in any direction, thus limiting the hero’s activity range. When hero meets certain conditions, it will open the channel of the next map, which can realize the switch of the scene, and the specifications between the maps are consistent.

3.2 Interface Design

There are not many UI interfaces involved in the game, mainly a large interface bound to hero and a backpack interface that shows the items currently owned by hero, UI that represents the gold and diamond hero has, UI of Hero level, health, blue quantity, name, button UI of backpack and setting interface, as well as various game items. When the user first enters the game, he will stop at the main interface and carry out the specific development of the game according to the user’s choice. The game interface

3.3 Interaction Design

The interaction system of the whole game is triggered by the Hero. When the hero approaches the treasure chest, he randomly generates a treasure to be picked up by the hero and gets corresponding gold coins and diamonds at the same time. When NPCS approach the game, they will have corresponding conversations. When they meet monster, they can choose to fight or run away. If they beat the Monster, they can get the experience required for hero upgrade and have a chance to drop rare items.

3.4 Role Design

As an RPG, the first requirement is a player-controlled character, in this case a Hero character, that the player controls as they explore the game.

Players corresponding to a role, start the game, with the development of the later levels, there will be different enemies, the hero role played by the player against monster, players can carry out the corresponding attack according to the rules of the game.

Attributes for each character: BloodBase, bloodTime, blueBase, bloodTime, Experice, Grade, Attack, Property, bloodBase, bloodTime, bloodTime Goal, diamond These initial stats determine the character’s health, mana, and experience, and as each stat decreases, so does the health. If health is zero, the game has failed.

The initial HP value is 100, BP value is 100, EXP value is 0, you need to get through the game, the game will drop treasure chests, there may be treasures, or other items to improve the stats, beat monster will get some rewards.

Initial value for each attribute:

Description:

Initial values: HP=100, BP=100, EXP=0

Each level increases 1 attribute points, attribute points randomly enhance hero’s various attribute skills, according to the offset between 0-0.5, the game is a free random mechanism, attributes will be randomly allocated, the same conditions may produce different results, players can explore.

3.5 Enemy Design

The second need to fight with the protagonist of the enemy, in this game for the world’s monsters, including chicken, duck, dog, pig, dragon and so on.

The enemies are essentially the same characters as the player, but as the Hero progresses and we encounter more powerful properties, the game becomes more difficult. Players need to fight according to the actual situation, attack properly and defeat the enemy to win.

Attributes for each character: bloodBase, Grade, Property. These initial values determine the health of the character. Health starts at 100 and is reduced by the counter attribute and health is also reduced. If the monster health is zero, it means that the player has won, and the enemy health cannot be increased in general, but there are special monster skills that can increase life, and the player can use items to restore life.

Initial value for each attribute

3.6 Equipment Design

In order to increase playability, equipment systems are also needed, which should be divided into different qualities so that players are willing to spend time grinding equipment to increase their play time.

The game equipment should have costumes, and players can use the gold earned to buy some better costumes and dress up items to improve the game experience.

There are also props. Before the game starts, players can go to the store and use the gold coins to buy some equipment that can improve their skills and make them more powerful against the enemy. They can also buy some medicine that can make them recover.

Treasure chests: Players can purchase treasure chests, open them, and random items appear in them, which can be coins, copies, items, costumes, experience cards, resurrection cards, etc. Recovery drugs for different properties.

All of the player’s belongings are viewable in the backpack.

4. Game programming

4.1 HeroControl. Js

All the clues in the game are driven by the Hero, the script that controls the Hero controls the course of the game, and the other scripts enrich the game. Hero has a global attribute catalog, including backpack attribute, item attribute, etc., this series of attributes are shared by the whole game, which can be convenient for data update processing.

var box = require("BoxControl"); Cc. Class({extends: cc.component, properties: {// Animation: cc.animation, m_sprite: [cc.sprite],}, // Hero: function () {this.move = 0; // The current hero skill mark this.kill; / / Hero level label var nodeGrade = cc. Find (" Canvas/Main/Hero/name/grade "); this.gradeString = nodeGrade.getComponent(cc.Label); String = "+ hero.grade" + hero.grade; / / register button event cc. SystemEvent. On (cc) systemEvent) EventType. KEY_DOWN, enclosing onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); // hero static this.m_animation. Play ("3"); // Hero static this.m_animation. / / get the current experience of enclosing experice = cc. Find (' Canvas/Main/Hero/Experiencebar/Time '); This.herodiamondchange (); Bone = cc.loader.loadRes("Prefab/bone", cc.prefab, (err, Prefab) => {if (err) {console.error(err); return; } this.newMyPrefab = cc.instantiate(prefab); }); }, // The game frame controls the hero move update: function (dt) {this.blooddetection (); this.actionJudge(); if(this.move == 1){ this.node.x += speed; } else if(this.move == 2){ this.node.x += -speed; } else if(this.move == 3){ this.node.y += speed; } else if(this.move == 4){ this.node.y += -speed; }}, // Set the number of coins and diamonds to heroDiamondChange: Function () {/ / to get gold Label parent node var nodegoal = cc. Find (" Canvas/Main/Hero/buttongoal/New Label "); Var goal = nodegoal.getComponent(cc.label); var goal = nodegoal.getComponent(cc.label); goal.string = hero.goal; / / get the diamond tag parent node var nodediamond = cc. Find (" Canvas/Main/Hero/buttondiamond/New Label "); Var diamond = nodediamond.getComponent(cc.label); diamond.string = hero.diamond; This.expericechange (); // Hero expericeChange(); }, // Change the playing animation animationChange: Function (data){if(this.move == 1) this.m_animation. Play ("runr"); // If (this.move == 1) this.m_animation. Elseif (this.move == 2) this.m_animation.play("runl"); Elseif (this.move == 3) this.m_animation.play("runu"); Else if(this.move == 4){this.m_animation.play("rund"); Else if(this.move == 5){this.playingKill(); }}}, // onKeyDown:function(event){switch(event.keycode){// press D case 68:{this.move = 1; } break; // press A key case 65:{this.move = 2; } break; // Press W key case 87: this.move = 3; break; // Press the S key case 83: this.move = 4; break; // Press the K key case 75: pickUp = 1; break; // Press H key case 72: this.move = 5; this.kill = 1; break; case 74: this.move = 6; break; } this.animationChange(""); }, // onKeyUp: function(event){switch(event.keycode){case 68: break; case 65: break; case 87: break; case 83: break; case 75: pickUp = 0; break; } this.move = 0; this.heroDiamondChange(); }, // Check whether the animation can play actionJudge: function() { if(this.m_animation.getAnimationState("kill_swing")._isPlaying){ speed = 0; return false; } else{ if(this.node.getChildByName("bone") ! = null){ this.newMyPrefab.removeFromParent(); this.animationChange(); Speed = 1.5; } return true; }}, // Hero bloodDetection: Function () {this.m_sprite[0].fillrange = hero.bloodTime/hero.bloodbase * hero.grade; this.m_sprite[1].fillRange = hero.blueTime / hero.blueBase * hero.grade; }, // Hero experience bar update check expericeChange: Function () {if(hero.experice >= 100 * hero.grade){hero.experice -= 100 * hero.grade; hero.grade += 1; String = "+ hero.grade" + hero.grade; expericeChange(); } else{this.experice. ScaleX = hero.experice/(100 * hero.grade); }}, // Skill playingKill(){if(this.kill == 1){this.m_animation.play("kill_swing"); this.node.addChild(this.newMyPrefab); this.newMyPrefab.setPosition(-200, 0); }}});Copy the code

4.2 BoxControl. Js

Control all interface interactions in the game, such as jumping to the game interface, opening the backpack interface, generating hero items, etc.

cc.Class({ extends: cc.Component, properties: { packet: { default: null, type: cc.Node, count : Boolean, display : Boolean,}, monsterBame: {default: null, type: cc.Node,},}, // scene initialization onLoad: Function () {this.sign = true; This.packet. count = true; This.packet. display = true; / / blood of the monster the refresh rate of enclosing loadMonsterBloodPassTime = 0.2; this.loadMonsterBloodNowTime = 0; / / name and blood of the monster controls enclosing monstername = this. Monsterbame. GetChildByName (" name "). GetComponent (cc) Label); this.monsterblood = this.monsterbame.getChildByName("ui").getChildByName("blood").getComponent(cc.Sprite); / / register button event cc. SystemEvent. On (cc) systemEvent) EventType. KEY_DOWN, enclosing onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, update: function (dt) {/ / total refresh time enclosing loadMonsterBloodNowTime + = dt. if(this.loadMonsterBloodNowTime > this.loadMonsterBloodPassTime){ this.loadMonsterBloodNowTime = 0; if(isLoad){ this.loadMonsterBlood(); this.sign = false; } else{ this.removeMonsterBlood(); this.sign = true; }}}, // onKeyDown:function(event){switch(event.keycode){// Press B case 66: this.bagclick (); break; }}, // bagClick: function(data){if(this.packet.count){this.packet.setPosition(0, 0); this.packet.count = false; speed = 0; this.loadGoods(); } else if (! This.packet.count){this.packet.setPosition(1000, 0); this.packet.count = true; this.packet.display = true; var node = cc.find('Canvas/Main/Hero/package'); // Remove all items node.removeAllChildren(); Speed = 1.5; }}, // loadGoods loadGoods: function() {var node = cc.find('Canvas/Main/Hero/package'); node.removeAllChildren(); if(this.packet.display){ cc.loader.loadRes('Interface/button1',cc.SpriteAtlas, (err, atlas) => { let starNode = new cc.Node(); // Call the addComponent function of the newly created node, Returns a Sprite object const Sprite =starNode.addComponent(cc.sprite) // assigns the spriteFrame property to the Sprite sprite.spriteFrame=atlas.getSpriteFrame("slice85_85"); // Append the new node to the node. Starnode.parent = this.packet; }) } bagNum = 0; Cc.loader. LoadRes ("Food/Foods", cc.spriteAtlas, (err, atlas) => {if (err) {console.error(err); return; } // create a new node object using the image resource for (let index = 0; index < bag.length; Index ++) {if(bag[index].num > 0){// Create a new Node let starNode = new cc.node (); starNode.name = bag[index].name; Starnode. setPosition(-180 + bagNum * 60, 120); // Add Sprite component let starSprite = starNode.addComponent(cc.sprite); Starsprite.spriteframe = atlas.getSpriteFrame(bag[index].name); let button = starNode.addComponent(cc.Button); button.name = bag[index].name; button.node.on('click', this.callback, this); starNode.parent = this.packet; bagNum++; }}}); }, // Scene changeGame: function(target, data){}, // backpack item click callback: Function (event) {// The number of items decreases after clicking cc.log(event.target.name); Var index = -1; For (var I = 0; i < bag.length; i++) { if (bag[i].name == event.target.name) { index = i; break; Switch (event.target.name) {case "bun": hero.bloodtime += 8; break; case "cowpea": hero.blueTime += 15; break; case "drumstick": hero.bloodTime += 20; break; case "hot_dog": hero.bloodTime += 10; break; case "hot_pot": hero.bloodTime += 15; break; case "noodles": hero.bloodTime += 12; break; case "omelet_rice": hero.blueTime += 20; break; case "pepper_spray": hero.bloodTime += 30; break; case "sliced_bread": hero.bloodTime += 5; break; case "tortoise": hero.blueTime += 20; break; Hero.bloodtime = hero.bloodbase; hero.bloodtime = hero.bloodbase; hero.bloodtime = hero.bloodbase; hero.bloodtime = hero.bloodbase; If (hero.bluetime > hero.bluebase) {hero.bluetime = hero.bluebase; if (hero.bluetime > hero.bluebase) {hero.bluetime = hero.bluebase; } bag[index].num--; }, // loadMonsterBlood: The function () {if (this. Sign) {/ / monster information shows this. Monsterbame. SetPosition (110280); This.monstername. string = monsterDragon.name + "-- "+ monsterdragon. grade + "; This. Monstername. Node. Color = cc. Color (0, 255); this.monstername.fontSize = 15; } this.monsterblood.fillRange = monsterDragon.bloodTime / monsterDragon.bloodBase; }, // removeMonsterBlood: function(){if(! This. Sign) {/ / remove the blood of the monster interface shows this. Monsterbame. SetPosition (110400); } }, // save file fileClick: function() { cc.sys.localStorage.setItem("grade", hero.grade); cc.sys.localStorage.setItem("goal", hero.goal); cc.sys.localStorage.setItem("diamond", hero.diamond); }});Copy the code

4.3 AllControl. Js

Store all common attribute variables in the game, such as NPCS ‘conversations, game help files, etc.

// The screen speed can also be seen as the hero's moving speed window.speed = 1.5; Hero = {bloodBase: 100, bloodTime: 50, blueBase: 100, blueTime: 50, Experice: 0, grade: 1, goal : 0, diamond : 0, }; // Hero's backpack attribute window.bagNum = 0; Window. Bag = [{name: "cowpea", num: 0}, num: 0}, // {name: "hot_pot", num: 0}, Name: "omelet_rice", num: 0}, // name: "pepper_spray", num: 0}, // name: "pepper_spray", num: 0} {name: "tortoise bread", num: 0}]; // pickUp window. PickUp = 0; // Store NPC window.message = {// Store NPC shop: "Hello, adventurer, do you have any food to buy?" Smithy: "Hello adventurer, got any weapons to build!" NPC Tavern: "Hello adventurer, what potions can I get you?" // Grocery NPC Variety: "Hello adventurer, do you have anything to exchange?" }; BloodBase: 1000, bloodTime: 0, Experice: 100, grade: 10, name: bloodBase: 1000, experice: 100, grade: 10, name: AttackArea: 100,} // Whether to load monster blood bar window.isLoad = false; Tag = {tag0:0, // Arboreal box tag2:2, // NPC tag3:3, // Scene switch to forest tag4: // Hero skill tag6:6, tag7:7, tag8:8, tag9:9, tag10:10, // hero skill tag6:6, tag7:7, tag8:8, tag9:9, tag10:10, // heroCopy the code

4.4 HitDetect. Js

Responsible for the overall collision detection of the game, detection and action in the event of a collision between Hero and floor, road, wall, etc., as well as other detection scripts, specific collision detection for specific objects.

cc.Class({ extends: cc.Component, properties: { }, onLoad: The function () {/ / open the collision to monitor cc. Director. GetCollisionManager () enabled = true; }, onCollisionEnter: function (other) {if(other.tag == 1){speed = 1.5; } else if(other.tag == 2){speed = 1.5; } else if(other.tag == 3){ cc.director.loadScene('game2'); } else if(other.tag == 4){ cc.director.loadScene('game1'); } else{ speed = 0; }}, // Call onCollisionStay(other, self) {if(other.tag == 1){speed = 1.5; } else if(other.tag == 2){speed = 1.5; } else{speed = 0.1; }}, // Call onCollisionExit(other, self) {speed = 1.5; }});Copy the code

4.5 TreasureControl. Js

Responsible for hero and treasure chest can be picked up items collision detection and corresponding generation action.

cc.Class({ extends: cc.Component, properties: { }, onLoad: The function () {/ / open the collision to monitor cc. Director. GetCollisionManager () enabled = true; this.touch = 0; this.randomTreasure = parseInt(Math.random() * 5); }, onCollisionEnter: function (other) {if(other.tag == 10 &&this.touch == 0){// this.touch++; Cc.loader. LoadRes ("Food/Foods", cc.spriteAtlas, (err, atlas) => {if (err) {console.error(err); return; } // Create a new Node object using the image resource let starNode = new cc.node (); starNode.parent = this.node; starNode.name = ""; // Add Sprite component let starSprite = starNode.addComponent(cc.sprite); Starsprite.spriteframe = atlas.getSpriteFrame(bag[this.randomTreasure].name); Var move = cc. MoveTo (1, 0, 40); starNode.runAction(move) }); }}, // Call onCollisionStay(other, self) {if(pickUp == 1){this.pickup (); }}, // Call onCollisionExit(other, self) {; }, pickUp: function() {// Add gold and diamond count if(math.random () % 2 == 0){hero.goal += 10; } else{ hero.diamond += 5; } hero.experice += 20; bag[this.randomTreasure].num += 1; this.node.removeFromParent(); pickUp = 0; }, update: function (dt) { }, });Copy the code

4.6 NpcControl. Js

Responsible for the entire interaction system between players and NPCS in the game.

Cc. Class({extends: cc.component, properties: {// hero: m_hero: {default: null, type: cc.node,},}, onLoad: The function () {/ / open the collision to monitor cc. Director. GetCollisionManager () enabled = true; This.textnode = new cc.node (); this.textNode.name = "label"; this.textNode.parent = this.node; this.textNode.color = cc.color(255, 255, 0); / / create the position this. TextNode. SetPosition (80-80); / / add dialog box text nodes enclosing textSprite = this. TextNode. AddComponent (cc. Sprite); this.starLabel = this.textSprite.addComponent(cc.Label); this.starLabel.enableWrapText = true; this.starLabel.overflow = 3; this.starLabel.lineHeight = 15; this.starLabel.HorizontalAlign = cc.LEFT; this.starLabel.string = ""; this.starLabel.fontSize = 10; }, update: function (dt) {}, // call onCollisionEnter when the collision starts: Function (other) {if(other.tag == 10){// Load dialog panel this.loadText(); If (this.node.name == "shopnpc") {this.starlabel.string = message.shop; }else if (this.node.name == "smithynpc") {this.starlabel.string = message.smithy; }else if (this.node.name == "varietyNpc ") {this.starlabel.string = message.variety; }else if (this.node.name == "tavernnpc") {this.starlabel. string = message. Tavern; }} else{}}, // Call onCollisionStay(other, self) {}, // call onCollisionExit(other, self) at the end of the collision. self) { this.starLabel.string = ""; this.textSprite.spriteFrame = null; }, // Load dialog panel loadText: Function () {cc.loader.loadres ('Interface/text', cc.spriteFrame, (err,Frame) => { this.textSprite.spriteFrame = Frame; }); }});Copy the code

4.7 LoginControl. Js

Responsible for the game landing interface judgment, and the main interface jump work.

cc.Class({ extends: cc.Component, properties: { user: { default: null, type: cc.EditBox, }, password: { default: Null, type: cc.editBox,}}, onLoad: function () {this.infonode = new cc.node (); this.infoNode.parent = this.node; this.versionNode = new cc.Node(); this.versionNode.parent = this.node; / / create a site and display color enclosing infoNode. SetPosition (0, 245); this.infoNode.color = cc.color(0, 0, 255); this.versionNode.setPosition(0, 185); this.versionNode.color = cc.color(0, 0, 255); / / this dialogue text nodes are added. The info = this. InfoNode. AddComponent (cc) Label). this.version = this.versionNode.addComponent(cc.Label); String = "Magic baby"; // Set the text content this.info.string = "Magic baby"; This. Version. String = "version 1.1.0"; Var node = cc.find('Canvas/loginB/hint'); this.hint = node.getComponent(cc.Label); }, login: Function (params) {if (this.user.string == "admin" && this.password.string == "root") {function (params) {if (this.user.string == "admin" && this.password.string == "root") { this.hint.node.color = cc.color(0, 0, 255); this.hint.string = "correct"; This.loadgameinfo (); Cc.director. LoadScene ('game1'); }else {this.hint.node.color = cc.color(255, 0, 0); this.hint.string = "error"; cc.log(cc.sys.localStorage.getItem("password")); }, update: function (dt) {}, loadGameInfo: Function () {cc.loader.loadres ('data/hero.json', function(err, object) { // if (err) { // console.log(err); // return; Hero.grade = object.grade; // hero.grade = object.grade; // hero.grade = object.grade; // hero.goal = object.goal; / /}); hero.grade = JSON.parse(cc.sys.localStorage.getItem("grade")); hero.goal = JSON.parse(cc.sys.localStorage.getItem("goal")); hero.diamond = JSON.parse(cc.sys.localStorage.getItem("diamond")); }});Copy the code

4.8 MonsterControl. Js

Responsible for monster control.

Cc. Class({extends: cc.component, properties: {// hero: m_hero: {default: null, type: cc.node,},}, onLoad: The function () {/ / open the collision to monitor cc. Director. GetCollisionManager () enabled = true; // This. Hero = this.m_hero; // This. Hero = this.m_hero; this.monster = this.node; this.name = this.node.name; This. area = 300; this.moveArea = 100; }, update: function (dt) { this.calculatePosition(); Function () {var mx = this.monster.x; // calculatePosition: function() {var mx = this.monster.x; var my = this.monster.y; var hx = this.hero.x; var hy = this.hero.y; if(Math.sqrt((mx-hx)*(mx-hx)+(my-hy)*(my-hy)) < this.area){ isLoad = true; } else{ isLoad = false; } }, onCollisionEnter: function (other) { monsterDragon.bloodTime -= 100; }, // Call onCollisionStay(other, self) {if(other.tag == 5){monsterDragon.bloodTime -= 2; }}, / / onCollisionExit crash at the end of the call (other, self) {if (monsterDragon. BloodTime < = 0) {this. Node. RemoveFromParent (); isLoad = false; hero.experice += 90; }}});Copy the code

5. Game operation

5.1 Operation Control

Click “Login” to enter the game interface.

At the beginning of the game, the game help can be accessed through the setting button of the game interface.

Mission interface, through the use of the keyboard to control the protagonist to complete a series of actions, destroy the enemy, to obtain experience value.

When an enemy disappears and gains experience points, the game is successfully challenged. When the cost of health and health is 0, the game fails and exits to reset.

Click the setting button of the game interface to pop out the key to exit the game, you can return to the main interface of the game to re-enter the game. (There is no database support, so all attributes generated in the current game will be cleared to 0 upon exit).

5.2 Operation Information

A, D, W and S are the left, right, up and down moving buttons of Hero respectively;

K key can pick up items;

J and H keys are hero’s skill attack keys;

B key can open the character’s backpack interface.