Slight pause/delay when moving - c++

I've been working on this little framework for my game today and realized that moving delays when moving around. I've used SFML before and have had the same problem, but never bothered to fix it. I'm wondering if anyone has had a similar issue and has found a solution.
Here's an example of the code which is giving me the slight pause in movement:
int main(){
sf::RenderWindow window (sf::VideoMode(640, 480), "Window");
//window.setVerticalSyncEnabled(true);
sf::Texture tex;
tex.loadFromFile("Assets/Textures/player.png");
sf::Sprite s;
s.setTexture(tex);
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
s.move(0.01f, 0.0f);
}
window.clear();
window.draw(s);
window.display();
}
}
The delay/pause/whatever I'm experience is very slight but I can notice it and it's really bugging me. Just seeing the slight break in movement when none of the values alter makes my programming mind extremely sad.

The keyboard input will have a delay just like if you hold a key in Microsoft Word. To get around this, you could create a variable and set it to true when a key is pressed.
int main(){
sf::RenderWindow window (sf::VideoMode(640, 480), "Window");
//window.setVerticalSyncEnabled(true);
sf::Texture tex;
tex.loadFromFile("Assets/Textures/player.png");
sf::Sprite s;
s.setTexture(tex);
bool moving = false;
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
moving = true;
}
if (moving) {
s.move(0.01f, 0.0f);
}
window.clear();
window.draw(s);
window.display();
}
}

This sounds like a framerate/timing issue. One frame in a 60hz game is 16.666.. milliseconds, but on Windows at least, the system clock only has a resolution of 1ms, so your delays are going to be either 16ms or 17ms. This inaccuracy results in occasional jitter as some frames are skipped (or rendered twice, in your case, giving the appearance of a short pause) even if vsync is enabled.
If you can get manual control of frame timing, e.g. by disabling sf::RenderWindow's framerate limit and calling sf::sleep directly, one solution is to delay each frame in the sequence: 17, 17, 16, 17, 17, 16, so that the long-term average is closer to 60hz, minimizing jitter.
I have never used SFML so I can't provide any code but I hope this points you in the right direction.
You should also ensure that your monitor's refresh rate is the same as your game's framerate. SFML might already be doing this automatically.

Related

Changing the world origin in C++ SFML

I've recently gotten into SFML and as an exercise to get more comfortable (and have fun), I started translating some Coding Challenges done by Daniel Shiffman on his Youtube channel, The Coding Train. Upon attempting to translate a star field effect in SFML, I started searching for the right function in SFML that would change the world origin from the top-left of the screen to the center. The closest thing I found to this was the setOrigin function, but that only works for sprites and not the whole window/screen. If you didn't understand my description of this function, it would be the equivalent of the translate(x, y) function in Processing. Any help would be appreciated.
You need to use sf::View
https://www.sfml-dev.org/tutorials/2.5/graphics-view.php
Here is a small implementation example:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(300, 300), "");
sf::Vector2u size = window.getSize();
sf::View view(sf::Vector2f(0, 0), sf::Vector2f(size.x, size.y));
window.setView(view);
sf::CircleShape cir(10);
cir.setOrigin(10, 10);
while(window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
if (event.type == sf::Event::Closed)
window.close();
window.clear();
window.draw(cir);
window.display();
}
return 0;
}

SFML Anti-Aliasing - lines look dotted and moving objects smear

Several months ago I made a Fourier Transform program using SFML 2.0. I used anti-aliasing level 8 and it looked perfectly fine. Just recently however (not quite sure when the problem began since I have not touched it in a while), it seems to have broken.
Whenever I draw a line it looks dotted and whenever something moves, it flashes between two states and it doesn't completely clear after calling window.clear(). It's not just that program however. Anytime I use any level of anti-aliasing greater than 0, even in SFML 2.5.1, the same problem occurs.
Here is the some sample code which does not work as it should on my computer:
#include <SFML/Graphics.hpp>
int main()
{
sf::Vertex line[2] =
{
sf::Vertex(sf::Vector2f(0, 0)),
sf::Vertex(sf::Vector2f(800, 0))
};
sf::ContextSettings settings;
settings.antialiasingLevel = 8.0;
sf::RenderWindow window(sf::VideoMode(800, 600), "Test", sf::Style::Close, settings);
window.setVerticalSyncEnabled(true);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
line[1].position.y += 1.0;
window.clear();
window.draw(line, 2, sf::Lines);
window.display();
}
return 0;
}
When the line finishes sweeping, it looks
like this
As this used to not be a problem, I don't think it's SFML's fault. I am using Windows 10 and my computer uses an integrated Intel UHD Graphics 620 graphics card, both of which have not changed since before the problem started happening. On a side note, I have not noticed any other programs on my computer break, only the ones I made.

