I'm new to programming and SFML. I'm trying to make something like a canon. It's gonna fire balls that will be flying in an arc. Sounds like a very simple task to accomplish, yet I cannot seem to figure out how angles work in SFML. For example, with ang_const = 0.13 Rad (7.44 Deg), my balls flies in a beautiful arc. However, when I change the value of ang_const to 0.14 Rad (8.021 Deg), the ball flies in the opposite direction! If I change the angle to 0.19 Rad (10.88 Deg), it flies downwards for whatever reason.
So here's my code:
#include <SFML/Graphics.hpp>
#include <math.h>
int WIDTH = 1024, HEIGHT = 704;
class Ball {
private:
float radius = 16.00;
public:
sf::CircleShape shape;
Ball () {
shape.setPosition(0 + radius*2, HEIGHT - radius*2);
shape.setRadius(radius);
shape.setFillColor(sf::Color::Cyan);
shape.setOrigin(radius, radius);
}
void update() {
if (x() - radius > WIDTH) {
this->shape.setPosition(0 - radius, y());
}
if (x() + radius < 0) {
this->shape.setPosition(WIDTH + radius, y());
}
if (y() - radius > HEIGHT) {
this->shape.setPosition(x(), 0 - radius);
}
if (y() + radius < 0) {
this->shape.setPosition(x(), HEIGHT + radius);
}
}
float RadToDeg (float radian) {
double pi = 3.14159;
return radian * (180 / pi);
}
float x() { return shape.getPosition().x; }
float y() { return shape.getPosition().y; }
float getRadius() { return radius; }
};
int main()
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "del");
// Some variables
float ang_const = 0.13;
float velX_const = 3.5, velY_const = 3.5;
float grav_const = -0.02;
float ang = ang_const;
float velX = velX_const, velY = velY_const;
float grav = grav_const;
// Text
int size_for_text = 64;
sf::Font f;
f.loadFromFile("Keyboard.ttf");
sf::Text text1;
text1.setFont(f);
text1.setCharacterSize(27);
text1.setFillColor(sf::Color::White);
text1.setPosition(size_for_text, size_for_text);
// Ball
Ball ball;
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window: exit
if (event.type == sf::Event::Closed) {
window.close();
}
// Escape pressed: exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
window.close();
}
// Restart
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) {
ang = ang_const;
velX = velX_const, velY = velY_const;
grav = grav_const;
ball.shape.setPosition(0 + ball.getRadius()*2, HEIGHT - ball.getRadius()*2);
}
}
// Ball movement
ball.update();
velY += grav;
ball.shape.move(velX * cos(ball.RadToDeg(ang)),
velY * -sin(ball.RadToDeg(ang)));
// Clear screen
window.clear(sf::Color(0,0,80,100));
// Draw ball
window.draw(ball.shape);
// Draw text
text1.setString("ang " + std::to_string(ang));
window.draw(text1);
// Update the window
window.display();
}
return EXIT_SUCCESS;
}
The main lines are these: Variables:
float ang_const = 0.13;
float velX_const = 3.5, velY_const = 3.5;
float grav_const = -0.02;
Ball movement:
velY += grav;
ball.shape.move(velX * cos(ball.RadToDeg(ang)), velY * -
sin(ball.RadToDeg(ang)));
Radians to Degrees function:
float RadToDeg (float radian) {
double pi = 3.14159;
return radian * (180 / pi);
}
Could someone explain what's wrong with my code and how angles work in SFML? I'd be appreciated for your help guys.
All the trigonometric functions defined in <cmath>
expect their parameters to be values representing angles in radians (see e.g. std::cos).
So, when you write something like
cos(ball.RadToDeg(ang))
where ang
is equal to, say 0.13, RadToDeg
will convert it to 7.44, but, even if your intention is to pass an angle in degrees, that value is interpreted by std::cos
(and std::sin
) as an angle of 7.44 radians (or 66.28°).
That leads to your unexpected results:
cosr(7.44) = 0.505 (instead of cosd(7.44°) = 0.993) and
cosr(8.021) = -0.166 (instead of cosd(8.021°) = 0.992)