Detect only one keypress in C++ - c++

I'm trying to use the glut framework to handle keypresses for a game I'm writing in c++. When a specific key is pressed, I want to start drawing a new curve and so I create a new curve and add it to my container of curves. However, when I use onKeyboard and debug I see that this function is called over and over when a key is pressed, not just on the initial press. Therefore, it's creating about 12 curves every time a key is pressed. My code for onKeyboard is below. Any help would be appreciated greatly!
void onKeyboard(unsigned char key,int x, int y) {
keysPressed[key] = true;
switch (key) {
case 'l':
curvesContainer.addCurve(new lCurve());
break;
case 'p':
curvesContainer.addCurve(new pCurve());
}
glutPostRedisplay();
}

You would simply check if keyPressed[key] is already true, and only add your curve if it is false.
void onKeyboard(unsigned char key,int x, int y)
{
if (keysPressed[key] == false)
{
keysPressed[key] = true;
switch (key)
{
case 'l':
curvesContainer.addCurve(new lCurve());
break;
case 'p':
curvesContainer.addCurve(new pCurve());
break;
}
}
glutPostRedisplay();
}
You will additionally need to clear keysPressed[key] in an onKeyUp event, using glutKeyboardUpFunc
void onKeyUp(unsigned char key,int x, int y)
{
keysPressed[key] == false;
}

glutIgnoreKeyRepeat(1) is probably what you want. (1 = on)

Use input flush define in studio.in
It avoid rest of input

Related

Clueless about how to use switch

