ClickEvent not being detected SDL - sdl

I know I must be being stupid but for the life of me I can't see it.
What's wrong with
while(SDL_PollEvent(&mEvent))
{
if(mEvent.type == SDL_MOUSEBUTTONDOWN)
{
if(mEvent.button.button == SDL_BUTTON_LEFT)
{
handleClicking();
}
}
}
I've slapped a breakpoint at the if(mEvent.type == SDL_MOUSEBUTTONDOWN) and it's never being hit. Any ideas?

Related

Multiple key presses SFML

I'm trying to detect keyPress only once, but it goes for random amount of presses. I'm using keyrelease, and it work normally if I have breakpoint.
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
} else {
characterScreen.handleEvent(event, window);
}
}
bool keyReleased = event.type == sf::Event::KeyPressed;
bool rightArrowKey = event.key.code == sf::Keyboard::Right;
bool leftArrowKey = event.key.code == sf::Keyboard::Left;
if (keyReleased&&leftArrowKey)
{
if (selectedCharacter == 0)
{
selectedCharacter = characterList.size() - 1;
}
else
{
selectedCharacter--;
}
changeCharacters(characterList[selectedCharacter], font, characterScreen);
std::cout << "left pressed" << std::endl;
keyReleased = false;
std::cout << keyReleased << std::endl;
}
else if (keyReleased && rightArrowKey)
{
if (selectedCharacter == characterList.size()-1)
{
selectedCharacter = 0;
}
else
{
selectedCharacter++;
}
changeCharacters(characterList[selectedCharacter], font, characterScreen);
}
window.clear(sf::Color::White);
characterScreen.update();
characterScreen.render(window);
window.display();
}
I've tryed window.setKeyRepeatEnabled(false); and keypressed, still nothing. Tryed different keyboard aswell.
When using (C)SMFL, we generally have a main loop condition rendering the main frame (the windows) and checking events, it can be an infinite loop (such as while (1)) or a more recomanded one like your while (window.isOpen()).
It means that the windows and all events listener are refreshed / updated each loop's turn, so if you press a key on your keyboard, you will trigger your keyboard's event listener, fine, and you will continue your code until re-enter in your main loop, and re-refreshing the windows and re-updating your event listener.
What the point of explaining that ? it just means by only pressing once a key, your computer will process maybe 10, 100 or maybe 1000 iteration of your main loop (depending on it's performances and more). So it's "normal" to works fine when you use convenient features like breakpoints, but in reality you can't.
You have a lot of possibilities, bad ones (like "use delay / pause" who's not recommended since it will halt your window's refresh and can be interpreted by a crash by your OS) or good ones like tampon variables, who'll cancel the entrance of some conditions by their state:
Example:
bool tmp_var = false;
while (window.isOpen()) {
// Warn, you called your variable keyReleased but it check keyPressed
if (event.type == sf::Event::KeyPressed && tmp_var == false) {
// Check wich key is pressed and perform required actions
tmp_var = true;
} else if (event.type == sf::Event::KeyReleased) {
tmp_var = false;
}
}
Note that the code can be not correct, I wanted to point out the reasoning

SDL2_pollevent() Controller dpad continuous hold?

I'm trying to register controller button/dpad presses and continuous hold of said buttons that way it spits the output out continuously instead of one press at a time and then exiting the poll event loop. Right now I have a small piece of dummy code that I'm trying to print in a stream if I hold a button down. Any assistance into this issue?
while( !quit_program )
{
//Handle events on queue
while( SDL_PollEvent( &e ))
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit_program = true;
}
else if(e.type == SDL_CONTROLLERBUTTONDOWN)
{
count++;
cout<<"button pushed# "<<count<<endl;
}
}
}
Until you get a SDL_CONTROLLERBUTTONUP (for the same button of course) you can consider the button as being pressed. Then to count you could do something like this (for a single button):
bool that_button_pressed{false};
while(!quit_program) {
//Handle events on queue
while(SDL_PollEvent(&e)) {
// User requests quit
if(e.type == SDL_QUIT)
quit_program = true;
if (e.type == SDL_CONTROLLERBUTTONDOWN && e.button == a_button_of_your_choice) {
that_button_pressed = true;
}
if (e.type == SDL_CONTROLLERBUTTONUP && e.button == a_button_of_your_choice) {
that_button_pressed = false;
}
}
if (that_button_pressed) {
count++;
// Print or implement your logic
}
}
Of course this counter would also depend on your loop timings. Here that_button_pressed would represent one of the SDL_GameControllerButton's.

