Using `sleep()` for a time delay [duplicate] - c

This question already has answers here:
Sleep for milliseconds
(20 answers)
Closed 8 years ago.
I an trying to delay program execution for 200ms and then test if a key was pressed during the delay. How do I do this?
I am tryint to create a simple computer game similar to flappy birds, using C. I want the user to have tiny bit of time (~200ms) to press a key for the bird to jump, or it will fall down, but I am having trouble with implementing the delay.
I've read on some forums [where?] that sleep(100) should give a 100ms delay, but when I do it, I get 100 seconds.
I also tried using sleep(1/5), but the function only takes integers.
Additionally, I need to be able to test if a key was pressed during the 200ms; I read somewhere[where?] that the kbhit function can be used for that, but I have no idea how to use it.
while(!dead) {
sleep(200); // what do I put here to get 200ms?
if (keyWasPressedDuringWait()){ //what do I put here?
notDeadAnimation():
}else{
dead=true;
deadAimation()
}
}

To perform the desired delay, #include <unistd.h> and use usleep(microseconds). (To sleep for 200ms, the call is usleep(200000)).
To test the keyboard strike, #include <conio.h> and use _kbhit() in your test (short for keyboard hit). _kbhit tests if there is a key in the key buffer, but does not get rid of it. You also need to use _getch to retrieve the key, removing it from the key buffer. I'd recommend defining a helper function here:
int clearKeyBuffer(){
int count = 0;
while(_kbhit()){
_getch();
count++;
}
return count;
}
This method will clear all keys currently in the key buffer, and return the number of keys cleared. You can then use this in your test, as if(clearKeyBuffer()) to test if a key has been presses since the last time you tested it.
As for your program flow, you have a lot of extra stuff there. You can get rid of most of it and still be functionally identical:
do {
notDeadAnimation();
usleep(200000);
} while(clearKeyBuffer());
deadAnimation();
However, this has the obvious issue that someone could just

Use usleep() instead of sleep(). The former works in micro seconds.
And use _kbhit()+getch() to discover if a key was pressed and which key was it:
while (!dead) {
usleep(200*1000); // 200 msec
if (_kbhit()) { // if key was pressed during sleep
int key = getch();
// you can check key value here
notDeadAnimation();
} else {
dead = true;
deadAnimation();
}
}

Related

Monitor flashing when running a Windows SendInput API

Well, I certainly should go to python since I did several functions of this type, keyboard event and mouse event, but decide to try to learn the windows api.
My goal is to know when button 1 of the mouse is pressed.
I created this file in a very beginner way, it returns in mouseData only 0.
The curious thing is that whenever I run it, it flashes my monitor at short intervals in blinks, but between 1 second with it off. Very strange that, execution is not viable.
Could someone help me understand and try to execute to see if it is only here.
Code:
int main()
{
DWORD mouseData = 0;
MOUSEINPUT tagMouse;
tagMouse.dx = 0;
tagMouse.dy = 0;
tagMouse.mouseData = mouseData;
tagMouse.dwFlags = MOUSEEVENTF_XDOWN;
tagMouse.dwExtraInfo = 0;
INPUT tagInput;
tagInput.type = INPUT_MOUSE;
tagInput.mi = tagMouse;
while (true) {
if (GetAsyncKeyState(VK_DELETE)) break;
SendInput(1, &tagInput, sizeof(INPUT));
printf("KEYWORD: %d\n", mouseData);
Sleep(500);
}
system("pause");
return 0;
}
I can reproduce your reported 'symptoms' - and the effect is really brutal!
Now, while I cannot offer a full explanation, I can offer a fix! You have an uninitialized field in your tagMouse structure (the time member, which is a time-stamp used by the system). Setting this to zero (which tells the system to generate its own time-stamp) fixes the problem. So, just add this line to your other initializer statements:
//...
tagMouse.dwExtraInfo = 0;
tagMouse.time = 0; // Adding this line fixes it!
//...
Note: I, too, would appreciate a fuller explanation; however, an uninitialized field, to me, smells like undefined behaviour! I have tried a variety of other values (i.e. not zero) for the time field but haven't yet found one that works.
The discussion here on devblogs may help. This quote seems relevant:
And who knows what sort of havoc that will create if a program checks
the timestamps and notices that they are either from the future or
have traveled back in time.

How to access the PC Keyboard Buffer for Detecting multiple key press and key release?

