SFML Lag when moving rectangle on screen /Small stutters - c++

whenever I move the rectangle on the screen, it seems to stutter at times. I have tried to reinstall SFML but it hasn't worked.
This is the code:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "This is the title");
window.setFramerateLimit(60);
sf::RectangleShape rect(sf::Vector2f(20, 20));
rect.setFillColor(sf::Color::Green);
rect.setPosition(sf::Vector2f(50, 50));
while (window.isOpen())
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
rect.move(0, -5);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
rect.move(0, 5);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
rect.move(-5, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
rect.move(5, 0);
}
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
}
window.clear();
window.draw(rect);
window.display();
}
return 0;
}
These are my laptops specs:
coreM 6y30
intel HD 515
8Gb RAM
Windows 10
if anyone knows what the problem is, please help me.
thank you very much
henry

As per Jesper's comment, your time step has to be taken into account when doing the graphics. The time step is the time between the different frames. There are several ways to handle this. This page Jesper referred (Fix Your Timestep) summarizes them perfectly. It is kind of a reference.
I did a quick code adaptation to give you some guidance. Code is for Linux.
#include <SFML/Graphics.hpp>
#include <iostream>
int main(){
sf::RenderWindow window(sf::VideoMode(800, 600), "This is the title");
window.setFramerateLimit(60);
sf::RectangleShape rect(sf::Vector2f(20, 20));
rect.setFillColor(sf::Color::Green);
rect.setPosition(sf::Vector2f(50, 50));
// Timing
sf::Clock clock;
while (window.isOpen()){
// Update the delta time to measure movement accurately
sf::Time dt = clock.restart();
// Convert to seconds to do the maths
float dtAsSeconds = dt.asSeconds();
// For debuging, print the time to the terminal
// It illustrates the differences
std::cout << "Time step: " << dtAsSeconds << '\n';
// Calculate movement per dt
// Since the dt is a very small number,
// you have to multiply it with a large number to see faster movement
float movement = 250.0f * dtAsSeconds;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
rect.move(0, -movement);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
rect.move(0, movement);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
rect.move(-movement, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
rect.move(movement, 0);
}
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed){
window.close();
}
}
window.clear();
window.draw(rect);
window.display();
}
return 0;
}

Related

Clunky movement on transformable objects SFML

So I am working on a game in SFML and am having a weird problem with movement. I have implemented a delta time so the movement speed is constant but I have this weird issue where I press a move key, the object jumps by speed units, pauses, then proceeds to move smoothly. I haven't been able to find much on this as I don't really know what problems I should be looking for. Here is a copy of my current code.
#include <SFML/Graphics.hpp>
#include "Player.h"
#include <iostream>
#include <vector>
void handleKeyPress(sf::Event &event, Player &player, float dt);
int main() {
sf::ContextSettings settings;
settings.antialiasingLevel = 16;
sf::RenderWindow window(sf::VideoMode(800, 600), "Title", sf::Style::Default, settings);
sf::Event event;
Player player;
player.setPosition(100, 100);
sf::Clock dtClock;
while (window.isOpen()) {
float dt = dtClock.getElapsedTime().asSeconds();
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
handleKeyPress(event, player, dt);
window.clear(sf::Color::Black);
//drawing happens hear
window.draw(player);
//end of frame
window.display();
dtClock.restart();
}
}
}
void handleKeyPress(sf::Event& event, Player& player, float dt) {
sf::Vector2f moveVector(0.0f, 0.0f);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
moveVector.x = -player.speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
moveVector.x = player.speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
moveVector.y = -player.speed;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
moveVector.y = player.speed;
player.move(moveVector * dt);
}
Note that player is just an SFML Transformable object/drawable object.
Your main is mixing event processing and state updates with drawing, which makes it hard to respect the fractional updates you intend to do with dt.
The code below undoes that: it first eats all events, then updates the game state, then draws.
In order to have smooth movement, you need to remember the Player velocity depending on which keys are pressed/released:
Add a velocity vector to Player
Change handleKeyPress to modify the velocity appropriately. Pay attention to multiple keypresses, eg up + right = (+1, +1)
Add an update method to player that adds a dt fraction of velocity to position.
Change it to:
while (window.isOpen()) {
float dt = dtClock.getElapsedTime().asSeconds();
// process events
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
} else if (event.type == sf::Event::KeyPressed || event.type == sf::Event::KeyReleased) {
// rewrite this to update player.velocity depending on what key is pressed if released
handleKeyPress(event, player, dt);
}
}
// apply dt * player.velocity to player.position
player.update(dt);
// draw
window.clear(sf::Color::Black);
//drawing happens hear
window.draw(player);
// restart the dtclock here, as display() will pause for a bit
dtClock.restart();
//end of frame
window.display();
}

