Cocos Creator的Hello World

news2024/11/24 20:54:45

0、文档

Cocos官网文档

1、下载

访问cocos官网下载Cocos Dashboard
安装时选项安装 Visual Studio 2017可以不勾选
注意:Cocos Dashboard的快捷方式文件名为CocosDashboard.exe,不要误认为是安装文件

2、注册、登录

注册/登录cocos网址

3、Cocos Dashboard设置语言

Cocos Dashboard,点击右上角点击齿轮图标在这里插入图片描述打开设置界面
Language(Choose a display anguage.),修改为简体中文
点击右下角返回按钮退出设置界面。

4、安装编辑器

Cocos Dashboard(Cocos仪表板),版本管理软件。类似node.js的nvm,python的conda
它可以管理Cocos Creator游戏项目,无论项目基于的引擎版本是多少


Cocos Dashboard,点击右上角点击齿轮图标
自行决定修改编辑器目录,该设置会修改编辑器的存放位置

左侧边栏,点击编辑器,右下角点击下载编辑器按钮
选择一个版本点击右侧的下载图标在这里插入图片描述即可,本文选择下载CocosCreator 3.7.2
服务协议界面,点击同意按钮
等待下载
系统提示Cocos Creator 3.7.2 下载成功 正在解压中
(闲得无聊可以打开任务管理器查看CPU占用和磁盘占用,反正也没啥用)
系统提示Cocos Creator 3.7.2 安装成功 欢迎使用Cocos Creator 3.7.2
此时编辑器安装成功

5、新建项目

左侧边栏,点击项目,右下角点击新建按钮
编辑器版本默认选择刚安装的3.7.2
模板选择Empty(2D)
项目名称输入HiCocos(项目名称不能有特殊字符、空格,且不能以.结尾)
位置默认或自行修改
右下角点击创建按钮
等待加载

6、Cocos Creator设置语言

菜单栏 - File - Preferences,打开Preferences窗口
General分类,Language修改为中文
关闭Preferences窗口

7、配置代码编辑器

安装插件Prettier用于格式化ts脚本
格式化快捷键Shift+Alt+F,第一次格式化ts脚本时,配置默认格式化程序选择Prettier
VSCode左下角齿轮图标,设置,搜索Prettier: Tab Width,可以将其设置为4


如果安装了VSCode,默认情况下Cocos Creator可以找到VSCode,双击脚本文件自动就打开了,一般不用设置
(虽然它还是假装找不到,在控制台里提示如下(提示还是过时的):为更好地打开脚本,请在 偏好设置 -> 外部程序 -> 默认脚本编辑器 里配置打开脚本的应用程序)


如果双击脚本提示未关联脚本编辑器,按照以下步骤设置
VSCode下载教程,安装
安装完运行where.exe code得到路径C:\Program Files\Microsoft VS Code\bin\code
然后找到VSCode安装文件夹,C:\Program Files\Microsoft VS Code\Code.exe
Cocos Creator,菜单栏,文件,偏好设置,程序管理器,默认脚本编辑器,点击右侧的放大镜图标在这里插入图片描述
设置为Code.exe即可

8、扩大场景编辑器窗口

一般情况下,场景编辑器窗口大些比较容易查看,其他窗口可以随时拖拽回来
鼠标放到窗口边框,鼠标指针变为双向箭头时,拖拽窗口,使场景编辑器更大
请添加图片描述

9、如何重命名节点

层级管理器,选中要修改的节点
点击F2Enter、右键选择重命名或者在属性检查器的第一行修改名称

10、添加一个玩家

左上角层级管理器,右键Canvas,创建,空节点,重命名为玩家

11、添加一个玩家子节点精灵

左上角层级管理器,右键玩家,创建,2D对象,Sprite(精灵),重命名为身体
选中身体,查看右侧属性检查器,倒数第5项Sprite Frame,点击旁边的鼠标图标在这里插入图片描述修改精灵帧
选个按钮当身体用,选择default_btn_normal

层级如图,如果层级不对可以参考gif进行拖拽
在这里插入图片描述请添加图片描述

12、添加脚本

左下角资源管理器,右键assets,创建,文件夹,命名为脚本
右键脚本,创建,脚本(TypeScript),NewComponent,命名为PlayerController

