So, I was trying to create a class in C++ for an animated sprite that uses spritesheets for input, and when trying to move the sprite, it just sort of bounces back. It won't save to the position.
I tried using .setPostion() but that still bounces back to where it was. I have no other methods of moving the sprite implemented, nor updating it or anything else. The part in concern in the member function run, which is void is:
//if statement
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
curranim[2] = Right;
playerSprite.setPosition(playerSprite.getPosition().x + walkingSpeed, 0);
}
window.draw(playerSprite);
//spritesheet.cpp ends here
Now here is my main function:
int main()
{
sf::RenderWindow Window(sf::VideoMode(900, 600), "RPG");
animsprite sprite("dragon.png", 1, Window);
sprite.setWalkSpeed(10);
sf::Event Event;
while (Window.isOpen())
{
while (Window.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
Window.close();
break;
}
}
Window.clear();
sprite.run(Window);
Window.display();
}
return 0;
}
Will I be stuck to repeating my code forever or is there a fix?
Related
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();
}
I am working on a basic game in C++ using SFML for graphics. It is designed to use a grid system with functions to determine what should be displayed in each square. However, the compiler won't recognize the references to the window in the functions.
To keep it easier to expand there are functions for each type of terrain to be displayed, taking the coordinates as inputs (possibly not the correct term).
Good Question. SFML recommends that you create your window in the main function, but, if you want to modify it, you can simply pass it by reference. EX:
#include <SFML/Graphics.hpp>
void doSomething(sf::RenderWindow& window) {
sf::RectangleShape shape(sf::Vector2f(100, 100));
shape.setFillColor(sf::Color::Green);
shape.setPosition(50, 50);
window.draw(shape);
window.display();
}
int main() {
sf::RenderWindow window(sf::VideoMode(500, 500), "Test", sf::Style::Close);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
window.clear(sf::Color::Black);
//draw here
doSomething(window);
}
return 0;
}
You should take a look at https://www.sfml-dev.org/tutorials/2.5/. Specifically I would look at https://www.sfml-dev.org/tutorials/2.5/window-window.php
Well, I've been watching a tutorial on how to use SFML. I'm currently learning to move a sprite in the screen. Before adding window.clear(); every time I moved the sprite it left like a trail, like if the sprite was a brush. Then the tutorial man said to add window.clear BEFORE window.draw(player);
Could you please explain the logic behind that? Like, the window gets cleared, then draws the character and the displays it. Here is the code:
#include <SFML/Graphics.hpp>
#include <iostream>
int main() {
sf::RenderWindow window(sf::VideoMode(1920, 1080), "Screen", sf::Style::Default);
sf::RectangleShape player(sf::Vector2f(100.0f, 100.0f));
player.setFillColor(sf::Color::Green);
//run 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
sf::Event evnt;
while (window.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
window.close();
break;
case sf::Event::Resized:
printf("New window width: %i New window height: %i\n", evnt.size.width, evnt.size.height);
break;
case sf::Event::TextEntered:
if (evnt.text.unicode < 128) {
printf("%c", evnt.text.unicode);
}
}
// "close requested" event: we close the window
if (evnt.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W)){
player.move(0.0f, -0.1f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A)) {
player.move(-0.1f, 0.0f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S)) {
player.move(0.0f, 0.1f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) {
player.move(0.1f, 0.0f);
}
window.clear();
window.draw(player);
window.display();
}
return 0;
}
The logic behind sf::RenderWindow::clear() is actually quite simple. The reason you see a trail behind the sprite without clear is because you redraw the sprite again without getting rid of the old one. Clearing the screen gets rid of anything that was already on the screen, so you end up with a blank canvas to redraw everything on in its updated position. The character, which is your sprite, isn't actually moving, it is constantly getting redrawn in a new position on the window.
I'm working on a project at the moment which is basically a visualisation of Sort algorithms to explain how they work (rather than an overview). I'm new to using the SFML (or even OpenGL) and have limited experience with the library, but what I'm trying to do is move the drawn sprite to different locations to show the sorting. I've looked over tutorials and examples, but they all take in keyboard input to move the sprite - something that isn't used in this project. Does anyone know exactly how to achieve this?
Here's the current code:
DrawCups.h
class DrawCups
{
public:
DrawCups(sf::RenderWindow& window);
~DrawCups();
void loadImage(const char* pathname, sf::Texture& texture, sf::Sprite& sprite);
void drawCup1();
private:
sf::RenderWindow& _window;
};
DrawCups.cpp (selected function)
void DrawCups::drawCup1()
{
// load our image
sf::Texture cup1; // the texture which will contain our pixel data
sf::Sprite cup1Sprite; // the sprite which will actually draw it
loadImage("./images/InsertionSort/red_cup_1.png", cup1, cup1Sprite);
cup1Sprite.setPosition(sf::Vector2f(150, 230));
_window.draw(cup1Sprite);
}
main.cpp
int main()
{
sf::RenderWindow window(sf::VideoMode(1366, 768), "Sorting Algorithm Visualisation: SFML");
window.setFramerateLimit(60);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color::White);
DrawCups drawToWindow(window);;
drawToWindow.drawCup1();
window.display();
}
return 0;
}
Create the image before the loop and update it before you draw it.
DrawCups drawToWindow(window); //Constructor creates the sprite
while (window.isOpen())
{
...
drawToWindow.update(); //Update the position
//Redraw
window.clear(sf::Color::White);
drawToWindow.drawCup1();
window.display();
}
I'm not sure what type of movement you want but the update function can be something like this:
void DrawCups::update()
{
sf::Vector2f pos = this->cup1Sprite.getPosition();
pos.x++; //Move 1 pixel to the left
this->cup1Sprite.setPosition(pos);
}
Obviously change the movement to suit your needs. Make smaller/larger updates if it's moving too fast or slow.
The current update function should be moving the sprite to the left 10 pixels every time it's called, but the sprite (cup1Sprite) is static and not moving. I tried using sprite.rotate(); and the sprite rotated every frame (which was expected), so something is wrong with the way I've written the update function for updating the sprite position. Can anyone suggest what's going wrong?
Code:
DrawCups.h
class DrawCups
{
public:
DrawCups(sf::RenderWindow& window);
~DrawCups();
void update();
void drawCup1();
private:
sf::RenderWindow& _window;
//Cup1
sf::Texture _cup1; // the texture which will contain our pixel data
sf::Sprite _cup1Sprite; // the sprite which will actually draw it
};
Update function in DrawCups.cpp
void DrawCups::update()
{
sf::Vector2f pos = this->_cup1Sprite.getPosition();
pos.x+=10;
this->_cup1Sprite.setPosition(pos);
}
main.cpp
int main()
{
sf::RenderWindow window(sf::VideoMode(1366, 768), "Sorting Algorithm Visualisation: SFML");
window.setFramerateLimit(60);
DrawCups drawToWindow(window);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
drawToWindow.update();
window.clear(sf::Color::White);
drawToWindow.drawBench();
drawToWindow.drawCup1();
window.display();
}
return 0;
}