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

0 阅读3分钟

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

先看看效果

动画4.gif

实现过程

添加战斗场地

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

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

2.png

敌人生成整理

上一节中我们在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是提效工具, 项目的把控和兜底必须得自己来, 不能落后时代, 但也不要过分追新