I'm writing a simple game in C with SDL and I have defined that player one controls it's_for example_tank with arrow key of the keyboard and player two controls it's tank with the keys "W","A","S","D" of the key board.
My problem is they can't press the keys simultaneously.
I have a function called "handle_events" that controls the events in the infinite while of the game and it's code is like below:
int handle_events(Tank* tank,Tank* tanker, Wall walls[]){
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
return EXIT;
if (event.type == SDL_KEYDOWN){
if(event.key.keysym.sym==SDLK_UP){
move_tank_forward(tank,colliding(tank,walls));
}else if(event.key.keysym.sym==SDLK_DOWN){
move_tank_back(tank,colliding(tank,walls));
} else if(event.key.keysym.sym==SDLK_RIGHT || event.key.keysym.sym==SDLK_LEFT) {
turn_tank(event.key.keysym.sym, tank);
} else if(event.key.keysym.sym==SDLK_w){
move_tank_forward(tanker,colliding(tanker,walls));
} else if (event.key.keysym.sym==SDLK_s){
move_tank_back(tanker,colliding(tanker,walls));
} else if(event.key.keysym.sym==SDLK_d || event.key.keysym.sym==SDLK_a){
turn_tank(event.key.keysym.sym, tanker);
}
}
I'm looking for a way that two players can play simultaneously because right now if for example both players press the up key and the w key, none of them can move their tank.
It appears you rely on key repeat - feature of operating/windowing system to repeat last pressed key with fixed interval after some initial pause, e.g. when you keep key pressed in text editor it starts filling that symbol after some delay. Only last key is repeated though.
With SDL, you should know when key is repeated from repeat field of keyboard event. However, you almost never want to make prolonged movement based on keypress event. With your current scheme, I can press a key very quickly and tank will move faster, or I can modify my OS repeat interval. Movement, if supposed to be at constant speed, should rely on time, not how fast user can press a button. That is why you only need to take nothion of "ok, button A pressed, - as long as it pressed, I will attempt to rotate left at each fixed update interval", and when you get key-released event - you drop that intention.
As Danny_ds said, it is often much easier and robust to use key state array instead of events (mostly because of repeat) - with SDL, you can get that via SDL_GetKeyboardState. Make your update_movements or whatever function, and call it every N miliseconds.
On Windows you can use the GetAsyncKeyState() function.
For an equivalent on Linux see this question.
Related
In SDL2 there is an event SDL_TextInputEvent which captures input from the keyboard at the natural rate the OS is configured to be.
When I poll events, it's something like this:
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_TEXTINPUT:
Input_Listener.last_key = event.text.text;
break;
default:
break;
}
}
The event.text.text is a char[32] which contains the character in UTF-8 which the user inputs in the program. This is great as the delay is fine, so if you hold down the a key it wont insert loads of a characters as fast as possible.
However, this event doesn't seem to capture non-character input like pressing the enter key or the arrow keys. I can, however, capture them like so:
ubyte* states = SDL_GetKeyboardState(null);
if (states[SDL_SCANCODE_BACKSPACE]) {
... do stuff here
}
However this does not have the OS delay, and will fire as quickly as possible. My program is a text editor, but it's programmed as if it was a game. So there is a game loop, update/rendering methods, etc. Meaning that the check for input is done constantly every frame.
What can I do to get the non-character input at the same delay rate as the OS is configured? Is there some function I'm missing, or some way I can simulate this?
I have created a game using openGL in C. The game features a slider that can be moved left or right using arrow keys. Code is as given below (for handling keyboard events).
When I press any key(left or right) the slider moves by one unit then waits for a certain time and then keeps continuously moving until I release the key.
It is natural as computer waits for us to release key so as to verify whether we want multiple key stroke to be fed as input or we were just slow to release the key.
But this feature comes in the way of making slider responsive enough.
Is there any way to get rid of this? I have seen games in javascript where this problem doesn't arise.
Thanks!!
void specialKeys(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_LEFT:
sliderX -= 10;
if (sliderX < sliderXMin)
sliderX = sliderXMin;
break;
case GLUT_KEY_RIGHT:
sliderX += 10;
if (sliderX > sliderXMax)
sliderX = sliderXMax;
break;
case GLUT_KEY_UP:
xSpeed *= 1.05;
ySpeed *= 1.05;
break;
case GLUT_KEY_DOWN:
xSpeed *= 0.95;
ySpeed *= 0.95;
break;
}
}
OpenGL does not deal with user input. In your case you're using GLUT, which is not part of OpenGL and this is doing the user input stuff for you.
With GLUT what you want to do is difficult to achieve, because the keyboard callback is just called for character code input. What you want is getting events if a key is pressed and later depressed to set a flag, which you use to update the position in a timed loop.
Fortunately GLUT is not the only framework around. There are many others, better suited for the development of games, because of their far finer grained user input control. Well suited for games are GLFW, SDL-2 and SFML. I suggest you use one of those.
I'm programming now a snake program. I have a little problem in the movement. My direction buttons are the 'W' 'A' 'S' 'D' buttons.
I have a direction variable, wich type is char. I read a button from keyboard, direction gets a value, and the snake makes one step from the 4 directions, if I hit one from WASD and then enter. I'd like to fix the enter problem.
I want, that my snake moves continually, and doesn't wait for the enter.
I'd like to make a timer for direction that way, if I don't hit a character in X milliseconds, then the snake continues to move in the direction of the last value of direction.
How to make this timer? Or any other idea?
It depends on the language you are programming in :-).
Eg. if you have a sleep() or delay() function available, you don't need any special timers and a simple infinite loop will do the job.
The important thing is how you are reading the keyboard. You can read buttons as they are pressed (non-blocking) or waiting for them till they are pressed (blocking). In your case you are reading whole lines - this is why it waits for the enter.
Not sure what is your programming language, but this pseudo-code could explain it a bit. The keyPressed() and readKey() are some fictive library function, which you need to find in your language.
while (true) {
if (keyPressed()) {
direction = readKey();
}
move(direction);
sleep(1);
}
Unfortunately, without knowing the language and if an SDK like SDL, XNA, Monogame, etc. are used we can't help. I would suggest trying to search for handling keyboard events. In XNA while the game is running it calls Draw, Update, and Event. Usually the keyboard event would be handled like so:
//...
public void Update()
{
if(Keyboard.GetStates().IsKeyDown(Keys.W))
{
Player.ChangeDirection(Direction.UP);
}
//...
Player.Move();
}
Player.ChangeDirection(Direction) may will change how the snake moves. The movement is done in the Player.Move() command every time.
EDIT: In C++ are you using any SDKs like SDL, Allegro, DirectX or that?
I am trying to keep track of the pressed keys. I have glutIgnoreKeyRepeat(1) and I register the key events (down/up for normal and special) in an object that keeps track of the keys pressed (called the list of pressed keys from now on) so that I just check in my display function if a key is pressed by looking in that list.
The problem is with SHIFT: Different keys register as DOWN and UP (depending on whether SHIFT was pressed or not) for the same physical keyboard key (eg.
a and A, 1 and !, [ and { etc.)
Consider this (with {key1 key2} representing my list of pressed keys after the event):
initial state : {} no keys listed as pressed
SHIFT DOWN : {SHIFT}
a DOWN : {SHIFT A} (because SHIFT is still down, capital 'A' registers as the key down.
SHIFT UP: {A}
a UP: {A} (because SHIFT is not pressed, lower 'a' registers as the key up, so a is removed from the pressed key list (which actually doesn't exist), and A still remains)
final state: {A} even though no keys are still pressed on the keyboard.
For alpha keys I can solve this by adding/removing the lower case of the keys (a instead of A).
But what about 1 and ! or [ and {. glutGetModifiers doesn't help here. Or what if a key is pressed, the window looses focus, the key is released and the window gains focus again (there is no event to tell that the key was released when the windows lost focus)?
Is there a general solution to check if a key is pressed? (platform dependent solutions are ok, another library is not for me, but maybe for others who need to solve this)
What you want are the keycodes, the physical number of the key being pressed on the keyboard. These are different on Apple and PC keyboards, and can also be different on keyboards in other countries where the letters change positions.
Most programs don't care about keycodes, they want actual letters and modifier keys, so the system event handler provides a translation from keycode into the intended character/special key. GLUT is designed to be simple, portable, and cross-platform, so uses these routines.
If you're writing a game or simulator, just lowercasing everything is probably good enough. For that kind of high speed interaction, most players won't want to distinguish between 1 and !, or 2 and #. The Ins/Del and arrow key blocks (usually) don't have multiple symbols anyway, and the numeric keypad is too far away for most people to hold down a modifier key at the same time.
If you really, truly, need to track every key state, sorry GLUT won't work for you. On MacOS you ask the NSKeyEvent for the keycode, on MS Windows you use DirectX, on Linux you use the XKeyPress|ReleaseEvent keycode.
Hope this helps.
I'm currently coding a version of breakout as a quick learning experience of C and OpenGL.
Im having some issues with moving the paddle. I've set a keyboard callback so that when the left arrow is pressed, it subtracts 1 from the x value on the paddle, and adds 1 to the x value when pressing the right arrow.
With this in mind, the paddle moves incredibly slow when I hold either key. I can change this by increasing the amount the x value is changed to 10 for example. When I do this the paddle seems to stutter across the screen because it's jumping 10 at a time. It does of course move faster along the screen now but doesn't look smooth.
I'm using GLUT for windowing on OSX.
Is there a way of speeding this up and keeping it looking smooth?
A common thing in games is a keyboard array. Therefore you will be also able to press several buttons at a time.
You have an array where you keep state of keys (you put 1 when you get pressed, set 0 when released). And you process game in each frame by taking information just from array, not directly from input.
Here is some code from one of my projects:
bool keyDown[256];
...
//Called when a key is pressed
void handleKeypress(unsigned char key, int x, int y) {
keyDown[key] = true;
}
void handleKeyUp(unsigned char key, int x, int y){
keyDown[key] = false;
}
This essentially keeps an array of the states of each key, so you can just check them each time. Then you don't have to depend on the callbacks coming in that frequently.