13、玩家加载脚本

左上角层级管理器,选中玩家
右侧属性检查器,点击添加组件按钮
展开自定义脚本,点击PlayerController
加载完成

14、制作一个预制体

左下角资源管理器,右键assets,创建,文件夹,命名为预制体

左上角层级管理器,右键Canvas,创建,2D对象,Sprite(精灵),重命名为浮岛
右侧属性检查器,Sprite Frame,设置为default_btn_disabled

将创建好的浮岛拖拽进预制体文件夹
删除层级管理器里创建的浮岛

15、保存场景

左下角资源管理器,右键assets,创建,文件夹,命名为场景

快捷键Ctrl+S(或点击菜单栏 - 文件 - 保存场景(CTRL+S)),弹出保存场景窗口
进入场景文件夹,文件名scene.scene改为游戏.scene,保存

16、编辑脚本

左下角资源管理器,assets,脚本,PlayerController,双击文件打开 VSCode编辑器 编辑代码

16.1 改模板

查看默认代码.\HiCocos\assets\脚本\PlayerController.ts

import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('PlayerController')
export class PlayerController extends Component {
    start() {

    }

    update(deltaTime: number) {
        
    }
}

将其改为本教程的模板

// import 导入位置1
import { _decorator, Component, Node } from "cc";
const { ccclass, property } = _decorator;

// export 常量位置1

@ccclass("PlayerController")
export class PlayerController extends Component {
    // Animation 动画属性1

    // private 私有属性1
    // private 私有属性2

    // 组件第一次激活时调用的方法
    start() {}

    // 激活后关闭鼠标监听的方法

    // 重置方法

    // 监听鼠标输入方法

    // 根据步数跳跃方法

    // 监听跳跃结束的方法

    // 根据每次的更新来计算角色最新的位置方法
    update(deltaTime: number) {}

    // 直到教程结束, 此处的"}"符号一直作为脚本最后一个字符
    // ↙
} 
// ↖
// 它的配对符号必须为"export class PlayerController extends Component {"中的"{"
// VSCode会把这对花括号对"{}"显示为相同的颜色表明它们的配对关系, 点击其中一个, 两个符号会同时显示一个小边框

16.2 添加 PlayerController 在本教程的所有导入

    // import 导入位置1

改为

    // import 导入位置1
    import { Vec3, EventMouse, input, Input, AnimationComponent } from "cc";

16.3 添加监听鼠标输入方法

    // private 私有属性1

改为

    // private 私有属性1
    private _startJump: boolean = false;
    private _jumpStep: number = 0;
    private _curJumpTime: number = 0;
    private _jumpTime: number = 0.3;
    private _curJumpSpeed: number = 0;
    private _curPos: Vec3 = new Vec3();
    private _deltaPos: Vec3 = new Vec3(0, 0, 0);
    private _targetPos: Vec3 = new Vec3();

16.4 计算角色移动

    // 根据步数跳跃方法

改为

    // 根据步数跳跃方法
    jumpByStep(step: number) {
        if (this._startJump) {
            return;
        }

        // 动态计算_jumpTime

        this._startJump = true; // 标记开始跳跃
        this._jumpStep = step; // 跳跃的步数 1 或者 2
        this._curJumpTime = 0; // 重置开始跳跃的时间

        this._curJumpSpeed = this._jumpStep / this._jumpTime; // 根据时间计算出速度

        this.node.getPosition(this._curPos); // 获取角色当前的位置
        Vec3.add(
            this._targetPos,
            this._curPos,
            new Vec3(this._jumpStep, 0, 0)
        ); // 计算出目标位置

        // 播放动画

        // 增加步数
    }

16.5 判断鼠标是左键还是右键被按下

    // 监听鼠标输入方法

改为

    // 监听鼠标输入方法
    onMouseUp(event: EventMouse) {
        if (event.getButton() === 0) {
            this.jumpByStep(1);
        } else if (event.getButton() === 2) {
            this.jumpByStep(2);
        }
    }

16.6 使用input监听输入

    // 组件第一次激活时调用的方法
    start() {}

改为

    // 组件第一次激活时调用的方法
    start() {
        input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
    }

16.7 使用input监听输入

    // 根据每次的更新来计算角色最新的位置方法
    update(deltaTime: number) {}

