Adding a delay between key pressing - c++

I am using GetAsyncKeyState() to get the input every frame for a game that I'm making.
I want to move one x at each press, but not every frame, there has to be a delay. I currently I am doing this by having a cool down each time you press a key.
Here are some parts of my CoolDown class:
bool test(bool asumedStatus)
{
if(asumedStatus == status)
{
return true;
} else
{
return false;
}
}
void go()
{
if(currentCount == runFor)
{
status = OFF_COOLDOWN;
} else
{
currentCount++;
}
}
void start()
{
currentCount = 0;
status = ON_COOLDOWN;
}
controls gets called every frame to get the user input
void controls()
{
if(test(OFF_COOLDOWN))
{
if(KEY_L && !KEY_R && !KEY_U && !KEY_D)
{
left();
print();
cd.start();
}
else if(KEY_R && !KEY_L && !KEY_D && !KEY_U)
{
right();
print();
cd.start();
} else if(KEY_U && !KEY_L && !KEY_D && !KEY_R)
{
up();
print();
cd.start();
} else if(KEY_D && !KEY_L && !KEY_R && !KEY_U)
{
down();
print();
cd.start();
}
} else
{
cd.go();
}
}
Unfortunately, this does not work, the delay isn't there. Nothing changed.
Does someone have any ideas how I can accomplish this?

Here's how I would do it:
I use time to indicate frames, or ticks of the game.
I would make 2 variables:
startTime - Time point when the delay started
currentTime - Current time
Now, every tick, I'll update currentTime (by 1).
By taking the difference between those variables, you get the elapsed time since the start of the delay.
If the difference is greater than delay, then I have to reset the variables, to start all over again. So, setting startTime to currentTime, and setting currentTime to 0.
If the difference is less than delay, do nothing, because the delay isn't "done".
Something like:
startTime = 0;
currentTime = 0;
delay = 2000; //In frames/ticks
//Called every frame/tick
void update() {
++currentTime; //Update time
if (currentTime - startTime > delay) {
//Reset
startTime = currentTime;
currentTime = 0;
//Update whatever requires a delay
}
}

Related

GetKeyState detects so many clicks but I only clicked once c++

I also tried to use Sleep because I saw in someone's code which was similar to mine but now it doesn't detect clicks I want it to detect
first I tested using the space key in my keyboard I thought it was only for space but when I tested using a character and mouse button I had the same issue so now I'm here to get help
here's my code:
void waitforspace()
{
bool strtd = false, stop = true, set = false;
std::chrono::steady_clock::time_point nw, thn;
std::thread t1;
while (true)
{
if ((GetKeyState(VK_RBUTTON) & 0x8000))
{
// I tried this to fix the repeating issue it worked but now most of the time my clicks doesn't get detected
if (!(GetKeyState(VK_RBUTTON) & 0x8000))
{
if (set)
{
nw = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> time_span = nw - thn;
set = false;
if (time_span.count() < 350.0)
{
std::cout << "Double click Detected!\n";
if (!strtd)
{
// Function I want to run if user clicked twice
t1 = std::thread(sendclicks, &stop);
strtd = true;
}
else
{
stop = false;
strtd = false;
}
}
}
else
{
std::cout << "One click Detected!\n";
thn = std::chrono::high_resolution_clock::now();
set = true;
}
}
}
}
}

C++: Call function every x loops/seconds

I'm new to C++ and trying to make a simple update function.
I have built a "clock" which tracks time between frames as well as time since T0.
I also have a loops which every so many "clock" frames calls an update function.
void Engine::start()
{
float count = 0;
Clock clock;
clock.startClock();
while (true)
{
clock.Time(.001F);
count += clock.deltaTime();
if (count >= 1000) {
update(clock.deltaTime());
count = 0;
}
}
}
However this feels inelegant to me.
The clock code:
class Clock
{
private:
public:
float startTime=0;
float nextTime=0;
float currentTime=0;
void startClock()
{
float startTime = 0;
float currentTime = startTime;
}
float deltaTime()
{
return nextTime - currentTime;
}
void Time(float incrementTime)
{
currentTime = 0;
nextTime = incrementTime;
}
};
It works as written; I have a "counter" class which prints to the console every time the update function is called; however I'd like advice on how to improve this, to make it more elegant/efficient.

