tool extends "res://objects/enemy/enemy_move_sidesideupdown.gd" enum SpikeDirection {BOTH, LEFT, RIGHT} ## positions along the path where spikes will trigger export (Array, float) var spike_positions: Array = [] ## time spikes stay active export var spike_time: float = 0.25 ## which direction the turtle should be able to spike export (SpikeDirection) var spike_direction: int = SpikeDirection.BOTH # animates the spikes var can_spike: bool = true var spike_tween: SceneTreeTween # index of the current spike position to check for onready var current_spike_position: int = 0 onready var sprite: Sprite = $"%Sprite" onready var spike_shape: CollisionShape2D = $"%SpikeShape" func _ready() -> void: # don't act in the editor if Engine.editor_hint: return # positions must be in order spike_positions.sort() for i in spike_positions.size(): # scale to be in tiles spike_positions[i] = spike_positions[i] * 8.0 # should start with the first positive spike position if spike_positions[i] < 0.0: current_spike_position = i + 1 func _process(delta: float) -> void: # update debug graphics in editor if Engine.editor_hint and Engine.get_frames_drawn() % 10 == 0: update() func _physics_process(delta: float) -> void: # do nothing in editor if Engine.editor_hint: return # sync hitbox $HeadHitbox.scale.x = $ToFlip.scale.x # check if can still spike before doing all this work if not can_spike: return # use positions in correct axis var pos = position.x if move_direction == Direction.HORIZONTAL else position.y var pos_start = startpos.x if move_direction == Direction.HORIZONTAL else startpos.y # slightly different logic depending on forward/backwards unfortunately :I match sign(direction): 1.0: # make sure there are any positions left to check in this direction if current_spike_position < spike_positions.size(): # check if passed the spike position if pos >= pos_start + spike_positions[current_spike_position]: # move on to next position current_spike_position += 1 if spike_direction != SpikeDirection.LEFT: spike() -1.0: # make sure there are still positions left in this direction if current_spike_position - 1 >= 0: # check if passed the position if pos <= pos_start + spike_positions[current_spike_position - 1]: # move on to next (previous because backwards) position current_spike_position -= 1 if spike_direction != SpikeDirection.RIGHT: spike() ## performs the spike animation func spike() -> void: # reset tween if spike_tween != null: spike_tween.kill() # never have two tweens acting on the same thing spike_tween = create_tween() spike_tween.set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) # indicator sprite spike_tween.tween_property(sprite, "frame_coords:y", 1.0, 0.0) spike_tween.tween_interval(spike_time * 2.0) # spikes active spike_tween.tween_property(spike_shape, "disabled", false, 0.0) spike_tween.tween_property(sprite, "frame_coords:y", 2.0, 0.0) spike_tween.tween_interval(spike_time) # spikes gone once more spike_tween.tween_property(spike_shape, "disabled", true, 0.0) spike_tween.tween_property(sprite, "frame_coords:y", 0.0, 0.0) func die() -> void: # disable spiking can_spike = false # stop tween if spike_tween != null: spike_tween.kill() # disable hitbox spike_shape.set_deferred("disabled", true) # reset animation sprite.frame_coords.y = 3 Audio.play_sound(death_sound, Audio.ac_die) $"%DeathSplatter".emitting = true func _draw() -> void: if Engine.editor_hint: # still draw base moving enemy debug lines ._draw() # draw dots at spike positions for pos in spike_positions: var dir = Vector2.RIGHT if move_direction == Direction.HORIZONTAL else Vector2.DOWN draw_circle(dir * pos * 8.0, 2.0, Color.red)