extends RigidBody2D @export var speed = 400 @export var explosion_damage = 2000 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() # Check for spacebar press to explode, only if the bomb hasn't exploded if Input.is_action_just_pressed("throw_bomb") 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(): var center = global_position # This is the center of the explosion in global coordinates var radius = 30 # The radius of the explosion # Convert center to map coordinates, taking scale into account var map_center = tile_map_layer.local_to_map(center) print("Center: ", map_center) # Get the scale factor of the TileMapLayer var scale = tile_map_layer.scale.x # Assuming uniform scale for both x and y var tile_width = 16 var tile_height = 16 # Get the bounding box for the explosion area in map coordinates var min_x = int((map_center.x - radius * tile_width) / tile_width) var max_x = int((map_center.x + radius * tile_width) / tile_width) var min_y = int((map_center.y - radius * tile_height) / tile_height) var max_y = int((map_center.y + radius * tile_height) / tile_height) # Loop through all cells in the bounding box for x in range(min_x, max_x + 1): for y in range(min_y, max_y + 1): # Calculate distance from the center of the explosion (map coordinates) var dist = map_center.distance_to(Vector2(x, y)) # Check if the tile is within the explosion radius (using the distance check) if dist <= radius: # Print out some debug information print("Checking tile:", Vector2i(x, y), "Distance:", dist) # Check if the tile is within the bounds of the map and not empty if tile_map_layer.get_cell_source_id(Vector2i(x, y)) != -1: # Erase the tile at coordinates (x, y) in map coordinates tile_map_layer.erase_cell(Vector2i(x, y)) # 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()