Basic ground enemy AI, crosshair + laser for aiming

This commit is contained in:
ToasterPanic 2025-12-06 20:48:11 -05:00
parent be879a03a4
commit e4893a5cc6
6 changed files with 299 additions and 55 deletions

View file

@ -6,7 +6,7 @@
[ext_resource type="Texture2D" uid="uid://c0cyhybh30ogt" path="res://textures/player-ground-sheet.png" id="4_2c1ag"]
[ext_resource type="Texture2D" uid="uid://csrlh1sbdroud" path="res://textures/pistol.png" id="5_8gbjj"]
[ext_resource type="AudioStream" uid="uid://5x8fl2mk082h" path="res://sounds/gunshot_1.mp3" id="6_2c1ag"]
[ext_resource type="Script" uid="uid://bv7ymrwe6ciax" path="res://scripts/enemy_ground.gd" id="7_modao"]
[ext_resource type="Texture2D" uid="uid://coflscl1w4vtr" path="res://textures/crosshair.png" id="7_modao"]
[ext_resource type="Shader" uid="uid://d3hoh7ec2w8q7" path="res://scripts/outline.gdshader" id="7_vuhkc"]
[ext_resource type="Shader" uid="uid://d2e0541hawkml" path="res://scripts/vignette.gdshader" id="9_5vwr8"]
[ext_resource type="Shader" uid="uid://bk7q00br1ms30" path="res://scripts/retro.gdshader" id="9_257nh"]
@ -160,6 +160,15 @@ texture = ExtResource("5_8gbjj")
[node name="Gunshot" type="AudioStreamPlayer2D" parent="PlayerGround/HeldItem"]
stream = ExtResource("6_2c1ag")
[node name="Crosshair" type="Sprite2D" parent="PlayerGround/HeldItem"]
scale = Vector2(2, 2)
texture = ExtResource("7_modao")
[node name="Line" type="Line2D" parent="PlayerGround/HeldItem"]
points = PackedVector2Array(0, 0, 512, 0)
width = 2.0
default_color = Color(1, 0, 0, 1)
[node name="Hitbox" type="Area2D" parent="PlayerGround"]
collision_layer = 2
collision_mask = 2
@ -168,43 +177,6 @@ collision_mask = 2
shape = SubResource("CapsuleShape2D_8gbjj")
debug_color = Color(1, 0, 0, 0.41960785)
[node name="EnemyTest" type="CharacterBody2D" parent="."]
position = Vector2(349, -58)
script = ExtResource("7_modao")
[node name="Sprite" type="AnimatedSprite2D" parent="EnemyTest"]
scale = Vector2(2, 2)
sprite_frames = SubResource("SpriteFrames_aergo")
[node name="Camera" type="Camera2D" parent="EnemyTest"]
position_smoothing_enabled = true
[node name="CollisionShape" type="CollisionShape2D" parent="EnemyTest"]
position = Vector2(0, 40)
shape = SubResource("CapsuleShape2D_176r3")
[node name="HeldItem" type="Node2D" parent="EnemyTest"]
[node name="Cast" type="RayCast2D" parent="EnemyTest/HeldItem"]
target_position = Vector2(2048, 0)
collision_mask = 2
collide_with_areas = true
[node name="Sprite" type="Sprite2D" parent="EnemyTest/HeldItem"]
position = Vector2(56, 0)
texture = ExtResource("5_8gbjj")
[node name="Gunshot" type="AudioStreamPlayer2D" parent="EnemyTest/HeldItem"]
stream = ExtResource("6_2c1ag")
[node name="Hitbox" type="Area2D" parent="EnemyTest"]
collision_layer = 2
collision_mask = 2
[node name="CollisionShape" type="CollisionShape2D" parent="EnemyTest/Hitbox"]
shape = SubResource("CapsuleShape2D_8gbjj")
debug_color = Color(1, 0, 0, 0.41960785)
[node name="UI" type="CanvasLayer" parent="."]
[node name="Vignette" type="ColorRect" parent="UI"]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=47 format=4 uid="uid://dfjnikjjynj0e"]
[gd_scene load_steps=57 format=4 uid="uid://dfjnikjjynj0e"]
[ext_resource type="AudioStream" uid="uid://dgv01wy8r7ej2" path="res://sounds/uglyburger.mp3" id="1_kpeax"]
[ext_resource type="Texture2D" uid="uid://btcap3oh2dqt8" path="res://textures/wall_tile.png" id="2_4uppp"]
@ -20,6 +20,9 @@
[ext_resource type="Texture2D" uid="uid://ktvnppfhchoj" path="res://textures/bed.png" id="17_50pdk"]
[ext_resource type="Texture2D" uid="uid://cmv4wou5glrl7" path="res://textures/bed_foot.png" id="18_83fjc"]
[ext_resource type="Script" uid="uid://cva4b60iqolqy" path="res://scripts/story_handler_1.gd" id="19_akl5n"]
[ext_resource type="Script" uid="uid://bv7ymrwe6ciax" path="res://scripts/enemy_ground.gd" id="21_tvsp8"]
[ext_resource type="Texture2D" uid="uid://csrlh1sbdroud" path="res://textures/pistol.png" id="22_6l1ru"]
[ext_resource type="AudioStream" uid="uid://5x8fl2mk082h" path="res://sounds/gunshot_1.mp3" id="23_janyw"]
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_vmimc"]
light_mode = 1
@ -39,36 +42,65 @@ texture = ExtResource("3_ir5n7")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
[sub_resource type="NavigationPolygon" id="NavigationPolygon_tvsp8"]
vertices = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)])
agent_radius = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_bhfm6"]
texture = ExtResource("4_50pdk")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
0:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_tvsp8")
[sub_resource type="NavigationPolygon" id="NavigationPolygon_6l1ru"]
vertices = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)])
agent_radius = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_kl2qk"]
texture = ExtResource("5_83fjc")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
0:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_6l1ru")
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ga4dw"]
texture = ExtResource("6_akl5n")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
[sub_resource type="NavigationPolygon" id="NavigationPolygon_janyw"]
vertices = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)])
agent_radius = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ir5n7"]
texture = ExtResource("7_4uppp")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
0:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_janyw")
[sub_resource type="NavigationPolygon" id="NavigationPolygon_vmpfq"]
vertices = PackedVector2Array(16, 16, -16, 16, -16, -16, 16, -16)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)])
agent_radius = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_50pdk"]
texture = ExtResource("8_ir5n7")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
0:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_vmpfq")
[sub_resource type="TileSet" id="TileSet_uxsmb"]
tile_size = Vector2i(32, 32)
occlusion_layer_0/light_mask = 1
physics_layer_0/collision_layer = 3
physics_layer_0/collision_mask = 3
navigation_layer_0/layers = 1
sources/0 = SubResource("TileSetAtlasSource_k741b")
sources/1 = SubResource("TileSetAtlasSource_mdep3")
sources/2 = SubResource("TileSetAtlasSource_bhfm6")
@ -200,6 +232,59 @@ size = Vector2(40, 40)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_83fjc"]
size = Vector2(61.5, 21)
[sub_resource type="SpriteFrames" id="SpriteFrames_vmpfq"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_jo68p")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_6gpfv")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_fd1o3")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_yqhs4")
}],
"loop": true,
"name": &"default",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_jo68p")
}],
"loop": true,
"name": &"idle",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_6gpfv")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jo68p")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_fd1o3")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_yqhs4")
}],
"loop": true,
"name": &"walk",
"speed": 7.0
}]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_jxmby"]
radius = 21.0
height = 48.0
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_tvsp8"]
radius = 25.0
height = 148.0
[node name="SpaceStation1" type="Node2D"]
[node name="Uglyburger" type="AudioStreamPlayer" parent="."]
@ -356,6 +441,50 @@ texture = ExtResource("18_83fjc")
position = Vector2(-0.25, 37.5)
shape = SubResource("RectangleShape2D_83fjc")
[node name="EnemyTest" type="CharacterBody2D" parent="."]
position = Vector2(-162, -537)
script = ExtResource("21_tvsp8")
[node name="Sprite" type="AnimatedSprite2D" parent="EnemyTest"]
scale = Vector2(2, 2)
sprite_frames = SubResource("SpriteFrames_vmpfq")
[node name="CollisionShape" type="CollisionShape2D" parent="EnemyTest"]
position = Vector2(0, 40)
shape = SubResource("CapsuleShape2D_jxmby")
[node name="LineOfSight" type="RayCast2D" parent="EnemyTest"]
target_position = Vector2(2048, 0)
collision_mask = 2
collide_with_areas = true
[node name="HeldItem" type="Node2D" parent="EnemyTest"]
[node name="Cast" type="RayCast2D" parent="EnemyTest/HeldItem"]
target_position = Vector2(2048, 0)
collision_mask = 2
collide_with_areas = true
[node name="Sprite" type="Sprite2D" parent="EnemyTest/HeldItem"]
position = Vector2(56, 0)
texture = ExtResource("22_6l1ru")
[node name="Gunshot" type="AudioStreamPlayer2D" parent="EnemyTest/HeldItem"]
stream = ExtResource("23_janyw")
[node name="Hitbox" type="Area2D" parent="EnemyTest"]
collision_layer = 2
collision_mask = 2
[node name="CollisionShape" type="CollisionShape2D" parent="EnemyTest/Hitbox"]
shape = SubResource("CapsuleShape2D_tvsp8")
debug_color = Color(1, 0, 0, 0.41960785)
[node name="Navagent" type="NavigationAgent2D" parent="EnemyTest"]
path_desired_distance = 34.0
target_desired_distance = 34.0
path_postprocessing = 1
[connection signal="body_entered" from="GalactamartWorker/InteractArea" to="GalactamartWorker/InteractArea" method="_on_body_entered"]
[connection signal="body_exited" from="GalactamartWorker/InteractArea" to="GalactamartWorker/InteractArea" method="_on_body_exited"]
[connection signal="body_entered" from="ExitShip/InteractArea" to="ExitShip/InteractArea" method="_on_body_entered"]

