Moved player detection to external script

This commit is contained in:
Marco 2025-02-04 10:03:04 +01:00
commit d8e1459194
8 changed files with 237 additions and 69 deletions

View file

@ -1,2 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACastHelpers_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003F3c92637ae2e83da0a63791071c41eae291d594156062866d8621b7ed7245c_003FCastHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACanvasItem_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003Fe43c43ee5cdcf2c7c8ddb9366f75a76a3c61c77bf45ceac78721c269f3c360_003FCanvasItem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACastHelpers_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003F3c92637ae2e83da0a63791071c41eae291d594156062866d8621b7ed7245c_003FCastHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnemy_005FScriptProperties_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003Fd6739058209280d46591ab296d6b49dfcf7ecd2_003FEnemy_005FScriptProperties_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVariantUtils_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FDecompilerCache_003Fdecompiler_003F4fd22cd129a84c16b5d8004b467c426f518800_003F38_003Fb04c4423_003FVariantUtils_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View file

@ -0,0 +1,84 @@
[gd_scene load_steps=11 format=3 uid="uid://b2gnndqesf4kb"]
[ext_resource type="Script" path="res://Scripts/Enemy.cs" id="1_h0ey4"]
[ext_resource type="Texture2D" uid="uid://b4ynnb14mb4uq" path="res://Sprites/Reisen.png" id="2_ocghb"]
[ext_resource type="PackedScene" uid="uid://crry0rgk7a8sm" path="res://Scenes/Weapons/BaseWeapon.tscn" id="3_ihce0"]
[ext_resource type="Script" path="res://Scripts/Components/ProximityPlayerDetection.cs" id="3_udny0"]
[ext_resource type="PackedScene" uid="uid://cuixq5ex0j40h" path="res://Scenes/enemyBullet.tscn" id="4_iis8b"]
[sub_resource type="AtlasTexture" id="AtlasTexture_2brqc"]
atlas = ExtResource("2_ocghb")
region = Rect2(0, 0, 8, 16)
[sub_resource type="CircleShape2D" id="CircleShape2D_8gtts"]
radius = 7.0
[sub_resource type="CircleShape2D" id="CircleShape2D_cacb5"]
radius = 4.0
[sub_resource type="CircleShape2D" id="CircleShape2D_v711r"]
radius = 85.0529
[sub_resource type="RectangleShape2D" id="RectangleShape2D_m1rsg"]
size = Vector2(8, 12)
[node name="Enemy" type="CharacterBody2D" node_paths=PackedStringArray("EquippedWeapon") groups=["Destroyable"]]
collision_layer = 16
collision_mask = 9
script = ExtResource("1_h0ey4")
EquippedWeapon = NodePath("Weapon")
NavigationEnabled = true
metadata/_edit_group_ = true
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = SubResource("AtlasTexture_2brqc")
[node name="Damage_HitBox" type="CollisionShape2D" parent="."]
visible = false
shape = SubResource("CircleShape2D_8gtts")
[node name="RigidBody2D" type="RigidBody2D" parent="."]
collision_layer = 16
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"]
visible = false
position = Vector2(0, 5)
shape = SubResource("CircleShape2D_cacb5")
[node name="PlayerDetection" type="Area2D" parent="."]
visible = false
collision_layer = 16
collision_mask = 2
script = ExtResource("3_udny0")
[node name="PlayerDetectionArea" type="CollisionShape2D" parent="PlayerDetection"]
shape = SubResource("CircleShape2D_v711r")
[node name="ShootTimer" type="Timer" parent="."]
wait_time = 0.4
one_shot = true
[node name="Weapon" parent="." instance=ExtResource("3_ihce0")]
BulletScene = ExtResource("4_iis8b")
BulletCapacity = 4
BulletSpeed = 50.0
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
target_desired_distance = 64.0
path_max_distance = 800.0
path_postprocessing = 1
avoidance_enabled = true
debug_enabled = true
debug_path_custom_color = Color(1, 0, 0, 1)
[node name="DamageHitbox" type="Area2D" parent="."]
collision_layer = 16
collision_mask = 9
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageHitbox"]
shape = SubResource("RectangleShape2D_m1rsg")
[connection signal="area_entered" from="PlayerDetection" to="PlayerDetection" method="_on_area_entered"]
[connection signal="area_exited" from="PlayerDetection" to="." method="_on_area_exited"]
[connection signal="velocity_computed" from="NavigationAgent2D" to="." method="_on_navigation_agent_2d_velocity_computed"]
[connection signal="area_entered" from="DamageHitbox" to="." method="_on_damage_hitbox_area_entered"]