改为

    // 根据每次的更新来计算角色最新的位置方法
    update(deltaTime: number) {
        if (this._startJump) {
            this._curJumpTime += deltaTime; // 累计总的跳跃时间
            if (this._curJumpTime > this._jumpTime) {
                // 当跳跃时间是否结束
                // end
                this.node.setPosition(this._targetPos); // 强制位置到终点
                this._startJump = false; // 清理跳跃标记
                // 调用监听跳跃结束的方法
                
            } else {
                // tween
                this.node.getPosition(this._curPos);
                this._deltaPos.x = this._curJumpSpeed * deltaTime; //每一帧根据速度和时间计算位移
                Vec3.add(this._curPos, this._curPos, this._deltaPos); // 应用这个位移
                this.node.setPosition(this._curPos); // 将位移设置给角色
            }
        }
    }

16.8 运行试试,移动的不明显

请添加图片描述

16.9 放大移动动作

    // export 常量位置1

改为

    // export 常量位置1
    export const BLOCK_SIZE = 40; // 添加一个放大比

再将// 根据步数跳跃方法jumpByStep中的

this._curJumpSpeed = this._jumpStep / this._jumpTime; // 根据时间计算出速度

改为

this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime; // 根据时间计算出速度并放大

再再将// 根据步数跳跃方法jumpByStep中的

        Vec3.add(
            this._targetPos,
            this._curPos,
            new Vec3(this._jumpStep, 0, 0)
        ); // 计算出目标位置

改为

        Vec3.add(
            this._targetPos,
            this._curPos,
            new Vec3(this._jumpStep * BLOCK_SIZE, 0, 0)
        ); // 计算出目标位置

17、运行

回到Cocos Creator
抬头位置,点击三角运行按钮在这里插入图片描述
请添加图片描述

18、动画

左下角资源管理器,右键assets,创建,文件夹,命名为动画
右键动画文件夹,创建,动画剪辑(Animation Clip)
将新建的Animation重命名为oneStep

选中身体,查看右侧属性检查器,点击添加组件
选择Animation - Animation
oneStep拖拽到身体Clips属性上,Clips将由0变为1

选中身体
快捷键Ctrl+6(或将控制台切换为动画编辑器)
动画编辑器提示进入动画编辑模式(Ctrl/Cmd+E)(拖拽动画剪辑资源到面板上)
oneStep拖拽到动画编辑器
(鼠标放到动画编辑器的上边框,鼠标变为⬍上下箭头,拖拽变大)
在这里插入图片描述
动画编辑器
左下角 属性列表,点击旁边的+加号添加属性轨道,选择position
点击新建的position
(Y坐标必须删除默认值手动输入后才会记录该帧的属性)
设置为0,属性检查器修改身体Position,Y坐标为0
设置为10,属性检查器修改身体Position,Y坐标为80
设置为20,属性检查器修改身体Position,Y坐标为0

动画编辑器使用状态下,按Ctrl+S保存

动画编辑器,点击三角图标按钮播放,玩家在场景编辑器窗口中跳跃

同样方式再创建一个twoStep
twoStep拖拽到身体Clips属性上,Clips将由1变为2
编辑twoStep
帧设置为0,Y坐标为0
帧设置为20,Y坐标改为80
帧设置为40,Y坐标改为0

动画编辑器使用状态下,按Ctrl+S保存
Ctrl+Q退出动画编辑器模式

19、编辑脚本(播放动画代码)

左下角资源管理器,assets,脚本,PlayerController,双击文件打开 VSCode编辑器 编辑代码

// Animation 动画属性1

改为

// Animation 动画属性1
@property(AnimationComponent)
BodyAnim: AnimationComponent = null;

新建完BodyAnim:Animation = null;之后,保存,回到Cocos Creator设置玩家Body Anim
左上角层级管理器,选中玩家
身体拖拽到右侧属性检查器的Body Anim
Ctrl+S

回到VSCode
将 jumpByStep 中的 // 播放动画

        // 播放动画

改为

        // 播放动画
        if (this.BodyAnim) {
            if (step === 1) {
                this.BodyAnim.play("oneStep");
            } else if (step === 2) {
                this.BodyAnim.play("twoStep");
            }
        }

