-
I want to make certain sprites appear with a random time delay. For some reason just putting in this code in the beginning of main to begin with.
sf::Clock clock;
Time time1 = clock.getElapsedTime();
Time time2 = clock.restart();
It gives me an error that time is an undeclared identifier? How can I go about doing this. :(
-
Probably because it's missing the sf:: namespace?
-
Yes I figured it out by doing this
sf::Clock Clock;
sf::Time time;
time = Clock.getElapsedTime();
Clock.restart();
But how can I make sprites appear at random times within a certain time range somehow?
Also when I do something like this
if (time.asSeconds() >= 10.0f) {
Window.draw(Player1);
}
It just doesn't work. The code runs fine but nothing is drawn after the 10 seconds pass
-
You don't really give enough information about your code to tell what is going wrong. I'll try to take some guesses though.
sf::Clock Clock;
sf::Time time;
time = Clock.getElapsedTime();
Clock.restart();
Clock.getElapsedTime() returns the amount of time since the clock was constructed or last restarted. You are constructing the clock right before this call, so not much time will have passed at all. If you aren't reading from the clock again later in your code in a loop or something then your time variable certainly won't be 10 seconds.
Also, make sure you are displaying your window after you draw to it.
-
Time only holds a certain duration, e.g. like 2s or 500ms, it doesn't change unless you assign it a new value.
You can use the clock and generate random numbers with the functions found in the C++ header <random>.
-
Ok I will clarify,
As a test I first created the following:
sf::Clock clock;
sf::Time time;
time = clock.getElapsedTime();
while (Window.isOpen()) {
sf::Event Event;
while (Window.pollEvent(Event)) {
sf::Time t1 = sf::seconds(10.0);
time = clock.getElapsedTime();
std::cout << time.asSeconds() << std::endl;
std::cout << t1.asSeconds() << std::endl;
if (time.asSeconds() >= t1.asSeconds()) {
std::cout << "player 1 is drawn";
}
With this code I do in fact get "Player 1 is drawn" on the console after 10 seconds. However when I place the following code,
Window.draw(PlayerTwo); in the if statement and i already defined the sprite image and texture before in main. Nothing gets drawn on my window. What is going on here? There are no errors too.
-
make sure you are displaying your window after you draw to it.
You did not answer this.
Are you using window.display()?
-
Yes of course window display and window clear
-
Where is your clear? Is just before your display (but after your draw)?
-
It is after my window draw and window display. Is this what's causing the issue?
-
Ok so I removed the window clear and my code worked but now the sprite is flashing non stop I want it to be a stable image. What is causing this flashing if the condition of the time has been met?
I figured that this was due to me placing the code in the event poll area instead of the window open area.. Now how can I generate a random time within a certain time range for example. Generate random seconds between 5-10 seconds?
Also I realized that it will continue to draw the sprite continuously since the condition was met I only want it to draw the sprite once and thats it. How can I do that?
-
So you removed all clear statements?
You should always clear(), draw(), display().
-
That advice worked perfectly. Now, how can I make random variables?
float x for example
I want x to carry random numbers in a certain range? For example from 5-9
-
So you removed all clear statements?
You should always clear(), draw(), display().
clear() isn't always needed, well, it's useless in almost every bigger project which overwrites whole screen with some background.
That advice worked perfectly. Now, how can I make random variables?
float x for example
I want x to carry random numbers in a certain range? For example from 5-9
Use something like this:
rand() % (9 - 5) + 5;
or
rand() % (9 - 5 + 1) + 5;
EIDT: Or if you want floating point value like 0.01:
static_cast<float>(rand() % (900 - 500) + 500) / 100.f;
-
clear() isn't always needed, well, it's useless in almost every bigger project which overwrites whole screen with some background
This is wrong. SFML requires you to call clear, due to double buffering.
-
clear() isn't always needed, well, it's useless in almost every bigger project which overwrites whole screen with some background
This is wrong. SFML requires you to call clear, due to double buffering.
I don't use it for a long time and haven't noticed any problems, what can be wrong?
-
So you removed all clear statements?
You should always clear(), draw(), display().
clear() isn't always needed, well, it's useless in almost every bigger project which overwrites whole screen with some background.
Please, please don't say that.
Yes, if you do draw the entire screen, then clear() is pointless. But it is also harmless. It doesn't hurt performance and it doesn't screw up rendering.
When it /is/ needed it really is needed. You get strange rendering artifacts if you leave it out.
You should just always do it. It doesn't hurt when not needed and it does real needed work when needed (most of the time).
Please don't advice people to skip it.
clear(), draw(), display() - always!
-
So you removed all clear statements?
You should always clear(), draw(), display().
clear() isn't always needed, well, it's useless in almost every bigger project which overwrites whole screen with some background.
Please, please don't say that.
Yes, if you do draw the entire screen, then clear() is pointless. But it is also harmless. It doesn't hurt performance and it doesn't screw up rendering.
When it /is/ needed it really is needed. You get strange rendering artifacts if you leave it out.
You should just always do it. It doesn't hurt when not needed and it does real needed work when needed (most of the time).
Please don't advice people to skip it.
clear(), draw(), display() - always!
I don't say people should skip it. :)
However, those "strange rendering artifacts" are very characteristic and removing clear() helped me a lot in searching for other rendering bugs. I don't see any problem in using it for debugging.
-
This is wrong. SFML requires you to call clear, due to double buffering.
clear() just fills the whole buffer with a color. If the next thing you do is to fill it with something else, it is indeed not required -- it is even mentioned in the tutorials ;)
And double-buffering has nothing to do with this.
-
Alright back on topic haha. The random and all worked great. I want to be able to delay with time though for example
if (bla = bla){
Dosomething;
Wait 5 seconds then start again from the top
}
How can I do that using time or clock?
-
Bump anyone?
-
/*Use a boolean for your condition: mValue
a float that will holds the time: mCountDown
another float with a const value sf::seconds(5.f): TimeInterval
Use this inside an update function with an sf::Time dt that holds elapsedTime */
if (mValue && mCountDown <= sf::Time::Zero) {
mValue= false;
//Do your stuff here
mCountDown += TimeInterval;
}
else if (mCountDown > sf::Time::Zero) {
mCountDown -= dt;
}
-
I don't really understand the code you sent me ?
Why is mvalue which is a bool less than time zero? What are you achieving with the += and the -= Please elaborate ..
-
Have you ever sat down and thought it through on your own? I mean programming shouldn't consist of waiting for people to suggest random things that one can then pretty much copy&paste.
I suggest to take a piece of paper and a pen, sit down and go step by step through the logic of how to go about it.
Make use of what you have (clock, random number generator, sprites) and figure out when you can use what where and how it will fit into your solution. ;)
-
I don't really understand the code you sent me ?
Why is mvalue which is a bool less than time zero? What are you achieving with the += and the -= Please elaborate ..
I suggest you to read carefully what I wrote, I'm not trying to compare a bool with sf::Time::Zero.
The if statement tests the boolean and the mCountDown value.
eXpl0it3r is right, you should learn a bit more before asking for a pre-made solution.
-
Actually I was able to solve my problem in a completely different way on my own which is fine. But, because I want to learn more and have a thirst for knowledge I am asking since I tried to understand the logic behind the code you put here and didn't really get the Boolean part? That's why I am asking. It's fine to ask questions when you don't understand otherwise you won't learn. As for asking for code to copy paste in that's obviously not what I am asking for because that is pointless and each and every program is written in a different way.
-
Can you please past the solution here and put your problem as "solved" if you found a solution by your own?
I was not trying to be mean when I said that you should learn a bit more. The if statement was a basic condition, and you did not understand it. No offense.
I admire the fact that you are motivated and looking for how things work, but start with the begining (c++ basis, logic, etc) before.
It's fine when you ask questions of course, but the logic that I've put before is easy to understand.
Sorry if I offended you, that was not my purpose.
Good luck
-
Well the way I did it was like so
sf::Time t1 = sf::milliseconds(500);
sf::Time t2 = sf::milliseconds(1000);
time = clock.getElapsedTime();
sf::Event Event;
if ((time.asMilliseconds() >= t1.asMilliseconds()) && (time.asMilliseconds() <= t2.asMilliseconds())) {
clock.restart();
}
Basically that way it will meet this condition only once then the clock will restart achieving the delay effect I wanted. I understand if statements but, the way you went about it is just different.
-
This is fragile and will fail if, for some reason, you are not passing through this code at least once every 0.5 seconds and you end up with time.asMilliseconds() returns 5000 for example.
This could happen if the user drags the window so events are not processed for a while or for many other reasons.
-
Thank you Jesper what do you recommend then?
-
A way to avoid the missing the passing of time when the application is not active (i.e. blocked during OS modification), you can simple use an accumulation time and add to it the amount of time that has passed since the last frame - as long as that frame time is shorter than a chosen boundary.
sf::Clock;
sf::Time frameTime;
sf::Time accumulatedTime = sf::Time::Zero;
sf::Time maximumFrameTime = sf::milliseconds(200);
{
// inside main loop
frameTime = clock.restart();
if (frameTime > maximumFrameTime)
frameTime = maximumFrameTime;
accumulatedTime += frameTime;
}
Then, "accumulatedTime" is the current time passed and would never process a frame of more than 200 milli-seconds. Note that some time can be discarded in this method. Although that is the intention for this method, it may be unwanted in some cases (real-time timing, for example).
-
... what do you recommend then?
Well, there are many ways to do it.
If you want to stick to your current solution you could modify it slightly as
if ((time.asMilliseconds() >= t1.asMilliseconds()) &&
(time.asMilliseconds() <= t2.asMilliseconds()) ||
time.asMilliseconds() > t2.asMilliseconds()) {
that would address the specific problem I pointed out, but it's not really elegant.
Another option would be to calculate the time in the future when you want the object to spawn as "now() + nr_of_ms_until_spawn" and then simply check if "now()" is greater than or equal to that value and spawn an object if it is and then calculate a new spawn time.
What I would probably do myself would be to generate a random number between 500 and 1000 using the facillities in the <random> header (like std::random_device, std::mt19937 & std::uniform_int_distribution) and then set a timer to trigger a spawn_object() callback after that many milliseconds.
See also:
http://en.cppreference.com/w/cpp/numeric/random
http://en.cppreference.com/w/cpp/header/random
http://www.bromeon.ch/libraries/thor/documentation/v2.0/classthor_1_1_callback_timer.html
-
if ((time.asMilliseconds() >= t1.asMilliseconds()) &&
(time.asMilliseconds() <= t2.asMilliseconds()) ||
time.asMilliseconds() > t2.asMilliseconds()) {
Assuming that t1 is before t2, that code is equivalent to:
if (time.asMilliseconds() >= t1.asMilliseconds()) {
-
Right you are Hapax.
I didn't think too much about that since I think the better option in any case is a timer with a random time (within the required limits) and a callback function is the better option. So I just tacked on a bit of code to his version to address the issue I noted without giving it much thought ;)
-
Just as an aside, there's no real need for us to use "asMilliseconds()" here as an sf::Time can be compared to another sf::Time.
That line could just be:
if (time >= t1) {
;D
-
Sure. But that's not really central to OP's problem. But you are right of course (and it is nicer that way).