CocosCreator入门之《摘星星》-完全学习记录
Posted forrestcui94
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CocosCreator入门之《摘星星》-完全学习记录相关的知识,希望对你有一定的参考价值。
星星模块涉及内容:
- 使用对象池
- 使用进度条
- 文字的简单显/隐/变
完成态预览:
写在前面: 原来的坐标随机逻辑,测试100次还是10万次,前后两颗星星近乎重叠的概率都是10%,也就是每得十分、就有一次莫名其妙吃了一颗甚至几颗星星的负体验。
为突出目标,仅附上在完成主角模块(点击开始,主角能跳、动,屏幕有边界)基础上的新增内容,并不能直接运行。
1 // Game.js
const Player = require(‘Player‘); 2 3 cc.Class({ 4 extends: cc.Component, 5 6 properties: { 7 minStarDuration: 0, 8 maxStarDuration: 0, 9 starPrefab: { 10 default: null, 11 type: cc.Prefab 12 }, 13 progressBarOfStar: { 14 default: null, 15 type: cc.ProgressBar 16 }, 17 scoreAudio: { 18 default: null, 19 type: cc.AudioClip 20 }, 21 nameAndScore: cc.Label, 22 instructionGoal: cc.Label, 23 controlHint: cc.Label, 24 isMobile: { 25 default: ‘‘, 26 multiline: true 27 }, 28 isPC: { 29 default: ‘‘, 30 multiline: true 31 }, 32 }, 33 34 onLoad () { 35 this.enabled = false; 36 this.controlHint.string = cc.sys.isMobile ? this.isMobile : this.isPC; 37 // 保存当前星星,失败时放不到对象池,手动销毁 38 this.currentStar = null; 39 // 保存当前星星X坐标与下个X坐标作比较,防止前后两颗星星距离过近造成负体验 40 this.currentStarX = 0; 41 this.starPool = new cc.NodePool(‘StarPrefab‘); 42 this.starDuration = 0; 43 /** 44 * 初始化进度值,1.0为从满倒带,0.0为从空到满 45 * progress(进度值)只能是0-1之间的浮点数 46 * 组件默认progress就是1,不设置也可,但误触了属性检查器的progress会出错 47 */ 48 this.progressBarOfStar.progress = 1.0; 49 }, 50 51 start() { 52 this.score = 0; 53 this.starTimer = 0; 54 }, 55 56 onStartBtnClicked() { 57 this.nameAndScore.string = ‘Score: 0‘; 58 // 隐藏(active)是node下面的属性,这里声明Label就要调其下的node 59 this.instructionGoal.node.active = false; 60 this.controlHint.node.active = false; 61 this.score = 0; 62 this.spawnNewStar(); 63 }, 64 65 spawnNewStar() { 66 let newStar = this.starPool.get(); 67 68 if (!newStar) { 69 newStar = cc.instantiate(this.starPrefab); 70 } 71 72 this.node.addChild(newStar); 73 newStar.setPosition(this.randStarPosition()); 74 // 初始化必须在加入主节点之后,先有节点再初始化它 75 newStar.getComponent(‘StarPrefab‘).init(this); 76 this.setStarLife(); 77 this.currentStar = newStar; 78 this.progressBarOfStar.progress = 1.0; 79 }, 80 81 /** 82 * @param {cc.Prefab} star star节点 83 */ 84 despawnStar(star) { 85 this.starPool.put(star); 86 this.spawnNewStar(); 87 }, 88 89 /** 90 * @returns {cc.Vec2} 随机坐标 91 */ 92 randStarPosition() { 93 let randX = 0; 94 // 子节点最大、最小坐标绝对值是父节点宽度的一半 95 let absMaxX = this.node.width / 2; 96 97 // 新X坐标与旧X坐标至少间隔2颗星星的宽度,否则继续随机 98 do { 99 randX = (Math.random() - 0.5) * 2 * absMaxX; 100 } while (Math.abs(randX - this.currentStarX) < 120) 101 102 // 收集半径是60,不加配数可能星星一半穿帮地面,加太多可能碰不到星星,故加50 103 let randY = this.groundY + Math.random() * this.player.getComponent(‘Player‘).jumpHeight + 50; 104 this.currentStarX = randX; 105 106 return cc.v2(randX, randY); 107 }, 108 109 setStarLife() { 110 this.starTimer = 0; 111 this.starDuration = this.minStarDuration + Math.random() * (this.maxStarDuration - this.minStarDuration); 112 }, 113 114 getStarRatio() { 115 return 1 - this.starTimer / this.starDuration; 116 }, 117 118 gainScore() { 119 this.score += 1; 120 this.nameAndScore.string = ‘Score: ‘ + this.score; 121 cc.audioEngine.playEffect(this.scoreAudio, false); 122 }, 123 124 _updateProgressBar() { 125 this.progressBarOfStar.progress = this.getStarRatio(); 126 }, 127 128 update(dt) { 129 this._updateProgressBar(); 130 131 if (this.starTimer > this.starDuration) { 132 this.gameOver(); 133 return; 134 } 135 136 this.starTimer += dt; 137 }, 138 139 gameOver() { 140 this.enabled = false; 141 this.btnNode.x = 0; 142 this.controlHint.node.active = true; 143 this.instructionGoal.node.active = true; 144 this.currentStar.destroy(); 145 this.player.stopMove(); 146 this.saySomeThing(); 147 }, 148 149 saySomeThing() { 150 let score = this.score; 151 let string = this.instructionGoal.string; 152 153 if (score <= 10) { 154 string = ‘Are you kidding me?‘; 155 } else if (score > 10 && score <= 30) { 156 string = ‘Good job, One more try!‘; 157 } else if (score > 30) { 158 string = ‘Great job!‘ 159 } 160 161 this.instructionGoal.string = string; 162 } 163 });
1 // StarPrefab.js 2 3 cc.Class({ 4 extends: cc.Component, 5 6 properties: { 7 pickRadius: 0, 8 }, 9 10 init(game) { 11 this.enabled = true; 12 this.game = game; 13 this.node.opacity = 255; 14 }, 15 16 onLoad() { 17 // onLoad是节点初始化时调用,对象池是对象复用,故只在第一颗星星调用。 18 // cc.log(‘Star_onLoad()‘); 19 this.enabled = false; 20 }, 21 22 getStarPosition() { 23 return this.node.position; 24 }, 25 26 getPlayerDistance() { 27 let Player = this.game.player; 28 let playerPosition = Player.getCenterPos(); 29 let starPosition = this.getStarPosition(); 30 31 return starPosition.sub(playerPosition).mag(); 32 }, 33 34 onPicked() { 35 let Game = this.game; 36 Game.gainScore(); 37 Game.despawnStar(this.node); 38 }, 39 40 update(dt) { 41 if (this.getPlayerDistance() < this.pickRadius) { 42 this.onPicked(); 43 // 此情况就是单纯的将控制权转交给主调函数继续执行 44 return; 45 } 46 47 let opacityRatio = this.game.getStarRatio(); 48 let minOpacity = 50; 49 this.node.opacity = minOpacity + (255 - minOpacity) * opacityRatio; 50 } 51 });
这次没什么插曲,除了拼写错误引发的Bug。但还是想说:
1. 对象池概念初探——https://forum.cocos.org/t/cocoscreator/67879
2. 进度条组件上手——新建一个示例项目,搜progressBar。
复刻这两个练习项目,直到不觉得盲人摸象。
以上是关于CocosCreator入门之《摘星星》-完全学习记录的主要内容,如果未能解决你的问题,请参考以下文章