C++ SFML Font loading problems

I am having problems with loading my miranda.ttf file. I have the file in the same directory as main.cc and I am sure I am typing it the right way, but it still doesn't work for some reason. I have tried multiple other fonts without luck.
#include <SFML/Graphics.hpp>
#include "core/headers/util.hpp"
#include "core/headers/ui.hpp"
#include <time.h>
int main(void) {
srand((unsigned)time(NULL));
sf::RenderWindow window(sf::VideoMode(1000, 600, 32U), L"Kolonie Mravenců", sf::Style::Titlebar | sf::Style::Close);
sf::CircleShape circle;
circle.setFillColor(sf::Color::Black);
circle.setPosition(10, 10);
circle.setRadius(6);
sf::Font font;
if (!font.loadFromFile("miranda.ttf")){
return EXIT_FAILURE;
}
sf::Text text;
text.setFont(font);
text.setPosition(sf::Vector2<float>(200.0f, 600.0f / 2.0f));
text.setFillColor(sf::Color(0, 0, 0));
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color(227, 227, 227));
window.draw(text);
window.display();
}
return 0;
}
This is the code of main.cc.
I am executing the code using terminal in VS Code Insiders on a Macbook Air.

SFML window.draw(); only shows up for a small time

I'm attempting to get a picture to display by using SFML (just a test run). The program can find the picture, and open a new window, but when it opens the window it only pops up for half a second then returns with 1. Here is the code (which is just their example that I tweaked):
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(500, 500), "SFML works!");
sf::Texture Texture;
sf::Sprite Sprite;
if(!Texture.loadFromFile("resources/pepe.png"));
return 1;
Sprite.setTexture(Texture);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(Sprite);
window.display();
}
return 0;
}
I am assuming the error is coming from the return 1; after the loading, but I don't see what is wrong. Can someone post something that worked for them or give me tips on what may be going wrong?
Your code works just fine, except for the ; after the texture loading from a file, making your program always return 1, whatever was happening before.
It's a good idea to add error messages to know what's going wrong.
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(500, 500), "SFML works!");
sf::Texture Texture;
sf::Sprite Sprite;
if(!Texture.loadFromFile("resources/pepe.png")){ // there was a ; here.
// making the code below always run.
std::cerr << "Error loading my texture" << std::endl;
return 1;
}
Sprite.setTexture(Texture);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed){
window.close();
}
// you only get here when there is at least one event.
}
// but you always want to display to the screen.
window.clear();
window.draw(Sprite);
window.display();
}
return 0;
}
My rule of thumb is to always enclose code blocks with curly braces so you never make these kind of mistakes (or someone else changing your code is less prone to make that mistake).

SFML 2.0 – drawing with vector of sprites

