smashball/scenes/ball/ball.gd
2025-11-17 21:45:45 -03:00

72 lines
2.3 KiB
GDScript

extends RigidBody2D
@onready var hurtbox: Area2D = $HurtArea2D
@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
@export var launch_speed: Vector2 = Vector2(150, 250)
@export var speed_mult: float = 1.08
var current_decel_tween: Tween = null
var is_hit: bool = false
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
#connect("body_entered", _on_collision)
hurtbox.connect("area_entered", _on_hit)
launch()
func launch(angle: float = 0, speed_override: float = 0) -> void:
angle = randf_range(-PI/3, PI/3) + PI * float(randi()%2) if angle == 0 else angle
linear_velocity = Vector2(cos(angle), sin(angle)) * (randf_range(launch_speed.x, launch_speed.y) if speed_override == 0 else speed_override)
var length: float = linear_velocity.length()/100
play_animation(length)
decelerate_to_stop(length*2)
func play_animation(speed_scale: float = 0) -> void:
assert(speed_scale != 0, "speed_scale is zero for aniumation")
sprite.speed_scale = speed_scale * (1 if randi()%2 == 0 else -1)
sprite.play("default")
func decelerate_to_stop(duration: float = 0.3) -> void: # Call this after collision
# KILL ANY EXISTING TWEEN (one at a time guaranteed!)
if current_decel_tween:
current_decel_tween.kill()
# CREATE NEW ONE
current_decel_tween = create_tween()
current_decel_tween.tween_property(sprite, "speed_scale", 0.0, duration)
current_decel_tween.tween_callback(func() -> void:
sprite.pause() # Freeze on last frame
current_decel_tween = null # Clean up
)
func _on_hit(hitbox: Hit) -> void:
print("area detected")
if not is_hit:
if hitbox.is_in_group("hit"):
assert(hitbox.power_hit != null, "hit doesnt have correct metadata, is it a hit?")
print("ball not hit yet")
var player: Player = hitbox.get_parent()
var timer: Timer = player.hit_timer
var angle: float = randf_range(3*PI/4, PI/4) * (-1 if player.id == 1 else 1)
var speed: float = randf_range(300, 350) if hitbox.power_hit else 0.0 # o.o
launch(angle, speed)
print("ball hit")
if not timer.is_connected("timeout", _on_hit_end):
timer.connect("timeout", _on_hit_end)
EventBus.ball_hit.emit(player.id, linear_velocity)
is_hit = true
func _on_hit_end() -> void:
is_hit = false
func _on_collision(_body: Node) -> void:
var length: float = linear_velocity.length()/100
play_animation(length)
decelerate_to_stop(length)