• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

How to create a timer?

P

PupofAwesome!

Guest
So I'm making a game for my friends and I, who love speedrunning, and so I want to implement a super-precise timer. How would I go about doing so? Is there a built-in function for timers?

If what I want isn't clear, I want something that would begin counting up when a room begins, and that I could pause and restart at any given time. It'd be awesome if I could make it count in milliseconds, but I don't want to change my room speed to do so.
 
B

BACANAKBROS

Guest
@wagyu_so_gud hey dude your code is awesome but i cant modify it and it is shown like this. I want to see that like 01:05.54. How can i do that?
 

Attachments

W

wagyu_so_gud

Guest
hmm, my immediate thought/approach is to convert each variable to a string value, omitting (place) values you do not want, and then concatenate the strings as the final output.

I can spend a little time visiting this for you--if you haven't already solved it--when I've finished my work for the day.

edit: quick manual search. This might work:

Code:
string_format(val, tot, dec);
Look into that as a start.
 

CMAllen

Member
I actually did something like this. Rather than fumbling with converting between different digit sizes, I put the milliseconds, seconds, and minutes into their own variables (not the most efficient, but it's just a few extra bytes, so big whoop). When any variable dropped into single digit territory, I would append a "0" in front of the string value to keep each digit neatly aligned. Like this:
Code:
str_msecs = string(floor(msecs));
str_secs= string(secs);
str_mins=string(mins);
if(msecs<10) { str_msecs= "0" +str_msecs;}
if(secs<10) { str_secs= "0" +str_secs;}
if(mins<10) { str_mins= "0" +str_mins;}

draw_text(timerx, timery, str_mins+":"+str_secs+":"+str_msecs);
Of course, I wasn't going for super-high precision, so I was just using room_speed and the step event to modify the millisecond value. In the timer object's step event, I'd add the interval to the milliseconds. When the milliseconds exceeded a second, the seconds would be increased by 1, add the proper amount removed from milliseconds. In my case, since I wasn't technically using milliseconds (just 1/100th of a second instead of 1/1000th of a second), I'd subtract 100 from the milliseconds. So something like this:
Code:
msecs += 100/room_speed;
if(msecs>=100) {secs+=1; msecs-=100;}
if(secs>=60) {mins+=1; secs-=60;}
 

hippyman

Member
I would do something similar what CMAllen suggested, but you can get everything you need with one variable and a couple different functions.

First you want to store the lowest possible time value, which in your case is milliseconds. If you wanted you could even use microseconds since GM supports that with the delta_time variable. I personally use delta_time to increment the time variable because you can either use it for microseconds or you can multiply it by 0.001 and that will give you milliseconds. As the documentation states, delta_time returns the time between the current step and the last step so you need to increment your time every step.

Create
Code:
timerMS=0 //overall time in milliseconds
Step
Code:
timerMS += delta_time * 0.001; //add time passed since last step in milliseconds
Now that you have an accurate millisecond timer, you can make a couple scripts that convert that time in milliseconds to the whichever measurement of time you need.

The following functions all take the timerMS variable as an argument

scr_CurrentMS(time) --returns current millisecond value for this specific second
Code:
//returns the remainder of timerMS / 1000 which gives you the current millisecond value
return argument0 mod 1000;
scr_TotalSec(time) --returns overall seconds
Code:
//returns the floored quotient of timerMS / 1000 which gives you overall time in seconds
return argument0 div 1000
scr_CurrentSec(time) --returns current second value for this specific minute
Code:
//returns remainder of totalTimeInSeconds / 60 which gives you the current second value
return scr_TotalSec(argument0) mod 60
scr_CurrentMin(time) --returns current minute value for this specific hour
Code:
//returns the floored quotient of totalTimeInSeconds / 60 which gives you the current minute value
return scr_TotalSec(argument0) div 60
I put these scripts together in my head while converting an old script I had that did something similar but did the time starting from seconds and went up to hours. I haven't actually plugged these into GM but everything should work as you'd expect. Let me know if you have any issues understanding what is happening. I commented it a good amount to hopefully explain clearly what is going on. It's all really simple math.

Also I should mention that at a certain point you'll want to reset your timerMS value so you don't have to worry about integer overflow. There are 86,400,000 milliseconds in a day and since GM uses the double data type you should have no issue getting an entire day into your timer and probably way more. You mentioned this is a speed-running game so you shouldn't have any issues with integer overflow, but it's just something to remember.
 
Last edited:
Top