2013-07-28 6 views
7

TransformableとDrawableをSFMLで継承しようとしています。私は簡単なブレークアウトゲームを作っていますが、おそらく私はこれについて間違った方法をとっています。私のコードは次のとおりです:SFMLのTransformableとDrawableから継承

#include <SFML/Graphics.hpp> 
#include <SFML/System.hpp> 

class Player : public sf::Transformable, public sf::Drawable { 
    public: 
     Player(int x, int y); 
     ~Player() {}; 

     sf::RectangleShape p_rect; 

     void doMovement(const sf::RenderWindow& window); 
     sf::FloatRect getGlobalBounds() const; 
    private: 
     virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const { 
      states.transform *= getTransform(); 
      target.draw(p_rect, states); 
     } 

}; 

class Ball : public sf::Transformable, public sf::Drawable { 
    public: 
     Ball(int r, int x, int y); 
     ~Ball() {}; 

     sf::CircleShape b_circle; 

     void doXMovement(); 
     void doYMovement(); 
     bool doXCollisions(const Player& player); 
     bool doYCollisions(const Player& player); 
     sf::FloatRect getGlobalBounds() const; 
    private: 
     virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const { 
      states.transform *= getTransform(); 
      target.draw(b_circle, states); 
     } 

     bool right; 
     bool up; 
}; 

Player::Player(int x, int y) { 
    p_rect = sf::RectangleShape(sf::Vector2f(x, y)); 
} 

void Player::doMovement(const sf::RenderWindow& window) { 
    setPosition(sf::Mouse::getPosition(window).x, 500); 
    if (getPosition().x < 0) 
     setPosition(0, 500); 
    else if (getPosition().x > 720) 
     setPosition(720, 500); 
} 

sf::FloatRect Player::getGlobalBounds() const { 
    return getTransform().transformRect(p_rect.getGlobalBounds()); 
} 

Ball::Ball(int r, int x, int y) { 
    b_circle = sf::CircleShape(r); 
    b_circle.setPosition(x, y); 
    right = true; 
    up = false; 
} 

void Ball::doXMovement() { 
    if (right) 
     move(1, 0); 
    else 
     move(-1, 0); 
} 

void Ball::doYMovement() { 
    if (up) 
     move(0, -1); 
    else 
     move(0, 1); 
} 

bool Ball::doXCollisions(const Player& player) { 
    bool coll; 
    if (getGlobalBounds().intersects(player.getGlobalBounds())) { 
     right = !right; 
     coll = true; 
    } else 
     coll = false; 

    if (getPosition().x >= 800 - b_circle.getRadius()) 
     right = false; 
    else if (getPosition().x <= 0) 
     right = true; 
    return coll; 
} 

bool Ball::doYCollisions(const Player& player) { 
    bool coll; 
    if (getGlobalBounds().intersects(player.getGlobalBounds())) { 
     up = !up; 
     coll = true; 
    } else 
     coll = false; 
    if (getPosition().x <= 0) 
     up = false; 
    return coll; 
} 

sf::FloatRect Ball::getGlobalBounds() const { 
    return getTransform().transformRect(b_circle.getGlobalBounds()); 
} 

int main() { 
    sf::RenderWindow window(sf::VideoMode(800, 600), "Breakout"); 
    window.setMouseCursorVisible(false); 
    Player player(80, 10); 
    Ball ball(3, 100, 100); 
    sf::Clock clock; 
    while (window.isOpen()) { 
     sf::Event event; 
     while (window.pollEvent(event)) { 
      if (event.type == sf::Event::Closed) 
       window.close(); 
     } 
     player.doMovement(window); 
     if (clock.getElapsedTime().asMilliseconds() >= 3) { 
      clock.restart(); 
      if (!ball.doYCollisions(player)) 
       ball.doXCollisions(player); 
      ball.doYMovement(); 
      ball.doXMovement(); 
     } 
     window.clear(sf::Color::Black); 
     window.draw(player); 
     window.draw(ball); 
     window.display(); 
    } 
    return 0; 
} 