I am making a harmonium synthesizer software for PC in C language, for that I have to detect multiple keypress and keyrelease so that to play notes simultaneously accordingly. So, I am thinking that accessing the keyboard buffer would be helpful. But I don't know how to. So can anyone suggest the method to do so or some new idea to detect multiple keypress. For detecting single keypress and keyrelease I have made following C code using kbhit() and getch() functions:-
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
void keypress(char);
void delay(int);
int flag=0;
int main()
{
char c;
while(1)
{
if(kbhit())
{
c=getch();
printf("\nCharacter:%c",c);
getch();
keypress(c);
printf("\nKey Released");
}
}
return 0;
}
void keypress(char ch)
{
char c;
delay(50);
if(kbhit())
{
c=getch();
if(c==ch)
{
keypress(c);
}
}
}
void delay(int milliSeconds)
{
clock_t final_time = milliSeconds + clock();
while (final_time > clock());
}
But it has some issues like:-
1).Multiple keypress not detected
2).It generates a very small delay
So can anybody suggest Improvement to code to solve the above issue or some new techniques for detecting multiple key press and key release.
Platform:-Windows 8.1
It would be good if the solution would platform friendly.
Thanks!
This shows how to use the Windows GetAsyncKeyState function. It does not need to be in a GUI - this console app works as shown. It will be up to you to examine the bit status flags as documented to determine action. For example, auto-repeat is honoured when a key is pressed. You probably won't need to check every key either.
#include <stdio.h>
#include <windows.h>
int main(void)
{
unsigned short buff[256] = {0};
unsigned short kval;
int i;
while (1) {
for(i=0; i<256; i++) {
kval = GetAsyncKeyState(i);
if(kval != buff[i]) {
printf("%02X:%04X ", i, kval);
buff[i] = kval;
}
}
}
return 0;
}
In this test, the first line was output before I pressed any key. The second line was output when I pressed and released 'A'.
0D:0001 26:0001 45:0001 53:0001 54:0001 0D:0000 26:0000 45:0000 53:0000 54:0000
41:8001 41:8000 41:0000
Note: linked with user32.lib.
As you include conio.h, the solution is already tied to a Windows (or MS/DOS) platform.
Here as i assume you do not really need a command line program, the best way would be build a Windows GUI program having an event loop and directly processing the WM_KEYDOWN and WM_KEYUP messages to be alerted as soon as a key is pressed on released on the keyboard. To avoid any risk of loosing one change in the state of the key, you could even consistently use the GetKeyboardState API function to load the current state of all keys on the keyboard.
I know this is more a hint that a precise answer, but a detailed answer would be much too long for a SO post.

Constantly check for keyboard input while theres already a loop

