2Dゲーム用の重力計算モジュール作った、google test試しに使ってみた
moveable.hh
#include <cmath> #ifndef _MOVEABLE_H_ #define _MOVEABLE_H_ namespace moveable { //いろいろな定数値、後でcommon.hに入れてもらう const float PI = static_cast<float>(atan(1.0) * 4); const float RAD = PI / 180;//HACK 30度 = 1/6ラジアン const float LEFT_HORIZON_ANGLE = PI; const float RIGHT_HORIZON_ANGLE = 0.0; const float RIGHT_JUMP_ANGLE = -((2/6) * PI); const float LEFT_JUMP_ANGLE = -((4/6) * PI); const float VERTICAL_JUMP_ANGLE = -((3/6) * PI); const float GLOBAL_INIT_GRAVITY = 2.0; //座標を表わすクラス class point { public: float _x; float _y; point(): _x(0.0), _y(0.0) {} virtual ~point(){} inline point operator + (point &other) { point result; result._x = this->_x + other._x; result._y = this->_y + other._y; return result; } }; //座標を動かしたいクラスにこれを継承させ仮想関数を定義させる、下のコンポジションさせたクラスが値を取得するために必要 class moveable_mixin { public: virtual void set_point(point) = 0; virtual point get_point() = 0; virtual bool is_ground_stick() = 0; }; //座標を動かしたいクラスにコンポジションさせる //コンストラクタにMoveableMixinを継承させたクラスのthisポインタを入れること //加速度(set_acceleration)などを設定した後、座標と速度を更新するためにmoveメソッドを最後に呼ぶ class moveable { public: moveable(moveable_mixin *p) : _parent(p), _acceleration(), _velocity(), _gravity(GLOBAL_INIT_GRAVITY){} virtual ~moveable(){} void force_stop(); void move(); void add_acceleration(float acceleration, float angle); void set_const_velocity(float speed, float angle); void set_gravity(float g); private: moveable_mixin *_parent; point _acceleration; point _velocity; float _gravity; }; } #endif /*_MOVEABLE_H_*/
moveable.cc
#include "moveable.hh" namespace moveable { //加速度と速度をゼロにして、動きを止める void moveable::force_stop() { _velocity._x = 0.0; _velocity._y = 0.0; _acceleration._x = 0.0; _acceleration._y = 0.0; } //加速度を速度に足し、速度を座標に足して動かす、重力がはたらいているならば考慮し、計算する void moveable::move() { _velocity._x += _acceleration._x; _velocity._y = (_parent->is_ground_stick() ? 0.0f : _velocity._y + _acceleration._y + _gravity); _parent->set_point(_parent->get_point() + _velocity); } //加速度と角度をもらって加速度ベクトルを表わす極座標に足す void moveable::add_acceleration(float acceleration, float angle) { this->_acceleration._x += acceleration * cos(angle); this->_acceleration._y += acceleration * sin(angle); } //加速度をゼロにして、速度のみをセットする、速度と角度をもらって速度ベクトルを表わす極座標に足す void moveable::set_const_velocity(float velocity, float angle) { force_stop(); this->_velocity._x = velocity * cos(angle); this->_velocity._y = velocity * sin(angle); } //重力をセットする void moveable::set_gravity(float g) { _gravity = g; } }
test.cc
#include <gtest/gtest.h> #include "moveable.hh" //test用ドライバークラス class obj :public moveable::moveable_mixin { public: obj() { _moveable = new moveable::moveable(this); } virtual ~obj(){} moveable::point get_point() { return point; } void set_point(moveable::point p) { point = p; } bool is_ground_stick() { return ground_stick; } bool ground_stick; moveable::point point; moveable::moveable *_moveable; }; TEST(MoveableTest, Assert) { obj testobj; //addAccelerationでの移動距離が合っているか、加速度がはたらくか testobj.ground_stick = false; testobj._moveable->set_gravity(0.0); testobj._moveable->add_acceleration(sqrt(8.0f),(moveable::PI / -4)); testobj._moveable->move(); EXPECT_FLOAT_EQ(testobj.get_point()._x, 2.0f); EXPECT_FLOAT_EQ(testobj.get_point()._y, -2.0f); testobj._moveable->move(); EXPECT_FLOAT_EQ(testobj.get_point()._x, 6.0f); EXPECT_FLOAT_EQ(testobj.get_point()._y, -6.0f); //地面より下に落さないための処理がはたらくか testobj.point._x = 0; testobj.point._y = 0; testobj._moveable->force_stop(); testobj.ground_stick = true; testobj._moveable->set_gravity(moveable::GLOBAL_INIT_GRAVITY); testobj._moveable->add_acceleration(sqrt(2.0f),(moveable::PI / -4)); testobj._moveable->move(); EXPECT_FLOAT_EQ(testobj.get_point()._x, 1.0f); EXPECT_FLOAT_EQ(testobj.get_point()._y, 0.0f); //setconstVelocityでの移動距離が合っているか testobj.point._x = 0; testobj.point._y = 0; testobj.ground_stick = false; testobj._moveable->set_gravity(0.0); testobj._moveable->set_const_velocity(sqrt(2.0f),(moveable::PI / -4)); testobj._moveable->move(); EXPECT_FLOAT_EQ(testobj.get_point()._x, 1.0f); EXPECT_FLOAT_EQ(testobj.get_point()._y, -1.0f); testobj._moveable->move(); EXPECT_FLOAT_EQ(testobj.get_point()._x, 2.0f); EXPECT_FLOAT_EQ(testobj.get_point()._y, -2.0f); //重力がはたらくか testobj.point._x = 0; testobj.point._y = 0; testobj._moveable->force_stop(); testobj.ground_stick = false; testobj._moveable->set_gravity(moveable::GLOBAL_INIT_GRAVITY); testobj._moveable->add_acceleration(sqrt(8.0f),(moveable::PI / -4)); testobj._moveable->move(); EXPECT_FLOAT_EQ(testobj.get_point()._x, 2.0f); EXPECT_NEAR(testobj.get_point()._y, 0, 1e-6f); } //int main(int argc, char **argv) //{ // testing::InitGoogleTest(&argc, argv); // RUN_ALL_TESTS(); // return 0; //}