game: add base enemy and rat
This commit is contained in:
144
scenes/enemies/enemy_base.gd
Normal file
144
scenes/enemies/enemy_base.gd
Normal file
@@ -0,0 +1,144 @@
|
||||
class_name EnemyBase
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var move_speed: float = 100
|
||||
@export var max_health: float = 10.0
|
||||
@export var default_contact_damage: float = 0.0
|
||||
@export var target_distance: float = 6.0
|
||||
@export var path_update_interval: float = 0.5
|
||||
|
||||
@onready var target_cast: RayCast2D = $TargetCast
|
||||
@onready var animation_player: AnimationPlayer = $AnimationPlayer
|
||||
@onready var contact_damage_cd: Timer = $ContactDamageCD
|
||||
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
|
||||
@onready var collision_shape_2d: CollisionShape2D = $CollisionShape2D
|
||||
@onready var shape_cast_2d: ShapeCast2D = $ShapeCast2D
|
||||
|
||||
var player: Player
|
||||
var target: Node2D
|
||||
var god_mode: bool = false
|
||||
var is_dead: bool = false
|
||||
var health: float
|
||||
|
||||
var _path_update_timer: float = 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
health = max_health
|
||||
shape_cast_2d.shape.radius = collision_shape_2d.shape.radius
|
||||
shape_cast_2d.enabled = false
|
||||
_find_player()
|
||||
|
||||
|
||||
func _find_player():
|
||||
if not player:
|
||||
player = get_tree().get_first_node_in_group(GlobalConst.GROUP_PLAYER)
|
||||
target = player
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not target:
|
||||
return
|
||||
do_movement(delta)
|
||||
check_contact_damage()
|
||||
|
||||
|
||||
func do_movement(delta: float) -> void:
|
||||
if not target:
|
||||
return
|
||||
if global_position.distance_to(target.global_position) < target_distance:
|
||||
return
|
||||
_path_update_timer -= delta
|
||||
if _has_direct_path():
|
||||
shape_cast_2d.enabled = false
|
||||
_do_simple_movement()
|
||||
else:
|
||||
_do_nav_agent_movement()
|
||||
|
||||
|
||||
func _has_direct_path():
|
||||
target_cast.target_position = to_local(target.global_position)
|
||||
target_cast.enabled = true
|
||||
return not target_cast.is_colliding()
|
||||
|
||||
|
||||
func _do_simple_movement():
|
||||
var direction = global_position.direction_to(target.global_position)
|
||||
var distance = global_position.distance_to(target.global_position)
|
||||
if distance > 4:
|
||||
velocity = direction * move_speed
|
||||
move_and_slide()
|
||||
|
||||
|
||||
func _do_nav_agent_movement():
|
||||
if _path_update_timer <= 0.0:
|
||||
_path_update_timer = path_update_interval
|
||||
nav_agent.target_position = target.global_position
|
||||
|
||||
if nav_agent.is_navigation_finished():
|
||||
return
|
||||
var next_point = nav_agent.get_next_path_position()
|
||||
var direction = (next_point - global_position).normalized()
|
||||
shape_cast_2d.target_position = to_local(next_point)
|
||||
shape_cast_2d.enabled = true
|
||||
if shape_cast_2d.is_colliding():
|
||||
direction = direction.bounce(shape_cast_2d.get_collision_normal(0)).normalized()
|
||||
|
||||
velocity = direction * move_speed
|
||||
move_and_slide()
|
||||
|
||||
|
||||
func check_contact_damage():
|
||||
if default_contact_damage == 0.0:
|
||||
return
|
||||
if global_position.distance_to(target.global_position) > target_distance:
|
||||
return
|
||||
deal_contact_damage()
|
||||
|
||||
|
||||
func deal_contact_damage():
|
||||
if target.is_in_group("damagable"):
|
||||
if contact_damage_cd.is_stopped():
|
||||
target.take_damage(default_contact_damage)
|
||||
contact_damage_cd.start()
|
||||
|
||||
|
||||
func take_damage(value: float, is_crit: bool = false):
|
||||
if god_mode:
|
||||
return
|
||||
health -= value
|
||||
var dm = preload("res://scenes/damage_numbers.tscn").instantiate()
|
||||
dm.damage_taken = value
|
||||
dm.critical_damage = is_crit
|
||||
animation_player.play("generic_anims/take_damage")
|
||||
add_child(dm)
|
||||
if health <= 0:
|
||||
die()
|
||||
|
||||
|
||||
func cheer():
|
||||
target_distance = 2
|
||||
if not animation_player.is_playing():
|
||||
animation_player.play("generic_anims/cheer")
|
||||
|
||||
|
||||
func die():
|
||||
if is_dead:
|
||||
return
|
||||
is_dead = true
|
||||
drop_xp_orb()
|
||||
target = null
|
||||
velocity = Vector2.ZERO
|
||||
animation_player.play("generic_anims/die")
|
||||
|
||||
|
||||
func drop_xp_orb() -> void:
|
||||
var orb: XPOrb = preload("res://scenes/xp_orb.tscn").instantiate()
|
||||
orb.value = 5
|
||||
orb.position = position
|
||||
get_parent().add_child(orb)
|
||||
|
||||
|
||||
func _on_animation_player_animation_finished(anim_name: StringName) -> void:
|
||||
if is_dead:
|
||||
queue_free()
|
1
scenes/enemies/enemy_base.gd.uid
Normal file
1
scenes/enemies/enemy_base.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dxn17u7ltuibw
|
75
scenes/enemies/enemy_base.tscn
Normal file
75
scenes/enemies/enemy_base.tscn
Normal file
@@ -0,0 +1,75 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://b7vq8xspnlyeu"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dxn17u7ltuibw" path="res://scenes/enemies/enemy_base.gd" id="1_qty17"]
|
||||
[ext_resource type="AnimationLibrary" uid="uid://dos4y853hq1gu" path="res://animation/generic_anims.res" id="2_pkqou"]
|
||||
|
||||
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_pkqou"]
|
||||
size = Vector2(32, 32)
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_satqt"]
|
||||
radius = 6.0
|
||||
|
||||
[sub_resource type="Animation" id="Animation_satqt"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Sprite2D:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 0)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("Sprite2D:modulate")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 1, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_qa0nx"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_satqt")
|
||||
}
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_pkqou"]
|
||||
|
||||
[node name="EnemyBase" type="CharacterBody2D"]
|
||||
collision_layer = 2
|
||||
collision_mask = 3
|
||||
script = ExtResource("1_qty17")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
texture = SubResource("PlaceholderTexture2D_pkqou")
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("CircleShape2D_satqt")
|
||||
|
||||
[node name="TargetCast" type="RayCast2D" parent="." groups=["damagable", "enemy"]]
|
||||
enabled = false
|
||||
collision_mask = 3
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
libraries = {
|
||||
&"": SubResource("AnimationLibrary_qa0nx"),
|
||||
&"generic_anims": ExtResource("2_pkqou")
|
||||
}
|
||||
|
||||
[node name="ContactDamageCD" type="Timer" parent="."]
|
||||
wait_time = 0.5
|
||||
|
||||
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
|
||||
|
||||
[node name="ShapeCast2D" type="ShapeCast2D" parent="."]
|
||||
shape = SubResource("CircleShape2D_pkqou")
|
||||
|
||||
[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_player_animation_finished"]
|
1
scenes/enemies/enemy_rat.gd
Normal file
1
scenes/enemies/enemy_rat.gd
Normal file
@@ -0,0 +1 @@
|
||||
extends EnemyBase
|
1
scenes/enemies/enemy_rat.gd.uid
Normal file
1
scenes/enemies/enemy_rat.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ddvxp8eada0mw
|
13
scenes/enemies/enemy_rat.tscn
Normal file
13
scenes/enemies/enemy_rat.tscn
Normal file
@@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://c7jaqltfjhn5n"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://b7vq8xspnlyeu" path="res://scenes/enemies/enemy_base.tscn" id="1_o1awd"]
|
||||
[ext_resource type="Texture2D" uid="uid://in5id1p5bxux" path="res://assets/sprites/rat_small.png" id="2_gscll"]
|
||||
[ext_resource type="Script" uid="uid://ddvxp8eada0mw" path="res://scenes/enemies/enemy_rat.gd" id="2_sari4"]
|
||||
|
||||
[node name="EnemyRat" instance=ExtResource("1_o1awd")]
|
||||
script = ExtResource("2_sari4")
|
||||
max_health = 50.0
|
||||
default_contact_damage = 5.0
|
||||
|
||||
[node name="Sprite2D" parent="." index="0"]
|
||||
texture = ExtResource("2_gscll")
|
Reference in New Issue
Block a user