I'm trying to create a loop to draw 10 blocks on the screen, but nothing is showing. I got no error, so I think that the vector is not storing the sprites. I'm new to SFML, so I don't really know what I'm doing wrong.
sf::Texture bTexture;
sf::Texture bloqueTexture;
sf::Sprite bloqueSprite;
//create vector of blocks
std::vector<sf::Sprite> bricks(10, sf::Sprite(bloqueTexture));
fondo.setTexture(img_mgr.getImage("fondo.jpg"));
personaje.setTexture(img_mgr.getImage("jumper.png"));
personaje.setPosition(100,POSICION_TERRENO_Y);
bloqueSprite.setTexture(img_mgr.getImage("bloque.png"));
bloqueTexture.loadFromFile("Recursos/imagenes/bloque.png");
//Fill the vector with the texture
for (int i = 0; i < bricks.size(); i++)
{
bricks[i].setTexture(bloqueTexture);
bricks[i].setPosition(100 + (i * 45) , 320);
window.draw(bricks[i]);
}
2nd edit with final answer : if you want to display png files with SFML, save them 8bit.
Edit: I had some bad copy/paste in the second code, I fixed it
As SFML is made for multi media applications (mostly games), you need to refresh and draw to screen many times by second (that's frames). That being said, the basic approach is to have a main loop doing 3 things : handling inputs, updating your game logic and then drawing.
See the classic example from SFML's website :
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
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;
}
Your texture loading and filling the vector have to be done before the main loop, and then between window.clear() and window.display you need to draw everything you want to display (your blocks).
You may end up with something like this :
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
sf::Texture bTexture;
sf::Texture bloqueTexture;
sf::Sprite bloqueSprite;
//create vector of blocks
std::vector<sf::Sprite> bricks(10, sf::Sprite(bloqueTexture));
fondo.setTexture(img_mgr.getImage("fondo.jpg"));
personaje.setTexture(img_mgr.getImage("jumper.png"));
personaje.setPosition(100,POSICION_TERRENO_Y);
bloqueSprite.setTexture(img_mgr.getImage("bloque.png"));
bloqueTexture.loadFromFile("Recursos/imagenes/bloque.png");
for (int i = 0; i < bricks.size(); i++)
{
bricks[i].setTexture(bloqueTexture);
bricks[i].setPosition(100 + (i * 45) , 320);
}
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
for (int i = 0; i < bricks.size(); i++)
{
window.draw(bricks[i];
}
// Consider doing this :
// for(const auto& brick : bricks)
// window.draw(brick);
window.display();
}
return 0;
}
I think problem is with loading textures, try to check is loadFromFile function returning true.

SFML 2.0 - Drawing a starfield

I'm using sfml 2.0 to make a game. The background is going to be a starfield. Rather than use an image, I thought it might be neat to randomly generate a starfield each time the game starts up, so the background looks slightly different each time. Problem is, the way I'm currently doing it slows my game down A LOT. Does anyone know what is causing the speed hit? I've looked through the documentation to see what, but I haven't found anything...
Here's my code:
#include <SFML/Graphics.hpp>
#include "sfml helper/initialization_helpers.h"
#include "sfml helper/cursor_functions.h"
#include "sfml helper/global_event_handler.h"
#include "sfml helper/globals.h"
#include <cstdio>
int main(int argc, char* argv[])
{
try {
// some non-related preparations...
PrepareApplication(argv[0]);
float width = 640, height = 480;
sf::RenderWindow window(sf::VideoMode(width, height), "SFML Test", sf::Style::Close);
window.setFramerateLimit(60);
// Textures is a global object that has an internal std::map<string, sf::Texture>
Textures.add("ball.png", "ball");
sf::Sprite sprite;
sprite.setTexture(Textures.get("ball"));
// This is the snippet that generates the starfield
srand(time(NULL));
sf::Image starsImg;
starsImg.create(width, height, sf::Color::Black);
int numStars = rand() % 20 + 490;
for (int i = 0; i < numStars; i++) {
int x = rand() % (int)width;
int y = rand() % (int)height;
sf::Color color(255, 255, 255, rand() % 75 + 25);
starsImg.setPixel(x, y, color);
}
sf::Texture starsTexture;
starsTexture.loadFromImage(starsImg);
sf::Sprite stars;
stars.setTexture(starsTexture);
// main loop
while (window.isOpen()) {
if (Flags.isActive && Flags.inFocus) {
confineCursorToWindow(window);
} else {
freeCursor();
}
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Escape) {
Flags.isActive = (!Flags.isActive);
}
}
if (event.type == sf::Event::MouseMoved) {
sprite.setPosition(event.mouseMove.x, event.mouseMove.y);
}
// handles default events like sf::Event::WindowClosed
handleDefaultEventsForWindow(event, window);
}
window.clear();
window.draw(stars); // here's where I draw the stars
window.draw(sprite);
window.display();
}
} catch (const char* error) {
printf("%s\n", error);
exit(1);
}
return 0;
}
EDIT
I tried loading an image of a starfield and tried drawing that, the game still runs slow!
Also, by slow, I mean the sprite called "sprite" lags when following the mouse. Is that actually a speed issue?