2013-07-28 20 views
7

我试图从SFML中的Transformable和Drawable继承,以便使我的对象...好,可转换和可绘制。我正在做一个简单的突破游戏,但也许我会以错误的方式去解决这个问题。这里是我的代码:继承自SFML中的可变换和可绘制

#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. 我应该直接在形状上进行转换,还是应该将转换函数传递给draw函数,例如我现在是?

一些奇怪的现象也可能是一个快速修复的绘图。现在,getPosition方法为我的球对象返回不正确的值。它返回的区域似乎向下移动并向右移动一点。任何可能的原因?

感谢您的帮助!

编辑:也欢迎任何一般的C++技巧,我仍然是一个初学者。

回答

1

如果我是你,我会定义一个新类,称为TransformableAndDrawable这样的:

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

在这个类,你应该定义它们通常需要由变形和绘制类的所有成员。另外,在这个类中,你应该定义所有可以在可变形和可绘制类中普遍实现的方法。然后,你的类应该从TransformableAndDrawable被继承,像这样:现在

class Player : TransformableAndDrawable { 
    // Your code here 
} 

,回答的第一个问题是:我将在TransformableAndDrawable类的给定方法实现,如果它是一个通用的方法,因此,所有的从TransformableAndDrawable继承的类将具有此方法。

而不是给不同的名称,如p_rectp_circle,命名这些成员具有相同的名称,如p_shape,所以你不会有任何问题的命名。此外,我相信你可以声明你的p_shape是一个祖先类或接口(我不知道你正在使用的库中定义了什么类),并且只有在需要时指定形状的性质(不管它是圆或矩形或别的东西)。

至于第二个问题:我喜欢你已经实现了事情的方式,但你已经犯了两个错误:

  • 它是不可扩展的:我们希望有一个通用的解决方案,它可用于一类你现在和未来的任何形状,不是吗?
  • 它不够通用:当我想知道形状的全局范围,那么我对形状的本质不感兴趣,我宁愿你的代码处理形状的本质,而不知道它

总之,你应该做到以下几点:

  1. 创建将从TransformableDrawable

  2. 继承在你的包装类包装类,b对形状的性质不可知,尽可能通用,希望有一些类别或界面是RectangleShapeCircleShape的祖先。

  3. 继承所有的绘制和可转换课程从您的包装类,所以你将有你的类

  4. 之间共享功能。如果东西在你的包装类是不利于这是从它继承的类,覆盖该类中的方法。

编辑:

我已经调查使用的是更详细地库,发现有一个名为Shape的类,它是祖先都CircleShapeRectangleShape。所以,而不是这些类使用Shape和您的代码将更通用和可重用。

+0

好酷,我正在考虑为这些类做一个超类,因为我真的很讨厌两次写相同的代码。希望在做这件事情时,我能解决我绘制的奇怪问题。 – mrobinson7627

+0

使用getRadius函数时,转换形状指针是个好主意吗?它会工作,但我觉得这可能是不好的做法。我个人不这么认为,因为它在一个班级必须有一个圆形的形状。编辑:像这样:'if(getPosition()。x> = 800 - dynamic_cast (shape) - > getRadius())' – mrobinson7627

+0

您可以转换它,但我相信你应该实现一个在超类的功能也是如此,你可以使用模板来支持任何类。 –