Im creating a little game thats like a keyboard version of guitar hero. I'm almost done, but i'm just confused over one thing. I want to constantly be checking if the player is pressing anything on the keyboard and to see if they are pressing the correct key, but I already have a loop that sleeps every 1 second to update the game, so I cant have another loop running at the same time to constantly check the keyboard input (or can I?). I tried putting the keyboard check inside the game loop, but since it sleeps every second, it sometimes doesnt catch when the player presses the key.
This is my while loop:
while (playing)
{
updateBoard(score, game);
checkKeyPress(game);
Sleep(time);
if (rand() % 2 == 1)
spawnNewLetter(game);
}
updateBoard just prints out the new board, spawnNewLetter is just to spawn a new letter to fall down the board, and checkKeyPress is to check the keyboard input, this is it:
void checkKeyPress(char game[GAME_ROW][GAME_COL])
{
if (_kbhit())
{
switch (_getch())
{
case 97:
checkLetter(game, 'a');
break;
case 98:
checkLetter(game, 'b');
break;
The function goes on, but its just repeating to check for all the letters.
Any help would be appreciated, thanks!

Returning program to pre-triggered state

First this gets triggered:
if ((temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) | (temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit))
activateAlarm(channelID);
Activate alarm is triggered, then from there:
void activateAlarm(int channelID);
{ while (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit || temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit)
{
logSubsystem(temperatureChannel[channelID].currentTemperature);
}
}
Then alarm screen is triggered with following case:
int logSubsystem(int currentTemperature)
case 'F': //if user input is 'F'
case 'f': //if user input is 'f'
currentTemperature--;
printf("your current exceeded temp is %i\n \n", currentTemperature);
if (currentTemperature <= 100 || currentTemperature >= 50);
compareLimit();
break; //exits loop
How do I set up this function so that if the user decrements with F and gets the current temperature to below the limit (<100, or >50), then it will return back to the compareLimit function and the requirement for the high limit/low limit triggered state will be FALSE, returning the program to its original pre-alarm state?
I think you would benefit considerably from thinking a lot about how your program flows. Right now, what I can deduce of your program flow is:
You have an outer loop that checks the temperature, on at least one channel ID. Inside that loop, you have the if statement you first showed us.
Then activate alarm does some other stuff, but loops until the temperature goes down, calling logSubsystem.
logSubsystem then presumably gets some kind of user input, and from there, you want it to call to your initial function, presumably called prepare limit.
The problem with this is that none of these functions ever complete. They all call each other, and you'll eventually get a stack overflow. Nice, since that's the name of this site, but not something you want to aspire to.
What you basically need is a state machine. You need something that keeps track of values, looks at those values, and calls functions that return that operate on those values. There should only be one loop, and it should do all the control of what happens based on what those values are. The good news is, you have all of this in place already. temperatureChannel is keeping track of the values for you, and you have while loops a-plenty.
Let me give you my suggestion of the way I suggest your program should flow:
bool checkTemperatureValuesOutOfRange(int channelID) {
// this is just a convenience, to make the state machine flow easier.
return (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) || // note the || not just one |
(temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit);
}
void actOnUserInput() {
char input = // ... something that gets a user input. It should check if any is available, otherwise return.
switch (input) {
case 'F':
case 'f':
temperatureChannel[channelID].currentTemperature--;
break; // This doesn't exit the loop - it gets you out of the switch statement
}
void activateAlarm(int channelID) {
// presumably this does something other than call logSubsystem?
// if that's all it does, just call it directly
// note - no loop here
logSubsystem(channelID);
}
void logSubsystem(int channelID) { // Not the current temperature - that's a local value, and you want to set the observed value
// I really think actOnUserInput should be (an early) part of the while loop below.
// It's just another input for the state machine, but I'll leave it here per your design
// Presumably actually logs things, too, otherwise it's an unnecessary function
actOnUserInput();
}
while (TRUE) { // this is the main loop of your function, and shouldn't exit unless the program does
// do anything else you need to - check other stuff
// maybe have a for loop going through different channelIDs?
if (checkTemperatureValuesOutOfRange(channelID)) {
activateAlarm(channelId);
// do anything else you need to
}
I'm sure you can see lots of differences between your code and mine. Here are some key things to consider:
All the functions now return. The master while loop calls functions that check status, and calls function that change status.
I would highly suggest acting on the user input as part of the master while loop. It's just another input to the state machine. Get it, act on it, and then check your statuses. You presumably need to have some input from the user, otherwise you'll never get in a bad state in the first place.
Right now, activate alarm happens every time. With the code you showed, that's fine - because logSubsystem was all that was being called. If you only want the alarm to ring once, keep a boolean tracker inside temperatureChannel[channelId] that says if the alarm rang, set it true within activateAlarm, and then reset it to false based on the return value of checkTemperatureValuesOutOfRange.
Rather than leaving yourself in the activateAlarm/logSubsystem area, you return each time, and check your values each time to see if you're still there. This is the key point - your functions should be fast, and not monopolize your processor. Make each function do just one sort of thing, and have all the control come from within the master loop.
I made a lot of changes to your code, and I don't know if you're allowed to make all of them, but you'll need something similar to this. It's much more robust, and gives you room to grow all around.

How to pause a loop in C/C++

I am trying to make a screen for a car game and make the screen wait for a key to go into the next screen, thing is that with this code it changes colors too fast. I've already tried delay() and sleep() which haven't worked properly. Also, after hitting a key, it closes and doesn't wait for me to enter a key. I just want the title to blink between white and red until a key is hit, and get to know why it exits after hitting a key.
Here is my code:
#include <dos.h>
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
int main(void)
{
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "C|\\BORLANDC\\BGI");
outtextxy(250,280,"POINTER DRIVER 1.0");
outtextxy(250,290,"LCCM 10070249");
do
{
setcolor(WHITE);
outtextxy(250,380,"PRESS ANY KEY TO CONTINUE");
// delay(10); nothing works here :(
setcolor(RED);
outtextxy(250,380,"PRESS ANY KEY TO CONTINUE");
} while(!kbhit());
cleardevice();
outtextxy(250,290,"HELLO"); //here it draws mega fast and then exits
getch();
closegraph();
return 0;
}
Instead of using delay(10), maybe try using some sort of timer variable to do this. Try something like the following (a modification of your do-while loop):
unsigned flashTimer = 0;
unsigned flashInterval = 30; // Change this to vary flash speed
do
{
if ( flashTimer > flashInterval )
setcolor(RED);
else
setcolor(WHITE);
outtextxy(250,380,"PRESS ANY KEY TO CONTINUE");
++flashTimer;
if ( flashTimer > flashInterval * 2 )
flashTimer = 0;
// Remember to employ any required screen-sync routine here
} while(!kbhit());
kbhit() returns true if there's a character in the buffer, but doesn't remove the character before it returns. Once you reach the getch() line, it takes the first key that you pressed to break out of the while loop.
Possible solution: While it's a bit hacky, adding a getch() right after your while loop would probably fix it.
May I also suggest using ncurses instead of those Borland libraries?

Resources