• 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!

Legacy GM [SOLVED]Help with setting time trial/best lap for time attack mode

A

AutoZ

Guest
Hey everyone,
I've been at this for a few days and I'm stumped. Started learning code with GM a year or so ago but I thought I'd ask some of the wizards on here after not finding a solution in the archives or making use/sense of some of the time functions from the manual.
Anyways the issue is a time trial mode for a topdown racing game. I have the timer counting up with the milliseconds/seconds which are being displayed in the UI and when the car passes over the finish line for a second lap the timer rests to zero and begins counting up again. That's all good.

What I would like to know is how to record and display the time when the car crosses the finish line as a best/fastest lap. How can I grab that time and display it as the current best lap time lap time while the counter starts again for lap 2 just like in other racing games.

Thank you so much in advance!
 
Last edited by a moderator:

sp202

Member
It seems you have the necessary infrastructure in place so all you'd need to do is record the time into a variable before you reset the timer and then draw it using a method similar to the timer.
 

rIKmAN

Member
It seems you have the necessary infrastructure in place so all you'd need to do is record the time into a variable before you reset the timer and then draw it using a method similar to the timer.
To add to this, I would also setup a series of invisible checkpoints around the course that must all be passed through and activated before a lap counts as complete.

This will stop people reversing over the start line, going back through it and having a lap registered in 1.5 seconds.
 
A

AutoZ

Guest
Thanks for the reply. The issue is that I can't figure out how to store the time from the finish line because it instantly resets the timer. In the timer object I have Create Event - global.seconds = 0 then in the Step Event - global.seconds += 1/room_speed and in the DrawGUI -
display_set_gui_size(view_wview[0], view_hview[0])
draw_set_font(fnt_emulator)
draw_set_color(c_black)
draw_text(200,16, "Time: " + string(global.seconds))

I have a finish line object that resets global.seconds to zero when the car passes over it.
 
A

AutoZ

Guest
It seems you have the necessary infrastructure in place so all you'd need to do is record the time into a variable before you reset the timer and then draw it using a method similar to the timer.
Thanks for the reply. The issue is that I can't figure out how to store the time from the finish line because it instantly resets the timer. In the timer object I have Create Event - global.seconds = 0 then in the Step Event - global.seconds += 1/room_speed and in the DrawGUI -
display_set_gui_size(view_wview[0], view_hview[0])
draw_set_font(fnt_emulator)
draw_set_color(c_black)
draw_text(200,16, "Time: " + string(global.seconds))

I have a finish line object that resets global.seconds to zero when the car passes over it.
 
A

AutoZ

Guest
It seems you have the necessary infrastructure in place so all you'd need to do is record the time into a variable before you reset the timer and then draw it using a method similar to the timer.
Thanks for the reply. The issue is that I can't figure out how to store the time from the finish line because it instantly resets the timer. In the timer object I have Create Event - global.seconds = 0 then in the Step Event - global.seconds += 1/room_speed and in the DrawGUI -
display_set_gui_size(view_wview[0], view_hview[0])
draw_set_font(fnt_emulator)
draw_set_color(c_black)
draw_text(200,16, "Time: " + string(global.seconds))

I have a finish line object that resets global.seconds to zero when the car passes over it.
 
A

AutoZ

Guest
So in the finish line object you'd have:
Code:
global.besttime=global.seconds
global.seconds=0
Got this error Push :: Execution Error - Variable Get -5.besttime(100010, -2147483648)
 
A

AutoZ

Guest
Yeah I knew it's probably something simple I'm not doing but global variables and declaring variables are still new to me, still learning how to structure all this.
 

rIKmAN

Member
Post your code, what events they are in, and the full error message.
Use [ CODE ] tags for readability.
 
A

AutoZ

Guest
Post your code, what events they are in, and the full error message.
Use [ CODE ] tags for readability.
Timer object Create Event - global.seconds = 0
Step Event - global.seconds += 1/room_speed

Finish line object Collision with car - global.seconds = 0

That's all that is there right now. The Timer object Draw GUI is like above. Not sure what code tags are sorry!

Here's the error I had
FATAL ERROR in
action number 1
of Draw Event
for object obj_downtimer:

Push :: Execution Error - Variable Get -5.besttime(100002, -2147483648)
at gml_Object_obj_downtimer_DrawGUI_1 (line 5) - draw_text(200,32, "Best: " + string(global.besttime))
 
Last edited by a moderator:

rIKmAN

