Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Handle multiple pressed Keys in a switch statement  (Read 7714 times)

0 Members and 1 Guest are viewing this topic.

valenciano

  • Newbie
  • *
  • Posts: 16
    • View Profile
Handle multiple pressed Keys in a switch statement
« on: May 12, 2018, 05:28:39 pm »
Hello !

I'd like to design a little game in which, a little ship (a Triangle) would move on the screen.
The problem is that I'd like to make the ship rotate when multiple keys are pressed (see below).

But the compiler refuses :

make all (in directory: /home//Desktop/C++)
g++ -c main.cpp Game.cpp Ship.cpp
Game.cpp: In member function ‘void Game::run()’:
Game.cpp:56:6: error: duplicate case value
      case((sf::Keyboard::Down) && (sf::Keyboard::Right)):
      ^~~~
Game.cpp:53:6: note: previously used here
      case((sf::Keyboard::Up) && (sf::Keyboard::Left)):
      ^~~~
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 1
Compilation failed.
 

void Game::run()
{
        window.create(sf::VideoMode(800,600), "Test", sf::Style::Default);
                window.setVerticalSyncEnabled(true);
       
        std::unique_ptr<Ship> player = std::make_unique<Ship>(10,10,40);
       
        while(window.isOpen() == true)
        {
                sf::Event ev;
               
                while(window.pollEvent(ev) == true)
                {
                        if(ev.type == sf::Event::Closed)
                        {
                                window.close();
                        }
                        if(ev.type == sf::Event::KeyPressed)
                        {
                                switch(ev.key.code)
                                {
                                        case(sf::Keyboard::Escape):
                                                window.close();
                                                break;
                                        case(sf::Keyboard::Up):
                                                player->move_y(-10);
                                                break;
                                        case(sf::Keyboard::Down):
                                                player->move_y(10);
                                                break;
                                        case(sf::Keyboard::Left):
                                                player->move_x(-10);
                                                break;
                                        case(sf::Keyboard::Right):
                                                player->move_x(10);
                                                break;
                                        case((sf::Keyboard::Up) && (sf::Keyboard::Left)):
                                                player->rotate(10);
                                                break;
                                        case((sf::Keyboard::Down) && (sf::Keyboard::Right)):
                                                player->rotate(-10);
                                                break;
                                        default:
                                                break;
                                }
                        }
                }
               
                window.clear(sf::Color::Black);
                player->drawOn(&window);
                window.display();
        }
}

Regards

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Handle multiple pressed Keys in a switch statement
« Reply #1 on: May 12, 2018, 09:15:54 pm »
A 'case' in a 'switch' is not an expression, it must be a single compile-time integral constant.

The syntax to execute the same code for multiple constants is:
case sf::Keyboard::Up:
case sf::Keyboard::Left:
   ...
   break;

But since you already have different code for these constants alone, this won't work as you can't have the same constant multiple times in the same 'switch'. So maybe a sequence of 'if'/'else if' is better in this case.
« Last Edit: May 12, 2018, 09:17:54 pm by Laurent »
Laurent Gomila - SFML developer

valenciano

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Handle multiple pressed Keys in a switch statement
« Reply #2 on: May 12, 2018, 10:46:00 pm »
Thanks for your answer Laurent,

I changed my code but there is no rotations when I simultaneously press Up and Left for example.

sf::Event ev;
               
                while(window.pollEvent(ev) == true)
                {
                        if(ev.type == sf::Event::Closed)
                        {
                                window.close();
                        }
                        if(ev.type == sf::Event::KeyPressed)
                        {
                               
                                switch(ev.key.code)
                                {
                                        case(sf::Keyboard::Escape):
                                                window.close();
                                                break;
                                        case(sf::Keyboard::Up):
                                                player->move_y(-10);
                                                break;
                                        case(sf::Keyboard::Down):
                                                player->move_y(10);
                                                break;
                                        case(sf::Keyboard::Left):
                                                player->rotate(10);
                                                break;
                                        case(sf::Keyboard::Right):
                                                player->move_x(10);
                                                break;
                                }
                                if((ev.key.code == sf::Keyboard::Up) && (ev.key.code == sf::Keyboard::Left))
                                {
                                                player->rotate(10);
                                }
                                if((ev.key.code == sf::Keyboard::Down) && (ev.key.code == sf::Keyboard::Right))
                                {
                                                player->rotate(10);
                                }
                        }
                }

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Handle multiple pressed Keys in a switch statement
« Reply #3 on: May 13, 2018, 08:50:58 am »
How do you expect a single variable to be equal to 2 different values at the same time? ::)

This logic cannot be tested in the event loop, you should rather use real-time keyboard state (see sf::Keyboard) outside the event loop.
Laurent Gomila - SFML developer

valenciano

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Handle multiple pressed Keys in a switch statement
« Reply #4 on: May 13, 2018, 03:52:10 pm »
Ahah yeah you are right !

I reviewed my code, here are the changes :

#include <iostream>
#include <SFML/Graphics.hpp>
#include <memory>
#include "Game.hpp"
#include "Ship.hpp"

Game::Game()
{
        std::cout << "Object created : Game" << std::endl;
}

Game::~Game()
{
        std::cout << "Object destroyed : Game" << std::endl;
}

