HappyClearance开发笔记
一、HappyClearance简介HappyClearance是类似于消消乐的休闲小游戏,玩法简单,易于上手。
1、游戏演示
2、游戏法则
游戏开始时,会自动生成一排小球,小球的颜色是随机的,一共有6种分歧的颜色。玩家把所有小球的颜色点成一样的之后,进入下一个level,而且前4个level是30s的倒计时,之后的level是40s的倒计时。倒计时结束后,玩家未能把所有小球颜色点成一样的,游戏从头开始。
二、HappyClearance开发规划
1、工程目录规划
创建好游戏工程后,需要规划工程目录,任何一个游戏项目,都需要有完善的目录布局规划,将场景、图片、脚本、音频、动画等资源进行分门别类保留。项目中,笔者把目录布局规划为Audios、Prefabs、Scenes、Scripts、Textures等目录。创建好的目录,如下图所示。
工程目录布局
2、场景规划和搭建
游戏中使用的设计分辩率是720x1280的竖屏模式,在场景中的Canvas根节点设置如下图所示。按照情况来选择适配策略,这里选择的是Fit Height和Fit Width,暗示不管屏幕宽高比如何,都完整显示设计分辩率中的所有内容,并添加一个Widget组件,使其填充满整个屏幕。创建好工程后,引擎默认自动打开一个场景,此中包罗了Canvas节点及其子节点Main Camera。按Ctrl+S组合键,保留整个场景到Scenes目录,并给场景起名为Game。
3、界面设计和框架
三、HappyClearance具体实现
1、添加游戏节点
在Canvas节点下,新建一个空节点,改削节点名称为bg,作为一个容器节点,并添加一个Widget组件使其填充满整个屏幕。
Widget (对齐组件) 是一个很常用的 UI 布局组件。它能使当前节点自动对齐到父物体的任意位置,或者约束尺寸,让你的游戏可以便利地适配分歧的分辩率。节点层级说明如下:
[*]bg:空节点,挂载游戏主控脚本。
[*]bg/ctrlArea:Sprite(单色)节点,游戏主区域。
[*]bg/hint:Label节点,等级及倒计时提示Label。
[*]logo:图片,显示游戏名称。
2、制作预制体
每个自动生成的小球都是一个预制体,创建与改削ball预制体的方式如下:
(1)在Canvas节点下,创建一个Sprite节点,定名为ball,大小设置为(64,64)。
(2)在ball节点的Sprite的Atlas属性中,添加图集资源,并挂载脚本ball.ts。
(3)给ball节点添加UI组件-Button组件,并添加一个点击事件,使其实现点击一下ball,可以自动切换图片。
(4)拖动ball节点到资源打点器的Prefab目录中,并删除场景中的ball节点,这样,就创建了小球的预制体。
(5)在资源打点器中,双击ball节点,可改削预制体。
制作预制体
3、读取图集
图集(Atlas)也称作 Sprite Sheet,是游戏开发中常见的一种美术资源。图集是通过专门的东西将多张图片合并成一张大图,并通过plist等格式的文件索引的资源。可供 Cocos Creator 使用的图集资源由plist和png文件组成。Cocos Creator中,使用SpriteAltas暗示一个图集。当需要动态改削一个cc.Sprite的spriteFrame属性时,如果是使用数组,遇到图片资源斗劲多时,比如100张图片,那么操作起来就会很麻烦。这时,使用cc.SpriteAtlas就会很便利。
randBall(typeCnt) {
// 获取图集里的图, 返回的是SpriteFrame数组
let frames = this.ballAtlas.getSpriteFrames();
this.sprite = this.node.getComponent(cc.Sprite);
if (typeCnt > frames.length) {
typeCnt = frames.length;
}
cc.log(typeCnt);
let randIndex = Math.floor(Math.random() * typeCnt);
cc.log(”randIndex:” + randIndex);
//图集里随机的图,改换节点的sprite.spriteFrame
this.sprite.spriteFrame = frames;
}4、window全局变量
5、动态生成小球
游戏中的小球是如何动态生成和销毁的呢?这里使用到了对象池的概念。
对象池就是一组可回收的节点对象,我们通过创建cc.NodePool的实例来初始化一种节点的对象池。凡是当我们有多个 prefab 需要实例化时,应该为每个 prefab 创建一个cc.NodePool实例。当我们需要创建节点时,向对象池申请一个节点,如果对象池里有空闲的可用节点,就会把节点返回给用户,用户通过 node.addChild 将这个新节点插手参加景节点树中。 当我们需要销毁节点时,调用对象池实例的 put(node) 方式,传入需要销毁的节点实例,对象池会自动完成把节点从场景节点树中移除的操作,然后返回给对象池。这样就实现了少数节点的循环操作。—Introduction · Cocos Creator
for (let i = 0; i < ballCnt; i++) {
let ballNode = null;
// 如果节点不存在
if (!this.ballNodeArr) {
if (ballNode == null) {
ballNode = this.ballPool.get();
ballNode = cc.instantiate(this.ballPrefab);
this.ctrlAreaNode.addChild(ballNode);
this.ballNodeArr.push(ballNode);
}
}
else {
//如果存在,即已生成,则直接从数组里取出
ballNode = this.ballNodeArr;
}
ballNode.getComponent('ball').randBall(typeCnt);
}
6、游戏倒计时
游戏倒计时的实现,使用了scheduleOnce。游戏结束3s后,从头开始新的游戏。
下面是 Component 中所有关于计时器的函数:
schedule:开始一个计时器
scheduleOnce:开始一个只执行一次的计时器
unschedule:打消一个计时器
unscheduleAllCallbacks:打消这个组件的所有计时器update (dt) {
this.nowTime += dt;
let resTime = Math.floor(this.time - this.nowTime);
if (resTime <= 0) {
this.gameOver = true;
this.hintLabel.string = '时间到, 游戏结束, 3s后从头开始';
this.clearScreen();
// 3s后从头开始
this.scheduleOnce(function(){
this.init();
this.unscheduleAllCallbacks(this);
},3);
return;
}
else{
cc.log('残剩时间:', resTime);
this.hintLabel.string = 'level : ' + this.level + ', time : ' + resTime + 's';
}
}
7、添加布景音乐
添加布景音乐的做法是在脚本中使用AudioEngine的api来控制,具体的示例代码如下。游戏开始时,使用cc.audioEngine.playMusic进行播放。
init() {
if (this.bgmAudio != null) {
this.bgmAudioID = cc.audioEngine.playMusic(this.bgmAudio, true);
}
}
未完待续。。。
页:
[1]