View file

@ -1,8 +1,9 @@
[gd_scene load_steps=10 format=3 uid="uid://v8s3kubgb2qg"] [gd_scene load_steps=11 format=3 uid="uid://v8s3kubgb2qg"]
[ext_resource type="Texture2D" uid="uid://b4ynnb14mb4uq" path="res://Sprites/Reisen.png" id="1_4w8mj"] [ext_resource type="Texture2D" uid="uid://b4ynnb14mb4uq" path="res://Sprites/Reisen.png" id="1_4w8mj"]
[ext_resource type="Script" path="res://Scripts/Enemy.cs" id="1_lpwdj"] [ext_resource type="Script" path="res://Scripts/Enemy.cs" id="1_lpwdj"]
[ext_resource type="PackedScene" uid="uid://cuixq5ex0j40h" path="res://Scenes/enemyBullet.tscn" id="2_ogldd"] [ext_resource type="PackedScene" uid="uid://cuixq5ex0j40h" path="res://Scenes/enemyBullet.tscn" id="2_ogldd"]
[ext_resource type="Script" path="res://Scripts/Components/ProximityPlayerDetection.cs" id="3_1nqn5"]
[ext_resource type="PackedScene" uid="uid://crry0rgk7a8sm" path="res://Scenes/Weapons/BaseWeapon.tscn" id="4_2k1dv"] [ext_resource type="PackedScene" uid="uid://crry0rgk7a8sm" path="res://Scenes/Weapons/BaseWeapon.tscn" id="4_2k1dv"]
[sub_resource type="AtlasTexture" id="AtlasTexture_2brqc"] [sub_resource type="AtlasTexture" id="AtlasTexture_2brqc"]
@ -21,11 +22,12 @@ radius = 85.0529
[sub_resource type="RectangleShape2D" id="RectangleShape2D_m1rsg"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_m1rsg"]
size = Vector2(8, 12) size = Vector2(8, 12)
[node name="Enemy" type="CharacterBody2D" node_paths=PackedStringArray("EquippedWeapon") groups=["Destroyable"]] [node name="Enemy" type="CharacterBody2D" node_paths=PackedStringArray("EquippedWeapon", "_playerDetection") groups=["Destroyable"]]
collision_layer = 16 collision_layer = 16
collision_mask = 9 collision_mask = 9
script = ExtResource("1_lpwdj") script = ExtResource("1_lpwdj")
EquippedWeapon = NodePath("Weapon") EquippedWeapon = NodePath("Weapon")
_playerDetection = NodePath("PlayerDetection")
NavigationEnabled = true NavigationEnabled = true
metadata/_edit_group_ = true metadata/_edit_group_ = true
@ -48,6 +50,7 @@ shape = SubResource("CircleShape2D_cacb5")
visible = false visible = false
collision_layer = 16 collision_layer = 16
collision_mask = 2 collision_mask = 2
script = ExtResource("3_1nqn5")
[node name="PlayerDetectionArea" type="CollisionShape2D" parent="PlayerDetection"] [node name="PlayerDetectionArea" type="CollisionShape2D" parent="PlayerDetection"]
shape = SubResource("CircleShape2D_v711r") shape = SubResource("CircleShape2D_v711r")
@ -76,7 +79,7 @@ collision_mask = 9
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageHitbox"] [node name="CollisionShape2D" type="CollisionShape2D" parent="DamageHitbox"]
shape = SubResource("RectangleShape2D_m1rsg") shape = SubResource("RectangleShape2D_m1rsg")
[connection signal="area_entered" from="PlayerDetection" to="." method="_on_player_detection_area_entered"] [connection signal="area_entered" from="PlayerDetection" to="PlayerDetection" method="_on_area_entered"]
[connection signal="area_exited" from="PlayerDetection" to="." method="_on_player_detection_area_exited"] [connection signal="area_exited" from="PlayerDetection" to="PlayerDetection" method="_on_area_exited"]
[connection signal="velocity_computed" from="NavigationAgent2D" to="." method="_on_navigation_agent_2d_velocity_computed"] [connection signal="velocity_computed" from="NavigationAgent2D" to="." method="_on_navigation_agent_2d_velocity_computed"]
[connection signal="area_entered" from="DamageHitbox" to="." method="_on_damage_hitbox_area_entered"] [connection signal="area_entered" from="DamageHitbox" to="." method="_on_damage_hitbox_area_entered"]

View file

@ -26,8 +26,10 @@ animations = [{
"speed": 5.0 "speed": 5.0
}] }]
[node name="HUD" type="CanvasLayer"] [node name="HUD" type="CanvasLayer" node_paths=PackedStringArray("_healthLabel", "_itemsContainer")]
script = ExtResource("1_m0hb0") script = ExtResource("1_m0hb0")
_healthLabel = NodePath("VBoxContainer/HealthLabel")
_itemsContainer = NodePath("VBoxContainer/ItemsContainer")
[node name="GameOver" type="Label" parent="."] [node name="GameOver" type="Label" parent="."]
visible = false visible = false

