Tire drift / skid marks with Line2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Tato64

Hey gang! Im here once again finding new ways to lose my mind :slight_smile:

Basically, top-down 2D, im trying to implement skid marks for when cars drift.

The marks will start when the car is drifting, will add line2D points while it’s drifting, and stop adding point when it stops drifting. (Afterwards the line2D will fade out and delete itself)

To be clear, this https://www.youtube.com/watch?v=s5DwZZ0fZDg is NOT what im trying to do. (trails that follow the wheels all the time), i want trails that will appear when triggered, stop when triggered to stop, stay there in the world for a while and then dissapear.

Believe me i have tried a lot of methods but none worked like i want to.

My relevant code is the following, it seems to correctly manage the “Start, drift, end”, but doesnt work at all since no Line2D shows, im adding it in case its worthy to “fix”:

(This is in _physics_process)

var drifting = false
var driftmark1 = driftmark.instance()

	if Input.is_action_just_pressed("space"): #The first press of space starts the drift.
		print("drift start") #Debugging purposes
		get_parent().add_child(driftmark1) #Adds the "driftmark" node to the world.
		driftmark1.set_global_position($Wheelpos.global_position) #In the position of the wheel
		drifting = true #Its drifting


	if Input.is_action_just_released("ui_select"): #When space is released
		print("drift end") #Debugging purposes
		drifting = false #It's not drifting


	if Input.is_action_pressed("ui_select"): #WHILE space is held down
		print("adding point")
		if drifting:
			driftmark1.add_point($Wheelpos.global_position) #Adds points to the Line2D in the wheel position

(The “Fading out and deleting itself” part is managed in the driftmark node itself. It’s just a timer that fades everything out, and then another timer that queue_free’s the node)

Thanks in advance for any help!

A few comments / questions:

First, I notice you’re using both a “space” action and a “ui_select” action. I assume both are wired to the space bar, right? Since you say the code seems to correctly manage start, drift, and end, I assume so…

Once you’ve added (or think you’ve added a drift mark) in-game, you should be able to inspect the live scene tree and see what your line looks like.

Just run your game, add some drift points (but don’t delete them for now), open the Remote scene tree, navigate to the Line2D node that represents your drift mark and see what it looks like.

  • Does it exist?
  • Is it where (in space) you expect it to be?
  • Does it have any points associated with it?
  • Are the points as expected?

jgodfrey | 2020-12-11 22:58

Hey!
First of all, thanks for helping out.

And yes, “space” and “ui_select” are the same, thanks for pointing that out, didnt notice.

Second, after launching the sandbox scene and drifting a bit, the “driftmark” nodes show up correctly on the “remote” list (I drifted 4 times, i have 4 instances of it) and delete themselves after some time like intended.

After that, i added a “print” for get_point_count() to see if they’re being added. Only 1 point is being added.

This surely seems to be the culprit.

I’m looking into it but let me know if you figure something out :slight_smile:

Tato64 | 2020-12-11 23:37

Hmmm, what seems weird to me is that:

if Input.is_action_pressed("ui_select"):
    print("adding point")
    if drifting:
        driftmark1.add_point($Wheelpos.global_position)

This prints an “Adding point” every frame. But it doesnt add a point every frame, it only adds one. (I tried removing the “If drifting” condition but it did nothing.

EDIT: Ok, i added print("adding point") to the “if drifting” and it triggers only once, so that var should be removed altogether.

EDIT 2: OMG IT WAS SO HARD TO FIGURE OUT BUT I COULD DO IT, THANK YOU SO MUCH FOR MAKING ME SEE WHERE THE ACTUAL PROBLEM WAS., i’ll update with a detailed answer right now :slight_smile:

Tato64 | 2020-12-11 23:48

:bust_in_silhouette: Reply From: Tato64

SOLVED

Ok, so…

Basically, in the car node, the press (is_action_just_pressed) of spacebar spawns the driftmark node, in the position of the wheel. And while spacebar is being held down (is_action_pressed) it updates a singleton (Google this if you’re unfamiliar with them, but it’s basically a script thats autoloaded everywhere, where you can store info) that stores the wheel position.

That’s it for the car node. And here’s the code:

	if Input.is_action_just_pressed("ui_select"):
		get_parent().add_child(driftmark1)
		driftmark1.set_global_position($Wheel3pos.global_position)
	if Input.is_action_pressed("ui_select"):
		Playervars.wheel3pos = $Wheel3pos.global_position

Now, on the driftmark node part…

The driftmark requires two essential variables called “drifting” (set to true), and “target” (set to nothing right now), then, every frame it updates the “target” to the wheel position, how? Using the singleton i named before, it also adds a point in that target position, but only if it’s drifting! (That’s why its set to true at first). And finally, releasing spacebar (is_action_just_released) sets “drifting” to false, so no more points are added to the line2d.

This is the whole code for the driftmark node:

var target
var point
var length = 100
var drifting = true

func _ready():
	$Life.start()
	
func _process(delta):
	target = Playervars.wheel3pos
	global_position = Vector2.ZERO
	global_rotation = 0
	print(Playervars.wheel3pos)
	point = target
	if drifting:
		add_point(point)

	if Input.is_action_just_released("ui_select"):
		drifting = false
	
	while get_point_count() > length:
		remove_point(0)

func _on_Life_timeout():
	$Delete.start()

func _on_Delete_timeout():
	remove_point(0)
	if get_point_count() <= 0:
		queue_free()

(I have added a “length” variable to delete the oldest point once the line reaches a certain ammount of points on it. Then “Life” is a timer that starts the delete after 3 seconds, and “Delete” is a timer on a loop, that deletes the oldest point every 0.01 seconds, and ultimately deletes the whole node when there are no more points.

This is all for performance concerns, but should be tweaked to your needs. For example, with this code if you start tapping space a bunch of times, FPS will start to drop a noticeable ammount, you could also add all the driftmark node to á group of it’s own, and if the nodes in that group reach a certain number, you start deleting the oldest ones.)

Big shoutout to Jgodfrey for leading me to the actual cause of the problem!

See y’all next time!