View file

@ -1,32 +1,125 @@
extends "res://scripts/character_ground.gd"
var last_aim_direction = Vector2(0, 0)
var alerted = false
var inaccuracy = 15
var reaction_time = 0.35
var reaction_halve_distance = 720
var reaction_timer = 0
enum {
AI_MODE_IDLE,
AI_MODE_ATTACK,
AI_MODE_SEARCH
}
enum {
AI_STATE_DEFAULT,
AI_STATE_CHASE,
AI_STATE_CHASE_LAST_SEEN
}
var ai_mode = AI_MODE_IDLE
var ai_state = AI_STATE_DEFAULT
var last_seen_player_position = null
@onready var player = null
var game = null
@export var starting_gun: String = &"pistol"
@export var starting_health: int = 50
func _ready() -> void:
super()
health = starting_health
set_ground_gun(starting_gun)
func _process(delta: float) -> void:
super(delta)
if input_icon.using_gamepad:
if !((Input.get_axis("aim_left", "aim_right") == 0) and (Input.get_axis("aim_up", "aim_down") == 0)):
$HeldItem.rotation = Vector2(
Input.get_axis("aim_left", "aim_right"),
Input.get_axis("aim_up", "aim_down")
).angle()
if !player:
if game:
player = game.get_node("PlayerGround")
else: return
if ($HeldItem.rotation_degrees < -90) or ($HeldItem.rotation_degrees > 90):
$HeldItem/Sprite.scale.y = -1
if ai_mode == AI_MODE_IDLE:
$LineOfSight.look_at(player.global_position)
if player.is_ancestor_of($LineOfSight.get_collider()):
var divider = clamp((player.global_position - global_position).length() / reaction_halve_distance, 1, 8) * 1.5
reaction_timer += delta / divider
if reaction_time < reaction_timer:
ai_mode = AI_MODE_ATTACK
reaction_timer = 0
else:
$HeldItem/Sprite.scale.y = 1
reaction_timer -= delta
if reaction_timer < 0:
reaction_timer = 0
elif ai_mode == AI_MODE_ATTACK:
$LineOfSight.look_at(player.global_position)
if player.is_ancestor_of($LineOfSight.get_collider()):
if !$Navagent.target_position or ($Navagent.target_position != player.global_position):
$Navagent.target_position = player.global_position
ai_state = AI_STATE_CHASE
elif last_seen_player_position:
if !$Navagent.target_position or ($Navagent.target_position != last_seen_player_position):
$Navagent.target_position = last_seen_player_position
ai_state = AI_STATE_CHASE_LAST_SEEN
$HeldItem.look_at(player.global_position)
if ai_state == AI_STATE_CHASE:
if (player.global_position - global_position).length() > 256:
if $Navagent.is_navigation_finished():
last_seen_player_position = null
ai_mode = AI_MODE_IDLE
else:
$HeldItem.look_at(get_global_mouse_position())
var next_position = $Navagent.get_next_path_position()
next_position.y -= 32
var axes = global_position.direction_to(next_position)
horizontial_movement = Input.get_axis("ground_left", "ground_right")
vertical_movement = Input.get_axis("ground_up", "ground_down")
horizontial_movement = axes.x
vertical_movement = axes.y
firing = Input.is_action_pressed("fire")
else:
horizontial_movement = 0
vertical_movement = 0
reaction_timer += delta
if reaction_timer > reaction_time:
firing = true
$HeldItem/Cast.rotation_degrees = randi_range(-inaccuracy, inaccuracy)
reaction_timer = reaction_time
last_seen_player_position = player.global_position
elif ai_state == AI_STATE_CHASE_LAST_SEEN:
if $Navagent.is_navigation_finished():
last_seen_player_position = null
ai_mode = AI_MODE_IDLE
else:
var next_position = $Navagent.get_next_path_position()
next_position.y -= 32
var axes = global_position.direction_to(next_position)
horizontial_movement = axes.x
vertical_movement = axes.y
else:
reaction_timer -= delta
if reaction_timer < 0:
firing = false
reaction_timer = 0

View file

@ -27,4 +27,14 @@ func _process(delta: float) -> void:
horizontial_movement = Input.get_axis("ground_left", "ground_right")
vertical_movement = Input.get_axis("ground_up", "ground_down")
if $HeldItem/Cast.get_collision_point():
$HeldItem/Crosshair.visible = true
$HeldItem/Line.visible = true
$HeldItem/Crosshair.global_position = $HeldItem/Cast.get_collision_point()
$HeldItem/Line.points[1].x = ($HeldItem/Cast.get_collision_point() - global_position).length()
else:
$HeldItem/Crosshair.visible = false
$HeldItem/Line.visible = false
firing = Input.is_action_pressed("fire")

BIN
textures/crosshair.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

View file

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://coflscl1w4vtr"
path="res://.godot/imported/crosshair.png-226e785e0f22bb09c3ce42bf42008081.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://textures/crosshair.png"
dest_files=["res://.godot/imported/crosshair.png-226e785e0f22bb09c3ce42bf42008081.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1