回到Cocos Creator运行游戏,左键小跳,右键大跳(但是回落很诡异,因为还没有修改_jumpTime)

修改_jumpTime
将 jumpByStep 中的 // 动态计算_jumpTime

        // 动态计算_jumpTime

改为

        // 动态计算_jumpTime
        if (step === 1) {
            const oneStep = "oneStep";
            const state = this.BodyAnim.getState(oneStep);
            this._jumpTime = state.duration;
        } else if (step === 2) {
            const twoStep = "twoStep";
            const state = this.BodyAnim.getState(twoStep);
            this._jumpTime = state.duration;
        }

再次运行游戏,左键小跳,右键大跳,回落正常

20、游戏管理器

左下角资源管理器
右键脚本,创建,脚本(TypeScript),NewComponent,命名为GameManager

左上角层级管理器,右键Canvas,创建,空节点,重命名为游戏管理层级
选中游戏管理层级,属性检查器点击添加组件
展开自定义脚本,点击GameManager,加载完成

双击GameManager编辑它

20.1 改模板

查看默认代码.\HiCocos\assets\脚本\GameManager.ts

import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {
    start() {

    }

    update(deltaTime: number) {
        
    }
}

将其改为模板

// import 导入位置1
// import 导入位置2
import { _decorator, Component, Node } from "cc";
const { ccclass, property } = _decorator;

// enum 枚举1

// enum 枚举2

@ccclass("GameManager")
export class GameManager extends Component {
    // 预制体

    // 道路长度

    // 地图数据

    // 属性2

    // 组件第一次激活时调用的方法
    start() {}

    // 初始化的方法

    // 控制游戏状态的读取器

    // 生成地图的方法

    // 根据所需的数量和前1个位置来生成方块

    // 根据 BlockType 生成方块

    // 响应 开始游戏 按钮按下的事件

    // 判断跳坑失败或游戏完成的方法

    // 更新计步器的显示并判断"跳坑失败或游戏完成"

    // 没有用到update,注释掉
    // update(deltaTime: number) {}

    // 直到教程结束, 此处的"}"符号一直作为脚本最后一个字符
    // ↙
} 
// ↖
// 它的配对符号必须为"export class PlayerController extends Component {"中的"{"
// VSCode会把这对花括号对"{}"显示为相同的颜色表明它们的配对关系, 点击其中一个, 两个符号会同时显示一个小边框

20.2 添加 GameManager 在本教程的所有导入

// import 导入位置1
// import 导入位置2

改为

// import 导入位置1
import { CCInteger, instantiate, Label, Prefab, Vec3 } from "cc";
// import 导入位置2
import { BLOCK_SIZE, PlayerController } from "./PlayerController";

20.3 添加一个boxPrefab

    // 预制体

改为

    // 预制体
    @property({ type: Prefab })
    public boxPrefab: Prefab | null = null;

返回Cocos Creator
选中游戏管理层级
浮岛拖拽属性检查器到Box Prefab
Ctrl+S保存

20.4 添加枚举BlockType

// enum 枚举1

改为

// enum 枚举1
enum BlockType {
    BT_NONE,
    BT_STONE,
}

20.5 spawnBlockByType

    // 根据 BlockType 生成方块

改为

    // 根据 BlockType 生成方块
    spawnBlockByType(type: BlockType) {
        if (!this.boxPrefab) {
            return null;
        }

        let block: Node | null = null;
        switch (type) {
            case BlockType.BT_STONE:
                block = instantiate(this.boxPrefab);
                break;
        }

        return block;
    }

20.6 spawnBlockByCount

    // 根据所需的数量和前1个位置来生成方块

改为

    // 根据所需的数量和前1个位置来生成方块
    spawnBlockByCount(lastPos: number, count: number) {
        let block: Node | null = this.spawnBlockByType(BlockType.BT_STONE);
        if (block) {
            this.node.addChild(block);
            block?.setScale(count, 1, 1);
            block?.setPosition(
                (lastPos - (count - 1) * 0.5) * BLOCK_SIZE,
                -(BLOCK_SIZE + 1.5),
                0
            );
        }
    }

20.7 roadLength 和 _road

    // 道路长度

    // 地图数据

改为

    // 道路长度
    public roadLength: number = 50;
    // 地图数据
    private _road: BlockType[] = [];

