Files
brotato/scenes/weapons/weapon.gd
T
luke358 cf8c5b90ff feat: 1. 武器自动根据最近的敌人旋转
2. 流程:player 初始化调用 add_weapon,更新weapon_container,weapon_punch在_process每一帧中监听,更新update_closest_target最近的敌人,然后rotate_to_target旋转到最近的敌人
2026-05-19 16:44:31 +08:00

109 lines
2.4 KiB
GDScript

extends Node2D
class_name Weapon
@onready var sprite_2d: Sprite2D = $Sprite2D
@onready var collision: CollisionShape2D = %CollisionShape2D
@onready var cooldown_timer: Timer = $CooldownTimer
var data: ItemWeapon
var is_attacking := false
var atk_start_pos: Vector2
var targets: Array[Enemy]
var closest_target: Enemy
var weapon_spread: float
func _ready() -> void:
atk_start_pos = sprite_2d.position
func _process(delta: float) -> void:
if not is_attacking:
if targets.size() > 0:
update_closest_target()
else:
closest_target = null
rotate_to_target()
func setup_weapon(_data: ItemWeapon) -> void:
self.data = _data
collision.shape.radius = data.stats.max_range
func use_weapon() -> void:
calculate_spread()
func rotate_to_target() -> void:
if is_attacking:
rotation = get_custom_rotation_to_target()
else:
rotation = get_rotation_target()
func get_custom_rotation_to_target() -> float:
if not closest_target or not is_instance_valid(closest_target):
return rotation
var rot := global_position.direction_to(closest_target.global_position).angle()
return rot + weapon_spread
func get_rotation_target() -> float:
if targets.size() == 0:
return get_idle_rotation()
var rot := global_position.direction_to(closest_target.global_position).angle()
return rot
func get_idle_rotation() -> float:
if Global.player.is_facing_right():
return 0
else:
return PI
func calculate_spread() -> void:
weapon_spread += randf_range(-1 + data.stats.accurary, 1- data.stats.accurary)
rotation += weapon_spread
func update_closest_target() -> void:
closest_target = get_closest_target()
func get_closest_target() -> Node2D:
# 没有敌人在攻击范围
if targets.size() == 0:
return
var closest_enemy := targets[0]
var closest_distance := global_position.distance_to(closest_enemy.global_position)
for i in range(1, targets.size()):
var target: Enemy = targets[i]
var distance := global_position.distance_to(target.global_position)
if distance < closest_distance:
closest_enemy = target
closest_distance = distance
return closest_enemy
func can_use_weapon() -> bool:
return cooldown_timer.is_stopped() and closest_target
func _on_range_area_area_entered(area: Area2D) -> void:
targets.push_back(area)
func _on_range_area_area_exited(area: Area2D) -> void:
targets.erase(area)
if targets.size() == 0:
closest_target = null