Add fade away component, simple AI and shooting
This commit is contained in:
@@ -15,7 +15,7 @@ size = Vector2(16, 31)
|
||||
|
||||
[node name="Brick Player" type="CharacterBody2D"]
|
||||
collision_layer = 4
|
||||
collision_mask = 3
|
||||
collision_mask = 11
|
||||
script = ExtResource("1_8j4h4")
|
||||
|
||||
[node name="Root" type="Node2D" parent="."]
|
||||
|
41
objects/bullet.tscn
Normal file
41
objects/bullet.tscn
Normal 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
|
@@ -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="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="Script" path="res://scripts/components/fade_away.gd" id="4_fx1h2"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_3ask2"]
|
||||
radius = 9.0
|
||||
@@ -24,3 +25,10 @@ frame = 51
|
||||
script = ExtResource("2_y0k47")
|
||||
area2d = NodePath("..")
|
||||
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
59
objects/enemy.tscn
Normal 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)
|
@@ -74,6 +74,7 @@ down={
|
||||
2d_physics/layer_1="Terrain"
|
||||
2d_physics/layer_2="Collectible Entities"
|
||||
2d_physics/layer_3="Player"
|
||||
2d_physics/layer_4="Enemy"
|
||||
|
||||
[rendering]
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
32
scripts/components/bullet.gd
Normal file
32
scripts/components/bullet.gd
Normal 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()
|
@@ -2,6 +2,7 @@ class_name CollectableComponent
|
||||
extends Node
|
||||
|
||||
var root: Node
|
||||
var has_fade_away: bool = false
|
||||
|
||||
@export var area2d: Area2D
|
||||
@export var collectable_data: Resource
|
||||
@@ -16,7 +17,11 @@ func _ready() -> void:
|
||||
|
||||
root = get_parent()
|
||||
|
||||
if root.has_node("FadeAwayComponent"):
|
||||
has_fade_away = true
|
||||
|
||||
func _on_area2d_body_entered(body: Node2D) -> void:
|
||||
if body.has_node("CanPickUpComponent"):
|
||||
collected.emit(collectable_data.amount)
|
||||
if not has_fade_away:
|
||||
root.queue_free()
|
||||
|
27
scripts/components/fade_away.gd
Normal file
27
scripts/components/fade_away.gd
Normal 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()
|
44
scripts/components/periodic_shooting.gd
Normal file
44
scripts/components/periodic_shooting.gd
Normal 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)
|
@@ -15,6 +15,5 @@ func on_collected(amount: int) -> void:
|
||||
return
|
||||
|
||||
game_manager.add_coins(amount)
|
||||
print("Coins: ", game_manager.get_coins())
|
||||
# todo: play sound
|
||||
# todo: update ui
|
||||
|
82
scripts/components/side_to_side_movement.gd
Normal file
82
scripts/components/side_to_side_movement.gd
Normal 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
BIN
sprites/robot_cutout.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 225 B |
34
sprites/robot_cutout.png.import
Normal file
34
sprites/robot_cutout.png.import
Normal 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
|
@@ -367,7 +367,7 @@ texture = ExtResource("1")
|
||||
|
||||
[resource]
|
||||
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/terrain_0/name = "Village 0"
|
||||
terrain_set_0/terrain_0/color = Color(0.520131, 0.153738, 0.75213, 1)
|
||||
|
Reference in New Issue
Block a user