文章持续记录开发中遇到常用的功能
节点平移缩放旋转
基本操作
@ccclass('CubeScale')
export class CubeScale extends Component {
i = 0
j = 0
update(deltaTime: number) {
//平移
this.node.translate(new Vec3(0.01, 0, 0))
//缩放
this.node.setScale(this.i += 0.01, 1, 1)
//3D旋转
if (this.j >= 360) {
this.j = 0
}
this.node.setRotationFromEuler(v3(this.j += 1, 0, 0))
//2D旋转
this.node.angle = (this.node.angle + 3) % 360
}
}
飞刀游戏:物体跟着圆一起旋转运动
update(deltaTime: number) {
//飞刀盘子的目标物旋转(圆形)
this.targetNode.angle = (this.targetNode.angle + 3) % 360
//飞刀跟着目标物绕弧度一起旋转
this.knifeNodeArray.forEach(element => {
element.angle = (element.angle + 3) % 360
//半径
let r = this.targetNode.getComponent(UITransform).width / 2
//弧度 = PI * 角度 / 180
let rad = Math.PI * (element.angle - 90) / 180
//x = x1 + Math.cos(弧度) y = y1 + Math.sin(弧度)
element.setPosition(this.targetNode.position.x + r * Math.cos(rad), this.targetNode.position.y + r * Math.sin(rad))
});
}
飞刀游戏:检测碰撞原理靠角度判断即可(只要角度符合一定间隙表示碰撞成功)如果有多个方向的判断,则要增加Math.abs()
判断
this.knifeNodeArray.forEach(element => {
if (element.angle < gap || 360 - element.angle < gap) {
isHit = true
}
});
物体移动(刚体移动)
物体平移
let rb = this.node.getComponent(RigidBody)
let lv = v3(0, 0, 0)
rb.getLinearVelocity(lv)
lv.x = 0
lv.z = speed
rb.setLinearVelocity(lv)
物体旋转
let angle = this.node.eulerAngles
this.node.setRotationFromEuler(v3(angle.x, angle.y + 5, angle.z))
物体移动根据节点旋转而变化
let rb = this.node.getComponent(RigidBody)
let lv = v3(0, 0, 0)
rb.getLinearVelocity(lv)
Vec3.transformQuat(lv, lv, this.node.getRotation())
rb.setLinearVelocity(lv)
FPS游戏:第一人称的移动,根据aswd控制移动,qe控制视角转动
update(deltaTime: number) {
let speed = 15
let jumpSpeed = 5
let cameraSpeend = 3
let rb = this.node.getComponent(RigidBody)
let lv = v3(0, 0, 0)
rb.getLinearVelocity(lv)
if (this.keyMask & (1 << 1)) {
lv.x = 0
lv.z = speed
}
if (this.keyMask & (1 << 2)) {
lv.x = 0
lv.z = -speed
}
if (this.keyMask & (1 << 3)) {
lv.x = speed
lv.z = 0
}
if (this.keyMask & (1 << 0)) {
lv.x = -speed
lv.z = 0
}
if (this.keyMask & (1 << 4)) {
lv.y = jumpSpeed
lv.z = 0
}
let angle = this.node.eulerAngles
if (this.keyMask & (1 << 5)) {
this.node.setRotationFromEuler(v3(angle.x, angle.y + cameraSpeend, angle.z))
} else if (this.keyMask & (1 << 6)) {
this.node.setRotationFromEuler(v3(angle.x, angle.y - cameraSpeend, angle.z))
}
Vec3.transformQuat(lv, lv, this.node.getRotation())
if (!this.keyMask) {
lv.x = 0
lv.z = 0
}
rb.setLinearVelocity(lv)
}
打开2D碰撞Debug
PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.Aabb |
EPhysics2DDrawFlags.Pair |
EPhysics2DDrawFlags.CenterOfMass |
EPhysics2DDrawFlags.Joint |
EPhysics2DDrawFlags.Shape;
2D粒子系统播放
制作好的2D粒子ParticleSystem2D
记得选择Layer为UI_2D,否则看不到效果
_boom(pos, color) {
let ps: ParticleSystem2D = this.boom.getComponent(ParticleSystem2D)
this.boom.setPosition(pos)
if (color != undefined) {
ps.startColor = ps.endColor = color
}
ps.resetSystem()
}
骨骼动画播放
let skeletalAnimation = this.node.getComponent(SkeletalAnimation);
let clip = skeletalAnimation.clips[3]
skeletalAnimation.crossFade(clip.name, 0.3)
缓冲系统
缓冲系统主要是针对路径不固定的移动
tween()
.target(this.node)
.to(0.4, { position: new Vec3(0, -view.getFrameSize().height), eulerAngles: v3(5, -100, 10) }, { easing: 'linear' }) //平移和旋转
.delay(1.0)
.call(()=> {
//动作完成回调
})
.start()
持久化存储
写在WebView的本地存储
localStorage.setItem("name", "hensen")
localStorage.getItem("name")
定时器
5s执行一次,无限循环执行
start() {
this.schedule(this._changeEnemy, 5, macro.REPEAT_FOREVER)
}
_changeEnemy() {}
2s执行一次,且只有一次
this.scheduleOnce(function() {
}, 2);
声音播放
将声音部分全部保存声音管理组件中,并设置好AudioClip
属性,对外提供接口进行播放
interface IAudioBean {
[name: string]: AudioClip
}
@ccclass('AudioManager')
export class AudioManager extends Component {
@property([AudioClip])
audios: AudioClip[] = []
beans: IAudioBean = {}
source: AudioSource = null
start() {
this.source = this.getComponent(AudioSource)
for (let index = 0; index < this.audios.length; index++) {
const element = this.audios[index];
this.beans[element.name] = element
}
}
//对外提供接口播放
play(name) {
const audio = this.beans[name]
if (audio !== undefined) {
this.source.playOneShot(audio)
}
}
}
使用播放
@property(AudioManager)
audioManager: AudioManager = null
this.audioManager.play("player")
动态图片加载
SpriteFrame
动态加载资源中的图片,有个前提条件,图片必须存放在asset/resources
目录下
resources.load("image/magnet_tool/spriteFrame", SpriteFrame, (err, spriteFrame) => {
this.tool.spriteFrame = spriteFrame;
});
场景加载
director.loadScene("game.scene")
画布背景透明
这里踩了很多坑,最后发现只要勾选配置项目的设置即可,不需要多于的任何代码。