Member
Timer object Create Event - global.seconds = 0
Step Event - global.seconds += 1/room_speed

Finish line object Collision with car - global.seconds = 0

That's all that is there right now. The Timer object Draw GUI is like above. Not sure what code tags are sorry!

Here's the error I had
FATAL ERROR in
action number 1
of Draw Event
for object obj_downtimer:

Push :: Execution Error - Variable Get -5.besttime(100002, -2147483648)
at gml_Object_obj_downtimer_DrawGUI_1 (line 5) - draw_text(200,32, "Best: " + string(global.besttime))
I don't see global.besttime anywhere in that code other than you trying to draw it?
You can't draw what doesn't exist.

The error is pointing to the DrawEvent of obj_downtimer, which is the part you haven't posted.

Code tags are used to make your code easier to read.
Put [ code ] before it, and [ /code ] after it (minus the spaces).
 
A

AutoZ

Guest
I don't see global.besttime anywhere in that code other than you trying to draw it?
You can't draw what doesn't exist.

The error is pointing to the DrawEvent of obj_downtimer, which is the part you haven't posted.

Code tags are used to make your code easier to read.
Put [ code ] before it, and [ /code ] after it (minus the spaces).
Thanks for taking a look. I deleted the code suggested from the finish line object. I had it in the Collision Event with the car object
Code:
 global.besttime=global.seconds
global.seconds=0
In the GUI Event I had
Code:
display_set_gui_size(view_wview[0], view_hview[0])
draw_set_font(fnt_emulator)
draw_set_color(c_black)

draw_text(200,16, "Time: " + string(global.seconds))
draw_text(200,32, "Best: " + string(global.besttime))

if global.shift = 1 {
    draw_sprite(spr_gearshift,1,416,32)
}
if global.shift = 2 {
    draw_sprite(spr_gearshift,0,416,32)
    }
/code
But this didn't work out.
 

rIKmAN

Member
You don't need to call display_set_gui_size every frame, you can just do it once in a Creat Event, and once whenever the screen resolution changes.

In the first bit of code, has
global.seconds been defined anywhere before this?
If not you are trying to set
global.besttime = global.seconds before you have defined it in the next line global.seconds = 0

ie. You are trying to set global.besttime to something which doesn't exist yet - try swapping them round.
 
A

AutoZ

Guest
You don't need to call display_set_gui_size every frame, you can just do it once in a Creat Event, and once whenever the screen resolution changes.

In the first bit of code, has
global.seconds been defined anywhere before this?
If not you are trying to set
global.besttime = global.seconds before you have defined it in the next line global.seconds = 0

ie. You are trying to set global.besttime to something which doesn't exist yet - try swapping them round.
Yes, it's in the Create Event of the timer object. global.seconds = 0. Swapping them doesn't seem to work.
 

rIKmAN

Member
Is the timer object created before the object that has that code above in the Instance Creation list?
 
S

signal

Guest
If the best time is recorded on collision with the finish line (and reset to zero immediately), is it possible that the collision is triggered multiple times before the car passes over it? Meaning it would save your best time as zero.
 
A

AutoZ

Guest
If the best time is recorded on collision with the finish line (and reset to zero immediately), is it possible that the collision is triggered multiple times before the car passes over it? Meaning it would save your best time as zero.
After messing around all day that did happen. Everything was drawing to the screen the counter was working but the best time was 0.2?
 
A

AutoZ

Guest
So are you still getting an error, or is it working but the best time is set to 0.2?
Yeah the error is gone that time happens when I put this in the Create of the timer object
Code:
global.seconds=0
global.besttime=global.seconds
 

rIKmAN

Member
If it's in the Create Event, it's only run once when the object is created so that code isn't the issue unless you are destroying / creating the timer object?

I think @signal is correct in that you are getting a collision in multiple frames so once it's reset to 0 on the first collision, the following collisions are also registering until there is no more collisions leaving you with a best time of 0.2s.

It's getting kind of annoying to scroll up and down and pick out the various fragments of info you are giving in each post, so I suggest you use code tags and post all your events, with all the code and any error messages / incorrect behaviour you are seeing all in one post so we can see where you are upto.

I didn't even know you weren't getting the error anymore, and it's kind of hard to help when we have no idea what is going on, what you are doing or where you are upto.

How big is your collision object?
Are you using a flag to set whether it has been triggered so it isn't called on any subsequent collisions until the next lap?
 
A

AutoZ