View file

@ -185,6 +185,7 @@ animation = &"walk_left"
z_index = 100 z_index = 100
[node name="HitboxSprite" type="Sprite2D" parent="Smoothing2D"] [node name="HitboxSprite" type="Sprite2D" parent="Smoothing2D"]
visible = false
texture = ExtResource("7_msn8i") texture = ExtResource("7_msn8i")
[node name="InteractionController" type="Area2D" parent="."] [node name="InteractionController" type="Area2D" parent="."]

View file

@ -0,0 +1,17 @@
using Godot;
using Godot.Collections;
namespace Cirno.Scripts.Components;
public partial class PlayerDetection : Area2D
{
public InteractionController CachedPlayer => _cachedPlayer;
protected InteractionController _cachedPlayer;
public virtual bool IsPlayerInRange { get; set; }
public virtual bool IsPlayerInSight(uint collisionMask)
{
return false;
}
}

View file

@ -0,0 +1,45 @@
using System.Diagnostics;
using Godot;
using Godot.Collections;
namespace Cirno.Scripts.Components;
public partial class ProximityPlayerDetection : PlayerDetection
{
public override bool IsPlayerInRange { get; set; }
public override bool IsPlayerInSight(uint collisionMask)
{
if (_cachedPlayer == null) return false;
var spaceState = GetWorld2D().DirectSpaceState;
// I have no idea why I need to use the parent's collision mask instead of the local one but it doesn't detect the player otherwise
var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, _cachedPlayer.GlobalPosition, collisionMask, new Array<Rid> { GetRid() });
// var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, _cachedPlayer.GlobalPosition, CollisionMask, new Array<Rid> { GetRid() });
var result = spaceState.IntersectRay(query);
// If count is 0 then the player is in sight, otherwise there is level geometry in the way
return result.Count == 0;
}
private void _on_area_entered(Area2D area)
{
// Assume area is player for now
if (area is not InteractionController player) return;
Debug.WriteLine("Enemy detection area Entered by interaction controller");
_cachedPlayer = player;
IsPlayerInRange = true;
}
private void _on_area_exited(Area2D area)
{
if (area is not InteractionController player) return;
IsPlayerInRange = false;
}
}

View file

