1. 初来乍到

打开 Cocos Creator 点击新建空白项目,在默认布局的左下区域,一个黄黄assets文件夹映入眼帘。作为前端的你对这个文件是不是再熟悉不过了。是的,和你想象的一样,开发游戏中所有资源,脚本都会放置到该文件。

2. 初步探索

项目建立好以后,对各区域的功能大致了解下,作为前端的你,主要还是要迅速的掌握cc提供的各种NB的功能。所以,还得赶紧打开 [官网](https://docs.cocos.com/creator/manual/zh/) 快速浏览一遍。官网也写得很好,提供中文和英文,对于英文能力不好的伙伴来说,简直是不能太好了。是不是找到了当初学习Vue的感觉。作为前端的你,整天写了一堆业务控制,处理各种布局,各种兼容,对奇怪的css优先级搞得云里雾里的。所以是时候换一个更有意思开发场景,给自己做个游戏解闷多好

cc是一个跨平台框架,一端编译多端发布。想想前端的 mpvue taro uni-app,无不是解决此类问题,再加上gulp,webpack,再来一堆node_modules,啥less sass stylus.各种环境配置那是相当的复杂。所以业界流传,前端已经进入深水区,真的一点不假。 然而cc依然可以让你舒适的写JS或者TS ,并且没有繁杂的配置,一键搞定打包发布。

3. 小试牛刀

上边说了一大堆,其实并没有什么鸟用。在官网首页中,给开发者提供了个完整坑爹的游戏《摘星星》,如果打包到微信小游戏,需要横屏,不太友好。本着举一反三的求学态度,我利用此场景,换了一个游戏玩法。开发了自己第一款小游戏《坦克侠》,当然也很坑爹

游戏开发主要是确定游戏规则,我新改编的玩法就是在星空中随机生成不同数量的星星,并一直往下掉落,我的主角坦克必须在星星掉落前接住。丢失一颗星星生命减一,生命为0游戏结束。当然我们主角每收集一颗星星,根据当前的难度会添加一定的分数。累计到一定的分数,又可以给主角添加一点生命值

在官网 [下载初始项目](https://github.com/cocos-creator/tutorial-first-game/releases/download/v2.0/start_project.zip) 下载一个基础项目,该项目中只有一些项目基本图片和声音。接下来,我们需要建立场景,制作预制资源,添加控制脚本,编译发布微信小游戏,[快速开始](https://docs.cocos.com/creator/manual/zh/getting-started/quick-start.html)

制作一个游戏场景,与官网不同的是,我将Canvas的Size属性,在属性检查器中设置为 288 x 512 ,并且勾选了 Fit Height以及 Fit Width 用以适应同的手机屏幕。然后拖动背景图片到层级管理器中,并在场景编辑器中设置背景Size属性,使其等于Canvas的Size属性。然后依次在层级管理器中新建三个Label控件,依次拖动到背景图片左上角和右上角,用以记录生命值,当前分数,以及最高分数。接着在场景中间添加一个Label控件和一个Button按钮用于显示游戏结束和开始游戏。在场景底部拖动放置我们的主角坦克。所以最新场景的效果应该是如下显示的那样

  

4. 一顿操作猛如虎

游戏场景设计,看似酷炫,无非就是拖拖拖。依稀找到了当年C#开发winform的感觉,随便搞整一下,一个界面就出来了。所以导致很多人开发winform,webform很简单,很傻瓜,其实不是的。重要的还是后边的业务逻辑,解决方案,这些都是超越语言之上的东西。所以cc的场景编辑,就不多说了,直接分析我们游戏实现逻辑。开始之前我们先初始一下typescript开发环境,操作如下图

依次点击安装vs code 扩展插件,添加 Typescript项目配置。接下来就要编写脚本了,所有还是有必要了解下cc脚本的生命周期

  1. onLoad 首次激活时触发,一般做一些初始化操作。对比Vue我觉得最合适的应该是beforeMount回调

  2. start 首次激活时触发,一般初始化一些中间状态的数据,改方法在onLoad之后,在第一次update之前,对比Vue自然应该是mounted回调

  3. update 该回调会频繁调用,每一帧调用一次。对比Vue应该是beforeUpdate回调,虽然他们性质不一样

  4. lateUpdate 该回调会频繁调用,也是每帧调用一次,对比Vue应该updated回调

  5. onDestroy 根据条件调用,当组件调用了自身的 destroy()方法,会触发此回调

  6. onEnable 根据条件调用, enabled 属性从 false 变为 true 或 active 属性从 false 变为 true 触发此回调

  7. onDisable 根据条件调用, enabled 属性从 true 变为 false 或active 属性从 true 变为 false触发此回调

4.1 让主角动起来

做过前端的你一定知道,要想拖动一个DIV,一定是在Body中监听鼠标的移动事件。在移动端一定是监听触摸移动事件。是的,在cc里边做游戏,希望一个组件动起来依然是这么操作的,那么cc里边是如何注册事件的呢?两个方式,一个在场景编辑器下角的属性中添加脚本里边的方法,另外一种就是直接在脚本里边添加。当然我推荐第二种。虽然IDE会帮我们生成很多代码,如果不自己写一遍,就永远不晓得数据流向。就像当年开发winform时,很多人拖动一个按钮控件,然后双击控件,IDE就自动帮你注册好了一个用户点击事件。殊不知,IDE是在xx.design.cs中通过代码替你注册好的。所以既然刚开始学,一定要了解清楚它的原理。

  • cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this) 注册一个系统事件 ,支持按键事件和重力感应事件

  • this.node.parent.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this) 在某个节点注册一个Node 支持的事件类型

