SFML shape rotates infinitely - c++

I'm making a robot arm which moves around a graph but when I try to rotate a shape with my keyboard it rotates infinetly: I want it to rotate just one time when I press the right arrow. How can I solve this?
Transform transform;
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
window.close();
}
if (event.type == Event::KeyPressed)
{
switch (event.key.code)
{
case Keyboard::Right:
ang += 1;
}
}
window.clear(Color::White);
window.draw(braccio, transform);
transform.rotate(ang, WIDTH / 2, HEIGHT / 2);
window.draw(assi);
window.display();
}

Right now, this line
transform.rotate(ang, WIDTH / 2, HEIGHT / 2);
Is called on every frame of your program because it's in the main loop, that runs constantly. If you want it to happen only while your game detects some input, put it inside your event polling, like so:
while (window.pollEvent(event))
{
// Do your event handling in here, input, etc.
if (event.type == Event::Closed)
window.close();
// This event case should also be inside here.
if (event.type == Event::KeyPressed)
{
switch (event.key.code)
{
case Keyboard::Right:
transform.rotate(ang, WIDTH / 2, HEIGHT / 2);
break;
}
}
}
Otherwise your arm will continue to rotate indefinitely.
EDIT: Thanks #alseether for pointing out that the Transform::rotate function adds the angle to the shape's current rotation. So incrementing ang each time will gradually make the shape rotate faster and faster... If you don't want this to happen just set ang to a constant value and it will rotate the cube at a constant rate.

Related

sfml animation of explosion after mouseclick

I need your piece of advice. I'm using SFML and I need to play animation from the spritesheet(f.e. 64 frames and 40px width/height of each frame) after mouseclick event. The only solution I've come to is:
if (event.type == sf::Event::MouseButtonPressed) {
if (event.key.code == sf::Mouse::Left) {
float frame = 0;
float frameCount = 64;
float animSpeed = 0.005;
while (frame < frameCount) {
spriteAnimation->setTextureRect(sf::IntRect(int(frame)*w, 0, w, w));
frame += animSpeed;
window->draw(rect); // clear the area of displaying animation
window->draw(*spriteAnimation);
window->display();
}
...
But calling window->display() so many times is really not good;
Can you suggest better variants?
Instead of jamming all of your code for the animation into the event block you should spread it out.
Your design here is very inflexible in that if you ever want to display anything other than an animation you are going to have to call window->display() again outside of your event loop.
Generally in SFML your game loop proceeds similarly to as follows:
initialize();
while(running)
{
checkEvents();
clear();
update();
display();
}
Instead of performing all of the calculations and displaying for your animation inside the event's if statement you should set a bool or call a doAnimation() function of some sort. I've written a rough example below:
bool doAnimation = 0;
//declare frame, framespeed, etc
if (event.type == sf::Event::MouseButtonPressed)
{
if (event.key.code == sf::Mouse::Left)
{
doAnimation = true;
//reset frame, framespeed, etc
}
}
clear();
if(doAnimation)
{
sprite->setTexture(...);
if(frame == endFrame)
{
doAnimation = 0;
}
drawSprite();
}
window->display();
There are tons of ways to solve your problem. My example is less flexible than I would think is ideal but depending on the needs of your program it may work fine. If you wanted to take the next step moving the animation into a class of some sort would make your life a lot easier in the long run.

Make Object Move Smoothly In C++-SFML

Hey Guys I'm a Beginner in Game Development with C++ and Sfml I Wrote this code to make that purple Object move,but the problem is that it doesn't move smoothly, it's like the text input, How to fix That ?
Here Is My code :
#include <SFML/Graphics.hpp>
int main()
{
sf::ContextSettings settings;
settings.antialiasingLevel = 12;
sf::RenderWindow window(sf::VideoMode(640, 480), "Ala Eddine", sf::Style::Default, settings);
sf::CircleShape player(20, 5);
player.setFillColor(sf::Color(150, 70, 250));
player.setOutlineThickness(4);
player.setOutlineColor(sf::Color(100, 50, 250));
player.setPosition(200, 200);
while(window.isOpen())
{
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
window.close();
}
//MOOVING PLAYER////////////////////////////////////////
// moving our player to the right //
if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)){ //
//
//
player.move(3, 0);
}
// moving our player to the left
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Q)){
player.move(-3, 0);
}
// moving our player to the UP
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Z)){
player.move(0, -3);
}
// moving our player to DOWN
if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)){
player.move(0, 3);
}
}
window.clear();
window.draw(player);
window.display();
}
return 0;
}
I assume your player.move() method simply adds the offset to the player position. This means that your object will always move with the same constant velocity (assuming frame rate is constant). What you want instead is to have an acceleration which updates the velocity in every frame.
Here's the basic idea (for one direction; the y direction will work accordingly, although using vectors would be better):
Give your object both a velocity and an acceleration.
If a key is held down, set the acceleration to a constant term, otherwise set it to zero.
In every frame, add timestep * acceleration to the velocity.
In every frame, add timestep * velocity to the object position.
In every frame, multiply the velocity with some decay factor, say 0.99.
This is assuming you have a fixed timestep (say, 1/60 s for 60 fps). Timestepping is slightly more advanced, and I'll refer you to this article on the topic.

Centering Shapes/Objects in SFML for C++