期待通りに動き回っていますが、衝突はちょっと怪しいです。最初に私の衝突の問題:

  1. 私はやったようにgetGlobalBounds関数を実装する必要がありますか?あるいは、TransformableとDrawableに含まれているものを使ってより良い方法を実現できますか?
  2. シェイプの変形を直接実行するか、現在のように描画関数に変換を渡す必要がありますか?

おそらく速い修正であるかもしれない何か変わったことが起こっています。現在、getPositionメソッドは、私のボールオブジェクトに不正な値を返します。それが返す領域は右に少しシフトしているようです。何らかの理由がありますか?

ご協力いただきありがとうございます!

編集:また、一般的なC++のヒントも歓迎します。私はまだ初心者です。あなたは、一般的にあなたの変形および描画可能なクラスが必要とするすべてのメンバーを定義する必要があり、このクラスでは

class TransformableAndDrawable : public sf::Transformable, public sf::Drawable { 
    // Your code here 
} 

:私があなただったら、私は新しいクラスを定義します

答えて

1

は、このようなTransformableAndDrawableと呼ばれます。また、このクラスでは、変換可能なクラスと描画可能なクラスで一般的に実装できるすべてのメソッドを定義する必要があります。次に、あなたのクラスはこのように、TransformableAndDrawableから継承する必要があります。

class Player : TransformableAndDrawable { 
    // Your code here 
} 

は今、最初の質問への答えは次のとおりです。私はそれが一般的な方法であればTransformableAndDrawableクラスで指定されたメソッドを実装するので、すべてのだろうTransformableAndDrawableから継承したクラスにはこのメソッドがあります。

p_rectp_circleのように異なる名前を付ける代わりに、これらのメンバーの名前を同じ名前(p_shapeなど)にすると、名前の問題は発生しません。また、私は、あなたがp_shapeを先祖のクラスまたはインタフェース(あなたが作業しているライブラリにどのクラスが定義されているかわからない)とする必要があると信じています。円や矩形など)。第二の質問については

:私はあなたが物事を実装している方法のように、しかし、あなたは2つのミス作った:それはスケーラブルではありません

  • を:私たちは一般的な解決策のために使用することができるクラスをしたいですあなたが今や将来一緒に働いているどんな形ですか?
  • これは一般的ではありません:シェイプのグローバル境界を知りたい場合は、シェイプの性質には興味がありません。シェイプの性質を私が知らないうちに扱うことをお勧めします。
  • 要するに

、次の操作を行う必要があります。

  1. B、ラッパークラスでTransformableDrawable

  2. から継承されますラッパークラスを作成します。可能であれば一般的なものにしてください。RectangleShapeCircleShapeの両方の祖先であるいくつかのクラスまたはインターフェースがあればうれしいです。あなたのラッパークラスから

  3. 継承するすべてのあなたの描画可能と変形クラス、あなたのラッパークラスで何かがそれから継承されたクラスのために良いではない場合、あなたのクラス

  4. の間で共有する機能を持つことになりますので、そのクラスのメソッドを上書きします。

EDIT:

私はあなたがより詳細に使用しているライブラリに見て、CircleShapeRectangleShape両方に祖先である形状と呼ばれるクラスがあることを見出しました。したがって、これらのクラスの代わりにShapeを使用すると、あなたのコードはより一般的で再利用可能になります。

+0

私は本当に同じコードを2回書くのが嫌なので、クールな、これらのクラスのスーパークラスを作ることを考えていました。うまくいけば、これで私の奇妙な問題を図面で修正できます。 – mrobinson7627

+0

getRadius関数を使用するときにShapeポインタをキャストすることをお勧めしますか?それはうまくいくだろうが、それは悪い習慣であるかもしれないように感じる。私は個人的にそうは思わない。それは、クラスがサークル型の形状を持たなければならないからだ。 編集します: '(getPosition()。x> = 800 - dynamic_cast (形) - > getRadius())' – mrobinson7627

+0

あなたはそれを変換することができますが、スーパークラスでもその機能を利用することができます。そこにはテンプレートを使用して任意のクラスをサポートすることができます。 –