-
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
-
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.
-
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);
}
}
}
-
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.
-
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 ?
-
As I said, you should do it outside the event loop.
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).
-
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)
-
No, I won't say it a 3rd time. Please read my previous replies carefully.
-
"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 !
-
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
-
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.