20.8 生成地图

    // 生成地图的方法

改为

    // 生成地图的方法
    generateRoad() {
        // 清理上次的结果
        this.node.removeAllChildren();

        this._road = [];
        // startPos 开始位置必须是方块
        this._road.push(BlockType.BT_STONE);

        // 随机的方法生成地图
        for (let i = 1; i < this.roadLength; i++) {
            if (this._road[i - 1] === BlockType.BT_NONE) {
                this._road.push(BlockType.BT_STONE);
            } else {
                this._road.push(Math.floor(Math.random() * 2));
            }
        }

        let linkedBlocks = 0;
        for (let j = 0; j < this._road.length; j++) {
            if (this._road[j]) {
                ++linkedBlocks;
            }
            if (this._road[j] == 0) {
                if (linkedBlocks > 0) {
                    this.spawnBlockByCount(j - 1, linkedBlocks);
                    linkedBlocks = 0;
                }
            }
            if (this._road.length == j + 1) {
                if (linkedBlocks > 0) {
                    this.spawnBlockByCount(j, linkedBlocks);
                    linkedBlocks = 0;
                }
            }
        }
    }

20.9 在 start 中调用 generateRoad 创建地图

    // 组件第一次激活时调用的方法
    start() {}

改为

    // 组件第一次激活时调用的方法
    start() {
        this.generateRoad();
    }

20.10 运行

运行游戏,生成了浮岛
在这里插入图片描述

21、相机跟随玩家

层级管理器,将CameraCanvas层级下拖拽到玩家层级下
运行游戏,相机跟随玩家

22、提前规划摄相机的显示内容,避免后续的双摄相机重叠显示同一物体

  1. 层级管理器,选中Canvas
    属性检查器,将Layer改为DEFAULT,显示如图的提示
    在这里插入图片描述
    点击连同修改子节点
    Ctrl+S 保存

  2. 资源管理器,预制体,双击浮岛
    属性检查器,将Layer改为DEFAULT
    Ctrl+S 保存,Ctrl+Q退出编辑预制体模式

  3. 层级管理器,Canvas - 玩家 - Camera,选中Camera
    属性检查器,取消勾选VisibilityUI_2D,保持勾选VisibilityDEFAULT

23、游戏菜单

层级管理器,右键顶级层级游戏
创建,UI 组件,Canvas(画布)
将其命名为UICanvas

右键UICanvas,创建,空节点,将其命名为开始菜单

右键UICanvas,创建,2D对象,Label(文本),将其命名为步数
Position属性改为-440280
清空String属性


右键开始菜单,创建,2D对象,Sprite(精灵),将其命名为背景
Content Size属性改为400250
Sprite Frame属性由default_sprite改为default_panel
Type属性由SIMPLE改为SLICED

右键开始菜单,创建,UI 组件,Button(按钮),将其命名为开始菜单按钮
开始菜单按钮Position属性改为0-80
展开开始菜单按钮,将LabelString属性改为开始游戏


右键开始菜单,创建,2D对象,Label(文本),将其命名为开始菜单标题
Position属性改为080
Color属性改为#000000
String属性改为跳跳乐 2D
Font Size属性改为40

右键开始菜单,创建,2D对象,Label(文本),将其命名为开始菜单提示
Position属性改为040
Color属性改为#000000
String属性改为操作:左键小跳,右键大跳

24、修改UICanvas的Camera可见的层

层级管理器,UICancas下,选中Camera
属性检查器,取消勾选VisibilityDEFAULT,保持勾选VisibilityUI_2D

UICanvas默认层就是UI_2D,不用修改

25、游戏状态

25.1 返回去修改 PlayerController

25.1.1 修改start PlayerController

    // 组件第一次激活时调用的方法
    start() {
        input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
    }

改为

    // 组件第一次激活时调用的方法
    start() {
        // input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
    }

25.1.2 修改setInputActive PlayerController

    // 激活后关闭鼠标监听的方法
    // 激活后关闭鼠标监听的方法
    setInputActive(active: boolean) {
        if (active) {
            input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
        } else {
            input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
        }
    }

25.1.3 添加reset PlayerController

    // 重置方法

改为

    // 重置方法
    reset() {}

25.2 添加枚举 GameManager

// enum 枚举2

