Add fade away component, simple AI and shooting

This commit is contained in:
2025-01-04 08:42:23 +01:00
parent 366c269817
commit f537722849
15 changed files with 347 additions and 12 deletions

View File

@@ -15,7 +15,7 @@ size = Vector2(16, 31)
[node name="Brick Player" type="CharacterBody2D"] [node name="Brick Player" type="CharacterBody2D"]
collision_layer = 4 collision_layer = 4
collision_mask = 3 collision_mask = 11
script = ExtResource("1_8j4h4") script = ExtResource("1_8j4h4")
[node name="Root" type="Node2D" parent="."] [node name="Root" type="Node2D" parent="."]

41
objects/bullet.tscn Normal file
View File

@@ -0,0 +1,41 @@
[gd_scene load_steps=5 format=3 uid="uid://bhc7y4xugu4q7"]
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_w543f"]
[ext_resource type="Script" path="res://scripts/components/damage.gd" id="2_qkwsu"]
[ext_resource type="Script" path="res://scripts/components/bullet.gd" id="3_keogl"]
[sub_resource type="CircleShape2D" id="CircleShape2D_txsw8"]
radius = 4.0
[node name="Bullet" type="Area2D"]
collision_layer = 8
collision_mask = 5
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_txsw8")
[node name="Sprite2D" type="Sprite2D" parent="."]
scale = Vector2(0.5, 0.5)
texture = ExtResource("1_w543f")
hframes = 12
vframes = 12
frame = 79
[node name="VisibleOnScreenNotifier2D" type="VisibleOnScreenNotifier2D" parent="."]
position = Vector2(2.38419e-07, 2.38419e-07)
scale = Vector2(0.4, 0.4)
[node name="DamageComponent" type="Node" parent="." node_paths=PackedStringArray("area2d")]
script = ExtResource("2_qkwsu")
area2d = NodePath("..")
[node name="BulletComponent" type="Node2D" parent="." node_paths=PackedStringArray("root", "area2d", "visibility_notifier", "timer")]
script = ExtResource("3_keogl")
root = NodePath("..")
speed = 100.0
area2d = NodePath("..")
visibility_notifier = NodePath("../VisibleOnScreenNotifier2D")
timer = NodePath("../Timer")
[node name="Timer" type="Timer" parent="."]
autostart = true

View File

@@ -1,8 +1,9 @@
[gd_scene load_steps=5 format=3 uid="uid://54w4wisfj8v8"] [gd_scene load_steps=6 format=3 uid="uid://54w4wisfj8v8"]
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_epuj5"] [ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_epuj5"]
[ext_resource type="Script" path="res://scripts/components/collectable.gd" id="2_y0k47"] [ext_resource type="Script" path="res://scripts/components/collectable.gd" id="2_y0k47"]
[ext_resource type="Resource" uid="uid://vql535ckoeqm" path="res://resources/collectables/coin.tres" id="3_fm2fq"] [ext_resource type="Resource" uid="uid://vql535ckoeqm" path="res://resources/collectables/coin.tres" id="3_fm2fq"]
[ext_resource type="Script" path="res://scripts/components/fade_away.gd" id="4_fx1h2"]
[sub_resource type="CircleShape2D" id="CircleShape2D_3ask2"] [sub_resource type="CircleShape2D" id="CircleShape2D_3ask2"]
radius = 9.0 radius = 9.0
@@ -24,3 +25,10 @@ frame = 51
script = ExtResource("2_y0k47") script = ExtResource("2_y0k47")
area2d = NodePath("..") area2d = NodePath("..")
collectable_data = ExtResource("3_fm2fq") collectable_data = ExtResource("3_fm2fq")
[node name="FadeAwayComponent" type="Node" parent="." node_paths=PackedStringArray("sprite2d", "root", "area2d")]
script = ExtResource("4_fx1h2")
sprite2d = NodePath("../Sprite2D")
fade_duration = 0.4
root = NodePath("..")
area2d = NodePath("..")

59
objects/enemy.tscn Normal file
View File

