JavaScriptでゲーム作ろう

ゲームでキャラクターがブロックの角に引っかかって動かしづらいとイライラします。

これはキャラクターの当たり判定が四角になっているためで、四角と四角の当たり判定では滑らかに動かすことができません。

これを解決するにはどうすればいいの?

っていうのをこないだ一生懸命考えて作ったので紹介しておきます。

基本は円と四角の当たり判定

まず上のツイッターのGIFを見てください。白いのがプレイヤーで青いのがブロックです。

見ての通り円と矩形の当たり判定になります。

円と矩形の当たり判定は以前記事に書いたので気になる方はそちらもチェックしてください(‘ω’)ノ

基本的には円と矩形の当たり判定のようなものなので中学校数学でできます。

辺の当たり判定は矩形の判定でOK

まずはブロックの各辺について考えます。

各辺が円と当たるときはどういう状態かというと円の中心と辺までの距離が円の半径より小さくなった場合です。

辺との当たり判定の図

上の画像の赤い所が円がブロックの上の辺と当たるところです。

円の中心がブロックのY座標から半径を引いた位置からブロックのY座標まで、そしてブロックの幅の範囲内に入っていれば辺に当たっています。

円の原点を(x1、y1)、ブロックの位置を(x2、y2)でブロックの幅をw、半径をrとして書くとこんな感じで行けます。

if(x1 > x2 && x1 < x2 + w){
  if(y1 > y2 && y1 < y2 + r){
    return true;
  }
}

範囲に入っていた場合は辺から半径分離れた場所に戻せば当たって止まっているように見えます。

あとは右左下の辺も同様のやり方で作ればOKです。

角と円の当たり判定

角と円の当たり判定は角の点が円の半径内に入っているかどうかだけです。

角の当たり判定の図

ここまでは簡単なんですよね。

問題は次の押し戻しの処理です。

角の押し戻しが重要

円と角が当たった場合にどうやって押し戻すのか?

これがこの処理の一番大事な部分です。

解説図1

まずどれだけ押し戻すのかというと上の図のaとbの長さ分です。aとbの長さ分だけキャラクターがブロックにめり込んでしまっているのでその分だけ戻せばOKなはずです。

ではこのaとbはどうやって計算するのか?

円の中心と角の距離は座標があるのでわかります。つまり上の図の内側の三角形の長さはすべてわかるということなのでそれを使って小さい方を出します。

解説図2

まず内側の三角形の斜辺を円の中心と角の座標から計算します。

それを半径で割ると比率が分かります。

そしてそれでX座標、Y座標の距離を割ると点線を含む三角形の辺の長さが分かります。

そこから2点のX座標、Y座標の距離を引いてやれば無事a、bの長さが出せます。

後はそれを円の座標から引いてやれば円がちょうど角の外に戻ります。

これで円の中心がブロックの角より外側になっていればそっちへ滑るように移動してくれます。

あとがき

簡単に説明しましたが、実際自分で考えているときは簡単ではなかったんですよ(^^;)

思い付きで「こんな感じかな?」みたいに直接プログラム書いてたら全然できなくて。。

でも、上の図のようにちゃんと図を書いて「どうやったらできるか?」っていうのを検証したら「ああ、そういうことか!」って気づくことができました。

なので皆さんも新しいことに挑戦するときはちゃんと図を書いて理解してからプログラムしましょうね(^^;)