改为

// enum 枚举2
enum GameState {
    GS_INIT,
    GS_PLAYING,
    GS_END,
}

25.3 添加属性 GameManager

    // 属性2

改为

    // 属性2
    @property({ type: Node })
    public startMenu: Node | null = null; // 开始的 UI
    @property({ type: PlayerController })
    public playerCtrl: PlayerController | null = null; // 角色控制器
    @property({ type: Label })
    public stepsLabel: Label | null = null; // 计步器

25.4 添加init GameManager

    // 初始化的方法

改为

    // 初始化的方法
    init() {
        if (this.startMenu) {
            this.startMenu.active = true;
        }

        this.generateRoad();

        if (this.playerCtrl) {
            this.playerCtrl.setInputActive(false);
            this.playerCtrl.node.setPosition(Vec3.ZERO);
            this.playerCtrl.reset();
        }
    }

25.5 添加curState GameManager

    // 控制游戏状态的读取器

改为

    // 控制游戏状态的读取器
    set curState(value: GameState) {
        switch (value) {
            case GameState.GS_INIT:
                this.init();
                break;
            case GameState.GS_PLAYING:
                if (this.startMenu) {
                    this.startMenu.active = false;
                }

                if (this.stepsLabel) {
                    this.stepsLabel.string = "0"; // 将步数重置为0
                }

                setTimeout(() => {
                    //直接设置active会直接开始监听鼠标事件,做了一下延迟处理
                    if (this.playerCtrl) {
                        this.playerCtrl.setInputActive(true);
                    }
                }, 0.1);
                break;
            case GameState.GS_END:
                break;
        }
    }

25.6 修改游戏管理层级的属性

回到Cocos Creator编辑器
修改游戏管理层级的属性
开始菜单拖拽到Start Menu
玩家拖拽到Player Ctrl
步数拖拽到Steps Label
Ctrl+S保存

26、绑定按钮事件

    // 响应 开始游戏 按钮按下的事件

改为

    // 响应 开始游戏 按钮按下的事件
    onStartButtonClicked() {
        this.curState = GameState.GS_PLAYING;
    }

保存

回到Cocos Creator编辑器
修改开始菜单按钮的属性
Click Events(在cc.Button分类下),将0设置为1
游戏管理层级拖拽到第[0]项上,旁边选择GameManageronStartButtonClicked

运行游戏,正常运行
发现玩家踩在坑上没有反应,添加踩坑失败的游戏逻辑

27、监听跳跃结束 修改PlayerController.ts

1.添加属性

    // private 私有属性2

改为

    // private 私有属性2
    private _curMoveIndex: number = 0;



2.修改重置

    // 重置方法
    reset() {}

改为

    // 重置方法
    reset() {
        this._curMoveIndex = 0;
    }



3.添加jumpByStep中的// 增加步数

        // 增加步数

改为

        // 增加步数
        this._curMoveIndex += step;



4.监听跳跃结束

    // 监听跳跃结束的方法

改为

    // 监听跳跃结束的方法
    onOnceJumpEnd() {
        this.node.emit('JumpEnd', this._curMoveIndex);
    }



5.在update中调用监听跳跃结束

                // 调用监听跳跃结束的方法

改为

                // 调用监听跳跃结束的方法
                this.onOnceJumpEnd();

28、监听跳跃结束 修改GameManager.ts

1.添加一个空的onPlayerJumpEnd

    // 更新计步器的显示并判断"跳坑失败或游戏完成"

改为

    // 更新计步器的显示并判断"跳坑失败或游戏完成"
    onPlayerJumpEnd(moveIndex: number) {}

2.start

    // 组件第一次激活时调用的方法
    start() {
        this.generateRoad();
    }

改为

    // 组件第一次激活时调用的方法
    start() {
        this.curState = GameState.GS_INIT;
        this.playerCtrl?.node.on("JumpEnd", this.onPlayerJumpEnd, this);
    }

3.checkResult

    // 判断跳坑失败或游戏完成的方法

改为

    // 判断跳坑失败或游戏完成的方法
    checkResult(moveIndex: number) {
        if (moveIndex < this.roadLength) {
            if (this._road[moveIndex] == BlockType.BT_NONE) {
                //跳到了空方块上
                this.curState = GameState.GS_INIT;
            }
        } else {
            // 跳过了最大长度
            this.curState = GameState.GS_INIT;
        }
    }

