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.
衝突システム
仕組み
- すべてのオブジェクトはスプライトサイズに基づく矩形コライダーを持つ
- スプライトにはカスタムコライダーの境界を設定できる(スプライトエディタで設定)
- オブジェクトの回転はオブジェクトの中心オフセットの周りでコライダーを回転させる
- 衝突はSAT(Separating Axis Theorem)を使用するため、回転した矩形が実際の回転形状と衝突する
- 動的オブジェクトの衝突は毎フレームチェックされる
衝突タイプの説明
- なし - オブジェクトは衝突システムによって完全に無視される
- 静的 - 動かすことのできない壁として機能する(地形やプラットフォームに使用)
- 動的 - 他のコライダーから押し出される(プレイヤーや敵に使用)
- トリガー - 重複を検出するが移動を妨げない(収集物やゾーンに使用)
衝突解決
- 動的オブジェクトは自動的に静的オブジェクトや他の動的オブジェクトから押し出される
- トリガーは決して移動を妨げない - 重複のみを検出する
- 回転したコライダーは最小の重複方向に沿って解決される
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()オブジェクトのみが重力の影響を受け、自動的に速度が適用される