首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
安装和启动
Dashboard使用
Hello World 项目
项目结构
制作2D 游戏
环境搭建
创建主角
创建第一个脚本
制作地图
完善角色
制作动画
播放动画
游戏管理器
相机和卷轴
菜单制作
游戏状态
绑定按钮事件
监听跳跃结束
层级
完整代码
当前位置:
首页>>
技术小册>>
cocos游戏开发入门
小册名称:cocos游戏开发入门
我们游戏有三种状态,初始化、游戏中、游戏重置或者结算,和下棋类似,大部分游戏都可以粗略分解为这样的三个状态。 因此我们也可以定义这样的枚举来描述游戏状态。 ``` enum GameState{ GS_INIT, GS_PLAYING, GS_END, }; ``` 将上述的代码放在枚举 BlockType 附近。 这里我们为 GameManager 添加一个 setCurState 的方法提供给外界,使其可以用于控制游戏的状态: ``` setCurState (value: GameState) { switch(value) { case GameState.GS_INIT: break; case GameState.GS_PLAYING: break; case GameState.GS_END: break; } } ``` 添加一个 init 方法用于表示进入到 GS_INIT 时游戏的处理: ``` init() {} ``` 同时在 setCurState 的时候调用它: ``` setCurState (value: GameState) { switch(value) { case GameState.GS_INIT: this.init(); break; case GameState.GS_PLAYING: break; case GameState.GS_END: break; } } ``` 为了在游戏开始时不让用户操作角色,而在游戏进行时让用户操作角色,我们需要动态地开启和关闭角色对鼠标消息的监听。在 PlayerController 脚本中做如下修改: ``` start () { //input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this); } setInputActive(active: boolean) { if (active) { input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this); } else { input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this); } } ``` 此时的 GameManager 看起来是这样的: ``` import { _decorator, CCInteger, Component, instantiate, Node, Prefab } from 'cc'; import { BLOCK_SIZE, PlayerController } from './PlayerController'; const { ccclass, property } = _decorator; enum BlockType{ BT_NONE, BT_STONE, }; enum GameState{ GS_INIT, GS_PLAYING, GS_END, }; @ccclass('GameManager') export class GameManager extends Component { @property({type: Prefab}) public boxPrefab: Prefab|null = null; @property({type: CCInteger}) public roadLength: number = 50; private _road: BlockType[] = []; start() { this.setCurState(GameState.GS_INIT); // 第一初始化要在 start 里面调用 } init() { this.generateRoad(); } setCurState (value: GameState) { switch(value) { case GameState.GS_INIT: this.init(); break; case GameState.GS_PLAYING: break; case GameState.GS_END: break; } } 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)); } } for (let j = 0; j < this._road.length; j++) { let block: Node | null = this.spawnBlockByType(this._road[j]); if (block) { this.node.addChild(block); block.setPosition(j * BLOCK_SIZE, 0, 0); } } } 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; } } ``` 接下来我们分析下在每个状态下所需要处理的事情: GS_INIT:状态下需要初始化地图、将角色放回到初始点、显示游戏的UI,因此在属性中下列属性: ``` @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; // 计步器 ``` 在 init 方法中需要做如下的处理: ``` 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(); } } ``` init 时我们先显示 StartMenu、创建地图以及重设角色的为和状态并禁用角色输入。 GS_PLAYING:在状态下隐藏 StartMenu、重设计步器的数值以及启用用户输入: ``` 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); ``` GS_END:暂时没有什么好添加的,当然您可以根据喜好添加一些结算用的逻辑让游戏看起来更完善 回到编辑器,绑定好 GameManager 需要的属性: ![](/uploads/images/20230710/42dec514bccb530332c25cf0577ab193.png)
上一篇:
菜单制作
下一篇:
绑定按钮事件
该分类下的相关小册推荐:
暂无相关推荐.