Godot游戏练习01-第8节-添加场地和敌人追踪

今天还是继续完成游戏练习, 上次我们已经在场景中生成敌人, 但是没有一个战斗场地, 并且敌人不会动, 今天来完善这些内容

先看看效果

动画4

实现过程

添加战斗场地

这部分比较简单, 使用Sprite2D显示一张背景图

再到Main场景中新增4个StaticBody2D, 覆盖战斗场地的四周, 防止敌人或者玩家跑出场地之外

2

敌人生成整理

上一节中我们在Main场景中直接生成, 但是将所有逻辑都糅杂在一个场景中并不是一个好习惯, 最好使用组件化思路, 拆分逻辑

这里我们使用一个EnemySpawnComponent组件, 专门负责敌人生成逻辑

class_name EnemySpawnComponent
extends Node

const ENEMY = preload("uid://pu2c45uixpy0")

@export var spawn_root: Node2D
@export var spawn_rect: ReferenceRect


@onready var spawn_timer: Timer = $SpawnTimer

func _ready() -> void:
	if is_multiplayer_authority():
		spawn_timer.timeout.connect(_on_spawn_timer_timeout)
	else:
		spawn_timer.process_mode = Node.PROCESS_MODE_DISABLED


func _get_random_position() -> Vector2:
	var pos := Vector2(
		randf_range(0, spawn_rect.size.x),
		randf_range(0, spawn_rect.size.y),
	)
	pos += spawn_rect.global_position
	return pos


func _on_spawn_timer_timeout() -> void:
	var enemy := ENEMY.instantiate() as Node2D
	enemy.global_position = _get_random_position()
	#print("[peer %s] enemy spawn pos: %s" % [multiplayer.get_unique_id(), enemy.global_position])
	spawn_root.add_child(enemy, true)
	spawn_timer.start(randf_range(1.0, 5.0))

核心功能一个是获取一个随机的位置, 一个是生成敌人, 通过Timer控制生成频率, 并增加一些随机生成间隔

通过Main场景传入的ReferenceRect来确定敌人随机生成的范围, 也就是上面Main场景截图中的红色边框范围

注意: 敌人生成应当仅在服务端执行, 其余peer通过MultiplayerSpawner同步

敌人的自动跟踪

先将Player场景添加分组"player"

修改Enemy脚本逻辑

var track_target: Vector2
var has_track_target: bool = false

func _ready() -> void:
	if is_multiplayer_authority():
		area_2d.area_entered.connect(_on_area_entered)
		track_timer.timeout.connect(_on_track_timer_timeout)
		_update_track_target()
	else:
		track_timer.process_mode = Node.PROCESS_MODE_DISABLED


func _process(_delta: float) -> void:
	if is_multiplayer_authority():
		if has_track_target:
			velocity = global_position.direction_to(track_target) * 40
			move_and_slide()


func _update_track_target() -> void:
	var players := get_tree().get_nodes_in_group("player")
	var min_squared_distance: float
	var track_player: Node2D = null
	for player in players:
		if track_player == null:
			track_player = player
			min_squared_distance = track_player.global_position.distance_squared_to(global_position)
		var squared_distance = player.global_position.distance_squared_to(global_position)
		if squared_distance < min_squared_distance:
			min_squared_distance = squared_distance
			track_player = player
	if track_player != null:
		track_target = track_player.global_position
		has_track_target = true
	else:
		has_track_target = false

增加一个track_timer, 每0.2秒更新一次跟踪目标

跟踪目标的选择是通过group分组取得所有Player实例, 并找到距离最近的作为追踪目标

在process中朝着跟踪目标移动

调整MultiplayerSynchronizer中的global_position同步为"OnChange"

再次提醒: 多人游戏中, 关键的逻辑处理都在服务端, 其余peer仅同步显示

一些想法

看着自己的学习练习的小项目一点点完善, 还是挺有成就感的, 坚持下来总会逐步成长, 多做一些这样的练习, 后面开发自己的独立游戏也不会太难

现在AI发展迅猛, 小龙虾OpenClaw的消息铺天盖地, 到处都是AI颠覆世界的消息, 我也时常被这些消息淹没, 甚至弄得心烦, 总有一种FOMO情绪, 但我知道, 现在的很多消息其实是资本叙事和媒体夸大, 还有很多卖课机构

我们在日常生活中可以尝试用AI辅助开发, 辅助工作, 提高效率, 但是一旦发现自己过于追求新技术新消息, 投入的时间和精力完全超出预期, 甚至影响自己正常安排的时候, 就应该警惕起来, 想想自己最初的目标, AI是提效工具, 项目的把控和兜底必须得自己来, 不能落后时代, 但也不要过分追新

posted on 2026-03-12 23:00  风酥糖  阅读(34)  评论(0)    收藏  举报