继承自SFML中的可转换和可绘制
Inheriting from Transformable and Drawable in 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;
}
现在,移动和绘制工作(几乎)如预期,但碰撞有点不稳定。首先我的碰撞问题:
- 我需要像以前那样实现getGlobalBounds函数吗?或者有更好的方法来处理包含在Transformable和Drawable中的内容吗
- 我应该直接对形状执行转换,还是应该像现在这样将转换传递给draw函数
这幅画也发生了一些奇怪的事情,这可能是一个快速解决方案。现在,getPosition方法为我的球对象返回了不正确的值。它返回的区域似乎向下和向右移动了一点。有什么原因吗?
谢谢你能提供的任何帮助!
编辑:也欢迎任何通用的C++技巧,我仍然是一个初学者。
如果我是你,我会定义一个新的类,称为TransformableAndDrawable
,如下所示:
class TransformableAndDrawable : public sf::Transformable, public sf::Drawable {
// Your code here
}
在这个类中,您应该定义可转换和可绘制类通常需要的所有成员。此外,在这个类中,您应该定义所有通常可以在可转换和可绘制类中实现的方法。然后,您的类应该从TransformableAndDrawable
继承,如下所示:
class Player : TransformableAndDrawable {
// Your code here
}
现在,第一个问题的答案是:如果给定的方法是一个通用方法,我会在TransformableAndDrawable
类中实现它,所以从TransformableAndDrawable
继承的所有类都会有这个方法。
与其使用不同的名称(如p_rect
和p_circle
),不如使用相同的名称(例如p_shape
)命名这些成员,这样就不会出现命名问题。此外,我相信您可以将p_shape声明为祖先类或接口(我不知道您正在使用的库中定义了哪些类),并且只有在需要时才能指定形状的性质(无论是圆形、矩形还是其他什么)。
至于第二个问题:我喜欢你实现的方式,但你犯了两个错误:
- 它是不可扩展的:我们想要一个通用的解决方案,一个可以用于您现在和将来使用的任何形状的类,不是吗
- 这还不够普遍:当我想知道形状的全局边界时,我对形状的性质不感兴趣,我更希望你的代码在我不知道的情况下处理形状的性质
简而言之,你应该做以下事情:
创建一个将从
Transformable
和Drawable
继承的包装类在包装器类中,对形状的性质不可知,尽可能通用,希望有一些类或接口是
RectangleShape
和CircleShape
的祖先。从包装器类继承所有可绘制和可转换的类,这样你的类之间就有了共享功能
如果包装类中的某些内容对从中继承的类不好,请覆盖该类中的方法。
编辑:
我更详细地查看了您正在使用的库,发现有一个名为Shape的类,它是CircleShape
和RectangleShape
的祖先。因此,使用Shape
代替这些类,您的代码将更加通用和可重用。
- 隐式可转换参数,但属于引用类型
- 在sfml中获取可转换的边界框
- 从c++11 time_t创建一个可转换为.net DateTime的字符串
- 包含可变参数包的第一个可转换类型的别名的结构
- 为什么类型可转换性C++不传递
- std :: iS_constructiblinsibles与参数可转换为参数的参数
- 如果模板值可转换为布尔值,则在编译时禁用类方法
- 类中参数的可变可转换检查
- 在 DirectX 9/c++ 中绘制可读文本
- 未知类方法回调,它接受 0 个参数并返回可转换为 int 的类型
- 为可转换为指针的迭代器专门化一个类
- initializer_list<T>不能转换为 initializer_list<U>,但 T 可转换为 U
- 继承自SFML中的可转换和可绘制
- 如果加法表达式的第一个操作数可转换为指针和整数,则选择哪个转换
- 在c++中检查运行时的可转换性
- 对于可转换类型,设计比循环依赖项更好
- 使用隐式可转换对象调用move重载函数时的编译错误
- 当模板类is_可转换为已知类型时,特化函子
- 在定义的矩形内绘制可滚动的内容
- 是否可以使作用域枚举("enum class")在上下文中可转换为布尔值?