offside/player.gd

79 lines
2.1 KiB
GDScript

extends Area2D
# Maximum radial turning speed of the player
@export var turning_speed = PI/4 # (rad/sec)
# Maximum speed added to player's velocity per push
@export var skate_speed = 100 # (pixels/sec)
# Maximum speed deceleration while stopping
@export var braking_speed = 200 # (pixels/sec^2)
# "Natural" deceleration
@export var decel_ratio = 0.15 # (decel applied per second)
var velocity: Vector2
func _ready():
velocity = Vector2.ZERO
func _physics_process(delta: float):
# Flip sprite
if velocity.length() > 0:
$AnimatedSprite2D.flip_h = velocity.x > 0
# Update position
position = clamp_position(position + (velocity * delta))
# Decelerate naturally
# TODO fix vector math, need to apply to hypotenuse, not the sides
# TODO fix decel math, think compounding interest, it doesn't work this way
# TODO brake harder when almost stopped
velocity = velocity * (1 - decel_ratio * delta)
func push(effort: float, angle: float):
var delta_v = effort * skate_speed
velocity += delta_v * Vector2.from_angle(angle)
# TODO how to do doc comments?
# TODO should applying delta come from the controller or the player? It doesn't
# matter too much because these objects are pretty tightly coupled anyways.
func turn(effort: float, delta: float):
# Continuosly call with the effort while turning
# effort is +ve right, -ve left? maybe, some orientation
velocity = velocity.rotated(effort * turning_speed * delta)
func brake(effort: float, delta: float):
var delta_v = effort * braking_speed * delta
delta_v = min(delta_v, velocity.length())
velocity -= delta_v * velocity.normalized()
# TODO setup collision from world, and edges of arena, not the window
func clamp_position(new_pos: Vector2) -> Vector2:
var size = Vector2(get_window().size)
if new_pos.x > size.x:
if velocity.x > 0:
velocity.x = 0
new_pos.x = size.x
if new_pos.x < 0:
if velocity.x < 0:
velocity.x = 0
new_pos.x = 0
if new_pos.y > size.y:
if velocity.y > 0:
velocity.y = 0
new_pos.y = size.y
if new_pos.y < 0:
if velocity.y < 0:
velocity.y = 0
new_pos.y = 0
return new_pos