1.基础知识
1.1.cocos与CocosCreator编程思想差异
1.2.节点
创建节点
节点的属性设置
1.3.锚点与坐标系
锚点的设置
坐标系
1.4.精灵的使用
九宫格
1.5.精灵图集
1.6.向量与标量
1.7.向量的运算及意义
1.8.脚本解析
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
//@property能在面板上显示属性,括号里填写属性的类型能在面板显示属性类型
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
// onLoad () {}
start() {
}
// update (dt) {}
}
1.9.脚本生命周期
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
//初始化调用
onLoad() {
console.debug("onLoad");
}
onEnable() {
console.debug("onEnable");
}
//初始化调用
start() {
}
//每帧调用
update (dt) {}
lateUpdate() {}
onDisable() {}
//销毁时调用
onDestroy() {
console.debug("onDestroy");
}
}
1.10.节点的常用属性方法
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
start() {
console.debug("start");
// 获得子节点
// this.node.children[0];
// this.node.getChildByName("abc");
// cc.find("Canvas/Main Camera");
// 获得父节点
// this.node.getParent();
// this.node.setParent('ddd');
// 移除所有节点
// this.node.removeAllChildren();
// 移除某个节点
// this.node.removeChild(ddd);
// 从父节点中移除掉
// this.node.removeFromParent();
// 访问位置
// this.node.x;
// this.node.y;
// this.node.setPosition(3, 4);
// this.node.setPosition(cc.v2(3, 4));
// 旋转
// this.node.rotation;
// 缩放
// this.node.scale;
// 锚点
// this.node.anchorX;
// this.node.color = cc.Color.BLUE;
// 节点开关
// this.node.active = false;
// 组件开关
// this.enabled = false;
// 获取组件
// let sprite = this.getComponent(cc.Sprite);
// this.getComponentInChildren(cc.Sprite);
}
update(dt) {}
}
1.11.预设体的使用
生成预设体
通过脚本创建节点、添加组件
// 创建节点
// let node = new cc.Node("new");
// 添加组件
// node.addComponent(cc.Sprite);
使用预设体
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// 预设体
@property(cc.Prefab)
pre: cc.Prefab = null;
// LIFE-CYCLE CALLBACKS:
// 初始化调用
start() {
// 实例化预设体
let node = cc.instantiate(this.pre);
// 设置父节点
node.setParent(this.node);
}
update(dt) {}
}
1.12.资源动态加载
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
// 初始化调用
start() {
let that = this;
cc.loader.loadRes("test/land", cc.SpriteFrame, function (err, sp) {
that.getComponent(cc.Sprite).spriteFrame = sp;
});
//加载图集
cc.loader.loadRes(
"test/1",
cc.SpriteAtlas,
function (err, atlas: cc.SpriteAtlas) {
that.getComponent(cc.Sprite).spriteFrame =
atlas.getSpriteFrame("bg_day");
}
);
}
update(dt) {}
}
1.13.场景管理
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
// 初始化调用
start() {
//加载第二个场景
cc.director.loadScene("game2", function () {
//当前已经加载到新场景里了
});
// 预加载
cc.director.preloadScene("game2", function () {
//这个场景加载到内存了但是还没有用
cc.director.loadScene("game2");
});
//添加常驻节点,切换场景不会被注销
cc.game.addPersistRootNode(this.node);
//移除常驻节点
cc.game.removePersistRootNode(this.node);
}
update(dt) {}
}
1.14.键鼠事件
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
// 初始化调用
start() {
// 鼠标事件
this.node.on(cc.Node.EventType.MOUSE_DOWN, function (event) {
console.log("鼠标按下了" + event.getLocation());
if (event.getButton() == cc.Event.EventMouse.BUTTON_RIGHT) {
console.log("右键");
}
if (event.getButton() == cc.Event.EventMouse.BUTTON_LEFT) {
console.log("左键");
}
});
// 全局键盘事件
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function (event) {
if (event.keyCode == cc.macro.KEY.w) {
console.log("w");
}
if (event.keyCode == cc.macro.KEY.q) {
console.log("q");
}
});
}
update(dt) {}
}
1.15.触摸与自定义事件
const { ccclass, property } = cc._decorator;
@ccclass
export default class Test extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
// 初始化调用
start() {
// 触摸事件
let self = this;
this.node.on(cc.Node.EventType.TOUCH_START, (event) => {
console.log("触摸" + event.getID());
console.log("触摸" + event.getLocation());
// self.node.emit("myEvent1");
// true:是否冒泡
this.node.dispatchEvent(new cc.Event.EventCustom("myEvent1", true));
});
this.node.on("myEvent1", function (event) {
console.log("自定义事件");
});
}
update(dt) {}
}
1.16.碰撞检测
不基于物理性的碰撞
在bg_day挂载脚本
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = "hello";
// LIFE-CYCLE CALLBACKS:
// onLoad () {}
start() {
// 碰撞检测
cc.director.getCollisionManager().enabled = true;
}
// 产生碰撞
onCollisionEnter(other) {
// tag用于辨识碰撞到的物体
console.log("碰撞发生" + other.tag);
}
onCollisionStay(other) {
console.log("碰撞持续");
}
onCollisionExit(other) {
console.log("碰撞结束");
}
// update (dt) {}
}
1.17.音频播放
以代码的方式播放音频
const { ccclass, property } = cc._decorator;
@ccclass
export default class AudioManager extends cc.Component {
start() {
// 组件的方式进行播放
let player: cc.AudioSource = this.getComponent(cc.AudioSource);
cc.loader.loadRes("海阔天空", cc.AudioClip, (res, clip) => {
//赋值音频
player.clip = clip;
player.play();
// 是否正在播放
player.isPlaying;
// 暂停
player.pause();
// 恢复
player.resume();
// 停止
player.stop();
// 循环
player.loop = true;
player.volume = 1;
// });
// 不依赖组件的播放方式
cc.loader.loadRes("海阔天空", cc.AudioClip, (res, clip) => {
// 播放
let audioId: number = cc.audioEngine.playMusic(clip, true);
// 是否正在播放
cc.audioEngine.isMusicPlaying();
// 暂停
cc.audioEngine.pause(audioId);
// 恢复
cc.audioEngine.resume(audioId);
// 停止
cc.audioEngine.stop(audioId);
// 循环
cc.audioEngine.setLoop(audioId, true);
// 声音大小
cc.audioEngine.setVolume(audioId, 1);
});
}
// update (dt) {}
}
1.18.物理系统
const { ccclass, property } = cc._decorator;
@ccclass
export default class BirdControl extends cc.Component {
onLoad() {
// 启用物理系统
cc.director.getPhysicsManager().enabled = true;
}
}
1.19.物理碰撞
碰撞检测
const { ccclass, property } = cc._decorator;
@ccclass
export default class BirdControl extends cc.Component {
onLoad() {
// 启用物理系统
cc.director.getPhysicsManager().enabled = true;
}
start() {
let rbody = this.getComponent(cc.RigidBody);
//x轴y轴作用力 作用点 立刻运用
// rbody.applyForce(cc.v2(1000, 0), cc.v2(0, 0), true);
// rbody.applyForceToCenter(cc.v2(5000, 0), true);
rbody.linearVelocity = cc.v2(50, 0);
}
onBeginContact(contact, self, other) {
// 得到碰撞点
let points = contact.getWorldManifold().points;
// 法线
let normal = contact.getWorldManifold().points;
console.log("发生碰撞" + normal);
}
onEndContact(contact, self, other) {
console.log("结束碰撞");
}
}
1.20.射线
const { ccclass, property } = cc._decorator;
@ccclass
export default class BirdControl extends cc.Component {
onLoad() {
// 启用物理系统
cc.director.getPhysicsManager().enabled = true;
let results = cc.director
.getPhysicsManager()
.rayCast(
this.node.getPosition(),
cc.v2(this.node.x, this.node.y + 100),
cc.RayCastType.Closest
);
for (let i = 0; i < results.length; i++) {
let res = results[i];
//射线碰到的碰撞器
// res.collider;
//碰到的点
// res.point;
//碰到的法线
// res.normal;
}
}
}
1.21.动作系统
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
// onLoad () {}
start() {
// 动作
// 移动到点
let action = cc.moveTo(2, cc.v2(200, 200));
// 移动多少
action = cc.moveBy(2, cc.v2(200, 200));
// 旋转
action = cc.rotateTo(2, 100);
// 缩放
action = cc.scaleTo(2, 1.5, 0.5);
// 跳跃
action = cc.jumpBy(2, 200, 0, 100, 3);
// 闪烁
action = cc.blink(3, 5);
// 淡出
action = cc.fadeOut(3);
// 淡入
action = cc.fadeIn(3);
// 渐变
action = cc.fadeTo(3, 100);
// 颜色
action = cc.tintTo(3, 100, 30, 300);
// 执行动作
this.node.runAction(action);
// 停止动作
// this.node.stopAction(action);
// this.node.stopAllActions();
// action.setTag(33);
// this.node.stopActionByTag(33);
// this.node.pauseAllActions();
// this.node.resumeAllActions();
}
}
1.22.容器动作
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
// onLoad () {}
start() {
// 容器动作
// 显示
let action = cc.show();
// 隐藏
action = cc.hide();
// 切换显示隐藏
action = cc.toggleVisibility();
// 翻转
action = cc.flipX(true);
action = cc.flipY(true);
// 回调动作
action = cc.callFunc(() => {});
action = cc.fadeOut(1);
let action2 = cc.fadeIn(1);
// 队列/序列 动作
let seq = cc.sequence(
action,
action2,
cc.delayTime(1),
cc.callFunc(() => {})
);
let repeat = cc.repeat(seq, 3);
repeat = cc.repeatForever(seq);
// 并列动作
let move = cc.moveTo(3, 500, 500);
let color = cc.tintTo(3, 100, 100, 20);
let spawn = cc.spawn(move, color);
this.node.runAction(spawn);
}
}
1.23.动画系统
1.24.动画曲线与事件
动画曲线
事件
帧动画
代码控制播放动画
const { ccclass, property } = cc._decorator;
@ccclass
export default class PlayerControl extends cc.Component {
// onLoad () {}
start() {
let ani = this.getComponent(cc.Animation);
ani.play("run");
ani.pause();
ani.resume();
ani.stop();
}
// update (dt) {}
}
1.25.屏幕Canvas
label文本
1.26.图文混排
RichText富文本
我是<color=#ff0000>红色</color>,<size=60>大</size>号字体,<i>斜体</i>,<u>下划线</u>,<color=#ff0000><outline>描边</outline></color>
点击事件
图文混排
1.27.屏幕适配与遮罩
遮罩
屏幕适配
1.28.按钮与布局
点击事件
布局
1.29.滑动进度控件
1.30.输入框
1.31.补充控件
1.32.数据存储
const { ccclass, property } = cc._decorator;
@ccclass
export default class DataTest extends cc.Component {
start() {
// 储存数据
cc.sys.localStorage.setItem("name", "蜘蛛侠");
// 获取数据
let name = cc.sys.localStorage.getItem("name");
// 移除一个数据
cc.sys.localStorage.removeItem("name");
// 清除
cc.sys.localStorage.clear();
}
// update (dt) {}
}
1.33.Json数据
const { ccclass, property } = cc._decorator;
class Person {
id: number;
name: string;
wugong: string[];
}
@ccclass
export default class JsonTest extends cc.Component {
start() {
/*
json:
数据格式:json xml csv 写文本
客户端-客户端
游戏存档 -> 地图,坐标,等级,攻击,防御,物品,武功,好友度......
*/
let person: Person = new Person();
person.id = 10;
person.name = "李逍遥";
person.wugong = ["降龙十八掌", "独孤九剑"];
//对象->字符串
/*
json:{} 对象 []数组
'{"id":10,"name":"李逍遥","wugong":["降龙十八掌", "独孤九剑"]}'
*/
//对象->json 序列化
let json = JSON.stringify(person);
console.log(json);
cc.sys.localStorage.setItem("save1", person);
//json->对象
let person2: Person = Object.assign(new Person(), JSON.parse(json));
console.log(person2.name);
}
}
1.34.数字格式
const { ccclass, property } = cc._decorator;
class Person {
id: number;
name: string;
wugong: string[];
}
@ccclass
export default class JsonTest extends cc.Component {
start() {
//person[] ->字符串
//json
/*
[{
"id":10,
"name":"李逍遥",
"wugong":[
"降龙十八掌", "独孤九剑"
]
},{
"id":2,
"name":"王小虎",
"wugong":[
"魔刀", "凌波微步"
]
}]
*/
//xml
/*
<root>
<person id="10">
<name>李逍遥</name>
<wugong> 降龙十八掌,独孤九剑</wugong>
</person>
<person id="2">
<name>王小虎</name>
<wugong> 魔刀,凌波微步</wugong>
</person>
</root>
*/
//csv
/*
10,李逍遥,降龙十八掌/独孤九剑
2,王小虎,魔刀/凌波微步
*/
}
}
1.35.网络请求
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
start() {
let url = "http://iwenwiki.com:3000/search?keywords=海阔天空";
// 请求
let request = cc.loader.getXMLHttpRequest();
request.open("GET", url, true); //异步 同步
// 请求状态改变
request.onreadystatechange = () => {
// 请求结束后获取信息;
if (request.readyState == 4 && request.status == 200) {
console.log("请求完成");
console.log(request.responseText);
}
};
request.send();
}
// update (dt) {}
}
1.36.自定义Animation
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
//每秒播放速度
@property
speed: number = 0.1;
//播放帧数组
@property(cc.SpriteFrame)
sprites: cc.SpriteFrame[] = [];
//是否播放动画
@property
isPlayer: boolean = false;
//当前播放帧
index: number = 0;
//计时器
timer: number = 0;
start() {}
play() {
this.isPlayer = true;
}
stop() {
this.isPlayer = false;
}
update(dt) {
if (this.isPlayer) {
//播放动画
//计时器增加
this.timer += dt;
if (this.timer > this.speed) {
this.timer = 0;
this.index++;
if (this.index >= this.sprites.length) {
this.index = 0;
}
this.getComponent(cc.Sprite).spriteFrame = this.sprites[this.index];
}
}
}
}
1.37.nodejs服务端
let app = require("express")();
let http = require("http").Server(app);
let io = require("socket.io")(http);
http.listen(3000, () => {
console.log("server listen on 3000");
});
// 监听所有客户端连接
io.on("connection", (socket) => {
// 发送消息
// socket.emit("message", "连接成功了");
console.log("有客户端连接");
// 监听客户端发来的消息
socket.on("message", (data) => {
console.log("客户端发来消息:" + data);
socket.emit("message", "world");
});
});
1.38.Socket.io客户端
const { ccclass, property } = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
socket: Socket = null;
start() {
//连接服务器
this.socket = io.connect("http://localhost:3000");
// 判断是否连接成功
this.socket.on("connect", (data) => {
console.log("连接成功");
this.socket.emit("message", "hello");
//客户端接受消息
this.socket.on("message", function (data) {
console.log(data);
});
});
//判断是否断开
this.socket.on("disconnect", (data) => {});
}
// update (dt) {}
}
1.39.tielmap
const { ccclass, property } = cc._decorator;
@ccclass
export default class MapCOntrol extends cc.Component {
map: cc.TiledMap;
player: cc.Node = null;
start() {
//获取地图信息
this.map = this.getComponent(cc.TiledMap);
//普通层
// this.map.getLayer("item");
//对象层
let playerLayer = this.map.getObjectGroup("player");
//获取某个对象
let playerObj = playerLayer.getObject("startpos");
//判断是否是玩家对象
if (playerObj.isPlayer == true) {
//加载玩家预设体
cc.loader.loadRes("player", cc.Prefab, (res, playerPre) => {
//创建玩家
this.player = cc.instantiate(playerPre);
this.player.setParent(this.node.children[2].children[0]);
this.player.x = playerObj.x;
this.player.y = playerObj.y;
});
}
}
update(dt) {
//摄像头跟随玩家
if (this.player != null) {
cc.Camera.main.node.x = this.player.x - 240;
cc.Camera.main.node.y = this.player.y - 160;
}
}
}
1.40.控制封装
export default class Input {
private static instance: Input = null;
//水平轴
horizontal: number = 0;
//垂直轴
vertical: number = 0;
static get Instance() {
if (this.instance == null) {
this.instance = new Input();
}
return this.instance;
}
constructor() {
//键盘按下
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, (event) => {
if (event.KeyCode == cc.macro.KEY.w) {
this.vertical = 1;
} else if (event.KeyCode == cc.macro.KEY.s) {
this.vertical = -1;
}
if (event.KeyCode == cc.macro.KEY.a) {
this.vertical = -1;
} else if (event.KeyCode == cc.macro.KEY.d) {
this.vertical = 1;
}
});
//键盘抬起
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, (event) => {
if (event.KeyCode == cc.macro.KEY.w && this.vertical == 1) {
this.vertical = 0;
} else if (event.KeyCode == cc.macro.KEY.s && this.vertical == -1) {
this.vertical = 0;
}
if (event.KeyCode == cc.macro.KEY.a && this.horizontal == -1) {
this.vertical = 0;
} else if (event.KeyCode == cc.macro.KEY.d && this.horizontal == 1) {
this.vertical = 0;
}
});
}
}
import Input from "./input";
const { ccclass, property } = cc._decorator;
@ccclass
export default class PlayerControl extends cc.Component {
//速度
speed: number = 20;
start() {}
update(dt) {
this.node.x += this.speed * dt * Input.Instance.horizontal;
this.node.y += this.speed * dt * Input.Instance.vertical;
}
}
1.41.粒子系统
1.42.游戏框架
// Message.ts
const { ccclass, property } = cc._decorator;
@ccclass
export default class Message {
//类型 1 2 3
Type: number;
//命令 100 101 200 201
Command: number;
//参数
Content: any;
//构造函数
constructor(type: number, command: number, content: any) {
this.Type = type;
this.Command = command;
this.Content = content;
}
}
export class MessageType {
static Type_UI = 1;
static Type_NPC = 2;
static Type_Enemy = 3;
static Type_Audio = 4;
static UI_RefreshHp = 101;
static UI_RefreshScore = 102;
static UI_RefreshInventory = 103;
static NPC_npc1 = 201;
static NPC_npc2 = 202;
static Enemy_enemy1 = 301;
static Enemy_enemy2 = 302;
}
// ComponentBase.ts
import Message from "./Message";
const { ccclass, property } = cc._decorator;
@ccclass
export default class ComponentBase extends cc.Component {
//接受消息
ReceiveMessage(message: Message) {}
}
// ManagerBase.ts
import ComponentBase from "./ComponentBase";
import Message, { MessageType } from "./Message";
import MessageCenter from "./MessageCenter";
const { ccclass, property } = cc._decorator;
@ccclass
export default class ManagerBase extends ComponentBase {
//管理的消息接受者数组
ReceiveList: ComponentBase[] = [];
//当前管理类接收的具体消息类型
messageType: number;
onLoad() {
//设置当前管理类接收的消息类型
this.messageType = this.SetMessageType();
//把管理类添加到消息中心列表中
MessageCenter.Managers.push(this);
}
//设置当前管理类的消息类型
SetMessageType() {
return MessageType.Type_UI;
}
//注册消息监听
RegisterReceiver(cb: ComponentBase) {
this.ReceiveList.push(cb);
}
ReceiveMessage(message: Message) {
super.ReceiveMessage(message);
//判断消息类型
if (message.Type != this.messageType) {
return;
}
//向下层分发消息
for (let cb of this.ReceiveList) {
cb.ReceiveMessage(message);
}
}
}
// MessageCenter.ts
import ComponentBase from "./ComponentBase";
import Message from "./Message";
export default class MessageCenter {
//管理类列表
static Managers: ComponentBase[] = [];
//发送消息
static SendMessage(msg: Message) {
for (let manager of this.Managers) {
manager.ReceiveMessage(msg);
}
}
//发送自定义消息
static SendCustomMessage(type: number, command: number, content: any) {
let msg = new Message(type, command, content);
this.SendMessage(msg);
}
}
示例:
// PlayerControl.ts
import { MessageType } from "./Scripts/Message";
import MessageCenter from "./Scripts/MessageCenter";
const { ccclass, property } = cc._decorator;
@ccclass
export default class PlayerControl extends cc.Component {
start() {
//点击
this.node.on(cc.Node.EventType.MOUSE_DOWN, (event) => {
//血量减少
MessageCenter.SendCustomMessage(
MessageType.Type_UI,
MessageType.UI_RefreshHp,
10
);
});
}
// update (dt) {}
}
// UIManager.ts
import ManagerBase from "./Scripts/ManagerBase";
import { MessageType } from "./Scripts/Message";
const { ccclass, property } = cc._decorator;
@ccclass
export default class UIManager extends ManagerBase {
static Instance: UIManager;
onLoad() {
super.onLoad();
UIManager.Instance = this;
}
//接收消息的类型
SetMessageType() {
return MessageType.Type_UI;
}
}
// HpControl.ts
import ComponentBase from "./Scripts/ComponentBase";
import Message, { MessageType } from "./Scripts/Message";
import UIManager from "./UIManager";
const { ccclass, property } = cc._decorator;
@ccclass
export default class HpControl extends ComponentBase {
hp: number = 100;
start() {
//注册为ui的消息接收者
UIManager.Instance.RegisterReceiver(this);
}
//接收到的消息
ReceiveMessage(msg: Message) {
super.ReceiveMessage(msg);
if (msg.Command == MessageType.UI_RefreshHp) {
//得到参数
let num = <number>msg.Content;
this.ChangeHp(num);
}
}
//改变血量
ChangeHp(attack) {
this.hp -= attack;
this.node.children[1].getComponent(cc.Label).string = this.hp + "";
}
}
1.43.有限状态机
// FSMState.ts
import FSMManager from "./FSMManager";
const { ccclass, property } = cc._decorator;
export default class FSMState {
//当前状态ID
StateID: number;
//状态拥有者
component: cc.Component;
//所属状态机
fsmManager: FSMManager;
constructor(
stateID: number,
component: cc.Component,
fsmManager: FSMManager
) {
this.StateID = stateID;
this.component = component;
this.fsmManager = fsmManager;
}
//进入状态
OnEnter() {}
//状态更新中
OnUpdate() {}
}
// FSMManager.ts
import FSMState from "./FSMState";
const { ccclass, property } = cc._decorator;
export default class FSMManager {
//状态列表
StateList: FSMState[] = [];
//当前状态ID
CurrentIndex: number = -1;
//改变状态
ChangeState(StateID: number) {
//改变状态ID
this.CurrentIndex = StateID;
//调用新状态的OnEnter方法
this.StateList[this.CurrentIndex].OnEnter();
}
//更新调用
OnUpdate() {
if (this.CurrentIndex != -1) {
//调用当前状态的update方法
this.StateList[this.CurrentIndex].OnUpdate();
}
}
}
示例:
// BirdControl.ts
import DieState from "./DieState";
import FlyState from "./FlyState";
import FSMManager from "./Scripts/FSMManager";
const { ccclass, property } = cc._decorator;
enum BirdState {
Fly,
Die,
}
@ccclass
export default class BirdControl extends cc.Component {
ani: cc.Animation;
//状态机
fsmManager: FSMManager;
start() {
this.fsmManager = new FSMManager();
this.ani = this.getComponent(cc.Animation);
let fly = new FlyState(BirdState.Fly, this, this.fsmManager);
let die = new DieState(BirdState.Die, this, this.fsmManager);
this.fsmManager.StateList = [fly, die];
//开始执行状态
this.fsmManager.ChangeState(BirdState.Fly);
}
update(dt) {
if (this.fsmManager.CurrentIndex != -1) {
this.fsmManager.OnUpdate();
}
}
fly() {
this.fsmManager.ChangeState(BirdState.Fly);
}
die() {
this.fsmManager.ChangeState(BirdState.Die);
}
}
// FlyState.ts
import FSMState from "./Scripts/FSMState";
const { ccclass, property } = cc._decorator;
@ccclass
export default class FlyState extends FSMState {
start() {}
//进入状态
OnEnter() {
super.OnEnter();
this.component.getComponent(cc.Animation).play("fly");
}
//状态更新中
OnUpdate() {
super.OnUpdate();
}
}
// DieState.ts
import FSMState from "./Scripts/FSMState";
const { ccclass, property } = cc._decorator;
@ccclass
export default class DieState extends FSMState {
start() {}
//进入状态
OnEnter() {
super.OnEnter();
this.component.getComponent(cc.Animation).play("die");
}
//状态更新中
OnUpdate() {
super.OnUpdate();
}
}
状态机的一些应用方面