打开 Cocos Creator 点击新建空白项目,在默认布局的左下区域,一个黄黄assets文件夹映入眼帘。做为前端的你对这个文件是否是再熟悉不过了。是的,和你想象的同样,开发游戏中全部资源,脚本都会放置到该文件。javascript
项目创建好之后,对各区域的功能大体了解下,做为前端的你,主要仍是要迅速的掌握cc提供的各类NB的功能。因此,还得赶忙打开 官网 快速浏览一遍。官网也写得很好,提供中文和英文,对于英文能力很差的伙伴来讲,简直是不能太好了。是否是找到了当初学习Vue的感受。做为前端的你,成天写了一堆业务控制,处理各类布局,各类兼容,对奇怪的css优先级搞得云里雾里的。因此是时候换一个更有意思开发场景,给本身作个游戏解闷多好css
cc是一个跨平台框架,一端编译多端发布。想一想前端的 mpvue taro uni-app,无不是解决此类问题,再加上gulp,webpack,再来一堆node_modules,啥less sass stylus.各类环境配置那是至关的复杂。因此业界流传,前端已经进入深水区,真的一点不假。 然而cc依然可让你温馨的写JS或者TS ,而且没有繁杂的配置,一键搞定打包发布。html
<p>上边说了一大堆,其实并无什么鸟用。在官网首页中,给开发者提供了个完整坑爹的游戏《摘星星》,若是打包到微信小游戏,须要横屏,不太友好。本着触类旁通的求学态度,我利用此场景,换了一个游戏玩法。开发了本身第一款小游戏《坦克侠》,固然也很坑爹</p>
<p>游戏开发主要是肯定游戏规则,我新改编的玩法就是在星空中随机生成不一样数量的星星,并一直往下掉落,个人主角坦克必须在星星掉落前接住。丢失一颗星星生命减一,生命为0游戏结束。固然咱们主角每收集一颗星星,根据当前的难度会添加必定的分数。累计到必定的分数,又能够给主角添加一点生命值</p>
<p>在官网 下载初始项目 下载一个基础项目,该项目中只有一些项目基本图片和声音。接下来,咱们须要创建场景,制做预制资源,添加控制脚本,编译发布微信小游戏,快速开始 </p>前端
制做一个游戏场景,与官网不一样的是,我将Canvas的Size属性,在属性检查器中设置为 288 x 512 ,而且勾选了 Fit Height以及 Fit Width 用以适应同的手机屏幕。而后拖动背景图片到层级管理器中,并在场景编辑器中设置背景Size属性,使其等于Canvas的Size属性。而后依次在层级管理器中新建三个Label控件,依次拖动到背景图片左上角和右上角,用以记录生命值,当前分数,以及最高分数。接着在场景中间添加一个Label控件和一个Button按钮用于显示游戏结束和开始游戏。在场景底部拖动放置咱们的主角坦克。因此最新场景的效果应该是以下显示的那样vue
游戏场景设计,看似酷炫,无非就是拖拖拖。依稀找到了当年C#开发winform的感受,随便搞整一下,一个界面就出来了。因此致使不少人开发winform,webform很简单,很傻瓜,其实不是的。重要的仍是后边的业务逻辑,解决方案,这些都是超越语言之上的东西。因此cc的场景编辑,就很少说了,直接分析咱们游戏实现逻辑。开始以前咱们先初始一下typescript开发环境,操做以下图java
依次点击安装vs code 扩展插件,添加 Typescript项目配置。接下来就要编写脚本了,全部仍是有必要了解下cc脚本的生命周期node
作过前端的你必定知道,要想拖动一个DIV,必定是在Body中监听鼠标的移动事件。在移动端必定是监听触摸移动事件。是的,在cc里边作游戏,但愿一个组件动起来依然是这么操做的,那么cc里边是如何注册事件的呢?两个方式,一个在场景编辑器下角的属性中添加脚本里边的方法,另一种就是直接在脚本里边添加。固然我推荐第二种。虽然IDE会帮咱们生成不少代码,若是不本身写一遍,就永远不晓得数据流向。就像当年开发winform时,不少人拖动一个按钮控件,而后双击控件,IDE就自动帮你注册好了一个用户点击事件。却不知,IDE是在xx.design.cs中经过代码替你注册好的。因此既然刚开始学,必定要了解清楚它的原理。webpack
<p>因此,主角移动无非实在TouchMove时改本身的X/Y</p>git
// author:herbert qq:464884492 onTouchMove(e: cc.Event.EventTouch) { let deltaX = e.getDeltaX(); //获取本次和上次移动的增量 let deltaY = e.getDeltaY(); //左移 if (deltaX < 0 && this.node.x <= this.leftMinX) return; if (deltaX > 0 && this.node.x >= this.rightMaxX) return; if (deltaY > 0 && this.node.y >= this.topMaxY) return; if (deltaY < 0 && this.node.y <= this.bottomMinY) return; this.node.x += deltaX; this.node.y += deltaY; }
在cc里边须要重复生成的对象,咱们通常会制做成一个预制资源。而后在基本中经过代码实例化。何为预制资源,就权当它是一个模板吧。如今生成咱们第一颗小星星github
// author:herbert qq:464884492 buildOneStar() { let star = cc.instantiate(this.starPrefab); this.node.addChild(star); return star; }
是的,就是这么简单,有没有class.newInstance()的感受,固然这个只是在场景的默认位置生成了一个星星而已。咱们须要更多的信息,位置确定也不是默认位置,因此还得继续码代码
// author:herbert qq:464884492 buildRandomStar() { let tempX = 0; let tempY = 0; tempX = Math.floor(this.starMaxX - Math.random() * this.starMaxX);//生成一个不大于MaxX的坐标 tempY = Math.floor(this.starMaxY - Math.random() * this.starMaxY); if (Math.random() < 0.5) tempX = tempX * -1; let star = this.buildOneStar(); star.setPosition(tempX, tempY); star.zIndex = this.tank.zIndex - 1; star.name = "star"; star.getComponent("Star").index = this; }
这样感受好多了,能够生成不少星星了,不过,咱们的星星也得往下掉才行,做为前端的你首先想到的是否是更新星星的Y值,是的,我就是这么作的。利用生命周期中start方法,定义一个从上往最小Y运动的动画。后来才了解到全部的游戏引擎都有物理特性,开启了本身就掉下来了。不过原理确定仍是改变y值。况且这么简单的游戏彻底不必使用
start() { // 定义一个Action let downAction = cc.moveTo(this.index.starFallSpeed, this.node.x, this.minY - 60); downAction.easing(cc.easeSineOut()); this.node.runAction(downAction); }
只要是游戏少不了作碰撞检测,若是在CC中开启了物理引擎还好,直接跟星星和主角添加一个刚体就行了,不过咱们没开启,那就本身来了。不过碰撞检测无非就是判断两个区域有没有重叠地方,简单判断就上下左右,左上右上左下右下八个点。不过我这里偷了个懒,直接判断星星和主角间向量的距离。
//author:herbert qq:464884492 ... let distance = this.node.position.sub(this.tank.getPosition()).mag(); if (distance < (this.tank.width / 2 - 5)) { console.log("接住了"); } ...
游戏嘛,总不能一成不变那多没意思,因此随着时间的推移咱们的调整点难度。我这个游戏难度无非就一下两个方面
//author:herbert qq:464884492 ... this.index.scoreNum += this.index.starScoreSpeed; this.index.score.string = "得分:" + this.index.scoreNum; // 降落速度加 if (Math.floor(this.index.scoreNum / 100) == this.index.starScoreSpeed - 4 && this.index.starFallSpeed > 1) { this.index.starFallSpeed -= 0.2; //降低速度加快 if (this.index.starBuildTimeOut > 200) { this.index.starBuildTimeOut -= 100; //生成速度加快 } this.index.lifeNum += 1; if (this.index.starScoreSpeed < 10) { this.index.starScoreSpeed += 1; } } cc.audioEngine.play(this.index.scoreClip, false, 0.2); this.index.allStars.splice(this.index.allStars.indexOf(this.node), 1) this.node.destroy(); ...
游戏嘛,也不能一直玩下去。否则多没挑战。自从调整游戏难度后个人最高分重来就没有超过4000.
//author:herbert qq:464884492 ... if (this.node.y <= this.minY) { this.index.lifeNum -= 1; this.index.life.string = "生命:" + this.index.lifeNum; this.node.destroy(); this.index.allStars.splice(this.index.allStars.indexOf(this.node), 1) if (this.index.lifeNum <= 0) { this.index.gameOver.node.active = true; this.index.btnPlay.node.active = true; this.index.starIsRunning = false; let storageValue = cc.sys.localStorage.getItem(this.index.HIGHSTORAGEKEY); if (storageValue && parseInt(storageValue) > this.index.scoreNum) { return; } cc.sys.localStorage.setItem(this.index.HIGHSTORAGEKEY, this.index.scoreNum); this.index.highScore.string = "最高分:" + this.index.scoreNum; } } ...
作技术嘛,大多都是 Talk is cheap,Show me your code.作点总结吧