void Game::run()
{
        window.create(sf::VideoMode(800,600), "Test", sf::Style::Default);
                window.setVerticalSyncEnabled(true);
       
        std::unique_ptr<Ship> player = std::make_unique<Ship>(10,10,40);
       
        while(window.isOpen() == true)
        {
                sf::Event ev;
               
                while(window.pollEvent(ev) == true)
                {
                        if(ev.type == sf::Event::Closed)
                        {
                                window.close();
                        }
                        if(ev.type == sf::Event::KeyPressed)
                        {
                                //Escape
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                                {
                                        window.close();
                                }
                                //Left + !(Up && Down)
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) == false)
                                {
                                                player->move_x(-10);
                                }
                                //Left + (Up && Down)
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) == true)
                                {
                                                player->rotate(10);
                                }
                                //Right + !(Up && Down)
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) == false)
                                {
                                                player->move_x(10);
                                }
                                //Right + (Up && Down)
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) == true )
                                {
                                                player->rotate(10);
                                }
                                //Down + !(Left && Right)
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) == false)
                                {
                                                player->move_y(10);
                                }
                                //Up + !(Left && Right)
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) == false )
                                {
                                                player->move_y(-10);
                                }
                               
                        }
                }
               
                window.clear(sf::Color::Black);
                player->drawOn(&window);
                window.display();
        }
}
 

Now it works, but the idea would be to to rotations and not to move on the left or the right. How can I do it ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Handle multiple pressed Keys in a switch statement
« Reply #5 on: May 13, 2018, 06:14:53 pm »
As I said, you should do it outside the event loop.

Quote
Now it works, but the idea would be to to rotations and not to move on the left or the right. How can I do it ?
That's what the 'else' keyword is for ;)

You should really take the time to think about it and rewrite your code correctly. I think you're lost in your conditions, because to me they don't make sense (and the implementation doesn't even match the comments).
Laurent Gomila - SFML developer

valenciano

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Handle multiple pressed Keys in a switch statement
« Reply #6 on: May 14, 2018, 01:21:17 am »
Great this time it works for good !

//Left : If Left Key is pressed
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
        //Left rotation: If Left + Either Down or Up are pressed
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)))
        {
                player->rotate(10);
        }
        else
        {
                player->move_x(-10);
        }
}

//Right : If Right Key is pressed
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
        //Right rotation : If Right + Either Down or Up are pressed
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)))
        {
                player->rotate(-10);
        }
        else
        {
                player->move_x(10);
        }
}

//Up : If only Up Key is pressed
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) == false && sf::Keyboard::isKeyPressed(sf::Keyboard::Right) == false))
{
        player->move_y(-10);
}

//Down : If only Down Key is pressed
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) == false && sf::Keyboard::isKeyPressed(sf::Keyboard::Right) == false))
{
        player->move_y(10);
}

How can I make the game smoother ? Because it doesn't feel that smooth when I play with the ship : I'd like to move the ship with just the key pressed one time without that repeated effect (kind of delay between movements)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Handle multiple pressed Keys in a switch statement
« Reply #7 on: May 14, 2018, 06:36:53 am »
No, I won't say it a 3rd time. Please read my previous replies carefully.
Laurent Gomila - SFML developer

valenciano

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Handle multiple pressed Keys in a switch statement
« Reply #8 on: May 14, 2018, 02:17:35 pm »
"Outside the event loop" -> Got it !  ;)

void Game::run()
{
        window.create(sf::VideoMode(800,600), "Test", sf::Style::Default);
                window.setVerticalSyncEnabled(true);
               
        sf::SoundBuffer buffer;
       
        if(!buffer.loadFromFile("ship.ogg"))
        {
                std::cerr << "Failed to load ship sound" << std::endl;
        }
        else
        {
                std::unique_ptr<Ship> player = std::make_unique<Ship>(10,10,40);
               
                sf::Sound ship_sound;
                        ship_sound.setBuffer(buffer);
       
                while(window.isOpen() == true)
                {
                        sf::Event ev;
                       
                        while(window.pollEvent(ev) == true)
                        {
                                if(ev.type == sf::Event::Closed)
                                {
                                        window.close();
                                }
                                if(ev.type == sf::Event::KeyPressed)
                                {
                                        if(ev.key.code == sf::Keyboard::Escape)
                                        {
                                                window.close();
                                        }
                                }
                        }
                       
                        //Left : If only Left Key is pressed
                        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        {
                                //Left rotation: If Left + Either Down or Up are pressed
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)))
                                {
                                        player->rotate(10);
                                }
                                else
                                {
                                        player->move_x(-10);
                                }
                        }
                       
                        //Right : If only Right Key is pressed
                        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                        {
                                //Right rotation : If Right + Either Down or Up are pressed
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)))
                                {
                                        player->rotate(-10);
                                }
                                else
                                {
                                        player->move_x(10);
                                }
                        }

                        //Up : If only Up Key is pressed
                        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) == false && sf::Keyboard::isKeyPressed(sf::Keyboard::Right) == false))
                        {
                                player->move_y(-10);
                        }
                       
                        //Down : If only Down Key is pressed
                        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) == false && sf::Keyboard::isKeyPressed(sf::Keyboard::Right) == false))
                        {
                                player->move_y(10);
                        }
                       
                        window.clear(sf::Color::Black);
                        player->drawOn(&window);
                        window.display();
                }
        }
}

It's smooth now !

Tigre Pablito

  • Full Member
  • ***
  • Posts: 226
    • View Profile
    • Email
Re: Handle multiple pressed Keys in a switch statement
« Reply #9 on: May 16, 2018, 03:52:06 pm »
                        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        {
                                //Left rotation: If Left + Either Down or Up are pressed
                                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)))
                                {
                                        player->rotate(10);
                                }
                                else
                                {
                                        player->move_x(-10);
                                }
                        }

The first 'if' is not necesary because you check if Left is pressed in the 2nd one  ;) . Same with the check of the Right key

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Handle multiple pressed Keys in a switch statement
« Reply #10 on: May 16, 2018, 04:57:47 pm »
Quote
The first 'if' is not necesary because you check if Left is pressed in the 2nd one
Wrong. If you remove the first 'if', then the 'else' will execute in different conditions.
Laurent Gomila - SFML developer