从SFML中的可变形和可绘制继承 [英] Inheriting from Transformable and Drawable in SFML

查看:74
本文介绍了从SFML中的可变形和可绘制继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从SFML中的Transformable和Drawable继承,以使我的对象...良好,可变形和可绘制。我正在制作一个简单的突破游戏,但也许我会以错误的方式进行操作。这是我的代码:

I'm trying to inherit from Transformable and Drawable in SFML in order to make my objects... well, transformable and drawable. I'm making a simple breakout game, but perhaps I'm going about this the wrong way. Here's my code:

#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;
}

现在(几乎)按预期的方式移动和绘制工程,但是碰撞有点呆呆的。首先是我的碰撞问题:

Now moving and drawing work (nearly) as expected, however collisions are a bit wonky. First my collisions problems:


  1. 我是否需要像以前那样实现getGlobalBounds函数?还是有更好的方法来处理Transformable和Drawable中包含的内容?

  2. 我应该直接在形状上执行变换,还是应该像我一样将变换传递给draw函数?

绘图也发生了一些奇怪的事情,这可能是一种快速解决方案。现在,getPosition方法为我的ball对象返回了错误的值。它返回的区域似乎向右下移了一点。可能是任何原因?

Something strange is also happening with the drawing which is probably a quick fix. Right now the getPosition method returns incorrect values for my ball object. The area it returns seems to be shifted down and to the right a bit. Any reason that might be?

感谢您能够提供的帮助!

Thanks for any help you are able to give!

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

Also any general C++ tips are welcome, I'm still a beginner.

推荐答案

如果我是我,我将定义一个新类,称为 TransformableAndDrawable 像这样:

If I were you I would define a new class, called TransformableAndDrawable like this:

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

在该类中,您应该定义可变形和可绘制类通常需要的所有成员。同样,在该类中,您应该定义所有通常可以在可转换和可绘制类中实现的方法。然后,您的类应继承自 TransformableAndDrawable ,如下所示:

In this class you should define all the members which are generally needed by your transformable and drawable classes. Also, in this class you should define all the methods which can be generally implemented in your transformable and drawable classes. Then, your classes should be inherited from TransformableAndDrawable, like this:

class Player : TransformableAndDrawable {
    // Your code here
}

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

Now, the answer to the first question is: I would implement in the TransformableAndDrawable class the given method if it is a general method, so all the classes inherited from TransformableAndDrawable will have this method.

而不是使用其他名称,例如 p_rect p_circle ,用相同的名称命名这些成员,例如 p_shape ,这样就不会出现命名问题。另外,我相信您可以将p_shape声明为祖先类或接口(我不知道您正在使用的库中定义了哪些类),并且仅在需要时指定形状的性质(是否为

Instead of giving different names, like p_rect and p_circle, name these members with the same name, like p_shape, so you will have no naming issues. Also, I believe that you can declare your p_shape to be of an ancestor class or interface (I do not know what classes are defined in the library you are working with) and only when needed specify the nature of the shape (whether it is a circle or a rectangle or something else).

关于第二个问题:我喜欢您实现事物的方式,但是您犯了两个错误:

As for the second questions: I like the way you have implemented things, but you have made two mistakes:


  • 它不可扩展:我们需要一个通用的解决方案,该类可用于您现在和将来使用的任何形状,不要是吗?

  • 这还不够笼统:当我想知道形状的全局范围时,我对形状的本质不感兴趣,我希望您的代码能够处理形状的性质而我不知道它

总之,您应该执行以下操作:

In short, you should do the following:


  1. 创建一个包装类,该包装类将从 Transformable Drawable

在包装器类中,与形状的性质无关,尽可能通用,希望有一些祖先的类或接口到 RectangleShape CircleShape

In your wrapper class, be agnostic to the nature of the shape, be as general as possible, hopefully there is some class or interface which is ancestor to both RectangleShape and CircleShape.

从包装器类继承所有可绘制和可转换的类,这样,您的类之间将具有共享功能

Inherit all your drawable and transformable classes from your wrapper class, so you will have a shared functionality among your classes

如果包装器类中的某些内容不适合继承自该类的类,覆盖该类中的方法。

If something in your wrapper class is not good for a class which was inherited from it, overwrite the method in that class.

编辑:

我更详细地研究了您正在使用的库,发现有一个名为Shape的类,它是 CircleShape RectangleShape 。因此,不是使用这些类,而是使用 Shape ,您的代码将更加通用和可重用。

I have looked into the library you are using in more detail and found out that there is a class called Shape, which is the ancestor to both CircleShape and RectangleShape. So, instead of these classes use Shape and your code will be more general and reusable.

这篇关于从SFML中的可变形和可绘制继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