@@ -0,0 +1,59 @@
[gd_scene load_steps=8 format=3 uid="uid://bwdlmualj6xbw"]
[ext_resource type="Texture2D" uid="uid://xes6mt2dd5gu" path="res://sprites/robot_cutout.png" id="1_uh38l"]
[ext_resource type="Script" path="res://scripts/components/health.gd" id="2_o170m"]
[ext_resource type="Script" path="res://scripts/components/damage.gd" id="3_8jl3u"]
[ext_resource type="Script" path="res://scripts/components/side_to_side_movement.gd" id="4_gbsq8"]
[ext_resource type="Script" path="res://scripts/components/periodic_shooting.gd" id="5_m03v0"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_pwwji"]
size = Vector2(18, 27)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ejbqt"]
size = Vector2(18, 27)
[node name="Enemy" type="CharacterBody2D"]
collision_layer = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 0.5)
shape = SubResource("RectangleShape2D_pwwji")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_uh38l")
[node name="HealthComponent" type="Node" parent="."]
script = ExtResource("2_o170m")
[node name="DamageComponent" type="Node" parent="." node_paths=PackedStringArray("area2d")]
script = ExtResource("3_8jl3u")
area2d = NodePath("../Hitbox")
[node name="SideToSideMovement" type="Node" parent="." node_paths=PackedStringArray("root", "sprite2d", "left_ray", "right_ray")]
script = ExtResource("4_gbsq8")
root = NodePath("..")
sprite2d = NodePath("../Sprite2D")
speed = 60.0
wait_time = 0.5
left_ray = NodePath("../Left Ray")
right_ray = NodePath("../Right Ray")
[node name="PeriodicShootingComponent" type="Node" parent="." node_paths=PackedStringArray("side_to_side_movement", "root")]
script = ExtResource("5_m03v0")
side_to_side_movement = NodePath("../SideToSideMovement")
root = NodePath("..")
[node name="Hitbox" type="Area2D" parent="."]
collision_layer = 8
collision_mask = 4
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2(0, 0.5)
shape = SubResource("RectangleShape2D_ejbqt")
debug_color = Color(0.913521, 0.265052, 0.323172, 0.42)
[node name="Left Ray" type="RayCast2D" parent="."]
position = Vector2(-16, 13)
[node name="Right Ray" type="RayCast2D" parent="."]
position = Vector2(16, 13)

View File

