01 - FlappyBird开发Day1

今天开始接触Cocos2D游戏引擎(版本2.4.7),在开发Flappy Bird游戏的同时熟悉引擎的常用操作。

今天的工作内容是:

  • 搭建开始(Menu)和游戏(Level)场景
  • 通过点击按钮加载游戏场景
  • 一些小动画
  • 游戏基本逻辑(“重力”,单击屏幕鸟会往上飞)

项目初始化

编辑器布局

Cocos2D编辑器的界面布局如下:

从左到右依次是:

  • 层级管理器:管理一个 场景(Scene) 中的所有控件。
  • 资源管理器:负责管理游戏和编辑器的所有资源,如动画、纹理、脚本等资源。
  • 场景编辑器:是层级管理器的可视化,也能通过gizmo控件对场景中空间进行平移等操作。
  • 控制台:输出编辑器的信息。
  • 动画编辑器:负责编辑控件的 动画序列(Clip)
  • 游戏预览:负责渲染游戏最开始的前几帧。
  • 控件库:存放编辑器的内置控件和用户自定义控件。
  • 属性检查器:负责显示与管理控件的各个属性,包括反射脚本的properties

设置脚本编辑器

每次创建新项目后,需要在 开发者 -> VsCode工作流 中更新智能提示和扩展。由于使用JavaScript作为脚本语言,因此要删掉tsconfig.json,这样智能提示就正常工作了。

导入资源

在资源管理器的assets文件夹中新建res文件夹,导入项目的美术资源。在这个过程中,引擎会为每个资源生成.meta文件,描述每个资源的信息,如全局唯一的UUID标识。

搭建场景

在资源管理器的assets文件夹中新建scene文件夹,用来存储场景。

以开始场景(Menu)为例,新建一个叫做Menu的场景,此时默认有CanvasMain Camara两个控件。然后往场景中拖入背景等资源文件,会自动生成对应的 精灵(Sprite) 控件,其中Sprite Frame填充的就是背景等资源。接着拖入一个按钮控件,为它编辑背景控件和Transition属性。

最终搭建好的场景如下:

其中背景很长是为了之后设计滚动动画,当然背景滚动也能用脚本实现。

编辑动画

场景搭建完后,为了让控件动起来,可为它们编辑动画。Cocos2D引擎采用组件化设计,需要什么功能给控件添加相应组件即可,在这里需要为控件添加 动画(Animation)组件

添加动画组件后,需要打开动画编辑器编辑动画序列文件。先在资源管理器assets文件夹中创建animation文件夹用于存储动画序列文件,然后就能为控件创建动画了。

以标题的动画为例,需要用它的属性来K帧,然后编辑器会自动生成补间动画:

最后把对应的动画序列文件拖到标题控件的动画组件里即可,并启用Play On Load(上图右边)。

最终的标题动画如下:

编写脚本

脚本文件负责各控件的逻辑,是控件的灵魂。为了编写脚本,需要先在资源管理器assets文件夹中新建script文件夹,用来存储脚本。新建脚本后,需要绑定到对应的控件中,可以像添加组件一样添加用户自定义脚本组件。

脚本结构

脚本的结构如下:

cc.Class({
    extends: cc.Component,
    
    // 脚本组件的属性, 可反射到对应控件的属性检查器上
    properties: {
        // key: value
    },
    
    // 生命周期函数, 详见文档
    onLoad() {
        
    },
    
    start() {
        
    },
    
    update(dt) {
    	// 每帧运行一次  
    },
    // ...
    
    // 用户自定义脚本
    // ...
})

按钮和场景跳转

要想实现按钮的逻辑,得先找到按钮所在的 节点(Node),一共有五种方法找到节点:

  1. 公布一个cc.Node的属性到属性检查器,再把需要获取的节点拖拽到该属性上

  2. 组件.node,可以获取到组件所在的节点

  3. cc.find(“Canvas/…/….”)

  4. 父亲节点.getChildByName(“子节点的名称”);

  5. 子节点.parent,获取到父亲节点

这里使用第一种:

// Menu.js, 绑定Menu场景的Canvas
cc.Class({
    // ...

    properties: {
        btnStartNode: cc.Node,
    },

    onLoad() {
        // 绑定按钮按下的回调函数
        this.btnStartNode.on('click', this.btnStartCallback, this);
        // 场景预加载
        cc.director.preloadScene('Level', function () {
            console.log('预加载关卡...');
        })
    },

    btnStartCallback: function() {
        console.log('游戏开始了!');
        // 跳转游戏场景(Level)
        cc.director.loadScene('Level');
    }
});

有关事件(Event)和场景管理(cc.director)的更多信息详见文档。

小鸟逻辑

实现小鸟随着“重力”往下掉的逻辑如下:

// Bird.js, 绑定小鸟本身
cc.Class({
    extends: cc.Component,

    properties: {
        gravity: 0,
    },

    start() {
        this.speed = 0;
    },

    update(dt) {
        this.speed += this.gravity * dt;
        this.node.y -= this.speed * dt;
    },
});

触屏逻辑

实现触屏小鸟就往上飞的逻辑如下:

// Bird.js
cc.Class({
    // ...
    onLoad() {
        // 注册触屏事件
        this.touchLayer = cc.find('Canvas/touchLayer');
        // 将触摸touchLayer的事件的回调绑定到这里的onTouchStartCallback上
        this.touchLayer.on(cc.Node.EventType.TOUCH_START, this.onTouchStartCallback, this);
    },

    onTouchStartCallback: function (event) {
        console.log('点击跳跃, speed = ' + this.speed);
        this.speed = -150;
    }
});

如代码所示,需要先在场景上创建一个覆盖全屏的空Node,名字是touchLayer,然后在Bird.js中找到这个控件,进行注册。

明天要做的

可能进一步完善项目吧,比如加入碰撞检测,水管等。