一、简介
- Cocos简而言之就是一个开发工具,详见官方网站
- TypeScript简而言之就是开发语言,是JavaScript的一个超集详解官网
今天我们就来学习如何写一个打砖块的游戏,很简单的一个入门级小游戏。
二、实现过程
2.1 布局部分
首先来一个整体的工程界面:
一看就很简单吧,就几个元素+脚本(之所以分开写是为了便于查错)。
再来一个游戏界面:很简洁有木有?当然啦,美观的工作需要各位小伙伴自行发挥啦。好了,下面进入正题…
首先,创建一个新的“世界”名字叫game。将场景设置为640X960
然后,你在这个世界花了1亿买了一块地皮,当然得有地契“BG”(在Canvas下新增一个空节点将大小改为640X960,或者你自己选择一张背景,拖在Canvas下设置大小就ok了,至于其他的就默认)
好了,有地皮了,你就可以“为所欲为”了。先添加砖块吧:
将砖块拖到Canvas下,然后拖回Texture就成了预制体(很简单有木有)。
至于大小什么的可以用代码控制。
因为是砖块,要和小球碰撞,所以要加上物理碰撞。
知识点
- cc.RigidBodyType.Static:静态刚体,零质量,零速度,即不会受到重力或速度影响,但是可以设置他的位置来进行移动
- cc.RigidBodyType.Dynamic:动态刚体,有质量,可以设置速度,会受到重力影响
- cc.RigidBodyType.Kinematic:运动刚体,零质量,可以设置速度,不会受到重力的影响,但是可以设置速度来进行移动
- cc.RigidBodyType.Animated:动画刚体,在上面已经提到过,从 Kinematic 衍生的类型,主要用于刚体与动画编辑结合使用
这里我们选择:
- Type:Static(静止),在那等着小球来碰撞。然后给他添加一个包围盒PhysicsBoxCollider
- PhysicsBoxCollider 类型,摩擦力、弹性系数请自由发挥
再来是我们的主角:
同样的给他一个碰撞组件,Type: Dynamic;然后添加包围盒
下面就是托盘,也是Static
然后添加一个空节点,大小比BG小一些,他的作用其实就是“围墙”,避免小球或托盘飞出场景。同时添加碰撞组件和包围盒。
然后还有个foot_line,这个就是监测小球掉下去游戏结束。
还有个count ,后面再说这个计数。好了,罗里吧嗦的布局就完成了。
2.2 代码部分
我们首先建一个game的游戏脚本,用来初始化一些节点(其实所有的代码都可以放在一个脚本里,但是遇到复制的程序的时候不便于查错,所以该分开写的还是要分开写。
首先呢,我们要加载一些节点变量。写代码的时候带上注释是好习惯哦!
我们来一个创建砖块的方法吧:
我采用的是中规中矩的生成方法,通过i和j控制行和列,然后在设置横向间距即可最后生成的结果为:(其他的样式,只要找到规律生成即可。)
再来我们看onload方法:
第二句先忽略。因为小球和砖块碰撞会产生效果,所以要开启物理碰撞(默认是关闭的)。托盘是根据手指移动的,所以要监听手指的移动:
知识点
我们这里用touch_move,接着需要
//获取点击的坐标并转换成节点坐标系坐标
let eposition = self.node.convertToNodeSpaceAR(event.getLocation());
然后设置托盘的位置即可。托盘是左右移动的,所以还需要控制他不能移出屏幕
//控制不能移除屏幕
let minx = -self.node.width / 2 + this.wall.width / 2;//最小坐标
let maxx = -minx;
if (this.wall.x > maxx) {
this.wall.x = maxx;
}
if (this.wall.x < minx) {
this.wall.x = minx;
}
场景开始加载的时候我们需要快速的生成好砖块,所以这用了定时器使用计时器
//自动生成砖块
self.schedule(function () { self.createbrick(); }, 0.2, 1);
第一个参数就是回调方法,第二个是时间间隔,每隔多少秒调用一次,第三个是执行次数,默认为0执行一次。
好了,初始代码完了,简单吧(其实还有些新增的东西,如障碍物和多个小球的生成,这个我们就后面再讲)。
然后我把脚本挂在Canvas上,并把相应的节点和组件拖进去。运行可以看到已经生成了砖块了吧。
再来我们看主角:ball,同样的给他创建一个脚本ball并挂在小球上。
这个脚本的作用主要是检测,碰撞检测。关于碰撞标签tag,按顺序给碰撞体添加即可。
onBeginContact(contact:cc.PhysicsContact,selfCollider:cc.PhysicsCollider,otherCollider:cc.PhysicsCollider):void{}
用碰撞的tag来区分与小球(self)碰撞的是哪个碰撞体。如果是托盘,那就给小球一个速度。如果是托盘没接住小球掉下去了,游戏结束我们就要跳转到结束界面(后面讲)。
接着就是砖块了:
这个呢主要就是加分用的。基本是完工了,很简单的有木有。
再来看结束的场景:
创建一个结束的场景Sence,同样的需要一个脚本overcount,脚本里需要处理的是:
- 接收主场景传过来的分数并做展示,此处我直接把节点给传过来了
- 重新开始按钮功能
第一个,分数节点,我们创建一个label节点但是因为要是常驻节点所以它和Canvas平级。
然后新建一个脚本挂在此节点上
onLoad () {
cc.game.addPersistRootNode(this.node);
}
声明它为常驻节点。
Brick.ts:当小球和砖块碰撞的时候呢,分数+1,并且要销毁砖块。
if (otherCollider.tag == 0) {//球和砖块碰撞
let gamecc = cc.director.getScene().getChildByName('count').getComponent(cc.Label);
gamecc.string = String(Number(gamecc.string) + 1);
this.node.destroy();
拿到分数后,ball.ts:
if(otherCollider.tag==5){//球和foot_line碰撞
cc.director.getPhysicsManager().enabled = false;
cc.find('Canvas').destroyAllChildren();
cc.director.loadScene('over');
}
如果小球掉下去了(托盘没接到),然后我们将小球的物理状态关掉,清除game场景下的所有节点并跳转到结束场景over。
Over场景中有一个重新开始的按钮overcount.ts:
需要做的就是获取分数并将分数复制给结束界面的Label,然后隐藏此常驻节点。
let gamecount = cc.director.getScene().getChildByName('count').getComponent(cc.Label);
gamecount.node.active = false;
this.overcount.string = gamecount.string;
self.again.on(cc.Node.EventType.TOUCH_START, function () {
gamecount.string = String(0);
cc.director.loadScene('game');
}, self)
点击重新开始按钮,那么需要把分数置为0,当然还没完,前面我们是关闭了分数计数节点,现在需要打开Game.ts
onLoad() {
let self = this;
//开启分数节点
cc.director.getScene().getChildByName('count').getComponent(cc.Label).node.active = true;
好了,到这你就可以让你的程序跑起来了。
2.3 新增功能
障碍物
障碍物很简单的,也是通过预制体,然后给它上面挂个label用来当小球碰到障碍物的时候,这个数值自减最后在总分数上加上这个分值。
创建一个bar脚本并挂在此节点上,Bar.ts
脚本的作用呢就是给障碍物一个常量,小球和障碍物每碰撞一次就减1,当小于1 的时候就给总发加上3分。
好了,大概就是这些了,项目其实很简单。多练、多写ヾ(◍°∇°◍)ノ゙
还有添加隐藏的小球,碰撞后生成多个小球!这个请小伙伴自行发挥了…