1.生命周期
//初始化时调用
onLoad(){
}
//当组件的 enabled 属性从 false 变为 true 时,
//或者所在节点的 active 属性从 false 变为 true 时,
//会激活 onEnable 回调。
onEnable(){
}
//初始化时调用
start(){
}
//每帧调用
update(){
}
//在所有动画更新前执行
lateUpdata(){
}
//当组件的 enabled 属性从 true 变为 false 时,
//或者所在节点的 active 属性从 true 变为 false 时,
//会激活 onDisable 回调。
onDisable(){
}
//销毁时调用
onDestroy(){
}
2.节点常用属性方法
3.xxx以上版本
获得某个节点
与坐标变换计算相关的接口(例如:size 和 anchor)变更如下:
需要先获取节点上的 UITransform 组件,再使用对应的接口,例如:
const uiTrans = node.getComponent(UITransform)!;
uiTrans.anchorX = 0.5;
uiTrans.setContentSize(size);
访问位置
先用setPosition(x,y)设置位置
再用 this.node.getPosition().x, this.node.getPosition().y获取位置
//设置子弹位置
bullet.setPosition(
this.node.getPosition().x,
this.node.getPosition().y + 80
);
2.xxx版本
获得某个节点
this.node.children[0];
this.node.getChildByname("abc");
let powerNode = find("power", this.node);
获得父节点
this.node.getParent();
this.nbode.setParent(ddd);
从父节点中移除节点
this.node.removeFromParent();
移除所有节点
this.node.removeAllChild();
移除某个节点
this.node.removeChild(add)
访问位置
this.node.x;
this.node.y;
this.node.setPosition(3,4);
this.node.setPosition(v2(3,4));
旋转
this.node.rotation
缩放
this.ndoe.scale
锚点
this.node.anchorX
改变颜色
this.node.color = color.xxx //color自己提供的
节点开关
this.node.active = false;
组件开关
this.enabled = false;
获取组件
let sprite = this.getComponent(Sprite);
从子组件中获取精灵组件
this.getComponentInChildren(Sprite)
sprite.enabled = false //对组件进行操作
直接在代码里面创建节点
let node = new Node("new");
在创建的节点上添加精灵组件
node.addComponent(Sprite)
3.预设体
@property(Prefab)
pre:Prefab = null;
start(){
//实例化预设体
let node = instantiate(this.pre);
//设置父节点
node.setParent(this.node);
}
4.资源动态加载
resources------加载资源方法
3.xxx
//resources
//加载资源方法
//加载一张图片
//loader.loadRes=>resources.load “资源图片位置/spriteFrame”
resources.load("PlayAir/hero1_die/spriteFrame", SpriteFrame, (err, image) => {
this.node.getComponent(Sprite).spriteFrame = image
})
加载一张图片
//err:错误 sp:资源 SpriteFrame:指定sp类型
let self = this //function中调不到this,需要先定义或者直接使用()=>{}
loader.loadRes("资源名称/spriteFrame",SpriteFrame,function(err,sp){
self.getComponent(Sprite).SpriteFrame = sp;
});
加载图集(多张图片)
//err:错误 atlas:资源图集 SpriteAtlas:指定sp类型 bg01:具体图片资源
let self = this //function中调不到this,需要先定义或者直接使用()=>{}
loader.loadRes("资源名称",SpriteAtlas,function(err,atlas){
self.getComponent(Sprite).SpriteFrame = atlas.getSpriteFrame("bg01");
});
5.场景切换
加载第二个场景
director.loadScene("game2",function(){
//当前已经加载到新的场景里面
})
预加载
director.preloadScene("game2",function(){
//这个场景加载到内存了,但是还没有切换
director.loadScene("game2") //切换
})
//常驻节点 切换场景时不会被销毁
game.addPersisRootNode(this.node)
//把节点从常驻节点中移出去
game.removePersisRootNode(this.node)
6.键鼠事件
监听鼠标
//先把脚本添加到精灵里面
start(){
//this.node.on()开始进行监听 "":监听事件名称 event:事件参数 event.getLocation():获取鼠标位置(X,Y) Node.EventType.MOUSE_DOWN:自带的枚举
this.node.on(Node.EventType.MOUSE_DOWN,function(event){
console.debug("按下鼠标" + event.getLocation())
//判断鼠标按下的是左键还是右键
if(event.getButton() == Event.EventMouse.BUTTON_RIGHT){
console.log("右键")
}
if(event.getButton() == Event.EventMouse.BUTTON_LEFT){
console.log("左键")
}
监听键盘
//先把脚本添加到精灵里面
start(){
//3.4.0版本之后,systemEvent.on被弃用,用Input.on代替 event.keyCode:获取具体按键
systemEvent.on(SystemEvent.EventType.KEY_DOWN,funtion(event){
console.log(event.keyCode)
//判断键盘按下的具体键
if(event.keyCode == macro.KEY.w){
console.log("w")
}
if(event.keyCode == macro.KEY.q){
console.log("q")
}
})
})
//不监听鼠标事件 在销毁之前停止监听
onDestroy(){
this.node.off(Node.EventType.MOUSE_DOWN)
}
}
7.触摸事件与自定义事件
触摸事件
start(){
//event.getID():多点触摸 event.getLocation():触摸位置(X,Y)
//在匿名函数中需要先定义this,才能在内部使用this 或者直接使用()=>{}
let self = this;
this.node.on(Node.EventType.TOUCH_START,function(event){
console.log("触摸:" + event.getID())
console.log("触摸:" + event.getLocation())
//在触摸事件中 按下屏幕发送事件
self.node.emit("custom")
//
self.node.dispatchEvent("custom") //不能传字符串
self.node.dispatchEvent(new Event.EventCustom("custom",true)) //true是否冒泡
})
}
自定义事件
start(){
this.node.on("custom",function(event){
console.log("自定义事件")
}){
}
}
8.碰撞检查
start(){
//碰撞检测
director.getCollisionManager().enabled = true;
}
//产生碰撞 other:我碰到的别人
onCollisionEnter(other){
console.log("碰撞产生" + other.tag)
}
//碰撞持续
onCollisionStay(other){
console.log("碰撞持续")
}
//碰撞结束
onCollisionExit(other){
console.log("碰撞结束 ")
}
9.计时器
1 单位秒
this.schedule(()=>{
},0.5)
2 单位毫秒
setTimeout(()=>{
},300)
暂停所有计时器
this.unscheduleAllCallbacks();
//随机数 random:0-1的随机数
Math.random() * 400
10.物理碰撞
@ccclass('TestContactCallBack')
export class TestContactCallBack extends Component {
start () {
// 注册单个碰撞体的回调函数
let collider = this.getComponent(Collider2D);
if (collider) {
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
collider.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
collider.on(Contact2DType.POST_SOLVE, this.onPostSolve, this);
}
// 注册全局碰撞回调函数
if (PhysicsSystem2D.instance) {
PhysicsSystem2D.instance.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
PhysicsSystem2D.instance.on(Contact2DType.END_CONTACT, this.onEndContact, this);
PhysicsSystem2D.instance.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
PhysicsSystem2D.instance.on(Contact2DType.POST_SOLVE, this.onPostSolve, this);
}
}
onBeginContact (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
// 只在两个碰撞体开始接触时被调用一次
console.log('onBeginContact');
}
onEndContact (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
// 只在两个碰撞体结束接触时被调用一次
console.log('onEndContact');
}
onPreSolve (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
// 每次将要处理碰撞体接触逻辑时被调用
console.log('onPreSolve');
}
onPostSolve (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
// 每次处理完碰撞体接触逻辑时被调用
console.log('onPostSolve');
}
}
onLoad(): void {
//注册全局碰撞回调函数
PhysicsSystem2D.instance.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
//注册单个碰撞体的回调函数
onLoad() {
// 检测碰撞
let collider = this.getComponent(Collider2D);
if (collider) { collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
}
//selfCollider: Collider2D:自己 otherCollider: Collider2D:其他
onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D){
}
11.音频播放
创建AudioSource音频组件
或者直接在代码中添加音频文件,需要依赖音频组件
start(){
let player:AudioSource = this.getComponent(AudioSource);
//加载音频文件
resources.load("音频文件位置/spriteFrame",AudioSource,(res, clip)=>{
//赋值音频
player.clip = clip;
//播放
player.play();
//是否正在播放
player.isPlaying;
//暂停
palyer.pause();
//恢复播放
player.resume();
//暂停播放
player.stop();
//是否需要循环播放
player.loop = true;
//声音大小
player.volume = 1; //0-1之间,0最小,1最大
}
}
不需要依赖音频组件(新版本好像取消了)
start(){
//加载音频文件
resources.load("音频文件位置/spriteFrame",AudioSource,(res, clip)=>{
//播放
let audioId:number = audioEngine.playMusic(clip,true);
//是否正在播放
audioEngine.isMusicPlaying();
//暂停
audioEngine.pause(audioId);
//暂停背景音乐不需要Id,只能有一个背景音乐
audioEngine.pauseMusic();
//恢复播放
audioEngine.resume(audioId);
//暂停播放
audioEngine.stop(audioId);
//是否需要循环播放
audioEngine.setLoop(audioId,true);
//声音大小
audioEngine.setVolume(audioId,1); //0.6-1之间,0.6最小,1最大
}
}
12.物理系统/物理碰撞
//开启碰撞检测
onLoad() {
PhysicsSystem2D.instance.enable = true;
}
2.xxx到3.xxx版本
cc.director.getPhysicsManager()=>PhysicsSystem2D.instance
新版本物理系统默认开启,直接注册碰撞回调函数
onLoad(): void {
//注册全局碰撞回调函数
PhysicsSystem2D.instance.on(Contact2DType.BEGIN_CONTACT,
this.onBeginContact, this);
}
//开始碰撞
onBeginContact(contact,selfCollider: Collider2D,
otherCollider: Collider2D) {
//获得碰撞点
let points = contact.getWorldManifold().porints;
console.log("发生碰撞" + "碰撞点:" + points[0])
//法线
let normal = contact.getWorldManifold().normal;
console.log("发生碰撞" + "法线:" + normal)
}
13.射线
射线检测碰撞
//开启物理引擎
onLoad() {
PhysicsSystem2D.instance.enable = true;
}
updata(){
//射线检测
const checkRes = PhysicsSystem2D.instance.raycast(
this.node.worldPosition,v2(
this.node.worldPosition.x,
this.node.worldPosition.y + this.direct.y * 200),
ERaycast2DType.Closest)
}
14.动作系统 => 缓动
时间动作与瞬时动作
start(){
//动作 3.xxx没有动作,用tween缓动系统代替
//移动 2:时间 200,200:X轴,Y轴坐标
//moveTo移动到那个位置 绝对
let action = moveTo(2,200,200);
//moveBy移动多少多少 相对
let action = moveBy(2,200,200);
//旋转 2:时间 100:旋转角度
action = rotateTo(2,100)
//缩放 2:时间 1.5:缩放倍数
action = scaleTo(2,1.5)
//1.5:X轴 0.5:Y轴
action = scaleTo(2,1.5.0.5)
//跳跃 2:时间 200,0:往X轴方向跳200,Y轴不动 100:跳多高 1:跳几次
action = jumpBy(2,200,0,100,1)
//闪烁 3,5:三秒闪烁五次
action = blink(3,5)
//淡出 3:时间
action = fadeOut(3);
//淡入
action = fadeIn(3);
//渐变 3:时间 100:透明度 ,0-255
action = fadeTo(3,100)
//颜色 100,30,100:红绿蓝颜色的混合色
action = tintTo(3,100,30,100)
//立刻显示
let action = show();
//立刻隐藏
action = hide();
//切换显示隐藏 自动判断显示与否 若显示调用则隐藏,反之
action = toggleVisibility();
//翻转 ture:确认翻转 false:不翻转
action = flipX(ture);
action = flipY(ture);
//回调动作
action = callFunc(()=>{
})
//执行动作
this.node.runAction(action);
//停止动作
this.node.stopAction(action);
//停止该节点下所有动作
this.node.stopAllAction();
//设置动作的Tag值,根据Tag值停止动作
action.setTag(33);
this.node.stopActionByTag(33);
//暂停--所有动作
this.node.pauseAllActive();
//恢复--所有动作
this.node.resumeAllActive()
}
15.容器动作
start(){
let action = fadeOut(1);
let action2 = fadeIn(1);
// 队列/序列 动作
let seq = sequence(action,action2)
//delayTime(1):延迟1s 在执行完action,action2之后延迟一秒执行callFunc内容
let seq = sequence(action,action2,delayTime(1),callFunc(()=>{
}))
//重复动作 3:次数 对seq执行三次
let repeat = repeat(seq,3)
//重复动作一直重复下去
repeat = repeatForever(seq);
//并列动作
let move = moveTo(3,500,500);
let color = tintTo(3,100,100,20);
//多种动作并列执行
let spawn = spawn(move,color);
//执行动作
this.node.runAction(seq);
this.node.runAction(repeat);
this.node.runAction(spawn);
}
16.动画系统
先创建节点 然后创建动画文件 在节点上添加动画组件(Animation) 然后把动画文件拖入动画编辑器进行编辑 属性列表中position设置动画在X轴Y轴移动方向,设置旋转角度用rotation(eulerAngles)
插入事件帧 需要先在该动画上面绑定脚本 然后插入事件帧的函数时间才能触发
序列帧
start() {
let animation = this.getComponent(Animation);
//播放动画
animation.play("run")
//暂停动画
animation.pause("run")
//恢复动画
animation.resume("run")
//停止动画
animation.stop("run")
}
自定义Animation
先设置n张图片
//每秒播放速度
@property(number)
speed:number = 0.1;
//播放帧数组
@property([SpriteFrame])
sprite:SpriteFrame[] = [];
//是否播放动画
@property:boolean
isPlay:boolean = false;
//当前播放帧
index:number = 0;
//计时器 当前播放时间
timer:number = 0;
start(){
}
update(deltaTime: number) {
if(this.isPlay){
//播放动画
//计时器增加
this.timer += deltaTime;
if(this.timer > this.speed){
this.timer = 0;
//切换帧 0 1 2 循环
this.speed ++;
if(this.index >= this.sprites.length){
this.index = 0;
}
//更换帧图片
this.getComponentr(Sprite).spriteFrame = this.sprites[this.index];
}
}
}
也可以不用面板上的自动播放
//比如在MyAnimation组件中设置
play(){
this.isPlay = ture;
}
stop(){
this.isPlay = false;
}
//然后在其他组件中获取开关控制
start(){
//播放动画
this.getComponentr(MyAnimation).play();
}
17.数据储存
start(){
//储存数据 键值
localStorage.setItem("name","蝙蝠侠");
//读取数据
let name = localStorage.getItem("name");
console.log(name); //蝙蝠侠
//移除一个数据
localStorage.removeItem("name");
//清空所有数据
localStorage.clear();
}
json数据
//创建一个类
class Person{
id:number;
name:string:
//......
}
start(){
//创建实例化对象
let person:Person = new Person();
person.id = 10;
person.name = "李逍遥";
//对象-->json 序列化
let json = JSON.stringify(person);
//储存数据 键值
localStorage.setItem("save",json);
//json-->对象 反序列化
let person2:Person = Object.assign(new Person(),JSON.parse(json));
//读取数据
let name = person2.name;
}
18.网络请求
XML原生请求
19.Socket套接字
Socket
需要安装node.js 并下载依赖
需要把var io 中(http)改成(http,{cors:true})来解决跨域问题
服务端
启动 先cd进入桌面
客户端
20.游戏框架 - 消息机制
Message 消息脚本 MessageCenter 消息中心
ComponentBase 组件的基类 ManageBase 管理基类
Message 消息脚本 不继承与任何内容 只是一个消息
ComponentBase 组件的基类 主要目的是接收消息
ManageBase 管理基类 继承于ComponentBase 用于管理消息
import ComponentBase from "./ComponentBase";
const { ccclass, property } = _decorator;
@ccclass
export default class ManageBase extends ComponentBase {
//管理的消息接受者数组
ReceiveList:ComponentBase[] = [];
//当前管理类接收的具体消息类型
messageType:number;
onLoad(){
//设置当前管理类接收的消息类型
this.messageType = SetMessageType();
//把管理类添加到消息中心列表中
MessageCenter.Managers.push(this);
}
//设置当前管理类接收的消息类型
SetMessageType(){
return MessageType.Type_UI;
}
//举例子 不同的管理类返回不同的类型直接调用SetMessageType()可以覆盖掉原来的方法
//class EnemyManager extends ManageBase{
// SetMessageType(){
// return MessageType.Type_Enemy;
// }
//}
//注册消息监听 把小类加到消息数组里面
RegisterReceiver(cd: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 消息中心
21.有限状态机
FSMState状态脚本 FSMManager状态机
FSMState状态脚本 单独的一个对象不想需要继承组件
FSMManager状态机 单独的一个对象不想需要继承组件