Guest
If it's in the Create Event, it's only run once when the object is created so that code isn't the issue unless you are destroying / creating the timer object?

I think @signal is correct in that you are getting a collision in multiple frames so once it's reset to 0 on the first collision, the following collisions are also registering until there is no more collisions leaving you with a best time of 0.2s.

It's getting kind of annoying to scroll up and down and pick out the various fragments of info you are giving in each post, so I suggest you use code tags and post all your events, with all the code and any error messages / incorrect behaviour you are seeing all in one post so we can see where you are upto.

I didn't even know you weren't getting the error anymore, and it's kind of hard to help when we have no idea what is going on, what you are doing or where you are upto.

How big is your collision object?
Are you using a flag to set whether it has been triggered so it isn't called on any subsequent collisions until the next lap?
Well I certainly didn't mean annoy anyone. I was wondering how to achieve a best lap time like all other racing games with time trial modes.

Here is all the code I started with. This what I had when I posted this topic originally. When the car runs a lap and collides with the start/finish line the time resets to 0 as it should. I wanted to know how to add on a best lap counter.

Timer object Create Event
Code:
global.seconds = 0
Timer object Step Event
Code:
global.seconds += 1/room_speed
Timer Draw GUI
Code:
display_set_gui_size(view_wview[0], view_hview[0])
draw_set_font(fnt_emulator)
draw_set_color(c_black)

draw_text(200,16, "Time: " + string(global.seconds))


if global.shift = 1 {
    draw_sprite(spr_gearshift,1,416,32)
}
if global.shift = 2 {
    draw_sprite(spr_gearshift,0,416,32)
    }
Finish/Start line object collision with Obj_car object (sprite and collision mask 16x32 of finish line)
Code:
global.seconds = 0
If there is no solution you know of please save your time if you are annoyed by this one, thanks for taking a look.
 

rIKmAN

Member
Well I certainly didn't mean annoy anyone. I was wondering how to achieve a best lap time like all other racing games with time trial modes.

If there is no solution you know of please save your time if you are annoyed by this one, thanks for taking a look.
Sorry, I didn't mean you were being annoying, I meant having to scroll up and down through all the different posts to check a line of code from each one to check what you were doing etc. Cumbersome was probably a better word :)

Having all the code together in code blocks makes it much easier to look at and see what you are doing.

Have you checked if the same collision is being called in multiple steps?

As a test add a global variable to count them, and in the collision script add 1 to this each time a collision occurs, and do not reset it.
Draw this to the screen somewhere and run a lap, so then you can see how many times a collision is actually called when you drive your car past the finishing line.

If it's more than 1 (as suspected), add an 'if' check so that no more collisions are calculated until the whole car has passed through your collision object. Maybe add another invisible object at least 1 car length away and when they car passes through this then reset the collision check to false so it will be calculated again on the next lap.

Also, this is nothing to do with your issue, but remove display_set_gui_size(view_wview[0], view_hview[0])from the Timer Draw GUI Event. You only need this line once in your whole project to set the GUI size, calling it every step is unnecessary so put it in a Create Event.

Let me know if any of that doesn't make sense, I'm trying not to write the code out for you as you don't learn anything by just copying and pasting code so I'm trying to help you work through it.
 
A

AutoZ

Guest
Sorry, I didn't mean you were being annoying, I meant having to scroll up and down through all the different posts to check a line of code from each one to check what you were doing etc. Cumbersome was probably a better word :)

Having all the code together in code blocks makes it much easier to look at and see what you are doing.

Have you checked if the same collision is being called in multiple steps?

As a test add a global variable to count them, and in the collision script add 1 to this each time a collision occurs, and do not reset it.
Draw this to the screen somewhere and run a lap, so then you can see how many times a collision is actually called when you drive your car past the finishing line.

If it's more than 1 (as suspected), add an 'if' check so that no more collisions are calculated until the whole car has passed through your collision object. Maybe add another invisible object at least 1 car length away and when they car passes through this then reset the collision check to false so it will be calculated again on the next lap.

Also, this is nothing to do with your issue, but remove display_set_gui_size(view_wview[0], view_hview[0])from the Timer Draw GUI Event. You only need this line once in your whole project to set the GUI size, calling it every step is unnecessary so put it in a Create Event.

