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

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

先看看效果

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容