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