Going through the SFML tutorial I tried to write a small code example that slides the window to the right over time, it acted in a way that I didn't expect (the window slid all the way to the bottom). Here's a minimal example that has the window moving despite sticking the exact same coordinates that getPosition spits out into setPosition
#include <SFML/Window.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/System/Time.hpp>
int main(){
sf::Window window(sf::VideoMode(800,600), "Aydin's Window");
window.setPosition(sf::Vector2i(10, 10));
sf::Clock clock;
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::Closed)
window.close();
}
sf::Time elapsed = clock.getElapsedTime();
if(elapsed > sf::milliseconds(100)){
sf::Vector2i pos = window.getPosition();
window.setPosition(pos);
clock.restart();
}
}
return 0;
}
One would expect this code to keep the window where it is, but instead it slides to the right and downwards on my machine. I had a friend run the same code. On his machine it slides to the left and upwards. What is going on?
edit: when I create the window without decorations (sf::Style::None) the windows stays where it is. I'm guessing one of getPosition or setPosition is getting offset by the title bar and the other is not.
Related
i will make a beat em up game with sfml c++ on mobilephone. So i need to use the Touch function. The problem I have is, what is the best way to detect when the Touch has been pressed, and only execute the code which should be executed when the key has been pressed once? I need it for an animation when the Player make a kick. Now its always repeating the spritesheet animation loop, i wanna fix that, here is the a piece if my code where i need it:
...
if(animHit == true){
if(plrClock.getElapsedTime().asSeconds() > 0.1)
{
animRec.x ++;
if(animRec.x * 103 >= plrtex.getSize().x)
animRec.x = 0;
plrClock.restart();
}
}
FloatRect touchButtonRect = btnSprite.getGlobalBounds();
// the Touch is pressed the button
if(touchButtonRect.contains(worldPos)){
animHit = true;
}
else
{
if(animRec.x * 412<= plrtex.getSize().x){
animHit = false;
}
}
You haven't shown the minimal amount of code needed to replicate the problem, but i think i know where the problem lies. You most likely are trying to get the touch in the while loop without any events. Events are the things that tell your program to run things at, well, a trigger of sorts. This trigger can be a mouse click, resize of window, keyboard buttons or touch events.
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
using namespace std;
using namespace sf;
int main()
{
// create the window
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
window.setFramerateLimit(60);
// 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
sf::Event event;
while (window.pollEvent(event))
{
if(event.type == sf::Event::Closed) window.close();
if (event.type == sf::Event::TouchBegan)
{
//do something
}
if (event.type == sf::Event::TouchEnded)
{
//do something
}
if (event.type == sf::Event::TouchMoved)
{
//do something
}
}
// clear the window with black color
window.clear(sf::Color::Black);
// draw everything here...
// end the current frame
window.display();
}
return 0;
}
With events you can use the triggers really well such as a screen touch. Using touchBegan it will record the single screen touch, even if you hold down the touch it will still be considered single touch.
Hope this helped.
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
how can you change the make of a SFML interface?
#include <SFML/Graphics.hpp>
int main()
{
window.create(sf::VideoMode(800, 600), "The Veterans");
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.display();
}
return 0;
}
I want Background to be red.
Now it's black.
If you want to change the background of a SFML window, you have to use sf::RenderWindow::clear with a argument for the color (No argument = Black background). The function call would be:
window.clear(sf::Color::Red);
This "clears" the window with a red color. Place the call right before the window.display().
If you want the window to display something you have to draw it to the screen. Whether that is drawing a shape or an image (or if you are using a RenderWindow, passing a color argument to the clear() method).
There are probably millions of these questions but, I can't get the coordinates of the mouse so that they line up with the program coordinate system, when the window is re-sized. I've tried mapPixelToCoords() and getting the mouse coordinates using sf::Event::MouseButton or sf::Mouse, but to no avail.
This problem is most likely from my incompetence, but I can't figure it out for the life of me. Also, I need to do this to change the coordinates of a rectangle, not detecting whether a box is being hovered over, if it was the answer would be a lot easier to figure out I feel.
Edit:
Source Code:
//Standard C++:
#include <iostream>
//SFML:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "Example");
sf::Event event;
sf::RectangleShape mousePoint;
mousePoint.setSize(sf::Vector2f(1, 1));
mousePoint.setFillColor(sf::Color::Red);
while (window.isOpen())
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed) //Close window
{
window.close();
return 0;
}
if (event.type == sf::Event::MouseButtonPressed)
{
if (event.mouseButton.button == sf::Mouse::Left)
{
//Get the mouse position:
sf::Vector2i mouse = sf::Mouse::getPosition(window);
//Map Pixel to Coords:
window.mapPixelToCoords(mouse);
//Set position of the mouse to the rectangle:
mousePoint.setPosition(mouse.x, mouse.y);
}
}
}
window.clear();
window.draw(mousePoint);
window.display();
}
}
After some doubt, I have uploaded some simple source code, which demonstrates my point. When you click the LMB, it moves the rectangle to where the program thinks the mouse is. When the screen hasn't been scaled, it is correctly calibrated, but when it is changed, the rectangle moves to a point which is no where near where the mouse is.
As shown in the official documentation and the official tutorial section of SFML, you can use the mapPixelToCoords function to map pixel/screen coordinates to world coordinates.
The signature of the function is as following:
Vector2f sf::RenderTarget::mapPixelToCoords(const Vector2i& point) const
As such the usage would look something like that:
//Get the mouse position:
sf::Vector2i mouse = sf::Mouse::getPosition(window);
//Map Pixel to Coords:
sf::Vecotr2f mouse_world = window.mapPixelToCoords(mouse);
//Set position of the mouse to the rectangle:
mousePoint.setPosition(mouse_world);
In other words, the mapPixelToCoords function, takes a const sf::Vector2i& as parameter and returns a sf::Vector2f and the original vector is not being modified.
It's always recommended to take a closer look at the documentation if something doesn't work as expected.
I'm learning the SFML library at the moment but I'm a little lost on moving the sprite. Here's my main.cpp file:
#include <SFML/Graphics.hpp>
int main()
{
// Create the main window
sf::RenderWindow App(sf::VideoMode(800, 600), "SFML window");
// Load a sprite to display
sf::Texture Image;
if (!Image.LoadFromFile("cb.bmp"))
return EXIT_FAILURE;
sf::Sprite Sprite(Image);
// Define the spead of the sprite
float spriteSpeed = 10.f;
// Start the game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.PollEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up))
Sprite.Move(spriteSpeed * App.GetFrameTime(), 0);
}
// Clear screen
App.Clear();
// Draw the sprite
App.Draw(Sprite);
// Update the window
App.Display();
}
return EXIT_SUCCESS;
}
But I get really slow, inconsistent movements, why isn't the sprite moving steadily around the screen? Also, seeing as how I plan to use the mouse to control the character how will I use the loop to make the character move towards where the user clicks?
You shouldn't be checking if the key is held down in the event loop.
SFML only posts one event when the key is first pressed down, and then another event when the key is released. In this case, your code is only checking if the key is held when an event occurs (such as moving your mouse, clicking, or anything else).
Moving the IsKeyPressed check out of the event loop, preferably below it, should fix the issue.
Making the sprite move towards your mouse is a more complicated issue, better suited for the Game Development StackExchange.