junny4784 发表于 2024-7-15 18:33

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(&#39;ball&#39;).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 = &#39;时间到, 游戏结束, 3s后从头开始&#39;;

      this.clearScreen();

      // 3s后从头开始
      this.scheduleOnce(function(){
               
            this.init();
            this.unscheduleAllCallbacks(this);
      },3);

      return;
    }
    else{
      cc.log(&#39;残剩时间:&#39;, resTime);
      this.hintLabel.string = &#39;level : &#39; + this.level + &#39;, time : &#39; + resTime + &#39;s&#39;;
    }
}
7、添加布景音乐

添加布景音乐的做法是在脚本中使用AudioEngine的api来控制,具体的示例代码如下。游戏开始时,使用cc.audioEngine.playMusic进行播放。
init() {

    if (this.bgmAudio != null) {

      this.bgmAudioID = cc.audioEngine.playMusic(this.bgmAudio, true);
    }
}
未完待续。。。
页: [1]
查看完整版本: HappyClearance开发笔记