車画像の回転(```carImg.rotated(回転角度)```)は、画像の座標軸での回転方向(+が時計回り(clockwise))
数学座標での回転```Vec2 RotateVec(Vec2 _vec, double _angle)```は、+方向の回転が反時計回り(reverse clockwise)になる。
なので、今のプログラムでは座標自体は、数学座標→スクリーン座標に変換してるが、回転に関しては、
- 車の方向などのベクトル関連 ⇒ 数学座標で回転を計算しスクリーン座標で描画
- 車のグラフィック ⇒ 指定した座標に、描画命令の回転を使って描画
している。
したがって、ベクトル回転の数学的計算に回転方向を合わせてやるには、どちらも角度ベースで回転をかけているが、どこかで描画の方の回転を逆方向に直してやらないと、ベクトルと車が逆回転してしまう。
今回は、描画の時に車のグラフィックの回転方向にマイナスをかけて対応している。
# include <Siv3D.hpp> // OpenSiv3D v0.6.10 const double PI = 3.14159265359; const double vLength = 60.0; /// @brief 数学の座標をスクリーン座標に変換する関数 /// @param _point 変換前の数学座標 /// @return 変換されたスクリーン座標 Vec2 ConvertMath2Screen(Vec2 _point) { Vec2 resultPoint; Vec2 halfScrSize = { Scene::Width() / 2.0, Scene::Height() / 2.0 }; resultPoint.x = _point.x+halfScrSize.x; resultPoint.y = Scene::Height() - (_point.y + halfScrSize.y); return resultPoint; } /// @param _angle 角度を入力 /// @return ラジアンに変換された値 double Degree2Radians(double _angle) { return(_angle * (PI / 180.0)); } /// @brief 座標軸を描く関数 void DrawAxis() { Vec2 halfScrSize = { Scene::Width() / 2.0, Scene::Height() / 2.0 }; Vec2 xAxisStart = { 0, halfScrSize.y }; Vec2 xAxisEnd = { Scene::Width() , halfScrSize.y }; Vec2 yAxisStart = { halfScrSize.x, Scene::Height() }; Vec2 yAxisEnd = { halfScrSize.x, 0 }; Line{ xAxisStart, xAxisEnd }.drawArrow( 2, Vec2{5,5}, Palette::Black ); Line{ yAxisStart, yAxisEnd }.drawArrow(2, Vec2{ 5,5 }, Palette::Black); } /// @brief _angle度だけ_vecを原点中心に回転して返す /// @param _vec 回転されるベクトル /// @param _angle 回転角度(度) /// @return 回転後のベクトル Vec2 RotateVec(Vec2 _vec, double _angle) { double theta = Degree2Radians(_angle); //ラジアン Vec2 res; res.x = _vec.x * cos(theta) - _vec.y * sin(theta); res.y = _vec.x * sin(theta) + _vec.y * cos(theta); return(res); } /* -----車のパラメータを表すグローバル変数たち----- */ //車の基本方向を表すベクトル Vec2 sVec{0, 1}; //車の進行方向ベクトル Vec2 transVec; //車の位置 位置ベクトル Vec2 Vec2 carPosition = { 0, 0 }; //車の向き 回転角度 double double carRot = 0; //車のスピード pixel/sec double speed = 50.0; /* ---------------------------------------------- */ void Update() { transVec = RotateVec(sVec, carRot); //ベクトル = ベクトル + スカラー*ベクトル*フレーム経過時間 //フレーム経過時間をかけることによって、正確に1sあたりの移動量を計算する carPosition = carPosition + speed * transVec * Scene::DeltaTime(); } void Main() { // 背景の色を設定する | Set the background color Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 }); //// 絵文字からテクスチャを作成する | Create a texture from an emoji //const Texture emoji{ U"🦖"_emoji }; //// 太文字のフォントを作成する | Create a bold font with MSDF method //const Font font{ FontMethod::MSDF, 48, Typeface::Bold }; //// テキストに含まれる絵文字のためのフォントを作成し、font に追加する | Create a font for emojis in text and add it to font as a fallback //const Font emojiFont{ 48, Typeface::ColorEmoji }; //font.addFallback(emojiFont); TextureAsset::Register(U"CAR", U"car.png"); Vec2 origin{ 0,0 }; Vec2 sOrigin = ConvertMath2Screen(origin); Print << sOrigin; Texture carImg = TextureAsset(U"CAR"); //double rotation = 0; while (System::Update()) { DrawAxis(); if (MouseL.pressed()) { carRot += Scene::DeltaTime() * 90; } if (MouseR.pressed()) { carRot -= Scene::DeltaTime() * 90; } Update(); //ラジアンで回すのよ carImg.resized(Vec2{64, 64}).rotated(Degree2Radians(-carRot)).drawAt(ConvertMath2Screen(carPosition)); //車の向きのベクトルをvLengthの長さで描画 Line{ ConvertMath2Screen(carPosition), ConvertMath2Screen(carPosition + vLength * transVec) } .drawArrow(3, { 6,6 }, Palette::Yellow); } }