Collisions being counted twice for my KinematicBody2D
Asked Answered
G

3

0

I'm new to Godot and I'm making a 2-player racing game where the 2 cars should bounce against each other, but they needed to be KinematicBody2D types to get the movement how I wanted it, meaning I needed to hardcode the bounce functionality. Every works quite well actually, but sometimes (and only sometimes) the first player p1 collides with p2 and then, on the same frame, after the collision was detected, p2 detects the same collision. This causes 2 bounces in the same frame and the resulting bounce vectors are wrong.

Here's how the code works. If p1's bouncing property is false, it is considered to be in a moving state. move_player() is called in the _process(delta) function, and p1 moves. If it collides with p2, it calls the toBounceState() function, which calculates the vectors that both players should go into, setting their respective bounceVelocity properties, as well as setting bouncing to true for both players. After the toBounceState() and the move_player() functions finish, the code moves onto p2 and does the same thing. Except, if there was a collision, it should call p2's bounce_player() function instead of move_player(). bounce_player() just moves the player according to its bounceVelocity property, and if it notices another collision, manages that collision in exactly the same way as if it collided in its move state. The bounce state lasts for .5 seconds, then goes back to move.

Again, everything works as intended except the players sometimes bounce twice for one collision, causing p1 to
appear to sort of push p2 without actually bouncing correctly. I thought this was because p2 tries to detect collision before p1 actually attempts to bounce away on the next frame, meaning the two cars are still technically colliding, so I made it so collision detection causes the colliding car to call bounce_player() once before moving on. I was hoping to put some space in between the cars before p2 tries to move/bounce. This doesn't work though, and I don't know why.

extends Node

onready var p1 = get_node("Car")
onready var p2 = get_node("Car2")

func _ready():
	var player2Texture = preload("res://assets/blue_car.png")
	p2.get_node("Sprite").set_texture(player2Texture)
	
func _process(delta):
	if !p1.bouncing:
		move_player(delta, p1, "1")
	elif p1.bouncing:
		bounce_player(p1)
	if !p2.bouncing:
		move_player(delta, p2, "2")
	elif p2.bouncing:
		bounce_player(p2)
		
func move_player(delta, player, slot):
	var velocity = Vector2.ZERO
	
	if Input.is_action_pressed("p" + slot + "_up"):
		velocity.y -= 1
	if Input.is_action_pressed("p" + slot + "_down"):
		velocity.y += 1
	if Input.is_action_pressed("p" + slot + "_right"):
		velocity.x += 1
	if Input.is_action_pressed("p" + slot + "_left"):
		velocity.x -= 1
	
	if velocity.length() > 1:
		velocity = velocity.normalized()
	velocity *= player.speed * delta
	var collision = player.move_and_collide(velocity)
	if collision != null:
		toBounceState(collision, p1, velocity)
		bounce_player(player)

	
	if velocity.length() != 0:
		player.rotation = velocity.angle() + PI / 2
			
func bounce_player(player):
	var velocity = player.bounceVelocity
	var collision = player.move_and_collide(velocity)
	if collision != null:
		toBounceState(collision, player, velocity)

func toBounceState(collision, player, player_vel): # collider is the thing you're hitting
	var collider_v = collision.get_collider_velocity().limit_length(player_vel.length())
	var collider = collision.get_collider()
	
	# if x vectors are opposed, negate them
	# elif x vector is 0, add other x vector
	# else don't change them
	var new_collider_v = collider_v
	if new_collider_v.x == 0:
		new_collider_v.x = player_vel.x
		player_vel.x *= -1
	elif new_collider_v.x == -1 * player_vel.x:
		new_collider_v.x *= -1
		player_vel.x *= -1
		
	if new_collider_v.y == 0:
		new_collider_v.y = player_vel.y
		player_vel.y *= -1
	elif new_collider_v.y == -1 * player_vel.y:
		new_collider_v.y *= -1
		player_vel.y *= -1
		
	collider.bounceVelocity = new_collider_v
	collider.bouncing = true
	
	player.bounceVelocity = player_vel
	player.bouncing = true
Girdler answered 11/2, 2023 at 21:55 Comment(0)
G
0

Also shoot, the code is totally messed up in this post. Don't know why that happened.

Girdler answered 11/2, 2023 at 21:56 Comment(0)
M
0

Girdler Also shoot, the code is totally messed up in this post. Don't know why that happened.

I fixed it! For multi line code, you need to surround the code in three ~ characters rather than `, which is for single line code.

Mair answered 11/2, 2023 at 23:10 Comment(0)
G
0

Mair Ah, thank you.

Girdler answered 12/2, 2023 at 1:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.