Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2005-01-10

[アイデア]Easy Rocket インターフェース案 (3) 衝突判定

話がそれた。衝突の考察を続ける。

3D 衝突判定は平面、球、直方体、円錐でとればだいたいの場合大丈夫。 凹凸のある地面を歩くとかはまた別の話になりそうだが、それはやったことがなくてよく知らないので置いておく。

さっきチラッと書いたけど、衝突用のオブジェクトを作って、それを描画オブジェクトに登録していく形でどうだろうか。

e = 0.8 # 跳ね返り係数
ground = ClashObj.new "y=0"
ball.add_clash_obj ground, e

衝突オブジェクトの初期化はとりあえず。

これでできないのはボール同士の衝突か。いや、それ以前にこのスクリプトじゃボールのサイズなどの衝突情報が設定されていないか。

ball.clash_state "r=2", e
ground = ClashObj.new "y=0"

難しいのは、 a, b, c のオブジェクトがあったときに

  • a と b は衝突する
  • a と c は衝突する
  • b と c は衝突しない

となる場合。うーむ。これをどう書けばいいか。

a.add_clash_obj b, e
a.add_clash_obj c, e

a.clash_all e

clash_mg.set a, b, e
clash_mg.set a, c, e

clash_mg.set_all a, e

実際にいくつかのオブジェクトを生成して考えてみよう。

  • ボール 10 個
  • 人間 2 人
  • 地面
  • ゴール … ボールとだけあたり判定をとることにする
  • コートの境界線 … 人間はこれより外に出ることができない
10.times {
  balls << Model.new 
}
man1 = Model.new
man2 = Model.new
ground = Model.new
goal = Model.new
border = ClashObj.new

そうか、この場合動くものに着目しそれが何に衝突するかを考えればよい。

balls.each{|o|
  balls.each{|bsll| o.add_clash_obj ball, e}
  o.add_clash_obj ground, e
  o.add_clash_obj man1
  o.add_clash_obj man2
  o.add_clash_obj goal
}

[man1, man2].each{|o|
  balls.each{|bsll| o.add_clash_obj ball}
  o.add_clash_obj man1
  o.add_clash_obj man2
  o.add_clash_obj border
}

ボールと人の関係はすべてが無駄に相互リンクするがそれはいい。こうすればもう少しわかりやすいかも。

balls.each{|o|
  o.add_clash_objs balls + [ground], e
  o.add_clash_objs balls + [man1, man2, goal]
}

[man1, man2].each{|o|
  o.add_clash_objs balls + [man1, man2, ground, border]
}

とりあえずこれでいい。

跳ね返らない衝突

それと衝突時に跳ね返りが起こるとは限らない。 例えば壁に向かって斜めに進んだ場合は壁に平行なベクトル成分だけは残して壁に沿って移動したほうがいい。 キャラとキャラが衝突した場合もこの処理になること多い。 上のコードでも跳ね返り係数が指定されれば跳ね返りということにしている。 この衝突なんていうのだろう。