@ -2,6 +2,8 @@ using Cirno.Scripts;
using Godot; using Godot;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using Cirno.Scripts.Components;
using Godot.Collections;
public partial class Enemy : CharacterBody2D public partial class Enemy : CharacterBody2D
{ {
@ -22,10 +24,13 @@ public partial class Enemy : CharacterBody2D
private NavigationAgent2D _navigationAgent; private NavigationAgent2D _navigationAgent;
private bool _isPlayerInRange = false; private bool IsPlayerInRange => _playerDetection is { IsPlayerInRange: true };
private Vector2? _lastPlayerPosition = null; private Vector2? _lastPlayerPosition = null;
[Export]
private PlayerDetection _playerDetection;
[Export] public bool NavigationEnabled { get; set; } = false; [Export] public bool NavigationEnabled { get; set; } = false;
// Called when the node enters the scene tree for the first time. // Called when the node enters the scene tree for the first time.
@ -35,6 +40,10 @@ public partial class Enemy : CharacterBody2D
_navigationAgent = GetNode<NavigationAgent2D>("NavigationAgent2D"); _navigationAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");
//var asdf = GetNode<ProximityPlayerDetection>("PlayerDetection");
//_playerDetection = GetNode<PlayerDetection>("PlayerDetection");
//CallDeferred("Setup"); //CallDeferred("Setup");
} }
@ -67,15 +76,19 @@ public partial class Enemy : CharacterBody2D
switch (_currentState) switch (_currentState)
{ {
case EnemyState.Idle: case EnemyState.Idle:
HandlePlayerDetection(); if (_playerDetection != null && _playerDetection.IsPlayerInSight(CollisionMask))
{
_currentState = EnemyState.Alert;
}
//HandlePlayerDetection();
break; break;
case EnemyState.Alert: case EnemyState.Alert:
// Update last known player position if it's in range // Update last known player position if it's in range
if (_isPlayerInRange) if (IsPlayerInRange)
{ {
_lastPlayerPosition = _cachedPlayer.GlobalPosition; _lastPlayerPosition = _playerDetection.CachedPlayer.GlobalPosition;
} }
if (_lastPlayerPosition.HasValue) if (_lastPlayerPosition.HasValue)
@ -127,25 +140,25 @@ public partial class Enemy : CharacterBody2D
} }
private void HandlePlayerDetection() // private void HandlePlayerDetection()
{ // {
if (_cachedPlayer == null) // if (_cachedPlayer == null)
{ // {
return; // return;
} // }
//
if (IsPlayerInSight()) // if (IsPlayerInSight())
{ // {
// Update player position only if player is in sight // // Update player position only if player is in sight
// if (NavigationEnabled) // // if (NavigationEnabled)
// { // // {
// _navigationAgent.SetTargetPosition(_cachedPlayer.GlobalPosition); // // _navigationAgent.SetTargetPosition(_cachedPlayer.GlobalPosition);
// } // // }
//Shoot(); // //Shoot();
//
_currentState = EnemyState.Alert; // _currentState = EnemyState.Alert;
} // }
} // }
private void Shoot() private void Shoot()
{ {
@ -178,45 +191,45 @@ public partial class Enemy : CharacterBody2D
// } // }
} }
private bool IsPlayerInSight() // private bool IsPlayerInSight()
{ // {
var spaceState = GetWorld2D().DirectSpaceState; // var spaceState = GetWorld2D().DirectSpaceState;
var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, _cachedPlayer.GlobalPosition, CollisionMask, new Godot.Collections.Array<Rid> { GetRid() }); // var query = PhysicsRayQueryParameters2D.Create(this.GlobalPosition, _cachedPlayer.GlobalPosition, CollisionMask, new Godot.Collections.Array<Rid> { GetRid() });
var result = spaceState.IntersectRay(query); // var result = spaceState.IntersectRay(query);
//
// // If count is 0 then the player is in sight, otherwise there is level geometry in the way
// return result.Count == 0;
//
// // if (result.Count > 0)
// // GD.Print("Hit at point: ", result["position"]);
// }
// If count is 0 then the player is in sight, otherwise there is level geometry in the way // private void _on_player_detection_area_entered(Area2D area)
return result.Count == 0; // {
// // Assume area is player for now
// if (result.Count > 0) // if (area is InteractionController player)
// GD.Print("Hit at point: ", result["position"]); // {
} // Debug.WriteLine("Enemy detection area Entered by interaction controller");
//
private void _on_player_detection_area_entered(Area2D area) // _cachedPlayer = player;
{ //
// Assume area is player for now // _isPlayerInRange = true;
if (area is InteractionController player) // // if (_currentState is EnemyState.Idle)
{ // // {
Debug.WriteLine("Enemy detection area Entered by interaction controller"); // // _currentState = EnemyState.Primed;
// // }
_cachedPlayer = player; // }
// }
_isPlayerInRange = true; //
// if (_currentState is EnemyState.Idle) // private void _on_player_detection_area_exited(Area2D area)
// { // {
// _currentState = EnemyState.Primed; // _isPlayerInRange = false;
// } //
} // // if (_currentState is EnemyState.Primed)
} // // {
// // _currentState = EnemyState.Idle;
private void _on_player_detection_area_exited(Area2D area) // // }
{ // }
_isPlayerInRange = false;
// if (_currentState is EnemyState.Primed)
// {
// _currentState = EnemyState.Idle;
// }
}
private void _on_damage_hitbox_area_entered(Area2D area) private void _on_damage_hitbox_area_entered(Area2D area)
{ {