2

OpenGL/C++ を使用してゲームを作成しています。

私が取り組んでいるこのゲームの 1 つの側面は、そのキャラクターが向いている方向に発射物を発射するキャラクターを持つことです。これを行うために、「プレーヤー」と「発射物」があります。

キャラクターの x 座標と y 座標、つまりプレイヤーが向いている角度を発射物に渡します。これから、その方向に発射体を撃ちたいと思います。

私の描画では、現在、文字 x と y で glTranslate を使用し、文字が向いている方向に発射体を回転させています。これにより、発射物がプレイヤーが向いている方向に移動します。

glTranslatef(this->m_X, this->m_Y, 0);
        glRotatef(angle, 0, 0, 1);

これは私が立ち往生している場所です。移動の X 値と Y 値をインクリメント/デクリメントすることで、発射体の位置を移動できます。しかし、私が尋ねようとしているのは、プレイヤーが直面している線に沿って発射物を移動するにはどうすればよいかということです。

助けてくれてありがとう!

4

1 に答える 1

0

これらの計算には極ベクトルを使用できます。

http://mathworld.wolfram.com/PolarVector.html

極ベクトルを使用すると、通常は複雑で複雑ないくつかの計算を簡単な方法で行うことができます。彼らの応用数学を使用すると、あなたの要求は問題になりません.

これは極ベクトルの私の実装です。

ヘッダー ファイル:

#include <cmath>

//Using SFML Vector2 class, making a similar class is easy.
//Check this URL: http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1Vector2.php

class PolarVector 
{
    public:
        float r;
        float t; ///Angle stored in degrees.

        PolarVector();
        PolarVector(float radius, float angle);
        PolarVector(const sf::Vector2f V2); ///Conversion constructor.

        sf::Vector2f TurnToRectangular() const;

};

PolarVector TurnToPolar(const sf::Vector2f point);

float getConvertedRadius(const sf::Vector2f point);

float getConvertedAngle(sf::Vector2f point);

bool operator ==(const PolarVector& left, const PolarVector& right);

bool operator !=(const PolarVector& left, const PolarVector& right);

そしてソースファイル:

#include "PolarVector.hpp"

PolarVector::PolarVector()
  :r(0.f)
  ,t(0.f)
{}

PolarVector::PolarVector(float radius, float angle)
  :r(radius)
  ,t(angle)
{}

PolarVector::PolarVector(const sf::Vector2f V2)
 :r(getConvertedRadius(V2))
 ,t(getConvertedAngle(V2))
{}

sf::Vector2f PolarVector::TurnToRectangular() const
{ return sf::Vector2f(static_cast<float>(r* std::cos(t)),    static_cast<float>(r* std::sin(t))); }

PolarVector TurnToPolar(const sf::Vector2f point)
{
    PolarVector PV;
    PV.r = getConvertedAngle(point);
    PV.t = getConvertedRadius(point);
    return PV;
}

float getConvertedRadius(const sf::Vector2f point)
{ return std::sqrt((point.x * point.x) + (point.y * point.y) ); }

float getConvertedAngle(const sf::Vector2f point)
{ return std::atan2(point.y, point.x); }

bool operator ==(const PolarVector& left, const PolarVector& right)
{
    float diffR = left.r - right.r;
    float diffA = left.t - right.t;
    return ((diffR <= EPSILON) && (diffA <= EPSILON));
}

bool operator !=(const PolarVector& left, const PolarVector& right)
{
    float diffR = left.r - right.r;
    float diffA = left.t - right.t;
    return !((diffR <= EPSILON) && (diffA <= EPSILON));
}

これをお勧めする理由は、次のことができるからです。

2 次元のベクトルがあるとします。

sf::Vector2f character(0.f, 0.f); //Origin point. First parameter is X, second is Y
float angleCharFacesAt = 0.698132; //40 degrees in radians. C++ Trigonometry uses Radians. std::cos, std::sin and std::atan2 are used internally.

最初のオブジェクトまたは文字。他のオブジェクトの角度を同じにして、位置を変えたいとします。

他のオブジェクトがその上にあるとしましょう:

sf::Vector2f object(0.f, 10.f); //Above the origin point.
float angleObjectFacesAt = 0.f; //0 degrees.

したがって、極ベクトルを使用して回転させるだけです。

PolarVector PV = TurnToPolar(object); //Use this for calculations.
PV.t += angleCharFacesAt; //t is the angle parameter of the polar vector.

object = PV.TurnToRectangular(object);

これにより、オブジェクトの回転位置が得られます。

オブジェクト間の距離は、常に極ベクトルの r (半径) 値になります。したがって、次のようにして距離を長くしたり短くしたりできます。

PolarVector PV = TurnToPolar(object); //Use this for calculations.
PV.r += 10; //Increase the radius to increase the distance between the objects.

object = PV.TurnToRectangular(object);

これでより多くのことを達成できるようにするには、回転行列と極計算を理解しようとする必要がありますが、このコードではそれが可能です。このコードもすべてクラスに入れる必要がありますが、最初はよく理解するまで試してみてください。

長い回答で申し訳ありませんが、これは線形代数を掘り下げることなく説明するのは非常に簡単ではないトピックです。クラスは実際のコードの管理を容易にするためのものですが (私は自分のゲームでこれらを使用しています)、計算だけで同じ効果を再現できます。

個人的には、オブジェクトを回転させる以上の有用性があるため、回転行列を使用するよりも極ベクトルを好みます。ただし、回転行列をよりよく理解するためのリンクは次のとおりです: https://en.wikipedia.org/wiki/Rotation_matrix

極ベクトルで変換を行った後、極ベクトルによって指定された最終位置に glTranslate を実行できます。使用している原点を中心に回転していることを確認する必要があります。そうしないと、意図したとおりに回転しない場合があります。

于 2016-03-10T19:52:52.690 に答える