Moving Sprite (SFML) in c++ using Loops

I am new to c++ and as well as SFML. I am trying to make my sprite object move down in position relative to its last position using a loop. I am looking for the animation of it sprite object falling when the program starts.
I thought implementing a the sleep function in my for loop would help solve the issue i was having where the program would just display the object at the last iteration of the loop. However my program just freezes and crashes.
Looking for some direction. Maybe the sleep function isn't the right thing to call here?
#include <SFML/Graphics.hpp>
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
// Create the window here. Calling out the dimensions
sf::RenderWindow window(sf::VideoMode(800, 600), "Example Window");
// run the program as long as the window is open
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
//close window we requested
if (event.type == sf::Event::Closed)
{
window.close();
}
}
window.clear(sf::Color::Black);
sf::Texture texture;
if (!texture.loadFromFile("c:\\abstract.png"))
{
cout<<"Failed to load image...";
}
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(20,20,30,30));
for (float i = 0; i < 30.; i++)
{
sprite.move(sf::Vector2f(5.f, i));
window.draw(sprite);
Sleep(50);
}
window.display();
}
return 0;
}
What you are doing in your for is : Processing, drawing, processing, drawing... And finally displaying what you've drawn using window.display().
Meaning that what will be displayed on your window every frames, is the result of your "Processing, drawing" thing, in other word, 30 times your sprite at different positions.
What you want is to move your sprite a bit every frames. Thus, you have to finish your current while (window.isOpen()) iteration to move your sprite, draw it, and display it, and this over and over.
What you should do is declaring your sprite outside of your game loop (Which is while (window.isOpen())), and move it in this loop.
Step by step, your program should look like:
[Start]
Initialize your context
Create a sprite
Start looping
Clear the screen
Collect inputs
Move your sprite
Draw your sprite
Display your drawing on the window
End looping
[Exit]
The last thing you will need to handle is deltaTime (The timestep). Because if you move your sprite from (x,y) every frames, it means that the faster your computer is (Able to render a lot of frames quickly), the faster your sprite will move. In order to fix this problem, you'll have to move your sprite considering the time elapsed between the current frame and the previous frame (The slower is your PC, the more your sprite will move in one frame, the faster is your PC, the less your sprite will move in one frame). Timestep will cause your sprite to move (x,y) per second instead of (x,y) per frame, which is what you want in most graphic applications.

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.

SFML 2.1 Full Explanation of using Vectors to create multiple Sprites

I am using SFML 2.1 in Code Blocks and I can't figure out how to use Vectors to make clones of my asteroid sprite. It keeps saying that asteroid_V hasn't been declared, and a warning box pops up saying it is "using characters that are illegal in the selected coding" and that they "were changed to protect [me] from losing data".
The objective of this program is to continuously create asteroid sprites that will spawn at random points above the screen before dropping straight down. There were other sprites and aspects in the program but I removed them from this post to properly condense it. This appears to be the only problem after all.
int n;
int main()
{
RenderWindow window;
window.setFramerateLimit(30);
RenderWindow mainMenu;
srand( time(0));
Texture asteroid_Pic;
asteroid_Pic.loadFromFile("Asteroid.png");
std::vector<sf::Sprite> asteroid(n, Sprite(asteroid_Pic));
for (int i = 0; i < asteroid.size(); i++){
asteroid[n].setOrigin(15, 15);
asteroid[n].getPosition();
asteroid[n].setPosition(x = rand() % 790 + 10, y = rand() % -10 - 50);
}
// run the program as long as the window is open
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
Event event;
while (window.pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == Event::Closed){
window.close();
}
asteroid[n].setPosition(x, y+=1);
asteroid[n].rotate(1);
// clear the window with black color
window.clear(Color::Black);
// draw everything here...
// window.draw(...);
window.draw(player1);
window.draw(asteroid[n]);
// end the current frame
window.display();
}
return 0;
}
You have another while (window.isOpen()) inside your main loop. Your program will enter the main loop and then never get out of that inner loop. It will never get to drawing at least once.
You need to get rid of the inner while (window.isOpen()) loop and find another way.
Although the original question was about timers, you can find a basic explanation of a game loop here. You have to handle time in you loop if you want to do something (move sprites, create new ingame entities) based on time.