|
Timers |
Paladin
Member #6,645
December 2005
|
Is there a possible way I can wait a certain number of seconds(Even down to the fractions if possible) so that it's the same speed on all computers? I think that if you used rest it would work, but I have to be precise with the timing with this program. I'm not very well versed in delta time or any of that stuff, so an explanation on how I can wait "real" seconds would be great. Thanks. |
BrknPhoenix
Member #7,304
June 2006
|
volatile unsigned int timer; somewhere else... void tick() { timer++; } END_OF_FUNCTION (tick) elsewhere... LOCK_VARIABLE(timer); LOCK_FUNCTION(tick); install_int(tick, 1); timer increases 1 every millisecond. that's about it :p 1,000 ms to a second if (timer % 10 == 0) { Logic->DoLogic(scene); } Do logic 100 times per second. Note that yours won't look exactly the same... I just ripped this right out of something I'm working on right now, hehe |
Paladin
Member #6,645
December 2005
|
Ok so now that I have the timer code, how can I like use "rest()" with this function? I want the gamae to use a for loop and at the end of the loop, wait 2 seconds(example) and then repeat the for loop. Is this possible? |
CGamesPlay
Member #2,559
July 2002
|
Warning: You probably need to rethink your design! You should do something where an object has a counter counting up to 2 seconds, then goes into the loop state afterwards, where it sotres its iterator. Basically, instead of using rest, look into state-based programming. -- Ryan Patterson - <http://cgamesplay.com/> |
BrknPhoenix
Member #7,304
June 2006
|
Quote: Ok so now that I have the timer code, how can I like use "rest()" with this function? I want the gamae to use a for loop and at the end of the loop, wait 2 seconds(example) and then repeat the for loop. Is this possible? You don't want to use rest with it See the line that says: if (timer % 10 == 0) Since your timer is incrementing by 1 every millisecond, that event will occur every 10 milliseconds, which amounts to 100 times per second consistently through the duration of the program. If you are looking to just keep the program running the same speed on all systems as you said in your original post, just put your logic in that if block and you have done it If you want to time in another way, then you need to store the end time and do...something... until you reach the end time. So if you just wanted to pause two seconds, you could do something like: edit: whoops made a mistake |
Paladin
Member #6,645
December 2005
|
Damnit, I'm getting confused. So would something like this work? //This is the main loop while(!key[KEY_ESC]) { if(timer == 230)//.23 Seconds I think according to brknphoenix { doaction(); timer = 0; } } Is that what you mean cgamesplay? |
BrknPhoenix
Member #7,304
June 2006
|
That won't work because it'll reset your timer every .23 seconds... Just do timer % 10... Every tenth millisecond it will run your logic, so it will end up doing it 100 times per second. Let the number count up without resetting it, it can go up to like over 4 billion edit: And note what the actual number is, is not important... the value of it, I mean. we're just using it to time with... if (timer % 10 == 0) { //do stuff }
|
CGamesPlay
Member #2,559
July 2002
|
Here is an example, done in C because C++ requires too much indenation:
Now, 1000 times each second, call upd_ball on your ball and it will bounce around the screen for 3 seconds, then stop for 2, and repeat. -- Ryan Patterson - <http://cgamesplay.com/> |
Paladin
Member #6,645
December 2005
|
Ahh I see, so I could do something like: //This is the main loop while(!key[KEY_ESC]) { if(timer % 230 == 0)//.23 Seconds I think according to brknphoenix { doaction(); } } Possibly? EDIT: Sorry CGamesPlay, I posted after you posted and didn't see that. Would my idea here still work? |
BrknPhoenix
Member #7,304
June 2006
|
Nope, this: //This is the main loop while(!key[KEY_ESC]) { if(timer % 10 == 0) { //logic here } //drawing here } 1) You can't reset the timer, else you'll never be able to time things up to even one second. You just have to let it count up for the duration of your program. 2) 230 milliseconds is too long. That means your logic is only updating 4 times per second, which is EXTREMELY slow. Your computer and most others should be able to do 100 times per second easy, so if you use the number 10 there, you will accomplish that If you do it like that, it should run the same speed for everyone. Note that you shouldn't draw in there, you should draw after it. You want to draw as fast as possible Only the logic that comes before drawing anything goes in there |
CGamesPlay
Member #2,559
July 2002
|
Well, for the main loop, the ideal solution is: while(!key[KEY_ESC]) { while(timer > 0) { --timer; upd_ball(b); } // Draw everything outside of the timed loop. circlefill(screen, b->x, b->y, 32, -1); } [append] Now what BrokenPhoenix is saying is also fine, but I prefer my OO approach instead. -- Ryan Patterson - <http://cgamesplay.com/> |
Paladin
Member #6,645
December 2005
|
I don't think you guys are seeing what I'm trying to accomplish. This isn't to update the screen and such, this is to just simply do one action. I want to have an action occur every so-and-so seconds. I'm not trying to update the game logic every .230 seconds. |
BrknPhoenix
Member #7,304
June 2006
|
That would be what I posted at the end of my second post in this topic. If you want the value of 2 seconds from now, store the current value of the timer + 2000. If you wanted 10 seconds from now, store the current value of the timer + 10,000. Then do whatever you want to occur or pause whatever you want to pause using that time. //wait for 2 seconds eTime = timer + 2000; while (timer <= eTime); //it will end the loop once the current time //exceeds the target time of 2 seconds from when this started
|
CGamesPlay
Member #2,559
July 2002
|
You don't see what we just said. I will only speak for my method, but look: Quote: I want the gamae to use a for loop and at the end of the loop, wait 2 seconds(example) and then repeat the for loop. In my example, inside the "for" loop you are bouncing the ball. And that for loop lasts for 3 seconds. Then the program pauses for 2 seconds, and continues. If you wanted to have something happen instantly, try the same thing, just differently:
-- Ryan Patterson - <http://cgamesplay.com/> |
Paladin
Member #6,645
December 2005
|
So are you saying to put that in the main loop if I want it to occur every 2 seconds? I just see a problem with that because I thought that it would wait 2 seconds and NOTHING would occur. The thing is I want everything in the background to continue as normal but just have the action occur every 2 seconds. Will that while loop do what I described? I just thought that the if statement wouldn't do that. |
BrknPhoenix
Member #7,304
June 2006
|
Quote: So are you saying to put that in the main loop if I want it to occur every 2 seconds? I just see a problem with that because I thought that it would wait 2 seconds and NOTHING would occur. The thing is I want everything in the background to continue as normal but just have the action occur every 2 seconds. Will that while loop do what I described? I just thought that the if statement wouldn't do that.
//stuff happening all the time if (timer % 2000 == 0) { // stuff that happens every 2 seconds } //stuff happening all the time
|
Kitty Cat
Member #2,815
October 2002
|
if(timer % 10 == 0) But, even if they really were accurate, say one time you check, timer is 9 (which means you won't do anything yet). The OS interrupts your game to run other threads. You get back and timer is now 22 (~13ms later). You just missed two executions, and won't make them up since timer%10 still doesn't == 0. It's best to run the timer as fast as you want the game to update, and just do an update whenever the timer is > 0 (while decrementing timer every time you do an update). -- |
CGamesPlay
Member #2,559
July 2002
|
If, Brian, you were talking to me, I gave a main loop that calls that function in my post. My main loops works the same way as KittyCat's. -- Ryan Patterson - <http://cgamesplay.com/> |
Paladin
Member #6,645
December 2005
|
Sorry CGamesPlay, I consistently miss what you're saying. If I used your method, would I have to install a timer for that variable and such? I'm really sorry if I seem stupid, I just don't know very much about this topic. void function() { timer++; if(timer >= 2000) { play_sample(...); } } Ok, now assuming I check that every millisecond, would that work to fit my needs? I'm trying to incorporate what you're all saying into what I make, but it's difficult because of my lack of experience. |
CGamesPlay
Member #2,559
July 2002
|
No, you would use the same timer variable that BrknPhoenix said to use, except the main loop would look like mine. What I posted is pretty much the standard way of timing. What I would do in your case is this: (since all you need is a single event) int sound_last_played = 0; int game_time = 0; // This is the variable updated 1000 times each second by your timer interrupt. while(!key[KEY_ESC]) { if(game_time - sound_last_played > 2000) { play_sample(...); sound_last_played = game_time; } } But do keep that state-based programing in mind for when you want to have multiple unrelated objects acting at the same time. -- Ryan Patterson - <http://cgamesplay.com/> |
Paladin
Member #6,645
December 2005
|
Ok that makes sense. I'm going to have to use the state-based programming though because I have to update a pixel's location every so and so seconds as well. I guess I have enough knowledge to get it done and if I have any problems I should be able to figure it out. Thanks a lot everyone. |
BrknPhoenix
Member #7,304
June 2006
|
haha, switching to the other timing method fixed the keyboard problem i was having in the other topic I made :p |
|