I'm stuck on working out the correct syntax to pass the mouseX and mouseY position to my class.
My attempt was like this:
// Start the game loop
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed) {
window.close();
}
}
// Clear screen
window.clear();
// Draw the sprite
window.draw(sprite);
window.draw(lsprite);
if(btn_quit.IsIn(sf::Event::MouseMoveEvent::x,sf::Event::MouseMoveEvent::y){
btn_quit.RenderImg(window,"button_on.png");
} else {
btn_quit.RenderImg(window,"button.png");
}
///rest of the code not relevant to this issue
This is in my class:
bool IsIn( int mouseX, int mouseY )
{
if (((mouseX > m_x) && (mouseX < m_x + m_w))
&& ((mouseY > m_y) && (mouseY < m_y + m_h ) ) ) {
return true;
} else {
return false;
}
}
I keep getting an error with the inputs of x and y how ever which says this:
error C2597: illegal reference to non-static member 'sf::Event::MouseMoveEvent::x'
error C2597: illegal reference to non-static member 'sf::Event::MouseMoveEvent::y'
You're trying to statically access non-static member fields of a struct. You can't do that. Try something like this:
// Start the game loop
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed) {
window.close();
}
else if (event.type == sf::Event::MouseMove)
{
if(btn_quit.IsIn(event.MouseMoveEvent.x, event.MouseMoveEvent.x){
btn_quit.RenderImg(window,"button_on.png");
} else {
btn_quit.RenderImg(window,"button.png");
}
}
}
// Clear screen
window.clear();
// Draw the sprite
window.draw(sprite);
window.draw(lsprite);
What you're currently doing is incorrect in a few ways. First of all you can't access x and y as static data like that, it simply does not exist.
Next to that, SFML events are essentially unions, meaning their actual contents will depend on the type of event you try to handle. You cannot get an x and y value for every event, not from the event object at least. If you have a mouse event you'll do something like this:
if(event.type == sf::Event::MouseMoved)
{
// do something with event.mouseMove.x and event.mouseMove.y
}
Alternatively, if you want to do this outside a mouseMoved event scope, you can always use the Mouse class. This contains a getPosition method that will return a 2d vector containing x and y:
sf::Mouse::getPosition(); //Absolute coordinates
sf::Mouse::getPosition(window); //Relative to window
Related
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?
I'm making a school project about image modifying and I'm using sfml to make something like a console but a bit more "beautiful".
while (window.isOpen()) {
Event event;
while (window.pollEvent(event)) {
if (event.type == Event::Closed)
window.close();
}
if (event.type == sf::Event::TextEntered)
{
//display text on screen
}
}
The problem is that when i press a certain key shortly on the display it appears like I've hold the key for a long period of time...
Example: pressing G, expecting to see only 1 G on the screen but on the screens there appears like 20 G.
Your if belongs inside the event polling loop:
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
window.close();
if (event.type == sf::Event::TextEntered)
{
//display text on screen
}
}
}
From your description, there is probably more going wrong, but you need to post more code to see that.
I think this is because when pressing a key that signal is always transmitted, so
try this :
sf::RenderWindow window(...);
window.setKeyRepeatEnabled(false);
while(...)
{
stuff...
}
I have main like this :
#include <SFML/Graphics.hpp>
#include <iostream>
#include "okno.h"
using namespace sf;
int main()
{
// Create the main window
RenderWindow app(VideoMode::getDesktopMode(), "Okno" ,Style::Fullscreen);
app.setKeyRepeatEnabled(false);
okno aplikacja(app);
// Start the game loop
while (app.isOpen())
{
// Process events
Event event;
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
while (app.pollEvent(event))
{
// Close window : exit
if (event.type == Event::Closed)
app.close();
if( event.type == Event::KeyPressed && event.key.code == Keyboard::Escape )
app.close();
}
aplikacja.click_przyciski(event);
aplikacja.obsluga_przyciskow();
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
aplikacja.rysuj();
aplikacja.menu=true;
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
//sleep(seconds(5));
// Update the window
//app.display();
}
return EXIT_SUCCESS;
}
And class okno.cpp like this :
#include "okno.h"
#include <iostream>
using namespace std;
int wyswietlanie =0;
okno::okno(RenderWindow &app): window(app)
{
textures[0].loadFromFile("grafika/tlo.png");
textures[1].loadFromFile("grafika/logo.png");
textures[2].loadFromFile("grafika/siatka.png");
textures[3].loadFromFile("grafika/button_start.png");
textures[4].loadFromFile("grafika/button_informacje.png");
textures[5].loadFromFile("grafika/button_wyjscie.png");
textures[6].loadFromFile("grafika/button_cofnij.png");
czcionka.loadFromFile("czcionki/czcionka_1.ttf");
for (int j=0;j<i;j++)
sprites[j].setTexture(textures[j]);
float x,y;
x=window.getView().getSize().x;
y=window.getView().getSize().y;
tekst.setString("Projekt wykonal : \n Wojciech Sorota.");
tekst.setCharacterSize(30);
tekst.setPosition(x/10,y/10);
tekst.setColor(sf::Color::Red);
tekst.setFont(czcionka);
sprites[0].setScale(x/sprites[0].getTextureRect().width,y/sprites[0].getTextureRect().height);
sprites[1].setPosition(x/2 - sprites[1].getTextureRect().width/2,y/2 - sprites[1].getTextureRect().height/2);
sprites[3].setPosition(x/10,y/10);
sprites[2].setScale(x/2/sprites[2].getTextureRect().width,y/2/sprites[2].getTextureRect().height);
sprites[2].setPosition(x/8,y/4);
sprites[4].setPosition( x/10+ sprites[3].getPosition().x + x/ 15,y/10 );
sprites[5].setPosition( x/10 +sprites[4].getPosition().x +x/15,y/10);
sprites[6].setPosition(x/10 + tekst.getPosition().x + tekst.getGlobalBounds().width,y/10);
menu=true;
}
okno::~okno()
{}
void okno::rysuj()
{
this->rysuj_intro();
this->rysuj_menu();
}
void okno::start_gra()
{
}
void okno::click_przyciski(Event &event)
{
if(event.type == Event::MouseButtonReleased && event.mouseButton.button == Mouse::Left)
{
if(click_sprite(sprites[3]))
start_gra();
else if(click_sprite(sprites[5]))
window.close();
else if( click_sprite(sprites[4]))
wyswietl_info(event);
}
}
void okno::wyswietl_info(Event &event)
{
{
while(1)
{
if(sf::Mouse::isButtonPressed(sf::Mouse::Left) && click_sprite(sprites[6]))
{
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
return;
}
window.clear();
window.draw(sprites[0]);
window.draw(sprites[2]);
window.draw(sprites[6]);
window.draw(tekst);
obsluga_przyciskow();
window.display();
}
}}
bool okno::click_sprite(Sprite a)
{
// transform the mouse position from window coordinates to world coordinates
sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));
// retrieve the bounding box of the sprite
sf::FloatRect bounds = a.getGlobalBounds();
// hit test
if (bounds.contains(mouse))
{
return true;
}
return false;
}
void okno::obluga_cofnij()
{
}
void okno::obsluga_przyciskow()
{
if(mysz_nad_sprite(sprites[3]))
sprites[3].setColor(sf::Color(100,100,100));
else
sprites[3].setColor(sf::Color(255,255,255));
if(mysz_nad_sprite(sprites[4]))
sprites[4].setColor(sf::Color(100,100,100));
else
sprites[4].setColor(sf::Color(255,255,255));
if(mysz_nad_sprite(sprites[5]))
sprites[5].setColor(sf::Color(100,100,100));
else
sprites[5].setColor(sf::Color(255,255,255));
if(mysz_nad_sprite(sprites[6]))
sprites[6].setColor(sf::Color(100,100,100));
else
sprites[6].setColor(sf::Color(255,255,255));
}
bool okno::mysz_nad_sprite(Sprite a)
{
sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));
if (a.getGlobalBounds().contains(mouse))
return true;
return false;
}
void okno::rysuj_intro()
{
if (wyswietlanie == 0)
{
for ( int n=0;n<=254;n++)
{
window.clear();
sprites[0].setColor(sf::Color(255, 255, 255, n));
sprites[1].setColor(sf::Color(255,255,255,n));
sleep(milliseconds(n/15));
window.draw(sprites[0]);
window.draw(sprites[1]);
window.display();
}
for (int n=254;n>=0;n--)
{
window.clear();
sprites[1].setColor(sf::Color(255, 255, 255, n));
sleep(milliseconds(n/15));
window.draw(sprites[0]);
window.draw(sprites[1]);
window.display();
}
wyswietlanie++;
}
}
void okno::rysuj_menu()
{
window.clear();
if (wyswietlanie==1)
for ( int n=0;n<=254;n++)
{
window.clear();
sprites[2].setColor(sf::Color(255,255,255,n));
window.draw(sprites[0]);
window.draw(sprites[2]);
window.draw(sprites[3]);
window.draw(sprites[4]);
window.draw(sprites[5]);
window.display();
if (n==254)
wyswietlanie++;
window.clear();
}
window.draw(sprites[0]);
window.draw(sprites[2]);
window.draw(sprites[3]);
window.draw(sprites[4]);
window.draw(sprites[5]);
window.display();
}
My question is why after i click on sprites[6] then i go back to loop [ pollEvent ] and then pollEvent return last event , but last event is mouseclick soo then it run script on mouseclick how to protect my function for this ?
SFML Event handling
Events should be handled something like this:
sf::Event event;
while (app.pollEvent(event))
{
// handle each event you want
switch (event.type)
{
case sf::Event::Closed:
closed(event);
Exit();
break;
case sf::Event::KeyPressed:
keyPressed(event);
break;
case sf::Event::KeyReleased:
keyReleased(event);
break;
case sf::Event::MouseButtonPressed:
mouseButtonPressed(event);
break;
case sf::Event::MouseButtonReleased:
mouseButtonReleased(event);
break;
case sf::Event::MouseMoved:
mouseMoved(event);
break;
/* ...many more events exist */
default:
cerr << "unhandle event of type: " << event.type << endl;
break;
}
}
And then, have a function for each event you want to handle.
void mouseMoved(const sf::Event& event)
{
// do something with the mouse event
mRelMousePos.x = event.mouseMove.x - mMousePos.x;
mRelMousePos.y = event.mouseMove.y - mMousePos.y;
mMousePos.x = event.mouseMove.x;
mMousePos.y = event.mouseMove.y;
}
As mentionned by #Hiura, you can't assign an event type to an sf::event and then reuse it in the pollEvent method, to be more precise, it's more the event.mouseButton.button = Mouse::Right; part that is problematic here. This is partly because the sf::Event class stores its event parameters (mouseButton, key, etc.) inside a union and partly because that's not the use intended for the sf::Event class.
Your code
Please code in english, always, you never know when you'll need to share a piece of code. And I'm not saying this because I'm a self-centered english speaking individual, in fact, I'm a french canadian.
Now, let's take a look specifically at the code you provided.
// Process events
Event event;
// these are problematic, you shouldn't do that.
//event.type=Event::JoystickButtonPressed;
//event.mouseButton.button = Mouse::Right;
while (app.pollEvent(event))
{
// using a switch or else if here would lower code repetition
// and useless check.
// Since both cases do the same thing, you could have just merge them.
// Close window : exit
if ((event.type == Event::Closed)
|| (event.type == Event::KeyPressed
&& event.key.code == Keyboard::Escape ))
{
app.close();
}
else if (event.type == Event::MouseButtonReleased
&& event.mouseButton.button == Mouse::Left)
{
// this should really go here
aplikacja.click_button(event); // thanks Google Translation
}
}
// Why? Why do you send the last event from your event loop to that?
//aplikacja.click_przyciski(event);
Some unnecessary tweaks here just for fun:
bool okno::click_sprite(Sprite sprite) // remember, meaningful names
{
// transform the mouse position from window coordinates to world coordinates
sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));
// see how it's clearer and I just removed 7-8 LOC and the comments
// are now unnecessary here. The if clause was redundant since the contains
// method already returns a bool value.
return sprite.getGlobalBounds().contains(mouse);
}
I'm not going to go through the entire code, but you are close to a working app with SFML. There is some nice tutorials and the SFML source code is quite clear, see the SFML Github repo and the SFML game dev book for more info on how to use each part of SFML.
I am using SFML and C++ and I am getting an odd problem,
Here is my main game update method
while (renderService.Window.isOpen())
{
//Poll events
sf::Event event;
while (renderService.Window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
renderService.Window.close();
running = false;
}
MouseMovment(event);
MouseClick(event);
Update();
Draw();
}
and here is my MouseClick method
void Game::MouseClick(sf::Event event)
{
sf::Vector2i position = sf::Mouse::getPosition(renderService.Window);
if (event.mouseButton.button == sf::Mouse::Left && event.type == sf::Event::MouseButtonReleased)
{
std::cout << "Mouse released" << std::endl;
}
}
now here is the weird part, in my console sometimes my cout will be spammed like 10/20 times, but sometimes it will work perfectly, am I calling the event wrongly?
You're doing it wrong, suppose that a MouseButtonReleased event is fired and your polling function grabs it (follows the numbers in the comments):
while (renderService.Window.isOpen()) // 4) The loop starts again
{
//Poll events
sf::Event event;
while (renderService.Window.pollEvent(event)) // 1) Grabs the event // 5) No more events
{
if (event.type == sf::Event::Closed) // 2) Nope, it's not this one
renderService.Window.close();
running = false;
}
MouseMovment(event);
MouseClick(event); // 3) Yes, handle it // 6) Uses the unmodified event variable - undefined behavior
Update();
Draw();
}
you should rather do something like:
sf::Event event;
// while there are pending events...
while (window.pollEvent(event))
{
// check the type of the event...
switch (event.type)
{
// window closed
case sf::Event::Closed:
...
break;
// mouse button released
case sf::Event::MouseButtonReleased:
{
if (event.mouseButton.button == sf::Mouse::Left)
...
} break;
// we don't process other types of events
default:
break;
}
}
In SFML 2.1 on c++, is there a sf::Keyboard function that checks if any letter in the alphabet being pressed?
I know how to check if a certain key is pressed, like this:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key))
Do I have to type all this:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)&&sf::Keyboard::isKeyPressed(sf::Keyboard::B)&&sf::Keyboard::isKeyPressed(sf::Keyboard::C))
...all the way to sf::Keyboard::Z,
Or is there an easier way?
From the SFML website:
Many programmers use the KeyPressed event to get user input, and start to implement crazy algorithms that try to interpret all the possible key combinations to produce correct characters. Don't do that!
sf::Keyboard::isKeyPressed is for checking whether a key is pressed, which is good for things like movement: as long as the player is holding the 'left' key down, we wish to keep moving their character left. A KeyPressed event is for checking which key is pressed at the time it is pressed, which is good for things that happen only once: if the player jumps with the spacebar, we typically don't want them to keep jumping as long as the spacebar is held down.
When it comes to checking entered text, though, neither of these solutions are very good. In the official tutorials, we are advised against using these for checking text input - we have actually been given a different event for exactly this type of situation. The appropriate thing to do is to get the text-based contents of the key via the TextEntered event as described here. Get the text from the event then apply the logic you need to ensure its validity, or (if possible) use the text from the event directly.
Here's a solution with a counter increased every time when a letter key is pressed. window.setKeyRepeatEnabled() must be set to false to avoid getting multiple events while pressing a key:
#include <SFML/Graphics.hpp>
#include <iostream>
int main() {
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML");
int keyCounter = 0;
window.setKeyRepeatEnabled(false);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
else if(event.type == sf::Event::KeyPressed) {
if(event.key.code >= sf::Keyboard::A && event.key.code <= sf::Keyboard::Z) {
keyCounter++;
}
} else if(event.type == sf::Event::KeyReleased) {
if(event.key.code >= sf::Keyboard::A && event.key.code <= sf::Keyboard::Z) {
keyCounter--;
}
} else if(event.type == sf::Event::MouseMoved) {
/* move cursor inside the window to observe how the counter
behaves while pressing the keys */
std::cout << keyCounter << std::endl;
}
}
window.clear();
window.display();
}
return 0;
}
Alternative approach - iterating over enum:
#include <SFML/Graphics.hpp>
#include <iostream>
int main() {
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML");
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
} else if(event.type == sf::Event::MouseButtonPressed) {
/* click inside window to see if there is key pressed */
bool isp = false;
for (int i = sf::Keyboard::A; i <= sf::Keyboard::Z; ++i ) {
if(sf::Keyboard::isKeyPressed(static_cast<sf::Keyboard::Key>(i))) {
isp = true;
break;
}
}
std::cout << isp << std::endl;
}
}
window.clear();
window.display();
}
return 0;
}