C++ SFML - How to read two keys in SFML pressed at the same time?

I made a very simple two player game in which one person is the jellyfish, and the other is the shark in SFML. The only problem with it is that only one sprite can move at once. Is this possible to fix and how can I fix it?
EDIT: My attempt is this:
if (event.type == sf::Event::KeyPressed)
{
bool D;
bool A;
bool S;
bool W;
bool Up;
bool Right;
bool Left;
bool Down;
if (event.key.code == sf::Keyboard::A)
A = true;
if (event.key.code == sf::Keyboard::D)
D = true;
if (event.key.code == sf::Keyboard::W)
W = true;
if (event.key.code == sf::Keyboard::S)
S = true;
if (event.key.code == sf::Keyboard::Left)
Left = true;
if (event.key.code == sf::Keyboard::Right)
Right = true;
if (event.key.code == sf::Keyboard::Up)
Up = true;
if (event.key.code == sf::Keyboard::Down)
Down = true;
if (D and Right)
{
jelly.move(10, 0)
}
...
}
Alternatively, you can use sf::Keyboard::isKeyPressed to probe the state of the keyboard at a given point.
One issue with your current code is that all the variables are local to the if-statement and therefore reinitialised when processing the next event. They should be defined outside the if. Another problem is that you don't handle the KeyReleased event.
You solve it by having a flag that is set when one key is pressed, and cleared when the key is released. Then you can check this flag when the other key is pressed.

SFML - pollEvent double run mouseclick

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.

Why does SDL_NumJoysticks() never update?

I was writing a small program in C that utilizes SDL 2.0, and ran into a problem when I couldn't get SDL_NumJoysticks() to report the number of joysticks plugged in at the time of the function call. I believe that it is reporting the number of joysticks connected during one of SDL's initialization functions (I would guess 'SDL_Init()', but I have no evidence), and then keeps on giving you that number throughout the rest of the program. Here is a short test program that I have been using:
#include <stdio.h>
#include <SDL2/SDL.h>
int main() {
SDL_Event event;
SDL_Window *window;
short joysticks = 0;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
fprintf(stderr, "SDL_Init error: %s\n", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("Test window", 0, 0, 800, 600, SDL_WINDOW_SHOWN);
if (window == NULL) {
fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError());
return 1;
}
printf("%s\n", SDL_GetError());
while (1) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
printf("%s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
} else if (event.type == SDL_JOYDEVICEADDED) {
printf("Joystick added!\n");
} else if (event.type == SDL_JOYDEVICEREMOVED) {
printf("Joystick removed!\n");
}
}
if (SDL_NumJoysticks() > joysticks) {
printf("Joystick inserted.\n");
joysticks++;
} else if (SDL_NumJoysticks() < joysticks && SDL_NumJoysticks() >= 0) {
printf("Joystick removed.\n");
joysticks--;
} else if (SDL_NumJoysticks() < 0) {
printf("Something went wrong!\n");
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
return 0;
}
The program accurately reports the number of joysticks plugged in when the program is started, but does absolutely nothing after that.
The official SDL docs for SDL_Numjoysticks() state that it "Returns the number of attached joysticks on success". How can I get it to tell me the number of joysticks plugged in at the time of the function call? Am I making a mistake in my code, or is that just not the way that SDL_NumJoysticks() works?
Make sure you follow these steps and see if you still have problems:
Call SDL_JoystickEventState(SDL_ENABLE) after SDL_INIT
If that is not enough, try to force an update by calling SDL_JoystickUpdate(); before while (SDL_PollEvent(&event))
EDIT: More info that I think should be useful:
Always call SDL_PollEvent on the Main Thread (Or SDL_PumpEvents() on Main Thread and SDL_PeepEvents elsewhere)
If you dont do that, SDL wont update the number of joysticks nor hotplug events
Other joystick events work when you pump outside the Main thread but it is not recommended.