@@ -74,6 +74,7 @@ down={
2d_physics/layer_1="Terrain" 2d_physics/layer_1="Terrain"
2d_physics/layer_2="Collectible Entities" 2d_physics/layer_2="Collectible Entities"
2d_physics/layer_3="Player" 2d_physics/layer_3="Player"
2d_physics/layer_4="Enemy"
[rendering] [rendering]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,32 @@
class_name BulletComponent
extends Node
@export var root: Node2D
@export var direction: Vector2 = Vector2.RIGHT
@export var speed: float = 10.0
@export var area2d: Area2D
@export var visibility_notifier: VisibleOnScreenNotifier2D
@export var life_time: float = 5.0
@export var timer: Timer
func _ready() -> void:
root = get_parent()
visibility_notifier.screen_exited.connect(_on_screen_exited)
area2d.body_entered.connect(on_area2d_body_entered)
timer.wait_time = life_time
timer.timeout.connect(on_timer_timeout)
func _physics_process(delta: float) -> void:
root.position += direction * speed * delta
func _on_screen_exited() -> void:
root.queue_free()
func on_area2d_body_entered(_body: Node2D) -> void:
root.queue_free()
func on_timer_timeout() -> void:
root.queue_free()

View File

@@ -2,6 +2,7 @@ class_name CollectableComponent
extends Node extends Node
var root: Node var root: Node
var has_fade_away: bool = false
@export var area2d: Area2D @export var area2d: Area2D
@export var collectable_data: Resource @export var collectable_data: Resource
@@ -16,7 +17,11 @@ func _ready() -> void:
root = get_parent() root = get_parent()
if root.has_node("FadeAwayComponent"):
has_fade_away = true
func _on_area2d_body_entered(body: Node2D) -> void: func _on_area2d_body_entered(body: Node2D) -> void:
if body.has_node("CanPickUpComponent"): if body.has_node("CanPickUpComponent"):
collected.emit(collectable_data.amount) collected.emit(collectable_data.amount)
root.queue_free() if not has_fade_away:
root.queue_free()

View File

@@ -0,0 +1,27 @@
class_name FadeAwayComponent
extends Node
@export var sprite2d: Sprite2D
@export var fade_duration: float = 1.0
@export var speed: float = 10.0
@export var direction: Vector2 = Vector2.UP
@export var root: Node2D
@export var area2d: Area2D
func _ready():
root = get_parent()
if area2d:
area2d.body_entered.connect(on_area2d_body_entered)
func fade_away() -> void:
var fade_tween := create_tween().set_parallel(true)
fade_tween.tween_property(sprite2d, "modulate:a", 0, fade_duration)
fade_tween.tween_property(sprite2d, "position", sprite2d.position + (direction * speed), fade_duration)
await (fade_tween.finished)
root.queue_free()
func on_area2d_body_entered(_body: Node2D) -> void:
fade_away()

View File

@@ -0,0 +1,44 @@
class_name PeriodicShootingComponent
extends Node
@export var bullet_scene: PackedScene = preload("res://objects/bullet.tscn")
@export var shoot_interval: float = 1.0
@export var shoot_direction: Vector2 = Vector2.RIGHT
@export var side_to_side_movement: SideToSideMovement
@export var root: Node2D
var timer: Timer
func _ready() -> void:
root = get_parent()
setup_timer()
func _process(_delta: float) -> void:
if side_to_side_movement:
shoot_direction = side_to_side_movement.direction if side_to_side_movement.direction != Vector2.ZERO else Vector2.RIGHT
func shoot() -> void:
if shoot_direction == Vector2.ZERO:
return
var bullet_instance: Node2D = bullet_scene.instantiate()
var bullet_component: BulletComponent = bullet_instance.get_node("BulletComponent")
bullet_instance.position = root.position
bullet_component.direction = shoot_direction
get_tree().current_scene.add_child(bullet_instance)
func on_timer_timeout() -> void:
shoot()
timer.start()
func setup_timer() -> void:
timer = Timer.new()
timer.wait_time = shoot_interval
timer.one_shot = false
timer.autostart = true
timer.timeout.connect(on_timer_timeout)
add_child(timer)

View File

@@ -15,6 +15,5 @@ func on_collected(amount: int) -> void:
return return
game_manager.add_coins(amount) game_manager.add_coins(amount)
print("Coins: ", game_manager.get_coins())
# todo: play sound # todo: play sound
# todo: update ui # todo: update ui

View File

@@ -0,0 +1,82 @@
class_name SideToSideMovement
extends Node
@export var root: Node2D
@export var sprite2d: Sprite2D
@export var speed: float = 10.0
@export var wait_time: float = 1.0
@export var left_ray: RayCast2D
@export var right_ray: RayCast2D
var direction: Vector2 = Vector2.LEFT
var new_direction: Vector2 = Vector2.LEFT
var timer: Timer
var triggered_direction_change: bool = false
signal direction_changed()
func _ready() -> void:
root = get_parent()
if not sprite2d:
print("SideToSideMovement node missing Sprite2D child.")
return
if not left_ray or not right_ray:
print("SideToSideMovement node missing RayCast2D children.")
return
setup_timer()
direction_changed.connect(on_direction_changed)
func _physics_process(delta: float) -> void:
handle_direction()
handle_sprite_flip()
handle_movement(delta)
func handle_direction() -> void:
# we are not colliding with anything, which means we don't have ground to walk on. Stop moving.
if not left_ray.is_colliding() and not right_ray.is_colliding():
new_direction = Vector2.ZERO
return
# If the left ray is not colliding and the right ray is colliding, that means we have ground to the right and we should change direction to the right.
if not left_ray.is_colliding() and right_ray.is_colliding():
new_direction = Vector2.RIGHT
direction_changed.emit()
return
if not right_ray.is_colliding() and left_ray.is_colliding():
new_direction = Vector2.LEFT
direction_changed.emit()
return
func handle_sprite_flip() -> void:
if direction == Vector2.LEFT:
sprite2d.flip_h = true
else:
sprite2d.flip_h = false
func handle_movement(delta: float) -> void:
root.position += direction * speed * delta
func on_direction_changed() -> void:
if direction == new_direction or triggered_direction_change:
return
triggered_direction_change = true
direction = Vector2.ZERO
timer.start()
func on_timer_timeout() -> void:
timer.stop()
direction = new_direction
triggered_direction_change = false
func setup_timer() -> void:
timer = Timer.new()
add_child(timer)
timer.wait_time = wait_time
timer.one_shot = true
timer.timeout.connect(on_timer_timeout)

BIN
sprites/robot_cutout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://xes6mt2dd5gu"
path="res://.godot/imported/robot_cutout.png-b825d863e56b4040e1b056e369b0e91e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://sprites/robot_cutout.png"
dest_files=["res://.godot/imported/robot_cutout.png-b825d863e56b4040e1b056e369b0e91e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

View File

@@ -367,7 +367,7 @@ texture = ExtResource("1")
[resource] [resource]
physics_layer_0/collision_layer = 1 physics_layer_0/collision_layer = 1
physics_layer_0/collision_mask = 5 physics_layer_0/collision_mask = 13
terrain_set_0/mode = 0 terrain_set_0/mode = 0
terrain_set_0/terrain_0/name = "Village 0" terrain_set_0/terrain_0/name = "Village 0"
terrain_set_0/terrain_0/color = Color(0.520131, 0.153738, 0.75213, 1) terrain_set_0/terrain_0/color = Color(0.520131, 0.153738, 0.75213, 1)