← 返回 Day 90 正文

Day 90 · 图解

Day 090 — 碰撞检测与动画 · 图解

AABB 碰撞检测原理

两个矩形不碰撞的情况 (共4种):

情况1: A 在 B 左边
  ┌───┐     ┌───┐
  │ A │     │ B │
  └───┘     └───┘
  A.right < B.left

情况2: A 在 B 右边
      ┌───┐     ┌───┐
      │ B │     │ A │
      └───┘     └───┘
      A.left > B.right

情况3: A 在 B 上边
  ┌───┐
  │ A │
  └───┘
  ┌───┐
  │ B │
  └───┘
  A.bottom < B.top

情况4: A 在 B 下边
  ┌───┐
  │ B │
  └───┘
  ┌───┐
  │ A │
  └───┘
  A.top > B.bottom

碰撞条件: 以上4种情况都不发生

圆形碰撞检测

      ●───────── r_a (圆A半径)
       \
        \  距离 d
         \
          ●───────── r_b (圆B半径)

碰撞条件: d <= r_a + r_b

无碰撞:     碰撞:         刚好接触:
  ●    ●      ●●           ●─●
  d > r_a+r_b d < r_a+r_b  d = r_a+r_b

碰撞响应类型

┌─────────────────────────────────────────┐
│           碰撞响应类型                   │
├──────────┬──────────────────────────────┤
│ 弹性碰撞 │  🏀 → 🧱 → 🏀               │
│          │  速度反转,动能守恒            │
├──────────┼──────────────────────────────┤
│ 非弹性   │  🏀 → 🧱 → 💥 (停止)         │
│ 碰撞     │  物体粘在一起                  │
├──────────┼──────────────────────────────┤
│ 反射碰撞 │  🏀 ↗                        │
│          │  按法线方向反射                │
├──────────┼──────────────────────────────┤
│ 穿透碰撞 │  🔫 → 🧱 → 🔫 (穿过)         │
│          │  子弹穿过薄墙                 │
└──────────┴──────────────────────────────┘

帧动画原理

时间轴:
  0ms     100ms    200ms    300ms    400ms
  │         │        │        │        │
  ▼         ▼        ▼        ▼        ▼
┌────┐   ┌────┐   ┌────┐   ┌────┐   ┌────┐
│ 🧑 │   │ 🧑 │   │ 🧑 │   │ 🧑 │   │ 🧑 │
│ 站立│   │ 抬腿│   │ 跨步│   │ 落地│   │ 站立│
└────┘   └────┘   └────┘   └────┘   └────┘
  帧1      帧2      帧3      帧4      帧1(循环)

帧率 = 100ms/帧 = 10fps (每秒10帧)

动画状态机

                  ┌──────────┐
            ┌────→│   空闲   │←────┐
            │     │  idle    │     │
            │     └────┬─────┘     │
            │          │ 按键      │ 松开
            │          ↓           │
            │     ┌──────────┐     │
            └─────│   行走   │─────┘
                  │  walk    │
                  └────┬─────┘
                       │ 速度>阈值
                       ↓
                  ┌──────────┐
                  │   跑步   │
                  │  run     │
                  └────┬─────┘
                       │ 跳跃
                       ↓
                  ┌──────────┐
                  │   跳跃   │
                  │  jump    │
                  └──────────┘

缓动函数对比

线性 (linear):
  ████████████████████  匀速

二次加速 (ease-in):
  █                     先慢
  ██
  ███
  █████
  ████████████████████  后快

二次减速 (ease-out):
  ████████████████████  先快
  ██████████
  █████
  ██
  █                     后慢

弹跳 (bounce):
  ████████████████████
         ███
            █
          ██
        ███
  ████████████████████  到达后弹跳

四叉树空间分区

初始状态 (一个区域):
  ┌─────────────────┐
  │ · · · · · · · · │
  │ · · · · · · · · │
  │ · · · · · · · · │
  │ · · · · · · · · │
  └─────────────────┘

插入4个点后分裂:
  ┌────────┬────────┐
  │ ·    · │ ·      │
  │        │        │
  ├────────┼────────┤
  │        │      · │
  │      · │        │
  └────────┴────────┘

查询范围:
  ┌────────┬────────┐
  │ · ┌──┐ │ ·      │
  │   │▓▓│ │        │
  ├────│▓▓┼────────┤
  │   │▓▓│      · │
  │   └──┘      · │
  └────────┴────────┘
  
  只检测 ▓▓ 区域内的点,跳过其他区域!

碰撞检测流程

游戏循环:
  ┌─────────────────────────────────────┐
  │              游戏帧                  │
  │  ┌───────┐  ┌───────┐  ┌───────┐  │
  │  │ 处理  │  │ 移动  │  │ 碰撞  │  │
  │  │ 输入  │→│ 物体  │→│ 检测  │  │
  │  └───────┘  └───────┘  └───┬───┘  │
  │                             │       │
  │                    ┌────────┴───┐   │
  │                    ↓            ↓   │
  │              ┌──────────┐ ┌────────┐
  │              │ 子弹-敌人 │ │敌人-玩家│
  │              │  碰撞    │ │  碰撞  │
  │              └────┬─────┘ └───┬────┘
  │                   ↓           ↓     │
  │              ┌──────────────────┐   │
  │              │    碰撞响应      │   │
  │              │  (扣血/爆炸)     │   │
  │              └──────────────────┘   │
  └─────────────────────────────────────┘