使用 Tiniest2D 制作 2D 游戏
碰撞与物理
Lesson 9 of 11 • 10 XP
Keep your place in this quest
Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.
碰撞系统
工作原理
- 每个对象都有一个基于其精灵大小的 AABB(轴对齐包围盒)
- 精灵可以有自定义的碰撞边界(在精灵编辑器中设置)
- 对于动态对象,每帧都会检查碰撞
碰撞类型说明
- 无 - 对象完全被碰撞系统忽略
- 静态 - 充当不可移动的墙(用于地形、平台)
- 动态 - 移动并被其他碰撞体推开(用于玩家、敌人)
- 触发器 - 检测重叠但不阻止移动(用于收集物品、区域)
碰撞解析
- 动态对象会自动被推出静态和其他动态对象
- 触发器从不阻止移动 - 仅检测重叠
onCollision 回调
onCollision(objA, objB) 函数在对象重叠时被调用。回调模式为:
| objA 类型 | objB 类型 | 生成回调? | 备注 |
|---|---|---|---|
| 动态 | 静态 | 是 | 动态被推出静态 |
| 动态 | 动态 | 是(双向) | 两个对象都会获得回调 |
| 动态 | 触发器 | 是 | 检测到触发器 |
| 触发器 | 触发器 | 是 | 两个触发器相互检测 |
| 静态 | 静态 | 否 | 静态不生成回调 |
| 静态 | 触发器 | 否 | 两者均不生成回调 |
关键规则:
objA始终是动态或触发器- 当两个动态对象碰撞时,两者均会获得回调(各自作为 objA)
- 当两个触发器重叠时,会生成一个回调(第一个触发器作为 objA)
- 静态对象从未出现为 objA
示例:检测不同的碰撞类型
func onCollision(objA, objB) {
var typeA = getCollisionType(objA)
var typeB = getCollisionType(objB)
// 玩家(动态)碰到一个硬币(触发器)
if (getName(objA) == "player" && typeB == COLLISION_TRIGGER()) {
print("收集到!")
removeObject(gameScene, objB)
}
// 两个触发器重叠(例如,检测区域)
if (typeA == COLLISION_TRIGGER() && typeB == COLLISION_TRIGGER()) {
print(getName(objA) + " 进入了 " + getName(objB) + " 的区域")
}
// 玩家被敌人击中(均为动态)
if (getName(objA) == "player" && getName(objB) == "enemy") {
print("玩家被击中!")
}
}
物理系统
Tiniest Engine 具有内置的物理系统,自动处理动态对象的重力和速度。
物理工作原理
每帧,引擎会自动:
- 将场景重力应用到每个动态对象的速度
- 将速度应用到每个动态对象的位置
// 物理管道(由引擎自动处理):
velocity += gravity * dt
position += velocity * dt
设置重力
在场景中设置重力,使动态对象下落:
func start() {
// 设置向下重力(每秒 300 像素平方)
setGravityY(gameScene, 300)
// 可选:水平重力(风的效果)
setGravityX(gameScene, 0)
setScene(gameScene)
}
使用速度
使用速度控制对象,而不是直接设置位置:
var player = Object("player")
var jumpForce = -200 // 负值 = 向上
func start() {
setCollisionType(player, COLLISION_DYNAMIC())
addObject(gameScene, player)
setGravityY(gameScene, 300)
setScene(gameScene)
}
func onUpdate(dt) {
// 通过速度进行水平移动
if (isKeyHeld(KEY_LEFT())) {
setVelocityX(player, -100)
} else if (isKeyHeld(KEY_RIGHT())) {
setVelocityX(player, 100)
} else {
setVelocityX(player, 0)
}
// 通过设置向上速度进行跳跃
if (isKeyPressed(KEY_SPACE())) {
setVelocityY(player, jumpForce)
}
}
物理函数
| 函数 | 描述 |
|---|---|
getVelocityX(obj) |
返回对象的 X 速度 |
setVelocityX(obj, vx) |
设置对象的 X 速度 |
getVelocityY(obj) |
返回对象的 Y 速度 |
setVelocityY(obj, vy) |
设置对象的 Y 速度 |
getGravityX(scene) |
返回场景重力 X 分量 |
setGravityX(scene, gx) |
设置场景重力 X 分量 |
getGravityY(scene) |
返回场景重力 Y 分量 |
setGravityY(scene, gy) |
设置场景重力 Y(正值 = 向下) |
重要提示: 只有 COLLISION_DYNAMIC() 对象受到重力影响,并且其速度会自动应用