Extend photo-diode detector to support multiple sensors

I am quite new to C++, so I was hoping someone can help me answer my question. I am building an embedded system using Arduino.
I have a number of photo-diodes that generate an event when an physical object passes the sensor. The object passes the sensor too quickly, so the signal is short-lived and on non deterministic length. So I wish to implement a timer that holds the state to a period following detection.
The following code is my attempt to implement this for a single photo-diode sensor, (Note: I have not tried to compile it yet, there might be some mistakes). However how can I extend this to support multiple sensors.
Here is code:
struct DiodeResult {
bool diodePassed;
unsigned long timeOfSet;
}
void loop() {
static DiodeResult diodeResult;
bool diodePassed = readDiode();
if (diodePassed) {
diodeResult.diodePassed = true;
diodeResult.timeOfSet = millis();
} else {
if ((millis() - diodeResult.timeOfSet) > (5*1000) {
diodeResult.diodePassed = false;
}
}
}
Your existing solution can be extended to handle multiple photo-diodes simply by using an array of DiodeResult instances:
void loop()
{
static DiodeResult diodeResult[DIODE_COUNT];
for( int i = 0; i < DIODE_COUNT; i++ )
{
bool diodePassed = readDiode( i ) ;
if( diodePassed )
{
diodeResult[i].diodePassed = true;
diodeResult[i].timeOfSet = millis();
}
else
{
if( (millis() - diodeResult[i].timeOfSet) > (5 * 1000)
{
diodeResult[i].diodePassed = false;
}
}
}
}
Or perhaps more "Arduino-like":
void loop()
{
static DiodeResult diodeResult[DIODE_COUNT];
static int i= 0 ;
bool diodePassed = readDiode( i ) ;
if( diodePassed )
{
diodeResult[i].diodePassed = true;
diodeResult[i].timeOfSet = millis();
}
else
{
if( (millis() - diodeResult[i].timeOfSet) > (5 * 1000)
{
diodeResult[i].diodePassed = false;
}
}
// Next diode on next loop iteration
i = (i + 1) % DIODE_COUNT ;
}
However it relies on the photo-diode state remaining active for at least as long as it takes to iterate all ten sensors. This may be the case, but it highly dependent on your application and possibly the implementation of readDiode(). It may be necessary if polling is not fast enough to use interrupts.
Moreover the solution could arguably be improved by a little OOP:
class cMonoStable
{
public :
cMonoStable( unsigned long period_ms ) : m_time_ms(time_ms)
{
}
void trigger()
{
m_start_ms = millis() ;
}
bool getState()
{
return m_start_ms - millis() < m_time_ms ;
}
private :
unsigned long m_time_ms;
unsigned long m_start_ms
};
class cPhotoDiodeTriggeredMonostable : public cMonoStable
{
public :
cPhotoDiodeTriggeredMonostable( unsigned long period_ms, int diode = 0 ) : cMonoStable( period_ms ) : m_diode(diode)
{
}
void update()
{
if( readDiode( m_diode ) )
{
trigger() ;
}
}
private:
int m_diode ;
} ;
static const int DIODE_COUNT = 10 ;
static cPhotoDiodeTriggeredMonostable* photo_diode_state[DIODE_COUNT];
void setup()
{
for( int i = 0; i < DIODE_COUNT; i++ )
{
photo_diode_state[i] = new cPhotoDiodeTriggeredMonostable( 5000, i ) ;
}
}
void loop()
{
static int i = 0 ;
photo_diode_state[i]->update() ;
if( photo_diode_state[i].getState() )
{
// do whatever - state remains true for 5 seconds after diode was last active.
}
}
It looks a little long winded, but not how simple the individual elements are, and the cMonoStable class can be applied to other sensor types with similar characteristics, just be implementing a super-class with a different update() implementation.

Lowering CPU on MIDI playback thread

The function below is run on an std::thread that is detached. The code itself is written using the JUCE API (Hence Array<> object & MidiMessage).
void triggerMidiMessages(Array<Array<MidiMessage>> messageBundle)
{
//for each group of messages (bar) within the bundle
for(int bar = 0; bar < messageBundle.size(); bar ++)
{
//store our message from the bundle for playback
Array<MidiMessage> messages;
messages.clear();
messages = messageBundle[bar];
//intialise start time
double timestart = Time::getMillisecondCounterHiRes();
//for each midi inside a single "gene"
for(int i = 0; i <= messages.size();)
{
double elapsedTime = Time::getMillisecondCounterHiRes() - timestart;
//output message whens appropriate
if(elapsedTime > messages[i].getTimeStamp())
{
//output this message
masterMidiOutput->sendMessageNow(messages[i]);
//increment through the array
i++;
}
}
}
}
I need the midi messages to be output in real time but without having to run through the loop condition so much that the CPU runs super hot.
Any ideas? I'm stuck for how to playback the messages in such an order that doesn't require constant checking with a timer.
Thanks in advance.
//=====================================================================
update trying to sleep the thread...
void triggerMidiMessages(Array<Array<MidiMessage>> messageBundle)
{
//for each group of messages (bar) within a bundle
for(int bar = 0; bar < messageBundle.size(); bar ++)
{
//store our message from the bundle for playback
Array<MidiMessage> messages;
messages.clear();
messages = messageBundle[bar];
}
//intialise start time
double previousTimeStamp = 0;
//for each midi inside a single "gene"
for(int i = 0; i <= messages.size();)
{
//fire off all note on messages
while(messages[i].isNoteOn())
{
masterMidiOutput->sendMessageNow(messages[i]);
i++; //increment to the next
}
//fire off all note off messages
while(!messages[i].isNoteOn())
{
masterMidiOutput->sendMessageNow(messages[i]);
i++; // do the next one
//if the next message is back to a note on command
if(messages[i+1].isNoteOn() == true)
{
//sleep for x amount of time
int sleepTime = messages[i].getTimeStamp() - previousTimeStamp;
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
previousTimeStamp = messages[i].getTimeStamp();
}
}
}
}
}
To stop the build up within the thread it is better to turn on and off a timer object and trigger each message one by one.
Broadcast messages (Action Broadcaster )can then be used to keep track of the index.
Here is some example code to give the general idea :
MIDIThing::MIDIThing ()
{
startTimer(1); //start a timer
}
void MIDIThing::start ()
{
playstate = 1;
startTime = Time::getCurrentTime().toMilliseconds();
}
void MIDIThing::timerCallback()
{
if (playstate == 1) {
Time::getMillisecondCounterHiRes();
int64 target;
if (Time::getCurrentTime().toMilliseconds() > target) {
//fire off the message
}
//ended (possibly on a condition)
ActionBroadcaster::sendActionMessage(FINISHED_PLAYBACK);
}
}

Time lapse code in C++

I had to create timelapse function to wait for X amount of time in a loop.
The following code checks the boolean value of m_abortTimeLapseThread but after running for an hour I noticed the execution time of this code created 10 seconds delay. Is there a way to check m_abortTimeLapseThread as frequently as possible and wait for X amount of time in the function without the kind of delay I observed ?
void Acquisition::TimeLapseCount() {
int max10msWaitTimes = m_timeLapseInMs / 10;
while (true) {
m_timeLapseImageSaved = true;
for (int i = 0; i < max10msWaitTimes; i++)
{
if (m_abortTimeLapseThread) {
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
Thanks,
You could measure total time elapsed.
void Acquisition::TimeLapseCount() {
auto waitUntil = std::chrono::system_clock::now() + std::chrono::milliseconds(m_timeLapseInMs);
while (true) {
m_timeLapseImageSaved = true;
while (waitUntil > std::chrono::system_clock::now())
{
if (m_abortTimeLapseThread) {
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
waitUntil += std::chrono::milliseconds(m_timeLapseInMs);
}
}