所以,主角移动无非实在TouchMove时改自己的X/Y

// 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;
}

4.2 生成坑爹的星星

在cc里边需要重复生成的对象,我们一般会制作成一个预制资源。然后在基本中通过代码实例化。何为预制资源,就权当它是一个模板吧。现在生成我们第一颗小星星

// 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);
}

4.3 是时候接住星星了

只要是游戏少不了做碰撞检测,如果在CC中开启了物理引擎还好,直接跟星星和主角添加一个刚体就好了,不过我们没开启,那就自己来了。不过碰撞检测无非就是判断两个区域有没有重叠地方,简单判断就上下左右,左上右上左下右下八个点。不过我这里偷了个懒,直接判断星星和主角间向量的距离。

//author:herbert qq:464884492
...
let distance = this.node.position.sub(this.tank.getPosition()).mag();
if (distance < (this.tank.width / 2 - 5)) {
console.log("接住了");
}
...

4.4 来点刺激的

游戏嘛,总不能一成不变那多没意思,所以随着时间的推移我们的调整点难度。我这个游戏难度无非就一下两个方面

  1. 生成星星的速度加快

  2. 星星掉落的速度加快

//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();
...

4.5 是时候结束了

游戏嘛,也不能一直玩下去。不然多没挑战。自从调整游戏难度后我的最高分重来就没有超过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;
}
}
...

5. 来点实际的

做技术嘛,大多都是 Talk is cheap,Show me your code.做点总结吧

    • 开源地址

    • 在基本中定义的属性,切记在编辑器中拖动绑定

    • 多看官网api,多开实例代码

    • 发布微信小游戏一定不要有英文,会导致审核不通过

