-
Hello guys, thank you for joining this community.
Im new on SFML and C++ and want to learn several things. At first, im sorry for my bad english skills.
I want to make a little game. All works fine, but if I moving the "player sprite", so its like a "move judder".
I dont understand why and I hope you can give me the answer for this (maybe I did something wrong?)
The first one: Its SFML version 2.1, and Im working with Visual Studio 10.
The Codes are:
main.cpp
// internal
#include "Background.hpp"
#include "Player.hpp"
// external
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace sf;
int main()
{
// settings
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Window");
window.setFramerateLimit(60);
// classes
Background background;
Player player;
// variable
sf::Clock clock;
// Start the game loop
while (window.isOpen())
{
// Process events
sf::Event event;
float ElapsedTime = clock.restart().asMilliseconds();
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
// Clear the screen
window.clear();
// draw background
background.Update(window);
// draw player plus animation
player.Animation(window, ElapsedTime);
player.Draw(window);
// display window
window.display();
}
return EXIT_SUCCESS;
}
player.hpp:
#include <SFML\Graphics.hpp>
using namespace sf;
class Player
{
public:
void Animation(RenderWindow &window, float ElapsedTime);
void Draw(RenderWindow &window);
Vector2f getPosition();
Player();
public:
Texture tP;
Sprite sP;
private:
float Speed;
};
player.cpp:
// internal
#include "Player.hpp"
// external
#include <SFML\Graphics.hpp>
#include <iostream>
using namespace sf;
Player::Player()
{
Speed = .4f;
tP.setSmooth(true);
tP.loadFromFile("player1_r.png");
sP.setTexture(tP);
sP.setPosition(50,50);
}
void Player::Animation(RenderWindow &window, float ElapsedTime)
{
float x = sP.getPosition().x;
float y = sP.getPosition().y;
if(Keyboard::isKeyPressed(Keyboard::Left))
{
if(x <= 10)
{
x = 10;
}else{
x = x - (Speed*ElapsedTime);
}
}
if(Keyboard::isKeyPressed(Keyboard::Right))
{
if(x >= window.getSize().x - 10)
{
x = window.getSize().x - 10;
}else{
x = x + (Speed*ElapsedTime);
}
}
sP.setPosition(x,y);
}
void Player::Draw(RenderWindow &window)
{
window.draw(sP);
}
Vector2f Player::getPosition()
{
return sP.getPosition();
}
-
Hi,
do you mean your player goes back and forth a tinybit very rapidly if you walk all the way to one side and still hold down the key? It's because of your technique checking whether moving your player is valid.
Do it like this:
if((current position + what you want to move) is still acceptable)
move player
-
Also i suggest reading the SFML tutorial on real time input
specially this line
if(Keyboard::isKeyPressed(Keyboard::Left))
I just copy from the tutorial
Sometimes, people try to react to KeyPressed events directly to implement smooth movement. Doing so will not produce the expected effect, because when you hold a key you only get a few events (remember, the repeat delay). To achieve smooth movement with events, you must use a boolean that you set on KeyPressed and clear on KeyReleased; you can then move (independently of events) as long as the boolean is set.
The other (easier) solution to produce smooth movement is to use real-time keyboard input with sf::Keyboard (see the dedicated tutorial).
I am gonna be quick:
Some of reasons i had:
Using sf::KeyPressed.
window.setFramerateLimit(60);
This line is one of things that are horrible on some systems.
Use different way to pause a thread instead using the sfml implemented one.
#include <thread>
std::this_thread::x
instead of X see what is available cant remember from top of my head right now but there is something like "sleep" and as parameter use (std::chrono::Y)
instead of Y see what fits yours needs there are allot of different types you can put there, most likely
std::chrono::milliseconds(1);
You can pass there the time you need to pause in order to achieve your desired FPS.
-
oi, sure you hit the right topic?
-
Hello! Thank you for your replys!
I used two new methods. Method 1 by BaneTrapper (boolean method) and method 2 by Raincode.
"setFrameLimit" is removed.
But: Both are not works (same problem - there is no smooth movement).
Have a look at this code. Did I something wrong? I hope you can tell me more. :(
method 1 (current method):
Player.cpp
void Player::CheckInput(RenderWindow &window)
{
float x = sP.getPosition().x;
float y = sP.getPosition().y;
if(Keyboard::isKeyPressed(Keyboard::Left)&& x>=10)
{
Player::left=true;
}
else
{
Player::left=false;
}
if(Keyboard::isKeyPressed(Keyboard::Right)&& x<=680)
{
Player::right=true;
}
else
{
Player::right=false;
}
}
void Player::Animation(RenderWindow &window, float ElapsedTime)
{
if(Player::left==true)
{
sP.move( -Speed*ElapsedTime, 0);
}
if(Player::right==true)
{
sP.move(Speed*ElapsedTime, 0);
}
}
Player.hpp:
#include <SFML\Graphics.hpp>
using namespace sf;
class Player
{
public:
void Animation(RenderWindow &window, float ElapsedTime);
void Draw(RenderWindow &window);
void CheckInput(RenderWindow &window);
Vector2f getPosition();
Player();
public:
Texture tP;
Sprite sP;
bool right;
bool left;
private:
float Speed;
};
---
method 2:
Player.cpp
float x = sP.getPosition().x;
float y = sP.getPosition().y;
if(Keyboard::isKeyPressed(Keyboard::Left))
{
if(x >= 10)
{
sP.move( -Speed*ElapsedTime, 0);
}
else
{
x = 10;
}
}
if(Keyboard::isKeyPressed(Keyboard::Right))
{
if(x <= 690)
{
sP.move(Speed*ElapsedTime, 0);
}
else
{
x = 690;
}
}
std::cout << x << std::endl;
}
-
Hello, I found the mistake, guys. :)
It was because of my Background-Class. It was a really bad code and I dont know, why.
I rewritten the background class and the movement are smoth now. The order was important too. I changed it too. But thank you very much guys for your replys :).
My order in main.cpp:
main.cpp
// Player check Controll
player.CheckInput(window);
player.Animation(window, ElapsedTime);
// delete windows
window.clear();
// draw background
background.Draw(window);
// draw player
player.Draw(window);
// display window
window.display();
What do you think? Its okay? Or bad?
-
You still did it the incorrect way.
Try to spot difference between these two codes.
1 The correct way to achieve smooth
int main()
{
sf::RenderWindow win;
win.create(sf::VideoMode(800,600,32), "str");
win.setVerticalSyncEnabled(true);
sf::RectangleShape player;
player.setSize(sf::Vector2f(100,100));
player.setFillColor(sf::Color::Cyan);
player.setPosition(0, 0);
bool WP = false, SP = false, AP = false, DP = false;
while(win.isOpen())
{
win.clear();
sf::Event event;
while(win.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
win.close();
break;
case sf::Event::KeyPressed:
switch(event.key.code)
{
case sf::Keyboard::W:
WP = true;
break;
case sf::Keyboard::S:
SP = true;
break;
case sf::Keyboard::A:
AP = true;
break;
case sf::Keyboard::D:
DP = true;
break;
}
break;
case sf::Event::KeyReleased:
switch(event.key.code)
{
case sf::Keyboard::W:
WP = false;
break;
case sf::Keyboard::S:
SP = false;
break;
case sf::Keyboard::A:
AP = false;
break;
case sf::Keyboard::D:
DP = false;
break;
}
break;
}
}
if(WP)
player.move(0, -10);
else if(SP)
player.move(0, 10);
if(AP)
player.move(-10, 0);
else if(DP)
player.move(10, 0);
win.draw(player);
win.display();
}
return 0;
}
2 The incorrect way the one you used
int main()
{
sf::RenderWindow win;
win.create(sf::VideoMode(800,600,32), "str");
win.setVerticalSyncEnabled(true);
sf::RectangleShape player;
player.setSize(sf::Vector2f(100,100));
player.setFillColor(sf::Color::Cyan);
player.setPosition(0, 0);
while(win.isOpen())
{
win.clear();
sf::Event event;
while(win.pollEvent(event))
{
if(event.type == sf::Event::Closed)
win.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
player.move(0, -10);
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
player.move(0, 10);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
player.move(-10, 0);
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
player.move(10, 0);
win.draw(player);
win.display();
}
return 0;
}