相机
Camera2D 让画面跟随一个节点。通常挂在玩家下面:相机的全局位置就是画面中心。
ts
import { Camera2D, Node2D, Scene, v } from 'sapling2d'
const LEVEL_WIDTH = 4000
const LEVEL_HEIGHT = 1334
class Player extends Node2D {
override process(dt: number) {
this.x = Math.min(this.x + 300 * dt, LEVEL_WIDTH) // 一直向右走
}
}
export class Level extends Scene {
player!: Player
camera!: Camera2D
override ready() {
this.player = this.add(new Player({ position: v(100, 900) }))
// 相机挂在玩家下面:画面中心跟着玩家走;limit 让画面不超出关卡
this.camera = this.player.add(
new Camera2D({
limitLeft: 0,
limitTop: 0,
limitRight: LEVEL_WIDTH,
limitBottom: LEVEL_HEIGHT,
positionSmoothingEnabled: true, // 平滑跟随(默认关闭)
}),
)
}
}当前相机
场景里第一个启用(enabled,默认 true)的相机自动成为当前相机;makeCurrent() 切换,isCurrent 查询。当前相机被移除或关掉时换下一个,都没有时画面不偏移。
常用属性
| 属性 | 作用 |
|---|---|
offset | 画面中心相对相机的偏移 |
limitLeft / limitTop / limitRight / limitBottom | 画面不超出的世界范围 |
positionSmoothingEnabled / positionSmoothingSpeed | 平滑跟随(默认关闭,速度默认 5);瞬移后调用 resetSmoothing() |
screenCenter | 应用边界和平滑之后的画面中心 |
画面只平移,不支持缩放和旋转。相机在所有节点的 process 之后更新。
坐标
- 节点的全局坐标和指针坐标(
position、pointerPosition)都是世界坐标。没有相机时,世界坐标就是设计坐标。 tree.viewport.designToWorld/worldToDesign在世界坐标和屏幕上的位置之间换算;visibleWorldRect是屏幕上可见的世界范围。
固定在屏幕上的界面
有相机时,分数、按钮这类界面要放进 CanvasLayer,否则会跟着画面一起移走。
屏幕震动
没有专门的接口:用 Tween 把 offset 随机抖几下,再回到 0。
ts
private _shake: Tween | null = null
shake(camera: Camera2D, strength: number, duration: number) {
this._shake?.kill() // 上一次没抖完,先停掉
const rng = this.tree.fxRng // 震动只影响画面:不占游戏逻辑的随机数
const t = camera.createTween()
for (let i = 0; i < 4; i++) {
const s = strength * (1 - i / 4) // 越抖越小
t.to(camera, { offset: v(rng.randfRange(-s, s), rng.randfRange(-s, s)) }, duration / 5)
}
this._shake = t.to(camera, { offset: Vector2.ZERO }, duration / 5)
}