作为前端的你,CC游戏开发可以上车的更多相关文章

  1. [Canvas前端游戏开发]——FlappyBird详解

    一直想自己做点小东西,直到最近看了本<HTML5游戏开发>,才了解游戏开发中的一点点入门知识. 本篇就针对学习的几个样例,自己动手实践,做了个FlappyBird,源码共享在度盘 :也可以 ...

  2. Canvas前端游戏开发——FlappyBird详解

    一直想自己做点小东西,直到最近看了本<HTML5游戏开发>,才了解游戏开发中的一点点入门知识. 本篇就针对学习的几个样例,自己动手实践,做了个FlappyBird,源码共享在度盘;也可以参 ...

  3. PokemonGo:LBS游戏开发

    写在前面 去吧!皮卡丘!小时候拥有一台任天堂是多少熊孩子的梦想,每个夜晚被窝里透出的微弱光线,把小小的童年带入另一个世界,家门口的鸟和狗,森林里的虫和瀑布,山洞里的超音蝠,带着小小的梦,走过一个个城市 ...

  4. CutJS – 用于 HTML5 游戏开发的 2D 渲染引擎

    CutJS 是轻量级的,快速的,基于 Canvas 开发的 HTML5  2D 渲染引擎,可以用于游戏开发.它是开源的,跨平台的,与现代的浏览器和移动设备兼容.CutJS 提供了一个类似 DOM 树的 ...

  5. 优秀工具推荐:两款很棒的 HTML5 游戏开发工具

    HTML5 众多强大特性让我们不需要多么高深技术就能创建好玩的网页游戏,同时证明了开放的 Web 技术能与任何其他在游戏开发中使用的技术竞争.正如标题所说,这篇文章推荐的几款很棒 HTML5 游戏开发 ...

  6. Egret白鹭H5小游戏开发入门(一)

    前言: 好久没更新博客了,以前很多都不会,所以常常写博客总结,倒是现在有点点经验了就懒了.在过去的几个月里,在canvas游戏框架方面,撸过了CreateJS,玩得了Egret,又学过PIXI.js. ...

  7. HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)

    HTML5游戏开发进阶指南(亚马逊星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.)著 谢光磊译 ISBN 978-7-121-21226-0 201 ...

  8. [置顶] mmog游戏开发之业务篇

    这周不是很忙,因为我们的游戏开发了近一年,由于公司的业务调整,在游戏开第二服的时候,老板果断的把项目停到了. 感觉超级的不爽啊.因为这个游戏项目像我的孩子一样和我一样成长,里边的大概的业务逻辑都是偶实 ...

  9. 学习手机游戏开发的两个方向 Cocos2d-x 和 Unity 3D/2D,哪个前景更好?

    如题! 首先说一说学习手机游戏(移动游戏)这件事. 眼下移动互联网行业的在以井喷状态发展.全球几十亿人都持有智能终端设备(ios android),造就了非常多移动互联网创业机会: 一.移动社交 微信 ...

随机推荐

  1. 快速接入业务监控体系,grafana监控的艺术

    做一个系统,如果不做监控,是不完善的. 如果为做一个快速系统,花力气去做监控,是不值得的. 因为,我们有必要具备一个能够快速建立监控体系的能力.即使你只是一个普通开发人员! 个人觉得,做监控有三个核心 ...

  2. c# 开发ActiveX控件,添加事件,QT调用事件

    c# 开发 ActiveX 的过程参考我的另一篇文章 :  https://www.cnblogs.com/baqifanye/p/10414004.html 本篇讲如何 在C# 开发的ActiveX ...

  3. 使用SpringSecurity搭建授权认证服务(1) -- 基本demo认证原理

    使用SpringSecurity搭建授权认证服务(1) -- 基本demo 登录认证是做后台开发的最基本的能力,初学就知道一个interceptor或者filter拦截所有请求,然后判断参数是否合理, ...

  4. 常用的方法论-5W2H

  5. WebSocket API 学习笔记

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 W ...

  6. MYSQL5.7---ONLY_FULL_GROUP_BY 异常处理

    异常介绍: ONLY_FULL_GROUP_BY 指的是你查询的语句使用到了group by 例如  select name,age from person group by sex; 此时你grou ...

  7. MySql突然连接不上,报Can't connect to MySQL server on 'localhost' (10061),并且没有mysqld时解决方案

    今天连接数据库时突然连接不上,前一天还是好好的.打开数据库就报 Can't connect to MySQL server on 'localhost' (10061) 一直也知道是MySQL服务没有 ...

  8. vmware + opensuse windows如何远程登录到suse上

    vmware我还是比较偏向7.1.4版本,其他版本装在win7上似乎有点问题.windows平台下,使用vmware + opensuse的网络配置过程如下:      1. 装完vm后,会在本地连接 ...

  9. Spring MVC源码(四) ----- 统一异常处理原理解析

    SpringMVC除了对请求URL的路由处理特别方便外,还支持对异常的统一处理机制,可以对业务操作时抛出的异常,unchecked异常以及状态码的异常进行统一处理.SpringMVC既提供简单的配置类 ...

  10. 生成数据库自增不重复ID的方法

    namespace ConsoleApp1 { class Program { static void Main(string[] args) { ); ; i < ; i++) { var t ...