So recently, I have begun using SFML to make games in Visual Studio.
After setting everything up, and writing some sample code, I devised this:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(600, 600), "Move the Shape");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
return 0;
}
The program produces the following result:
How do I place the circle in the center? I want to set up some code after that lets the user move the circle with the keyboard's arrow keys, so I need the circle in the center.
You need to set the position of shape with shape.setPosition(x, y). You know the width and height of the window (600px each way), and you know the radius of the circle (100px), so you can calculate the x and y that the circle needs to be moved to be centered. I'll leave that as an exercise for you.
You may also want to consider setting the origin of your circle so that you can position it by its center point (see setOrigin).
Actually, I've answered my own question. To set the position of an item, write:
shape.setPosition(x, y);
If you want to center a circle you can do something like this
circle.setPosition((window.getSize().x / 2.f) - circle.getRadius(), (window.getSize().y / 2.f) - circle.getRadius());
First, you should set the origin of the circle in the middle of it:
circle.setOrigin( circle.getRadius() / 2 , circle.getRadius() / 2 );
The, just move the center of the circle in the middle of the scree:
circle.setPosition( window.getSize().x / 2 , window.getSize().y / 2 );

How can I set gravity using this code? SFML/C++ [duplicate]

This question already has an answer here:
How can I set gravity using this code?
(1 answer)
Closed 8 years ago.
I am trying to make a game and am stuck on gravity..... In the following code a rectangle stands for a player and when I press up key it moves in y-axis but when I activate gravity on it (i.e resetting it's previous position) it does not animate (i.e. it does not jumps) instead it just stays in it's position.I know why it it happening. Because it is just staying in its position because when I press Up key it executes the code rectangle.setPosition(0, 350). Yeah I want it to do that but I also want to see my player in movement. I am using SFML library of C++. Please Help!
#include <SFML/Graphics.hpp>
int main(){
sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Gravity");
sf::RectangleShape rectangle;
rectangle.setSize(sf::Vector2f(100, 100));
rectangle.setFillColor(sf::Color::Black);
rectangle.setPosition(sf::Vector2f(10, 350));
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if(Event.type == sf::Event::Closed)
{
window.close();
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
rectangle.move(0, -1);
}
if(rectangle.getPosition().y >= 350-1)
{
rectangle.setPosition(0, 350);
}
window.display();
window.clear(sf::Color::Cyan);
window.draw(rectangle);
}
}
Gravity is an acceleration: that is, the double derivative of displacement. So you can't directly set the displacement (as you're currently doing) to get a nice representation of gravity.
An approach would be to create an entity class of your own, adding members for velocity, acceleration; alongside sf::RectangleShape's internal displacement; then have member functions operate on initialization/every frame - a quick & dirty example (untested):
class SomeEntity {
public:
SomeEntity( float x_pos, float y_pos ) : position(x_pos, y_pos) {
m_shape.setSize(sf::Vector2f(100, 100));
m_shape.setFillColor(sf::Color::Black);
m_shape.setPosition(sf::Vector2f(x, y));
// Constants at the moment (initial velocity up, then gravity pulls down)
velocity = sf::Vector2f(0, -30);
acceleration = sf::Vector2f(0, 9.81); //Earth's acceleration
}
void Step() { // TODO: use delta time
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
velocity.y -= 1;
}
velocity.x += acceleration.x;
velocity.y += acceleration.y;
x += velocity.x;
y += velocity.y;
m_shape.setPosition(x, y);
}
void Draw(sf::RenderWindow &window) {
window.draw(m_shape);
}
private:
sf::RectangleShape m_shape;
sf::Vector2f position, velocity, acceleration;
}
Which also means you can rewrite your application so it's a little cleaner:
SomeEntity ent(360, 0);
while(window.isOpen()) {
sf::Event Event;
while(window.pollEvent(Event)) {
if(Event.type == sf::Event::Closed) {
window.close();
}
}
ent.Step();
window.display();
window.clear(sf::Color::Cyan);
ent.Draw();
}
Seeing as you're setting your rectangle to x = 0, y = 350 repeatedly, I'll work under the assumption that that's your 'ground plane'. To achieve that, you just want to check whether the entity is under the ground plane, and reset it's position to the ground plane if it is - either in the entity's 'Step' function or directly in your main loop. In the long run, you might be better off using an entity manager/third party physics engine to do this sort of thing (a la box2D, for example)
You can do something like this instead :
if(rectangle.getPosition().y > 350)
{
rectangle.move(0, 0.01);
}

Zooming in and out a picture (sfml) using recursion in c++

Using the following code I am to add a recursive function with out changing anything in the code for it to work:
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), TITLE);
int stop = 800;
sf::Color colour1(sf::Color::Black), colour2(sf::Color::Red);
// Start the main loop
while (window.isOpen()) {
// Process events
sf::Event event;
while (window.pollEvent(event)) {
// check the type of the event...
switch (event.type) {
// window closed
case sf::Event::Closed:
window.close();
break;
case sf::Event::MouseMoved: //mouse moved
stop = mapXtoMinSize(event.mouseMove.x); // convert x coordinate of mouse to minimum size of square to draw
break;
// we don't process other types of events
default:
break;
} //end switch
} //End-Process events
window.clear(colour2);
}
I just would like to know how to go about doing such.
A recursive function generally goes like this:
int recursive(int x) {
if (x == 0) {
return 0;
} else {
return (x + recursive(x - 1));
}
}
This will sum all the integers from 0 to x, by repeatedly calling itself to compute the sum of (x - 1) and adding this to the result. If the base case, x == 0, is encountered the recursion ends and the calls unwind until they reach the original, by which point the sum has been calculated. Please be more specific.
Without knowing what you are trying to achieve with your recursive function I cannot give you any more advice. I do not know what you mean with you comment "with out changing anything in the code".