当前位置:  首页>> 技术小册>> cocos游戏开发入门

我们游戏有三种状态,初始化、游戏中、游戏重置或者结算,和下棋类似,大部分游戏都可以粗略分解为这样的三个状态。

因此我们也可以定义这样的枚举来描述游戏状态。

  1. enum GameState{
  2. GS_INIT,
  3. GS_PLAYING,
  4. GS_END,
  5. };

将上述的代码放在枚举 BlockType 附近。

这里我们为 GameManager 添加一个 setCurState 的方法提供给外界,使其可以用于控制游戏的状态:

  1. setCurState (value: GameState) {
  2. switch(value) {
  3. case GameState.GS_INIT:
  4. break;
  5. case GameState.GS_PLAYING:
  6. break;
  7. case GameState.GS_END:
  8. break;
  9. }
  10. }

添加一个 init 方法用于表示进入到 GS_INIT 时游戏的处理:

  1. init() {}

同时在 setCurState 的时候调用它:

  1. setCurState (value: GameState) {
  2. switch(value) {
  3. case GameState.GS_INIT:
  4. this.init();
  5. break;
  6. case GameState.GS_PLAYING:
  7. break;
  8. case GameState.GS_END:
  9. break;
  10. }
  11. }

为了在游戏开始时不让用户操作角色,而在游戏进行时让用户操作角色,我们需要动态地开启和关闭角色对鼠标消息的监听。在 PlayerController 脚本中做如下修改:

  1. start () {
  2. //input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
  3. }
  4. setInputActive(active: boolean) {
  5. if (active) {
  6. input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
  7. } else {
  8. input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
  9. }
  10. }

此时的 GameManager 看起来是这样的:

  1. import { _decorator, CCInteger, Component, instantiate, Node, Prefab } from 'cc';
  2. import { BLOCK_SIZE, PlayerController } from './PlayerController';
  3. const { ccclass, property } = _decorator;
  4. enum BlockType{
  5. BT_NONE,
  6. BT_STONE,
  7. };
  8. enum GameState{
  9. GS_INIT,
  10. GS_PLAYING,
  11. GS_END,
  12. };
  13. @ccclass('GameManager')
  14. export class GameManager extends Component {
  15. @property({type: Prefab})
  16. public boxPrefab: Prefab|null = null;
  17. @property({type: CCInteger})
  18. public roadLength: number = 50;
  19. private _road: BlockType[] = [];
  20. start() {
  21. this.setCurState(GameState.GS_INIT); // 第一初始化要在 start 里面调用
  22. }
  23. init() {
  24. this.generateRoad();
  25. }
  26. setCurState (value: GameState) {
  27. switch(value) {
  28. case GameState.GS_INIT:
  29. this.init();
  30. break;
  31. case GameState.GS_PLAYING:
  32. break;
  33. case GameState.GS_END:
  34. break;
  35. }
  36. }
  37. generateRoad() {
  38. this.node.removeAllChildren();
  39. this._road = [];
  40. // startPos
  41. this._road.push(BlockType.BT_STONE);
  42. for (let i = 1; i < this.roadLength; i++) {
  43. if (this._road[i - 1] === BlockType.BT_NONE) {
  44. this._road.push(BlockType.BT_STONE);
  45. } else {
  46. this._road.push(Math.floor(Math.random() * 2));
  47. }
  48. }
  49. for (let j = 0; j < this._road.length; j++) {
  50. let block: Node | null = this.spawnBlockByType(this._road[j]);
  51. if (block) {
  52. this.node.addChild(block);
  53. block.setPosition(j * BLOCK_SIZE, 0, 0);
  54. }
  55. }
  56. }
  57. spawnBlockByType(type: BlockType) {
  58. if (!this.boxPrefab) {
  59. return null;
  60. }
  61. let block: Node | null = null;
  62. switch (type) {
  63. case BlockType.BT_STONE:
  64. block = instantiate(this.boxPrefab);
  65. break;
  66. }
  67. return block;
  68. }
  69. }

接下来我们分析下在每个状态下所需要处理的事情:

GS_INIT:状态下需要初始化地图、将角色放回到初始点、显示游戏的UI,因此在属性中下列属性:

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

在 init 方法中需要做如下的处理:

  1. init() {
  2. if (this.startMenu) {
  3. this.startMenu.active = true;
  4. }
  5. this.generateRoad();
  6. if (this.playerCtrl) {
  7. this.playerCtrl.setInputActive(false);
  8. this.playerCtrl.node.setPosition(Vec3.ZERO);
  9. this.playerCtrl.reset();
  10. }
  11. }

init 时我们先显示 StartMenu、创建地图以及重设角色的为和状态并禁用角色输入。

GS_PLAYING:在状态下隐藏 StartMenu、重设计步器的数值以及启用用户输入:

  1. if (this.startMenu) {
  2. this.startMenu.active = false;
  3. }
  4. if (this.stepsLabel) {
  5. this.stepsLabel.string = '0'; // 将步数重置为0
  6. }
  7. setTimeout(() => { //直接设置active会直接开始监听鼠标事件,做了一下延迟处理
  8. if (this.playerCtrl) {
  9. this.playerCtrl.setInputActive(true);
  10. }
  11. }, 0.1);

GS_END:暂时没有什么好添加的,当然您可以根据喜好添加一些结算用的逻辑让游戏看起来更完善

回到编辑器,绑定好 GameManager 需要的属性:


该分类下的相关小册推荐:

暂无相关推荐.