this is my very first post :)
I'm a graphic design student in my second year and we have to make code for business cards.
What I want is when I click with my mouse the background of the business card will change.
It worked with a boolean for two pictures.
But now I want it to work with four images.
Have asked the teacher for help and she sent me information about Switch.
But I have no idea where to put in my code and how to fill it in.
This is my code so far
String Instagram="#Famoys_Saz";
String quote = "Guess my passion ;)";
PFont font;
PImage bg;
PImage Snake2;
PImage snake3;
PImage snake4;
boolean click = true;
void setup() {
size(850, 550);
font = createFont("Galaxyfaceano-4yM9.ttf", 45);
textFont(font);
textAlign(CENTER);
bg = loadImage("Snake.jpg");
Snake2= loadImage ("Snake2.jpg");
click = true;
}
void draw() {
background(bg);
if (click == true ) {
image(bg, 0, 0);
} else {
image(Snake2, 0, 0);
}
text(Instagram, mouseX, mouseY);
text(quote, mouseY, mouseX, 05);
}
void mousePressed() {
click =! click;
}
and this is the code my teacher send me:
if( imageNumber == 1 ) {
} else if ( imageNumber == 2 ) {
} else {
}
Could someone help me out? I'm quite a beginner when it comes to coding.
it will look something like this:
switch( imageNumber ) {
case 1: // same as saying imageNumber == 1
//some code
break;
case 2: // same as saying imageNumber == 2
//some code here
break;
}
switch(imageNumber) {
case 1:
// do stuff
break;
case 2:
// do stuff
break;
case 3:
// do stuff
break;
case 4:
// do stuff
break;
default:
// if no case was selected, do this
}
Switches are easy to read and efficient, and some programmers prefers them to else if. Both are fine, as long as they are readable, but the switch has some unique particularities, like having to use break; between cases. The break; will exit the switch, else it would evaluate every other possible case (thus you're saving some execution time).
It happened to me in a robotic project to deliberately skip the break; statement so the robot would do "everything from this point on", but it's very uncommon and a source of many beginner's bugs to forget the break;.
Depending on the language, switches can evaluate different things, but the classics are integers and strings.
Have fun!

C++ How do I Handle all possible Player Movement inputs?

I am trying to clean up movement code I followed from a video tutorial series that was never finished. My intent is for the character to only ever be able to move on X or Y at any given time (so no diagonal). The character has direction facing to keep in mind.
My issue is the player can still press any key they want, or accidently press two keys at the same time.
Ex. if you move Up and make a right turn, accidentally press Right before letting go of Up.
Or if you press Up, press and let go Right to make a slight movement right while continuing to press Up, the player should continue to move up after letting go of Right without having to re-press Up. etc.
Just to make sure all possible input cases are handled intuitively.
EDIT: This is the code so far and I'm getting weird errors I don't know what's wrong
#pragma once
#include "../game.h"
#include "ECS.h"
#include "Components.h"
#include <list>
using namespace std;
class KeyboardController : public Component
{
public:
TransformComponent *transform;
SpriteComponent *sprite;
std::list<SDL_Event> keyDownList;
SDL_Event lastDirection;
void updateKeyState()
{
if (Game::event.type == SDLK_ESCAPE) {
Game::isRunning = false;
}
else if (Game::event.type == SDL_KEYDOWN) {
keyDownList.push_back(Game::event.key.keysym.sym);
}
else if (Game::event.type == SDL_KEYUP) {
keyDownList.remove(Game::event.key.keysym.sym);
}
}
void init() override
{
transform = &entity->getComponent<TransformComponent>();
sprite = &entity->getComponent<SpriteComponent>();
}
void update() override
{
void updateKeyState();
void updateMovement();
}
};
Severity Code Description Project File Line Suppression State
Error (active) E0304 no instance of overloaded function "std::list<_Ty, _Alloc>::push_back [with _Ty=SDL_Event, _Alloc=std::allocator]" matches the argument list Sandbox C:\file_path\KeyboardController.h 31
Severity Code Description Project File Line Suppression State
Error (active) E0415 no suitable constructor exists to convert from "SDL_Keycode" to "SDL_Event" Sandbox C:\file_path\KeyboardController.h 34
You should basically clean up your code by separating the logic between key events and player movement. So your update() method could look like this:
void update() override
{
updateKeyState();
updateMovement();
}
Since you want the player to move only vertically or horizontally (never diagonally), you have to store the key press order in a data structure that can be easily accessed. I think you could use a doubly-linked list:
std::list<SDL_Event> keyDownList;
and we should also store the last key pressed in order to restore the idle animation of the player:
SDL_Event lastDirection;
The updateKeyState() method should add or remove the key to/from the linked list. We should also check if the player wants to leave the game by pressing ESC:
void updateKeyState() {
if (Game::event.type == SDLK_ESCAPE) {
Game::isRunning = false;
} else if (Game::event.type == SDL_KEYDOWN) {
keyDownList.push_back(Game::event.key.keysym.sym);
} else if (Game::event.type == SDL_KEYUP) {
keyDownList.remove(Game::event.key.keysym.sym);
}
}
The updatePlayerMovement() method is where the magic happens. We should basically check which key was pressed first and update the player position accordingly. We also save the down key in the lastDirection field in order to use it when no key is pressed.
void updateMovement() {
// if any key is down
if (keyDownList.size() > 0) {
const SDL_Event downKey = keyDownList.front();
switch (downKey) {
case SDLK_w:
transform->velocity.y = -1;
transform->velocity.x = 0;
sprite->Play("BackWalk");
lastDirection = downKey;
break;
case SDLK_a:
transform->velocity.x = -1;
transform->velocity.y = 0;
sprite->Play("SideWalk");
sprite->spriteFlip = SDL_FLIP_HORIZONTAL;
lastDirection = downKey;
break;
case SDLK_s:
transform->velocity.y = 1;
transform->velocity.x = 0;
sprite->Play("FrontWalk");
lastDirection = downKey;
break;
case SDLK_d:
transform->velocity.x = 1;
transform->velocity.y = 0;
sprite->Play("SideWalk");
sprite->spriteFlip = SDL_FLIP_NONE;
lastDirection = downKey;
break;
}
} else {
// no key is down, handle idle situations
transform->velocity.x= 0;
transform->velocity.y = 0;
switch (lastDirection) {
case SDLK_w:
sprite->Play("BackIdle");
break;
case SDLK_a:
sprite->Play("SideIdle");
break;
case SDLK_s:
sprite->Play("FrontIdle");
break;
case SDLK_d:
sprite->Play("SideIdle");
break;
}
}
}
Note: I haven't tested this code because I don't have the code and structures from your game. So you may have to edit a piece here and there to make it work for you.

Check Q button is held down using GLUT?

What function can I use to check if the Q button (or any other button is pressed down) and what will be the value needed to specify this for the Q button?
Using glut you need to define a Keyboard Handler function, and tell GLUT to use it for handling key strokes. Something along the lines of:
bool is_q_pressed = false;
void KeyboardHandler(unsigned char key, int x, int y)
{
switch (key)
{
case "q":
case "Q":
is_q_pressed = !is_q_pressed;
if (is_q_pressed)
// do something... or elsewhere in program
break;
}
}
void KeyboardUpHandler(unsigned char key, int x, int y)
{
switch (key)
{
case "q":
case "Q":
is_q_pressed = false;
break;
}
}
int main()
{
// Other glut init functions...
...
// Keyboard handler
glutKeyboardFunc(KeyboardHandler);
// Keyboard up handler
glutKeyboardUpFunc(KeyboardUpHandler);
...
glutMainLoop();
return 0;
}
EDIT: Added support for keyboard up. Using global variables isn't the best practice, but GLUT almost forces you to use them to keep track of program states. The good thing is that you can use the global variable (is_q_pressed) anywhere in your program... like in the idle() for some logic, or in the draw function to draw something if that key is pressed.
And, as #aslg said, you can make an array of bools to keep track of every key pressed, check his answer for ideas too :)
The simplest thing you can do is to use an array of bools with enough bools to contain the 256 regular keys and the special keys (right, left, etc.. ).
bool keys[256];
Use the KeyDown func to set the matching key to true, and KeyUp to set false.
void KeyboardDown( int key, int x, int y ) {
if ( isalpha( key ) ) {
key = toupper( key );
}
keys[ key ] = true;
}
void KeyboardUp( int key, int x, int y ) {
if ( isalpha( key ) ) {
key = toupper( key );
}
keys[ key ] = false;
}
The toupper just makes sure that pressing q or Q is the same whether Caps-lock is on or off. You don't have to use it if you don't need it.
Then somewhere in the update code you can check if a key was pressed like
if ( keys['Q'] ) {
// do things
}

Handling key events in SDL and C++

I'm in the process of migrating a program from GLUT to SDL. In my current program pressing the a key results in a different response then pressing the A key. This was pretty straightforward to do in GLUT as it the keyboard function callback passed in the ASCII value of the key that was pressed.
void keyPressedFn(unsigned char key, int x, int y){
switch(key){
case 'a':
// do work for a
break;
case 'A':
// do work for A
break;
}
}
I'm struggling to replicate similar functionality in SDL as pressing the a key produces the same response regardless of if SHIFT or CAPS LOCK are pressed as well.
Is there a simple way of replicating the above function in SDL?
Edit: In the example above I only show how to handle one key, in practice however, I am going to have a list of about 15 keys that I want to respond to differently if the shift key is pressed as well.
Check the keyboard modifiers that are present when you get a keydown event. For example:
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_a)
{
if(event.key.keysym.mod & KMOD_SHIFT)
{
// Handle 'A'
}
else
{
// Handle 'a'
}
}
break;
...
}
}
SDL_keysym has mod field, which contains state of modifier keys at the time the event has been emitted. Bit-AND it with KMOD_SHIFT to check whether Shift has been active. See SDL wiki.
Why not just do this?
void keyPressedFn(unsigned char key, int x, int y){
switch(key){
case 'a':
case 'A':
// do work for A or a
break;
}
}
Do you have some other concerns that you cannot do as what I have suggested? If not I think this is as simple as it can get.

