Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

碰撞系统

工作原理

  • 每个物体都有一个基于其精灵尺寸的矩形碰撞器
  • 精灵可以具有自定义的碰撞边界(在精灵编辑器中设置)
  • 物体旋转会围绕物体的中心偏移量旋转碰撞器
  • 碰撞使用SAT(分离轴定理),因此旋转的矩形会与其真实旋转形状碰撞
  • 每帧检查动态物体的碰撞

碰撞类型说明

  1. - 物体完全被碰撞系统忽略
  2. 静态 - 充当不可移动的墙(用于地形、平台)
  3. 动态 - 移动并被推开其他碰撞器(用于玩家、敌人)
  4. 触发器 - 检测重叠但不阻止移动(用于可收集物、区域)

碰撞解决

  • 动态物体会自动被推出静态和其他动态物体
  • 触发器永远不会阻止移动 - 它们仅检测重叠
  • 旋转的碰撞器沿着最小重叠方向进行解决

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 内置了一个物理系统,自动为动态物体处理重力和速度。

物理如何工作

每帧,引擎自动:

  1. 将场景重力应用于每个动态物体的速度
  2. 将速度应用于每个动态物体的位置
// 物理处理管道(由引擎自动处理):
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() 物体受重力影响并自动应用速度