How to fix movement in my snake program? - keyboard-events

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?

Related

Is there a way to render my Termbox game and handle keyboard events in the same loop?

I'm having issues with my termbox program rendering the screen and handling keyboard events. Recently, I've finished a C and C++ class at my university. I wanted to demonstrate my knowledge by creating a basic Snake game. The first steps, I wanted to get a simple render loop going and have a block of text simply move leftward and exit the game upon reaching the 0th x-coordinate. The issue arises when continuing to the next render frame, because the game is running single-threaded the next frame won't be rendered until a new keyboard event is accepted. Ordinarily, I would expect the game to continue rendering regardless of events, new events affecting the new frame.
As for potential solutions, I thought about using multiple threads to run the game loop and handle keyboard events. But, I think this would be overkill for such a small problem, there are likely easier alternatives than having to manage multiple threads for a simple snake game.
As for the code, it's as simple as:
while (1)
{
tb_clear();
draw(gameState);
tb_present();
struct tb_event event;
tb_poll_event(&event);
if (event.ch == 'q')
break;
}
After digging through the header file a bit more I found a method which doesn't wait forever.
/* Wait for an event up to 'timeout' milliseconds and fill the 'event'
* structure with it, when the event is available. Returns the type of the
* event (one of TB_EVENT_* constants) or -1 if there was an error or 0 in case
* there were no event during 'timeout' period.
*/
SO_IMPORT int tb_peek_event(struct tb_event *event, int timeout);

How to use two keys of keyboard simultaneously in sdl

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.

how to get Return key press event?

I'm coding a console editor in C. I'm using CodeLite Editor on Windows. I want to insert a newline ('\n') when the user presses Return (Enter) key. I want to accomplish this goal with getchar() function is that possible?
I need it because I want to increment the y axis variable.
Code I'm trying on :
int X = 0; // X-axis
int Y = 0; // Y-axis
char key = getchar();
if (key=='sth') // Here I want to perform my check
{
//Do Something
++Y;
}
Update :
If it has a code like : '\x45' for example post it in the comments plz!!!
If you are trying to implement an editor, you will quickly find that getchar() is not the way to interpret keyboard events. In this very simplistic example, where all you might do is wait for a single keystroke of input that either is or is not a newline, your program will work if you change 'sth' (an abbreviation for "something"?) to '\n'. However, as your editor becomes more complicated, you will want to have an actual event handler that can detect any sort of keyboard events and can asynchronously deal with them. getchar() is not the way to do that.
This answer from 7 years ago shows that (1) you can go a limited distance with getch() (and getchar()), but (2) a far larger number of people agree that it's no substitute for a real event handler: Detect Keyboard Event in C

Running two loops simultaneously for a game - C

I'm making a game in C for my programming class, and I have to place a time countdown on the game, but I can't make it work right, because if a put a countdown function and a delay(1000), it works for the countdown, but doesn't work for the game , because it makes wait the 1s every move.
My code so far is
while(tempo > 0)
{
tempo_na_tela(&tempo);
contador_tempo(&tempo);
if(kbhit())
{
mover_refem(getch(), p_refem, &refem.px, &refem.py,
numero_inimigos_na_tela(n, in1));
}
mover_inimigo(n, p_terrorista, in1);
}
The function tempo_na_tela(..) puts the string of time on the screen, the contador_tempo(..) is the countdown, the mover_refem(...) is the function to move the game character, and the mover_inimigo(..)is a function that randomly moves the enemy in the screen.
I need to place the tempo_na_tela and the contador_tempo functions in one loop, that run simultaneously with the other loop, that run the moving functions.
How can I do it?
You're experimenting a XY problem i think.
You don't need to run simultaneously thoses 2 functions. What you're trying to accomplish is a game loop, it's very common in video-games, especially early ones.
Ask yourself, when do you need to re-paint your elements ? The answer is probably after having updated all of your data (Time, ennemy position, and having logged your player's movement)
So, you don't need simultaneous looping (ie thread i would have suggested, even if it's not true simultaneous, but that's another story.)
Instead, you can stick with one loop, but you have to do something in this fashion :
while (game_not_ended())
{
update_data();
repaint_data();
}
I hope you'll take the time to reconsider your code and the scope of your issue.

GLUT Keyboard callback issues with C

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.

Resources