How to handle multiple keypresses at once with SDL?

been getting myself familiar with OpenGL programming using SDL on Ubuntu using c++. After some looking around and experimenting I am starting to understand. I need advice on keyboard event handling with SDL.
I have a 1st person camera, and can walk fwd, back, strafe left and right and use the mouse to look around which is great. Here is my processEvents function:
void processEvents()
{
int mid_x = screen_width >> 1;
int mid_y = screen_height >> 1;
int mpx = event.motion.x;
int mpy = event.motion.y;
float angle_y = 0.0f;
float angle_z = 0.0f;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
quit = true;
break;
case SDLK_w:
objCamera.Move_Camera( CAMERASPEED);
break;
case SDLK_s:
objCamera.Move_Camera(-CAMERASPEED);
break;
case SDLK_d:
objCamera.Strafe_Camera( CAMERASPEED);
break;
case SDLK_a:
objCamera.Strafe_Camera(-CAMERASPEED);
break;
default:
break;
}
break;
case SDL_MOUSEMOTION:
if( (mpx == mid_x) && (mpy == mid_y) ) return;
SDL_WarpMouse(mid_x, mid_y);
// Get the direction from the mouse cursor, set a resonable maneuvering speed
angle_y = (float)( (mid_x - mpx) ) / 1000;
angle_z = (float)( (mid_y - mpy) ) / 1000;
// The higher the value is the faster the camera looks around.
objCamera.mView.y += angle_z * 2;
// limit the rotation around the x-axis
if((objCamera.mView.y - objCamera.mPos.y) > 8) objCamera.mView.y = objCamera.mPos.y + 8;
if((objCamera.mView.y - objCamera.mPos.y) <-8) objCamera.mView.y = objCamera.mPos.y - 8;
objCamera.Rotate_View(-angle_y);
break;
case SDL_QUIT:
quit = true;
break;
case SDL_VIDEORESIZE:
screen = SDL_SetVideoMode( event.resize.w, event.resize.h, screen_bpp, SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE );
screen_width = event.resize.w;
screen_height = event.resize.h;
init_opengl();
std::cout << "Resized to width: " << event.resize.w << " height: " << event.resize.h << std::endl;
break;
default:
break;
}
}
}
now while this is working, it has some limitations. The biggest one and the purpose of my question is that it seems to only process the latest key that was pressed. So if I am holding 's' to walk backwards and I press 'd' to strafe right, I end up strafing right but not going backwards.
Can someone point me in the right direction for better keyboard handling with SDL, support for multiple keypresses at once, etc?
Thanks
SDL keeps track of the current state of all keys. You can access this state via:
SDL_GetKeyState()
So, each iteration you can update the movements based on the key state. To make the movement smooth you should update the movement magnitude based on the time elapsed between updates.
A good approach will be to write a keyboard ("input") handler that will process input events and keep the event's state in some sort of a structure (associative array sounds good - key[keyCode]).
Every time the keyboard handler receives a 'key pressed' event, it sets the key as enabled (true) and when it gets a key down event, it sets it as disabled (false).
Then you can check multiple keys at once without pulling events directly, and you will be able to re-use the keyboard across the entire frame without passing it around to subroutines.
Some fast pseudo code:
class KeyboardHandler {
handleKeyboardEvent(SDL Event) {
keyState[event.code] = event.state;
}
bool isPressed(keyCode) {
return (keyState[keyCode] == PRESSED);
}
bool isReleased(keyCode) {
return (keyState[keyCode] == RELEASED);
}
keyState[];
}
...
while(SDL Pull events)
{
switch(event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
keyHandler.handleKeyboardEvent(event);
break;
case SDL_ANOTHER_EVENT:
...
break;
}
}
// When you need to use it:
if(keyHandler.isPressed(SOME_KEY) && keyHandler.isPressed(SOME_OTHER_KEY))
doStuff(TM);
If you're using SDL2 then use SDL_GetKeyboardState.
Example:
const Uint8 *keyboard_state_array = SDL_GetKeyboardState(NULL);
SDL_PollEvent(&event);
if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
{
// Move centerpoint of rotation for one of the trees:
if (keyboard_state_array[SDL_SCANCODE_UP] && !(keyboard_state_array[SDL_SCANCODE_DOWN]))
{
--location.y;
}
else if (!keyboard_state_array[SDL_SCANCODE_UP] && keyboard_state_array[SDL_SCANCODE_DOWN])
{
++location.y;
}
if (keyboard_state_array[SDL_SCANCODE_RIGHT] && !keyboard_state_array[SDL_SCANCODE_LEFT])
{
++location.x;
}
else if (!keyboard_state_array[SDL_SCANCODE_RIGHT] && keyboard_state_array[SDL_SCANCODE_LEFT])
{
--location.x;
}
}
Instead of only looking at keydown events, any solution which is going to be caring about multiple keys at once is going to have to be looking at both keydown and keyup events, and keeping track of the state of the keys in question.
So instead of (pseudocode):
on keydown:
case left_key:
object.setMovement(left)
case forward_key:
object.setMovement(forward)
instead you'd have something more like (again pseudocode):
on keydown:
case left_key:
keystates[left] = true
object.updateMovement(keystates)
case forward_key:
keystates[forward] = true
object.updateMovement(keystates)
on keyup:
case left_key:
keystates[left] = false
object.updateMovement(keystates)
case forward_key:
keystates[forward] = false
object.updateMovement(keystates)
Then the updateMovement routine would look at keystates and figure out a composite movement based on the states of all movement keys together.
use SDL_GetKeyState to get the keyboard state