4.填充onPlayerJumpEnd

    // 更新计步器的显示并判断"跳坑失败或游戏完成"
    onPlayerJumpEnd(moveIndex: number) {}

改为

    // 更新计步器的显示并判断"跳坑失败或游戏完成"
    onPlayerJumpEnd(moveIndex: number) {
        if (this.stepsLabel) {
            this.stepsLabel.string =
                "" +
                (moveIndex >= this.roadLength ? this.roadLength : moveIndex);
        }
        this.checkResult(moveIndex);
    }

29、基本成品

官方教程就教到这里
1.通关
请添加图片描述
2.直接失败
请添加图片描述

其他

Cocos Creator3相比Cocos Creator2缺少控件库,在层级窗口右键创建即可



请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习之CD数据集创建

深度学习之数据集创建1. 原始文件相关文件路径2. 数据集创建2.1 数据格式一2.2 数据格式二1. 原始文件相关文件路径 原始路径 对于label图片文件&#xff0c;通道需要为单通道&#xff0c;如果不是单通道&#xff0c;训练数据会报错 报错信息例如&#xff1a;ValueError: Mask…

自然语言处理(八):Lexical Semantics

目录 1. Sentiment Analysis 2. Lexical Database 2.1 What is Lexical Database 2.2 Definitions 2.3 Meaning Through Dictionary 2.4 WordNet 2.5 Synsets 2.6 Hypernymy Chain 3. Word Similarity 3.1 Word Similarity with Paths 3.2 超越路径长度 3.3 Abstra…

波形失真总结

失真是输入信号与输出信号在幅度比例关系、相位关系及波形形状产生变化的现象。音频功放的失真分为电失真和声失真两大类。电失真是由电路引起的&#xff0c;声失真是由还音器件扬声器引起的。电失真的类型有&#xff1a;谐波失真、互调失真、瞬态失真。声失真主要是交流接口失…

idea使用之 单词拼写检查设置 分级管理

前言 idea的智能提示使用起来非常顺手, 拼接检查也是其中一项, 有些字段什么的, 不小心将单词的字母顺序写错了, idea的拼接检查就会提示(前提是字段命名规范,并且乱序之后的不再是一个具有意义的单词), 如此一来, 就能规避很多粗心大意的错误. 但是呢, 有些时候,项目中有些自…

用Claude和Stable Diffusion绘制《武松打虎》

绘制四大名著的经典画面 现在最火爆的AI&#xff0c;分为两类&#xff0c;一个是文本生成&#xff0c;一个是图片生成。如果让这两种结合到一起来&#xff0c;会是什么样的效果的。 这样是不是可能帮我们绘制很多场景下的图片&#xff0c;比如四大名著&#xff0c;帮我们的四…

Numpy基础用法

Numpy 【Numerical Python】是一个开源的Python科学计算库&#xff0c;用于快速处理任意维度的数组。Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务&#xff0c;使用Numpy比直接使用Python要简洁的多。Numpy使用ndarray对象来处理多维数组&#xff0c;该对象是一个快…

【项目分析】基于工艺融合的数控编程方法的设计与实现

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招项目的&#xff0c;按照面试常问及项目核心点整理 &#x1f970;来源&#xff1a;该项目源于数控系统迭代的实验项目 &#x1f92d;结语&#xff1a;如果有帮到你的地方&#xff0c;就点个赞和关注…

新版 Spring Security 配置的变化

进入到 SpringBoot2.7 时代&#xff0c;有小伙伴发现有一个常用的类忽然过期了&#xff1a; 在 Spring Security 时代&#xff0c;这个类可太重要了。过期的类当然可以继续使用&#xff0c;但是你要是决定别扭&#xff0c;只需要稍微看一下注释&#xff0c;基本上就明白该怎么玩…

机器视觉公司,在玩一局玩不起的游戏

导语 有个著名咨询公司曾经预测过&#xff1a;未来只有两种公司&#xff0c;是人工智能的和不赚钱的。 它可能没想到&#xff0c;还有第三种——不赚钱的AI公司。 去年我们报道过“正在消失的机器视觉公司”&#xff0c;昔日的“AI 四小龙”&#xff08; 商汤、旷视、云从、依图…

