HOME / 第 7 部分 · 完整游戏项目实战 / 第 84 课
MODULE 7 · 完整游戏项目实战
第 84 课 · 塔防游戏实战(二):炮塔与攻击
🎯 本课学习目标
- 实现炮塔放置
- 让炮塔瞄准并攻击敌人
- 敌人掉血与死亡
塔防第二课:玩家建炮塔,炮塔自动锁定并攻击路径上的敌人。
📖 详细教学步骤
炮塔场景搭建
- 新建 turret.tscn,根 Node2D
- 子节点:Sprite2D(炮塔底座)+ Sprite2D(炮管,可旋转)
- 子节点 Area2D(攻击范围,圆形)
- 挂脚本 turret.gd
炮塔放置代码
点击空地放置炮塔:
GDSCRIPT# main.gd
const TURRET = preload("res://turret.tscn")
func _unhandled_input(event):
if event is InputEventMouseButton and event.pressed:
if event.button_index == MOUSE_BUTTON_LEFT:
if can_afford(TURRET_COST):
spend_gold(TURRET_COST)
var t = TURRET.instantiate()
t.position = get_global_mouse_position()
add_child(t)
炮塔搜索敌人代码
在攻击范围内找最近的敌人:
GDSCRIPTextends Node2D
@onready var range_area: Area2D = $RangeArea
@onready var barrel: Sprite2D = $Barrel
@export var fire_rate: float = 1.0 # 每秒射击次数
@export var damage: int = 10
var cooldown: float = 0.0
func _physics_process(delta):
cooldown -= delta
var target = find_target()
if target:
# 炮管对准目标
barrel.rotation = (target.global_position - global_position).angle()
if cooldown <= 0:
cooldown = 1.0 / fire_rate
shoot(target)
func find_target():
var best = null
var best_progress = -1.0
for body in range_area.get_overlapping_bodies():
if body.has_method("take_damage"):
# 选「路径进度最大」的敌人(最靠前)
if body.progress > best_progress:
best = body
best_progress = body.progress
return best
射击代码
发射子弹:
GDSCRIPTconst BULLET = preload("res://bullet.tscn")
func shoot(target):
var bullet = BULLET.instantiate()
bullet.global_position = global_position
bullet.target = target
bullet.damage = damage
get_parent().add_child(bullet)
子弹追踪敌人代码
子弹朝目标飞去:
GDSCRIPTextends Area2D
var target
var damage: int = 10
@export var speed: float = 300.0
func _physics_process(delta):
if target == null or not is_instance_valid(target):
queue_free() # 目标没了,子弹消失
return
# 飞向目标
global_position = global_position.move_toward(
target.global_position, speed * delta)
敌人掉血死亡代码
敌人脚本补充:
GDSCRIPTvar hp: int = 100
func take_damage(amount: int):
hp -= amount
if hp <= 0:
die()
func die():
Globals.gold += 10 # 击杀奖励
queue_free()
测试测试
- 放几只敌人沿路径走
- 点击空地放炮塔
- 炮塔自动转向最近的敌人并射击
- 敌人掉血死亡加金币
🎉 塔防核心战斗完成!
⚠️
炮塔不攻击?
确认:①RangeArea 有 CollisionShape;②敌人是 Area2D/物理体且加入范围;③敌人有 take_damage 方法。
⚠️
子弹不追踪?
子弹 target 引用可能失效(敌人已删)。用 is_instance_valid 判断并销毁子弹。
🧪 动手试一试
🏋️ 课后练习
让炮塔发射「火球」(带拖尾粒子),击中敌人时播放爆炸小特效并造成范围伤害。
子弹 Area2D + 命中时实例化粒子。
💡
选「最靠前」敌人(progress 最大)是塔防常用策略。
💡
子弹用 Area2D 检测命中比物理碰撞更轻量。
🎓 本课小结
塔防战斗:点击放炮塔 → 攻击范围找最近/最靠前敌人 → 炮管瞄准 → 发射追踪子弹 → 敌人掉血死亡给金币。