「Android Studio」線分と円の衝突の実装

今回は線分と円の衝突の実装をします。

#include "DxLib.h"
#include <cmath>

using namespace std;

int Static = 1; //動かない物体
int Dynamic = 2; //動く物体
int CIRCLE = 3; //円
int RECTANGLE = 4; //四角形
int LINE = 5; //線分
int CENTER = 6; //線分の中心で回転させるか
int START = 7; //線分の始点で回転させるか

struct Vector2D
{
    double x;
    double y;

    Vector2D(double _x, double _y)
    {
        x = _x;
        y = _y;
    }

    Vector2D add(Vector2D v)
    {
        return Vector2D(x + v.x, y + v.y);
    }

    Vector2D mul(double _x, double _y)
    {
        return Vector2D(x * _x, y * _y);
    }

    int dot(Vector2D v)
    {
        return x * v.x + y * v.y;
    }

    int cross(Vector2D v)
    {
        return x * v.y - v.x * y;
    }

    double length()
    {
        return sqrt(x * x + y * y);
    }

    Vector2D unit()
    {
        return Vector2D(x / length(), y / length());
    }
};

struct Line
{
    int shape = LINE; //形状は線分
    int type; //動的か静的か
    double restitution; //反発係数
    double x0; //始点のx座標
    double y0; //始点のy座標
    double x1; //終点のx座標
    double y1; //終点のy座標
    bool on_hit; //物体と衝突したかどうかの判定

    Line(double _x0, double _y0, double _x1, double _y1)
    {
        x0 = _x0;
        y0 = _y0;
        x1 = _x1;
        y1 = _y1;
    }

    Line(double _x0, double _y0, double _x1, double _y1, int _type, double _restitution, bool _on_hit) //始点のx座標 始点のy座標 終点x座標 終点y座標 (動的か静的か) 反発係数 衝突したかの判定
    {
        x0 = _x0;
        y0 = _y0;
        x1 = _x1;
        y1 = _y1;
        type = _type;
        restitution = _restitution;
        on_hit = _on_hit;
    }

};

struct Circle
{
    int shape = CIRCLE;
    int type;
    double restitution;
    double  deceleration;
    double x;
    double y;
    int radius;
    Vector2D velocity = Vector2D(0, 0);
    Vector2D accel = Vector2D(0, 0);

    Circle(double _x, double _y, int _r, Vector2D _v, Vector2D _a)
    {
        x = _x;
        y = _y;
        radius = _r;
        velocity = _v;
        accel = _a;
    }

    Circle(double _x, double _y, int _r, Vector2D _v, Vector2D _a, int _type, double restituion, double _deceleration) //x座標 y座標 半径 速度 加速度 (動的か静的か) 反発係数 減速係数
    {
        x = _x;
        y = _y;
        radius = _r;
        velocity = _v;
        accel = _a;
        type = _type;
        restitution = restituion;
        deceleration = _deceleration;
    }

    void transfer(Vector2D gravity)
    {
        if(type == Dynamic)
        {
            velocity = velocity.add(gravity);
            velocity = velocity.add(accel);
            velocity = velocity.mul(deceleration, deceleration);
            x += velocity.x;
            y += velocity.y;
        }

    }

    bool is_hit(double _x, double _y)
    {
        double dd = pow(x - _x, 2) + pow(y - _y, 2);
        return dd < pow(radius, 2);
    }

    void collision_with_line(Line &line)
    {
        Vector2D v0 = Vector2D(line.x0 - x + velocity.x, line.y0 - y + velocity.y);
        Vector2D v1 = velocity;
        Vector2D v2 = Vector2D(line.x1 - line.x0, line.y1 - line.y0);
        Vector2D v2_unit = v2.unit();

        double cv1v2 = v1.cross(v2);
        double t1 = v0.cross(v1) / cv1v2;
        double t2 = v0.cross(v2) / cv1v2;
        bool crossed = (0 <= t1 && t1 <= 1) && (0 <= t2 && t2 <= 1);

        if(crossed)
        {
            move(-velocity.x, -velocity.y);
            double dot0 = velocity.dot(line.norm());
            Vector2D vec0 = line.norm().mul(-2 * dot0, -2 * dot0); //正射影ベクトル
            velocity = vec0.add(velocity);
            velocity = velocity.mul(line.restitution * restitution, line.restitution * restitution);
            line.on_hit = true;
        }

    }
};

上記のengine.hをインクルードして以下のプログラムを実行します。

#include "DxLib.h"
#include "engine.h"
#include <thread>
#include <chrono>

// プログラムは android_main から始まります

int android_main( void )
{
    if( DxLib_Init() == -1 )		// DXライブラリ初期化処理
    {
        return -1 ;			// エラーが起きたら直ちに終了
    }

    SetGraphMode(1080, 2220, 32); //1080×2220にサイズ変更

    int light_b = GetColor(0, 255, 255);
    int white = GetColor(255, 255, 255);

    Line line1 = Line(800, 1200, 300, 1700, Static, 0.9, false); //始点のx座標 始点のy座標 終点x座標 終点y座標 (動的か静的か) 反発係数 衝突したかの判定
     /*
    Line line2 = Line(500, 1000, 600, 1100);
    */

    Vector2D gravity = Vector2D(0, 0.98);

    Circle ball = Circle(0, 1000, 30, Vector2D(15, -15), Vector2D(0, 0), Dynamic, 1, 1); //x座標 y座標 半径 速度 加速度 (動的か静的か) 反発係数 減速係数

    this_thread::sleep_for(std::chrono::milliseconds(5000));

    while(ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen()==0)
    {
        /*
        DrawLine(line1.x0, line1.y0, line1.x1, line1.y1, light_b, TRUE);
        line1.rotation(1, CENTER);

        DrawLine(line2.x0, line2.y0, line2.x1, line2.y1, light_b, TRUE);
        line2.rotation(1, START);
        */

        this_thread::sleep_for(std::chrono::milliseconds(10));

        ball.transfer(gravity);
        ball.collision_with_line(line1);
        DrawCircle(ball.x, ball.y, ball.radius, light_b, TRUE);
        DrawLine(line1.x0, line1.y0, line1.x1, line1.y1, white, TRUE);

    }

    /*
    DrawLine(0, 0, 1079, 0, light_b, TRUE);
    DrawLine(1079, 0, 1079, 2219, light_b, TRUE);
    DrawLine(1079, 2219, 0, 2219, light_b, TRUE);
    DrawLine(0, 2219, 0, 0, light_b, TRUE);
    */

    WaitKey() ;				// キー入力待ち

    DxLib_End() ;				// DXライブラリ使用の終了処理

    return 0 ;					// ソフトの終了
}

実行結果はこんな感じになりました。

今回は以上になります。

ではまた。

コメント

タイトルとURLをコピーしました