Let me know if any of that doesn't make sense, I'm trying not to write the code out for you as you don't learn anything by just copying and pasting code so I'm trying to help you work through it.
Hey no worries I do appreciate any help, I'm not looking for anyone to make my games, I know that goes nowhere fast, but getting the answers to somethings helped me by analyzing the end results on my own. Anyways I did a check and the number of times it was triggered was 4 on average depending on the cars speed.
I put this code in the start line object collision Event as a check. This is all the code running in that object.
Code:
global.seconds = 0
global.checklap = global.checklap +1
if global.checklap >= 1 {
    global.checklap =1
    }
With the if check the number stays at 1 on screen now instead of 4 or 5 collisions.
This is just a test project I'm working on so I put the globals and gui stuff in the same object. I know it's not optimal but right now I only have a few objects I'm testing with. I'll organize for sure though.
 

rIKmAN

Member
Hey no worries I do appreciate any help, I'm not looking for anyone to make my games, I know that goes nowhere fast, but getting the answers to somethings helped me by analyzing the end results on my own. Anyways I did a check and the number of times it was triggered was 4 on average depending on the cars speed.
I put this code in the start line object collision Event as a check. This is all the code running in that object.
Code:
global.seconds = 0
global.checklap = global.checklap +1
if global.checklap >= 1 {
    global.checklap =1
    }
With the if check the number stays at 1 on screen now instead of 4 or 5 collisions.
This is just a test project I'm working on so I put the globals and gui stuff in the same object. I know it's not optimal but right now I only have a few objects I'm testing with. I'll organize for sure though.
global.checklap will always be 1 with that code, because right after adding 1 to it you check that if it's bigger than or equal to 1, reset it to 1.

The multiple collisions are still happening, but you are just drawing 1 to the screen.
 

FrostyCat

Redemption Seeker
Remember: Collision events recur every step as long as there is one.

Flags are the best way to stop unwanted recurrences of code in a repeated event. For step checks you use a simple if-else as shown here, but for collision events you use a 2-step alarm.

Create:
Code:
lapping = false;
Alarm 11:
Code:
lapping = false;
Collision:
Code:
alarm[11] = 2;
if (!lapping) {
  global.seconds = 0;
  global.checklap += 1;
  lapping = true;
}
 
Last edited:

sp202

Member
@FrostyCat I don't think an alarm would be the best idea for resetting lapping; imagine if the car paused for a moment on the finish line. Better off resetting it when the finish line is no longer colliding with the car:
Code:
//step event
if lapping=true and place_meeting(x,y,obj_car)=false
{
lapping=false
}
 

FrostyCat

Redemption Seeker
@sp202: I just corrected the code so that it correctly handles consecutive colliding steps. It intentionally holds the alarm open so that lapping would stay true from the second step forward. Moving off would release the hold and allow the alarm to trigger.
 
A

AutoZ

Guest
@FrostyCat @sp202 @rIKmAN @signal It works!! Thank you so much for your time and suggestions! Having no check for the collision of the car and start line was the main goof. In other projects I would destroy the instance on collision if it were to -hp from an enemy like a shmup but checking collision/flagging is not something I've run really dealt with like this so far, still learning. For the record both @sp202 and @FrostyCat solutions work.
Here it is.

Timer object Create Event
Code:
global.checklap = 0
global.seconds = 0
global.besttime=global.seconds
Timer object Step Event
Code:
global.seconds += 1/room_speed
Timer object draw GUI
Code:
display_set_gui_size(view_wview[0], view_hview[0])
draw_set_font(fnt_emulator)
draw_set_color(c_black)

draw_text(200,16, "Time: " + string(global.seconds))
draw_text(200,32, "Best: " + string(global.besttime))
draw_text(200,64, "check: " + string(global.checklap))
if global.shift = 1 {
    draw_sprite(spr_gearshift,1,416,32)
}
if global.shift = 2 {
    draw_sprite(spr_gearshift,0,416,32)
    }
Start/Finish line object Create Event
Code:
lapping = false
Start/Finish line Step Event
Code:
if lapping=true and place_meeting(x,y,obj_indycar)=false
{
lapping=false
}
Start/Finish line object Collision with car
Code:
if (!lapping) {
  global.besttime=global.seconds
  global.seconds = 0;
  global.checklap += 1;
  lapping = true;
 }
Both checks work and the timer counts up and resets, a lap best time is registered and the lap check counts one each time the car crosses the start/finish line. Thanks again everyone for your time,knowledge and patience.
 

sp202

Member
No problem. I'd advise against initializing best time to 0 and instead setting it to -1 which is for sure an illegal time (I know the time can never be 0, but it looks better!).
 
Top