How to apply a delay to a specific part of the code?

Hello!
My question is pretty simple, I am currently making a text-based top-down RPG game. Anyway, in the last game I made with my game engine I used a number of threads in order to run a couple of commands at the same time, with that method I didn't have issues adding delays to a specific part of the code, however, in the new game whenever I try to add a delay it affects the whole program (Because it runs on a single thread). I want to avoid using threads as much as possible.

The way I tried approaching it was by making a time-based function that measures if enough time has passed to do the command.

For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
 while(true)
{
Player();
Enemy();
}
 return 0;
}

void Enemy()
{
  if( time_passed(500)) attack();

}

bool time_passed(int milliseconds)
{
//Some magic

}




Long story short, I just want a delay function that doesn't affect the whole game loop.

Thanks!
Last edited on
A lot of context is required to answer.

What language (C++? - C++11/14 maybe 17? - C?)

That said, while a dozens ideas jump to my mind, the simple notion that Enemy is called repeatedly in an animation loop means you can just track how much time has elapsed during each call to Enemy (or Player).

This elapsed time is like a real time clock, but how you get that is up to a lot of controversy solved in modern C++ using a standard library (chronos).

So, let's say you want to attach in 500 milliseconds. What you are really saying is to schedule the attack function to be called 500 milliseconds in the future from the moment of that function call.

I could dive into everything from std::function or std::bind, talk about building a list of functions to be called at scheduled times (which is the kind of thing I like to do), but maybe you want something so simple it only applies to a study project.

Maybe all you need to have is some value which checks every call to Enemy if that wait time has been consumed, and if it is, call attach - and reset the variables tracking that so it no longer checks.

Say time is now 105050, a count of milliseconds the program has been running. You now decide you want to attack in 500 ms, which is 105550.

So, you set flags or create a structure that means you have this event you want to fire after time has reached (or exceeded) 105550.

That's about all there is to it for the simple case.

It's something that should be a service you can re-use in C++. You can schedule threaded tasks which wait for some time before executing (standard library async calls), but you might think that's overkill. Threaded development is an acquired skill (not as tough as many might tell you, but you do have to know what you're doing to use it).





Do I understand right that you want your program to block while it waits for player input, but then takes action based not only on what the player inputs, but how long it took them to do so?

If so, you could probably throw together a basic task scheduler with a priority_queue, which would be filed with tasks that have times that they're supposed to run at. Then, each time you get past the "player input" part of the code, check the frontmost element of the queue to see if the current time is past its time stamp, then pop it off and perform it if it is (and repeat). Whenever you want something in the game world to happen at a certain time, you'd just add a new task to the queue.

Just a thought. Good luck!

-Albatross
Hello again,
I kind of forgot to mention that I'm using standard C++ (no fancy versions or something). The whole idea of the player function is that it doesn't stop the loop waiting for input,it just checks if the keys are down. But yes, I want to schedule my functions, but I didn't say I'm not going to use threads at all,I just don't want to use them that quickly.
Thanks for the help!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <chrono>
#include <thread>

struct timer
{
    unsigned long long elapsed_millisecs() const
    {
        using namespace std::chrono ;
        return duration_cast<milliseconds>( steady_clock::now() - start_time ).count() ;
    }

    std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now() ;
};

void enemy()
{
    // attack only if 500 millisecs have elapsed since the last attack
    const int interval_millisecs = 500 ;

    static timer t ; // note: static

    const auto elapsed = t.elapsed_millisecs() ;
    if( elapsed > interval_millisecs ) // if interval has elapsed
    {
        std::cout << "\n*** enemy *** : attack (" << elapsed
                  << " millisecs since last attack)\n" << std::flush ;
        t = {} ; // reset the timer to start over again
    }

    // else do nothing; return immediately
}

int main()
{
    timer t ;
    while( t.elapsed_millisecs() < 10'000 ) // run for about 10 seconds
    {
        std::cout << '.' << std::flush ;

        // call enemy every time a dot is printed (roughly once every 10 millisecs)
        enemy() ;

        std::this_thread::sleep_for( std::chrono::milliseconds(10) ) ; // wait for 10 millisecs
    }
} 
That's almost exactly what I was going for.
Ummm, when I tried using it on two objects it seemed that one object waited for the other object to finish his delay, for example, I tried adding the function to the movement of the player (to control his speed), I also had the delay function in the movement of the enemy. As soon as the player moves the enemy stops and continue moving when the player stops.

Last edited on
Use two different timer objects: one for the player and another for enemy.
Ok, it's working now.
Thanks! :D
Topic archived. No new replies allowed.