大数据 | HBase基本工作原理

前文回顾&#xff1a;MapReduce基本原理 目录 &#x1f4da;HBase基本介绍 &#x1f407;HBase的设计目标和功能特点 &#x1f407;HBase在Hadoop中的生态环境 &#x1f4da;HBase的数据模型 &#x1f407;逻辑数据模型 &#x1f407;物理存储格式 &#x1f4da;HBase基…

rust网络编程以及unsafe模块

网络层目前 IPv4 和 IPv6 分庭抗礼&#xff0c;IPv6 还未完全对 IPv4 取而代之&#xff1b;传输层除了对延迟非常敏感的应用&#xff08;比如游戏quic协议&#xff09;&#xff0c;绝大多数应用都使用 TCP&#xff1b;而在应用层&#xff0c;对用户友好&#xff0c;且对防火墙友…

PageRank算法介绍

互联网上有数百亿个网页&#xff0c;可以分为这么几类&#xff1a;不含有用信息的&#xff0c;比如垃圾邮件&#xff1b;少数人比较感兴趣的&#xff0c;但范围不是很广的&#xff0c;比如个人博客、婚礼公告或家庭像册&#xff1b;很多人感兴趣的并且十分有用的&#xff0c;比…

基于DBN神经网络的语音分类识别

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN的语音分类识别 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN算法应用于语音分类 DBN神…

排污口漂浮物监测系统 yolov5

排污口漂浮物监测系统通过YOLOV5网络模型技术&#xff0c;排污口漂浮物监测算法模型对河道两岸各处排污口进行7*24小时不间断实时监测&#xff0c;当监测到河道两岸的排污口违规乱排乱放时&#xff0c;不需人为干预系统立即抓拍存档告警。我们选择当下YOLO卷积神经网络YOLOv5来…

实现数字化转型升级,快速开发平台流辰信息来助力!

在如今迅猛发展的年代里&#xff0c;科技的力量是伟大的&#xff0c;可以让老百姓的生活变得丰富多彩&#xff0c;也可以让各行各业的企业实现办公自动化&#xff0c;朝着数字化转型升级&#xff0c;快速提升办公协作效率。快速开发平台流辰信息作为一家低代码平台服务商&#…

(顺序栈)有效括号序列

文章目录前言&#xff1a;问题描述&#xff1a;问题解析&#xff1a;代码实现&#xff1a;总结&#xff1a;前言&#xff1a; 此篇是针对顺序栈的经典练习题。 问题描述&#xff1a; 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘…

iOS / iPadOS 15.7.4发布安全更新 旧版iPhone和ipad无法升级系统解决方法

苹果于昨日面向无法升级到 iOS / iPadOS 16 的旧款 iPhone 和 iPad&#xff0c;发布了 iOS / iPadOS 15.7.4 更新。本次更新并未引入新的功能&#xff0c;而是重点修复了存在于 WebKit 的两个“关键”漏洞。 iOS / iPadOS 15.7.4发布安全更新&#xff1a; 目前已经有充足的证据…

adb基本操作操作

Mumu模拟器 进入终端 cd C:\Program Files\Netease\MuMuPlayer-12.0\shell 获取root权限 adb root 连接手机 adb connect 127.0.0.1:7555 adb shell 查看连接多少台设备 adb devices 安装程序apk adb install C:\Android\CalcTest.apk adb install -r C:\Android\CalcT…

遥感常用库的比较:Rasterio vs GDAL

一、前言本博客对三种栅格处理工具做一个小小的比较&#xff1a;Python (rasterio) 和 GDAL。当我开始使用 GIS 和栅格处理时&#xff0c;我并没有真正关注我编写的脚本和使用的工具的性能。 但现在&#xff0c;处理更大的数据、更高的空间分辨率、快速处理我的光栅文件是成功的…

国产PIE-SAR软件

1.产品定位 PIE-SAR是一款针对国内外主流星载SAR传感器的数据处理分析软件&#xff0c;提供图形化操作界面。目前已支持国内外主流星载SAR传感器的数据处理与分析&#xff0c;包括强度图像基础处理、区域网平差处理&#xff08;含异源匹配、RD/RPC区域网平差&#xff09;、InS…