2024-12-02 13:45:17 +01:00
|
|
|
|
extends RigidBody2D
|
|
|
|
|
|
|
|
|
|
|
|
@export var speed = 400
|
2024-12-04 08:48:48 +01:00
|
|
|
|
@export var explosion_damage = 600
|
2024-12-02 13:45:17 +01:00
|
|
|
|
|
|
|
|
|
|
var velocity = Vector2.ZERO
|
|
|
|
|
|
var is_in_flight = false
|
|
|
|
|
|
var has_exploded = false # Flag to track if the bomb has exploded
|
|
|
|
|
|
|
|
|
|
|
|
@onready var sprite = $Sprite2D
|
|
|
|
|
|
@onready var collision = $CollisionShape2D
|
|
|
|
|
|
@onready var particles = $Explosion
|
|
|
|
|
|
@onready var explosion_sound = $AudioStreamPlayer2D
|
|
|
|
|
|
@onready var explosion_area = $ExplosionArea
|
|
|
|
|
|
@onready var timer = $Timer
|
|
|
|
|
|
@onready var camera = get_parent().get_parent().get_node("MultiTargetCamera")
|
|
|
|
|
|
@onready var tile_map_layer = get_parent().get_parent().get_node("TileMapLayer")
|
|
|
|
|
|
@export var off_screen_margin = 2000
|
|
|
|
|
|
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
|
camera.add_target(self)
|
|
|
|
|
|
|
|
|
|
|
|
global_position = position
|
|
|
|
|
|
z_index = -1
|
|
|
|
|
|
# Disable the particles and audio on start
|
|
|
|
|
|
particles.emitting = false
|
|
|
|
|
|
explosion_sound.playing = false
|
|
|
|
|
|
|
|
|
|
|
|
# Connect the timer's timeout signal to the cleanup function
|
|
|
|
|
|
timer.connect("timeout", _on_timeout)
|
|
|
|
|
|
|
|
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
|
|
|
|
if is_in_flight:
|
|
|
|
|
|
# Explode if the bomb goes off-screen
|
|
|
|
|
|
if is_off_screen() and not has_exploded:
|
|
|
|
|
|
trigger_explosion()
|
|
|
|
|
|
|
|
|
|
|
|
# This function is used to set the velocity of the bomb when it’s thrown
|
|
|
|
|
|
func set_velocity(new_velocity: Vector2) -> void:
|
|
|
|
|
|
# Apply an impulse based on the new velocity
|
|
|
|
|
|
apply_central_impulse(new_velocity)
|
|
|
|
|
|
is_in_flight = true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to trigger the explosion
|
|
|
|
|
|
func trigger_explosion():
|
|
|
|
|
|
if has_exploded:
|
|
|
|
|
|
return # Prevent multiple explosions
|
|
|
|
|
|
|
|
|
|
|
|
# Set the flag to true, indicating that the bomb has exploded
|
|
|
|
|
|
has_exploded = true
|
|
|
|
|
|
|
|
|
|
|
|
camera.remove_target(self)
|
|
|
|
|
|
|
|
|
|
|
|
# Play the explosion sound
|
|
|
|
|
|
explosion_sound.play()
|
|
|
|
|
|
|
|
|
|
|
|
# Enable and emit the particles
|
|
|
|
|
|
particles.emitting = true
|
|
|
|
|
|
|
|
|
|
|
|
# Push away players within the explosion radius
|
|
|
|
|
|
push_away_players()
|
|
|
|
|
|
|
|
|
|
|
|
# Destroy tiles in the explosion radius
|
|
|
|
|
|
destroy_tiles_in_explosion_area()
|
|
|
|
|
|
|
|
|
|
|
|
# Start the timer to cleanup the explosion
|
|
|
|
|
|
timer.start()
|
|
|
|
|
|
|
|
|
|
|
|
sprite.hide()
|
|
|
|
|
|
|
|
|
|
|
|
func push_away_players():
|
|
|
|
|
|
if not explosion_area:
|
|
|
|
|
|
print("ExplosionArea2D is missing!")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
var overlapping_bodies = explosion_area.get_overlapping_bodies()
|
|
|
|
|
|
print("Overlapping bodies:", overlapping_bodies)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for body in overlapping_bodies:
|
|
|
|
|
|
if body is RigidBody2D:
|
|
|
|
|
|
print("Pushing body:", body.name)
|
|
|
|
|
|
|
|
|
|
|
|
var direction = (body.global_position - global_position).normalized()
|
|
|
|
|
|
var impulse = direction * explosion_damage
|
|
|
|
|
|
body.apply_central_impulse(impulse)
|
|
|
|
|
|
|
|
|
|
|
|
func destroy_tiles_in_explosion_area():
|
2024-12-03 20:16:17 +01:00
|
|
|
|
var center = global_position # Explosion center in global coordinates
|
|
|
|
|
|
var radius = 150 # Explosion radius in pixels
|
|
|
|
|
|
|
|
|
|
|
|
# Convert center to map coordinates
|
2024-12-02 13:45:17 +01:00
|
|
|
|
var map_center = tile_map_layer.local_to_map(center)
|
2024-12-03 20:16:17 +01:00
|
|
|
|
print("Explosion center in map coordinates:", center, map_center)
|
|
|
|
|
|
|
|
|
|
|
|
# Tile dimensions
|
2024-12-02 13:45:17 +01:00
|
|
|
|
var tile_width = 16
|
|
|
|
|
|
var tile_height = 16
|
2024-12-03 20:16:17 +01:00
|
|
|
|
|
|
|
|
|
|
# Calculate bounds of explosion in tile coordinates
|
|
|
|
|
|
var min_x = int((center.x - radius) / tile_width)
|
|
|
|
|
|
var max_x = int((center.x + radius) / tile_width)
|
|
|
|
|
|
var min_y = int((center.y - radius) / tile_height)
|
|
|
|
|
|
var max_y = int((center.y + radius) / tile_height)
|
|
|
|
|
|
|
|
|
|
|
|
print("Explosion bounds in tile coordinates: ", Vector2i(min_x, min_y), Vector2i(max_x, max_y))
|
|
|
|
|
|
|
|
|
|
|
|
# Loop through the affected tiles
|
2024-12-02 13:45:17 +01:00
|
|
|
|
for x in range(min_x, max_x + 1):
|
|
|
|
|
|
for y in range(min_y, max_y + 1):
|
2024-12-03 20:16:17 +01:00
|
|
|
|
# Calculate the distance from the explosion center to the tile center
|
|
|
|
|
|
var tile_pos = tile_map_layer.map_to_local(Vector2i(x, y))
|
|
|
|
|
|
var dist = center.distance_to(tile_pos)
|
|
|
|
|
|
|
|
|
|
|
|
# Check if the tile is within the explosion radius
|
2024-12-02 13:45:17 +01:00
|
|
|
|
if dist <= radius:
|
2024-12-03 20:16:17 +01:00
|
|
|
|
print("Checking tile at:", Vector2i(x, y), "Distance:", dist)
|
|
|
|
|
|
print(tile_map_layer.get_cell_source_id(Vector2i(x, y)))
|
|
|
|
|
|
|
|
|
|
|
|
# Erase the tile if it exists
|
2024-12-02 13:45:17 +01:00
|
|
|
|
if tile_map_layer.get_cell_source_id(Vector2i(x, y)) != -1:
|
|
|
|
|
|
tile_map_layer.erase_cell(Vector2i(x, y))
|
2024-12-03 20:16:17 +01:00
|
|
|
|
print("Erased tile at:", Vector2i(x, y))
|
2024-12-02 13:45:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Function to check if the bomb is off-screen
|
|
|
|
|
|
func is_off_screen() -> bool:
|
|
|
|
|
|
var screen_rect = Rect2(camera.position - camera.zoom * camera.get_viewport_rect().size / 2,
|
|
|
|
|
|
camera.zoom * camera.get_viewport_rect().size)
|
|
|
|
|
|
screen_rect = screen_rect.grow(off_screen_margin) # Expand the screen rectangle by the margin
|
|
|
|
|
|
return not screen_rect.has_point(global_position)
|
|
|
|
|
|
|
|
|
|
|
|
# Cleanup function called when the timer times out
|
|
|
|
|
|
func _on_timeout():
|
|
|
|
|
|
# Once the timer finishes, queue the particles for cleanup (optional)
|
|
|
|
|
|
particles.emitting = false
|
|
|
|
|
|
explosion_sound.stop() # Stop the sound if it's still playing
|
|
|
|
|
|
|
|
|
|
|
|
queue_free()
|