ライバルカーから見た視点を考える\\ OA・OB = |OA||OB|cosθ |OA|=1 |OB|=1のとき OA・OB = 1*1*cosθ = cosθ OA・OB -------- = cosθ |OA||OB| OA={x1, y1} OB={x2, y2} OA・OB = x1*x2+y1*y2 //車の基本方向を表すベクトル Vec2 sVec; //車の進行方向ベクトル Vec2 transVec; //車の位置 位置ベクトル Vec2 Vec2 carPosition; //車の向き 回転角度 double double carRot; //車のスピード pixel/sec double speed; # include // OpenSiv3D v0.6.10 const double PI = 3.14159265359; const double vLength = 60.0; const Vec2 SCRSIZE{ 800, 600}; const Vec2 CHRSIZE{ 64,64 }; /// @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); } /* -----車のパラメータを表すグローバル変数たち----- */ struct Car { //車の基本方向を表すベクトル Vec2 sVec; //車の進行方向ベクトル Vec2 transVec; //車の位置 位置ベクトル Vec2 Vec2 carPosition; //車の向き 回転角度 double double carRot; //車のスピード pixel/sec double speed; }; /* ---------------------------------------------- */ //myCarの初期値設定 //sVec transVec carPosition carRot speed Car myCar{ {0,1}, {0,0}, {0,0}, 0, 50.0 }; Car rivalCar{ {0,1}, {0,1.0}, {0,0}, -90, 50.0 }; //等速左右往復 void UpdateRivalCar() { //基本的に回転はcarRotのパラメータをベースに処理を行う //=>transVecは基本向きのベクトルをcarRot度回転させたものになる rivalCar.transVec = RotateVec(rivalCar.sVec, rivalCar.carRot); //ベクトル = ベクトル + スカラー*ベクトル*フレーム経過時間 //フレーム経過時間をかけることによって、正確に1sあたりの移動量を計算する rivalCar.carPosition = rivalCar.carPosition + rivalCar.speed * rivalCar.transVec * Scene::DeltaTime(); const Vec2 HSCRSIZE{ SCRSIZE.x / 2, SCRSIZE.y / 2 }; if (rivalCar.carPosition.x > HSCRSIZE.x - CHRSIZE.x / 2 || rivalCar.carPosition.x < -HSCRSIZE.x + CHRSIZE.x / 2) { if (rivalCar.carPosition.x < 0) { rivalCar.carPosition.x = -HSCRSIZE.x + CHRSIZE.x/2; }else rivalCar.carPosition.x = HSCRSIZE.x - CHRSIZE.x/2; rivalCar.carRot += 180; if (rivalCar.carRot > 360) rivalCar.carRot -= 360; } else { rivalCar.carPosition = rivalCar.carPosition + rivalCar.speed * rivalCar.transVec * Scene::DeltaTime(); } } void DrawViewRange(Car _car, Color _color) { Vec2 rRange, lRange; const double rangeLength = 200.0; Vec2 tVec = _car.transVec; tVec.normalize(); rRange = RotateVec(_car.transVec, -30); lRange = RotateVec(_car.transVec, 30); Triangle{ ConvertMath2Screen(_car.carPosition), ConvertMath2Screen(_car.carPosition + rangeLength * rRange), ConvertMath2Screen(_car.carPosition + rangeLength * lRange) }.draw({ _color,0.4 }); } double GetDistance(Car _src, Car _target) { double dist = ? ? ? ? ; return(dist); } bool IsViewTarget(Car _mySrc, Car _target) { //自分の進行方向と相手の角度が±30度以内 && 距離がviewDist以内ならtrue const double viewDist = 200; const double viewRange = 30;//自分の進行方向と±30度 //ヒント、2台の車の進行方向のベクトルのなす角度が±30度だとcosθは //いくつからいくつの範囲になるかな? } void DrawRivalCar() { Texture carImg = TextureAsset(U"RIVAL"); //ラジアンで回すのよ carImg.resized(CHRSIZE).rotated(Degree2Radians(-rivalCar.carRot)).drawAt(ConvertMath2Screen(rivalCar.carPosition)); //車の向きのベクトルをvLengthの長さで描画 Line{ ConvertMath2Screen(rivalCar.carPosition), ConvertMath2Screen(rivalCar.carPosition + vLength * rivalCar.transVec) } .drawArrow(3, { 6,6 }, Palette::Red); DrawViewRange(rivalCar, Palette::Aqua); } void UpdateMyCar() { if (MouseL.pressed()) { myCar.carRot += Scene::DeltaTime() * 90; } if (MouseR.pressed()) { myCar.carRot -= Scene::DeltaTime() * 90; } myCar.transVec = RotateVec(myCar.sVec, myCar.carRot); //ベクトル = ベクトル + スカラー*ベクトル*フレーム経過時間 //フレーム経過時間をかけることによって、正確に1sあたりの移動量を計算する myCar.carPosition = myCar.carPosition + myCar.speed * myCar.transVec * Scene::DeltaTime(); } void Update() { UpdateRivalCar(); UpdateMyCar(); if (IsViewTarget(rivalCar, myCar)) Print << U"見えた!"; } void DrawMyCar() { Texture carImg = TextureAsset(U"CAR"); //ラジアンで回すのよ carImg.resized(CHRSIZE).rotated(Degree2Radians(-myCar.carRot)).drawAt(ConvertMath2Screen(myCar.carPosition)); //車の向きのベクトルをvLengthの長さで描画 Line{ ConvertMath2Screen(myCar.carPosition), ConvertMath2Screen(myCar.carPosition + vLength * myCar.transVec) } .drawArrow(3, { 6,6 }, Palette::Yellow); } void Draw() { DrawRivalCar(); DrawMyCar(); } 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"); TextureAsset::Register(U"RIVAL", U"rival.png"); Vec2 origin{ 0,0 }; Vec2 sOrigin = ConvertMath2Screen(origin); Print << sOrigin; // //double rotation = 0; while (System::Update()) { DrawAxis(); Update(); Draw(); } }