カメラ移動をばねっぽくしてみた

みんなでつくるダンジョンでは、キャラクターを画面中央に表示するようにカメラ座標を決定しています。

今まではキャラクターの位置を以下のように決定していましたが、キャラクターのうごきががくがくするとカメラまでがくがくと動くようになり、画面酔いをしやすくなりそう~という懸念がありました。

camera.x = character.x + (character.width / 2) - (screenWidth / 2);
camera.y = character.y + (character.height / 2) - (screenHeight / 2);

f:id:piyorinpa:20190106135607p:plain
カメラ位置とキャラクター位置の関係

そこで、カメラとキャラクターをばねでつないで描画する仕組みに変更してみました。キャラクターが移動するとばねが引っ張られるのでカメラがゆるやかに遅れて動きます。

f:id:piyorinpa:20190106191504p:plain
キャラクターとカメラをばねでつなぐ

カメラの重さを m, カメラの加速度を \ddot{x}, ばね定数 k, ばねの伸び k_x とすると力のつり合い式を k x_k - m\ddot{x} = 0 みたいにかけるので、カメラの加速度は  \ddot{x} = \frac{k}{m}x_k で計算できます。 カメラの速度 \dot{x} = \int  \frac{k}{m}x_k dt = \frac{k}{m}tx_k + C_1 、カメラの速度 \dot{x}=0 のときばねの伸び  x_k=0 なので、積分定数 C_1 = 0 となります(あっているかな...)。

 k, m, t(フレーム間隔を一定とする) はいずれも定数なので  \frac{kt}{m}=C と置けば  \dot{x} = Cx_k と書けます。( C はばね定数と質量で決定される定数)

カメラ位置を x_c, キャラクタ位置を  x_a とすれば  x_k = x_a - x_c - x_o なので、最終的には

 \dot{x} = C (  x_a - x_c - x_o ) となります。(y方向も同様に、  \dot{y} = C (  y_a - y_c - y_o ) とします。)

 Cの値を適当に(1以下に)設定すれば、カメラの動き具合を調整することができます。計算した速度は1フレームあたりのカメラ座標の移動量とみなせるので、1フレームごとに速度を計算してカメラ位置 x_cに足していきます。

 x_c = x_c + \dot{x}  (y方向も同様に、 y_c = y_c + \dot{y} とします。)

上記のようにカメラを動かすと以下のようなかんじになります。

カメラを追尾したい対象とばねで繋ぐ実装にしておくと、たとえばばねを他のキャラクターに繋ぎ変えれば、特に何も考えなくてもスムーズに繋ぎ変えた先のキャラクターを見るように移動するのでよいなあという感じです。視点移動とかもらくらくにできそう。

ではでは~。