✨ Ebb and flow
BIN
assets/fonts/ibm-plex-sans-regular.otf
Normal file
33
assets/fonts/ibm-plex-sans-regular.otf.import
Normal file
@ -0,0 +1,33 @@
|
||||
[remap]
|
||||
|
||||
importer="font_data_dynamic"
|
||||
type="FontFile"
|
||||
uid="uid://cjga4eijrww18"
|
||||
path="res://.godot/imported/ibm-plex-sans-regular.otf-03ba595ab5fa8897c955d71d581c61dd.fontdata"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/fonts/ibm-plex-sans-regular.otf"
|
||||
dest_files=["res://.godot/imported/ibm-plex-sans-regular.otf-03ba595ab5fa8897c955d71d581c61dd.fontdata"]
|
||||
|
||||
[params]
|
||||
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
allow_system_fallback=true
|
||||
force_autohinter=false
|
||||
hinting=1
|
||||
subpixel_positioning=1
|
||||
oversampling=0.0
|
||||
Fallbacks=null
|
||||
fallbacks=[]
|
||||
Compress=null
|
||||
compress=true
|
||||
preload=[]
|
||||
language_support={}
|
||||
script_support={}
|
||||
opentype_features={}
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 249 B |
@ -3,15 +3,15 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://p3urintydjlo"
|
||||
path="res://.godot/imported/attacker.svg-150f6909959cc42ad50b11689a4301db.ctex"
|
||||
path="res://.godot/imported/attacker.svg-2be6a89ac945048dfab7b97c46f99d5f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/attacker.svg"
|
||||
dest_files=["res://.godot/imported/attacker.svg-150f6909959cc42ad50b11689a4301db.ctex"]
|
||||
source_file="res://assets/images/attacker.svg"
|
||||
dest_files=["res://.godot/imported/attacker.svg-2be6a89ac945048dfab7b97c46f99d5f.ctex"]
|
||||
|
||||
[params]
|
||||
|
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 226 B |
@ -3,15 +3,15 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://voltvmrkr73s"
|
||||
path="res://.godot/imported/bullet.svg-63ca26e6536cc1d6a6067a48f66d9b99.ctex"
|
||||
path="res://.godot/imported/bullet.svg-3164417db6ddc18184d97c37d20e19f8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/bullet.svg"
|
||||
dest_files=["res://.godot/imported/bullet.svg-63ca26e6536cc1d6a6067a48f66d9b99.ctex"]
|
||||
source_file="res://assets/images/bullet.svg"
|
||||
dest_files=["res://.godot/imported/bullet.svg-3164417db6ddc18184d97c37d20e19f8.ctex"]
|
||||
|
||||
[params]
|
||||
|
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B |
@ -3,15 +3,15 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b4daomndc1ag"
|
||||
path="res://.godot/imported/player.svg-e72d10ccf9c1b331af0b406534563f6c.ctex"
|
||||
path="res://.godot/imported/player.svg-351bec044cd47e73eb6ecd3eb5a3b51d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/player.svg"
|
||||
dest_files=["res://.godot/imported/player.svg-e72d10ccf9c1b331af0b406534563f6c.ctex"]
|
||||
source_file="res://assets/images/player.svg"
|
||||
dest_files=["res://.godot/imported/player.svg-351bec044cd47e73eb6ecd3eb5a3b51d.ctex"]
|
||||
|
||||
[params]
|
||||
|
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
@ -3,15 +3,15 @@
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://jxub8lma4oud"
|
||||
path="res://.godot/imported/tower_background.svg-e77d209753f33c422eeb2695c1195112.ctex"
|
||||
path="res://.godot/imported/tower.svg-0a634f4f37eb4a65b03541f661999487.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/tower_background.svg"
|
||||
dest_files=["res://.godot/imported/tower_background.svg-e77d209753f33c422eeb2695c1195112.ctex"]
|
||||
source_file="res://assets/images/tower.svg"
|
||||
dest_files=["res://.godot/imported/tower.svg-0a634f4f37eb4a65b03541f661999487.ctex"]
|
||||
|
||||
[params]
|
||||
|
@ -1,7 +0,0 @@
|
||||
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024">
|
||||
<title>Tower</title>
|
||||
<style>
|
||||
.s0 { fill: none;stroke: #4750a3;stroke-miterlimit:100;stroke-width: 64 }
|
||||
</style>
|
||||
<path id="Background" class="s0" d="m512 992c-265.4 0-480-214.6-480-480 0-265.4 214.6-480 480-480 265.4 0 480 214.6 480 480 0 265.4-214.6 480-480 480z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 385 B |
@ -1,37 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b4a5wo7y6orr0"
|
||||
path="res://.godot/imported/tower_forceground.svg-9f6d44720ea623d40c26c9524e3dd5b1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/tower_forceground.svg"
|
||||
dest_files=["res://.godot/imported/tower_forceground.svg-9f6d44720ea623d40c26c9524e3dd5b1.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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
6
codingland.tres
Normal file
@ -0,0 +1,6 @@
|
||||
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://gh5a3no0ojkl"]
|
||||
|
||||
[ext_resource type="FontFile" uid="uid://cjga4eijrww18" path="res://assets/fonts/ibm-plex-sans-regular.otf" id="1_5jc7o"]
|
||||
|
||||
[resource]
|
||||
default_font = ExtResource("1_5jc7o")
|
@ -51,7 +51,8 @@ skill_dash={
|
||||
}
|
||||
weapon_fire={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(163, 27),"global_position":Vector2(171, 107),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":256,"position":Vector2(234, 24),"global_position":Vector2(242, 104),"factor":1.0,"button_index":9,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(185, 16),"global_position":Vector2(193, 96),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/enemy_farm.gd" id="1_66qev"]
|
||||
|
||||
[node name="EnemyFarm" type="Node2D" node_paths=PackedStringArray("common_parent")]
|
||||
[node name="EnemyFarm" type="Node2D" node_paths=PackedStringArray("common_parent", "respawn_timer")]
|
||||
script = ExtResource("1_66qev")
|
||||
common_parent = NodePath(".")
|
||||
respawn_timer = NodePath("RespawnTimer")
|
||||
|
||||
[node name="RespawnTimer" type="Timer" parent="."]
|
||||
autostart = true
|
||||
|
@ -1,9 +1,12 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://l4mybb2dw107"]
|
||||
[gd_scene load_steps=9 format=3 uid="uid://l4mybb2dw107"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cwkcf8h5rspoh" path="res://scenes/objects/player.tscn" id="1_nq1ke"]
|
||||
[ext_resource type="PackedScene" uid="uid://cxlgt8h33u7os" path="res://scenes/objects/tower.tscn" id="2_betjv"]
|
||||
[ext_resource type="PackedScene" uid="uid://cppmks4ln28yd" path="res://scenes/objects/attacker.tscn" id="3_jg22m"]
|
||||
[ext_resource type="PackedScene" uid="uid://cy2xpilh8v7vx" path="res://scenes/farms/enemy_farm.tscn" id="3_ogjsq"]
|
||||
[ext_resource type="PackedScene" uid="uid://2tqfm73cc4id" path="res://scenes/manager/statistics.tscn" id="5_qd3ww"]
|
||||
[ext_resource type="PackedScene" uid="uid://cjam63kp5sg2o" path="res://scenes/ui/stats_overlay.tscn" id="5_rymed"]
|
||||
[ext_resource type="PackedScene" uid="uid://dy51uqtr2ng32" path="res://scenes/ui/finish_screen.tscn" id="6_b264x"]
|
||||
|
||||
[sub_resource type="Curve2D" id="Curve2D_gwd20"]
|
||||
_data = {
|
||||
@ -20,8 +23,9 @@ common_target = NodePath("../Player")
|
||||
|
||||
[node name="BulletFarm" type="Node2D" parent="."]
|
||||
|
||||
[node name="Player" parent="." node_paths=PackedStringArray("weapon_bullet_parent") instance=ExtResource("1_nq1ke")]
|
||||
[node name="Player" parent="." node_paths=PackedStringArray("weapon_bullet_parent", "statistics") instance=ExtResource("1_nq1ke")]
|
||||
weapon_bullet_parent = NodePath("../BulletFarm")
|
||||
statistics = NodePath("../Statistics")
|
||||
|
||||
[node name="Tower" parent="." instance=ExtResource("2_betjv")]
|
||||
|
||||
@ -31,3 +35,17 @@ curve = SubResource("Curve2D_gwd20")
|
||||
[node name="EnemySpawnPoint" type="PathFollow2D" parent="EnemySpawnPath"]
|
||||
position = Vector2(-309, -271)
|
||||
rotation = 1.5708
|
||||
|
||||
[node name="StatsOverlay" parent="." node_paths=PackedStringArray("stats") instance=ExtResource("5_rymed")]
|
||||
stats = NodePath("../Statistics")
|
||||
|
||||
[node name="FinishScreen" parent="." node_paths=PackedStringArray("stats") instance=ExtResource("6_b264x")]
|
||||
visible = false
|
||||
stats = NodePath("../Statistics")
|
||||
|
||||
[node name="Statistics" parent="." instance=ExtResource("5_qd3ww")]
|
||||
|
||||
[connection signal="enemy_defeat" from="EnemyFarm" to="Statistics" method="_on_enemy_defeated"]
|
||||
[connection signal="tower_broken" from="Tower" to="FinishScreen" method="_show"]
|
||||
[connection signal="wave_finished" from="Statistics" to="EnemyFarm" method="_on_wave_finished"]
|
||||
[connection signal="wave_started" from="Statistics" to="EnemyFarm" method="_on_wave_started"]
|
||||
|
18
scenes/manager/statistics.tscn
Normal file
@ -0,0 +1,18 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://2tqfm73cc4id"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/statistics.gd" id="1_4fj6w"]
|
||||
|
||||
[node name="Statistics" type="Node" node_paths=PackedStringArray("wave_timer", "wave_gap_timer")]
|
||||
script = ExtResource("1_4fj6w")
|
||||
wave_timer = NodePath("WaveTimer")
|
||||
wave_gap_timer = NodePath("WaveGapTimer")
|
||||
|
||||
[node name="WaveTimer" type="Timer" parent="."]
|
||||
wait_time = 10.0
|
||||
one_shot = true
|
||||
|
||||
[node name="WaveGapTimer" type="Timer" parent="."]
|
||||
one_shot = true
|
||||
|
||||
[connection signal="timeout" from="WaveTimer" to="." method="_on_wave_passed"]
|
||||
[connection signal="timeout" from="WaveGapTimer" to="." method="_on_wave_gap_passed"]
|
@ -1,6 +1,6 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://cppmks4ln28yd"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://p3urintydjlo" path="res://assets/attacker.svg" id="1_56wxx"]
|
||||
[ext_resource type="Texture2D" uid="uid://p3urintydjlo" path="res://assets/images/attacker.svg" id="1_56wxx"]
|
||||
[ext_resource type="Script" path="res://scripts/attacker.gd" id="1_d7hg4"]
|
||||
|
||||
[node name="Attacker" type="CharacterBody2D"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://h4fxpxqc6bpt"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/bullet.gd" id="1_7ic61"]
|
||||
[ext_resource type="Texture2D" uid="uid://voltvmrkr73s" path="res://assets/bullet.svg" id="1_tytsj"]
|
||||
[ext_resource type="Texture2D" uid="uid://voltvmrkr73s" path="res://assets/images/bullet.svg" id="1_tytsj"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_r7dy5"]
|
||||
size = Vector2(8, 24)
|
||||
@ -22,6 +22,7 @@ rotation = 1.5708
|
||||
shape = SubResource("RectangleShape2D_r7dy5")
|
||||
|
||||
[node name="DisposeTimer" type="Timer" parent="."]
|
||||
one_shot = true
|
||||
autostart = true
|
||||
|
||||
[connection signal="timeout" from="DisposeTimer" to="." method="_on_timed_out"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://cwkcf8h5rspoh"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/player.gd" id="1_sa7t7"]
|
||||
[ext_resource type="Texture2D" uid="uid://b4daomndc1ag" path="res://assets/player.svg" id="2_3pad2"]
|
||||
[ext_resource type="Texture2D" uid="uid://b4daomndc1ag" path="res://assets/images/player.svg" id="2_3pad2"]
|
||||
[ext_resource type="PackedScene" uid="uid://h4fxpxqc6bpt" path="res://scenes/objects/bullet.tscn" id="2_v83ov"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_k56cq"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://cxlgt8h33u7os"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/tower.gd" id="1_d5o8q"]
|
||||
[ext_resource type="Texture2D" uid="uid://jxub8lma4oud" path="res://assets/tower_background.svg" id="2_ynj1l"]
|
||||
[ext_resource type="Texture2D" uid="uid://jxub8lma4oud" path="res://assets/images/tower.svg" id="2_ynj1l"]
|
||||
[ext_resource type="Script" path="res://scripts/tower_health_display.gd" id="3_ijb8h"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_7mogk"]
|
||||
|
28
scenes/ui/finish_screen.tscn
Normal file
@ -0,0 +1,28 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dy51uqtr2ng32"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/finish_screen.gd" id="1_c1emt"]
|
||||
[ext_resource type="Theme" uid="uid://gh5a3no0ojkl" path="res://codingland.tres" id="1_l6ven"]
|
||||
|
||||
[node name="FinishScreen" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = ExtResource("1_l6ven")
|
||||
script = ExtResource("1_c1emt")
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
layout_mode = 0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 648.0
|
||||
|
||||
[node name="Title" type="Label" parent="Panel"]
|
||||
layout_mode = 0
|
||||
offset_top = 280.0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 364.0
|
||||
theme_override_font_sizes/font_size = 64
|
||||
text = "Game Over"
|
||||
horizontal_alignment = 1
|
78
scenes/ui/stats_overlay.tscn
Normal file
@ -0,0 +1,78 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://cjam63kp5sg2o"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/stats_overlay.gd" id="1_iejg3"]
|
||||
[ext_resource type="Theme" uid="uid://gh5a3no0ojkl" path="res://codingland.tres" id="1_ne3m3"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_bs475"]
|
||||
bg_color = Color(0.996078, 0.996078, 0.996078, 0.588235)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rfnxc"]
|
||||
bg_color = Color(0.517647, 0.729412, 0.478431, 1)
|
||||
|
||||
[node name="StatsOverlay" type="Control" node_paths=PackedStringArray("survived_indicator", "wave_indicator", "wave_progress")]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = ExtResource("1_ne3m3")
|
||||
script = ExtResource("1_iejg3")
|
||||
survived_indicator = NodePath("SurvivedControl/SurvivedTime")
|
||||
wave_indicator = NodePath("WaveControl/WaveCount")
|
||||
wave_progress = NodePath("WaveControl/WaveProgress")
|
||||
|
||||
[node name="SurvivedControl" type="Control" parent="."]
|
||||
anchors_preset = 0
|
||||
offset_top = 570.0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 648.0
|
||||
|
||||
[node name="SurvivedCaption" type="Label" parent="SurvivedControl"]
|
||||
layout_mode = 0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 26.0
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "You survived"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="SurvivedTime" type="Label" parent="SurvivedControl"]
|
||||
layout_mode = 0
|
||||
offset_top = 20.0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 65.0
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "0.0s"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="WaveControl" type="Control" parent="."]
|
||||
anchors_preset = 0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 648.0
|
||||
|
||||
[node name="WaveCaption" type="Label" parent="WaveControl"]
|
||||
layout_mode = 0
|
||||
offset_top = 14.0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 40.0
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Wave"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="WaveCount" type="Label" parent="WaveControl"]
|
||||
layout_mode = 0
|
||||
offset_top = 34.0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 79.0
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "1"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="WaveProgress" type="ProgressBar" parent="WaveControl"]
|
||||
custom_minimum_size = Vector2(2.08165e-12, 10)
|
||||
layout_mode = 0
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 8.0
|
||||
theme_override_styles/background = SubResource("StyleBoxFlat_bs475")
|
||||
theme_override_styles/fill = SubResource("StyleBoxFlat_rfnxc")
|
||||
show_percentage = false
|
@ -1,6 +1,7 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var damage = 12.0
|
||||
@export var knockback = 4
|
||||
|
||||
func _physics_process(delta):
|
||||
var collision = move_and_collide(velocity * delta)
|
||||
@ -8,6 +9,8 @@ func _physics_process(delta):
|
||||
if collision:
|
||||
var collider = collision.get_collider()
|
||||
if collider is Enemy:
|
||||
var normal = collision.get_normal()
|
||||
collider.velocity = collider.velocity.bounce(normal) * knockback
|
||||
collider.take_damage(damage)
|
||||
queue_free()
|
||||
|
||||
|
@ -2,6 +2,8 @@ class_name Enemy
|
||||
|
||||
extends CharacterBody2D
|
||||
|
||||
signal enemy_defeat
|
||||
|
||||
@export var damage = 8.0
|
||||
@export var max_health = 20
|
||||
|
||||
@ -13,4 +15,5 @@ func _ready():
|
||||
func take_damage(amount: float):
|
||||
health -= amount
|
||||
if health <= 0:
|
||||
enemy_defeat.emit()
|
||||
queue_free()
|
||||
|
@ -1,11 +1,15 @@
|
||||
extends Node2D
|
||||
|
||||
signal enemy_defeat
|
||||
|
||||
@export var common_parent: Node2D
|
||||
@export var path_follow: PathFollow2D
|
||||
|
||||
@export var target: PackedScene
|
||||
@export var common_target: Node2D
|
||||
|
||||
@export var respawn_timer: Timer
|
||||
|
||||
func spawn():
|
||||
var instance = target.instantiate()
|
||||
|
||||
@ -18,6 +22,16 @@ func spawn():
|
||||
instance.speed = randi_range(800, 1400)
|
||||
|
||||
instance.target = common_target
|
||||
instance.connect("enemy_defeat", _on_enemy_defeat)
|
||||
|
||||
# Add into common parent
|
||||
common_parent.add_child(instance)
|
||||
|
||||
func _on_wave_finished():
|
||||
respawn_timer.stop()
|
||||
|
||||
func _on_wave_started():
|
||||
respawn_timer.start()
|
||||
|
||||
func _on_enemy_defeat():
|
||||
enemy_defeat.emit()
|
||||
|
@ -14,6 +14,8 @@ extends CharacterBody2D
|
||||
@export var fire_cooldown_duration = 0.2
|
||||
@export var fire_cooldown_timer: Timer
|
||||
|
||||
@export var statistics: Statistics
|
||||
|
||||
func deal_move(delta):
|
||||
var input_direction = Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
||||
velocity = velocity.move_toward(input_direction * speed, speed * delta)
|
||||
@ -36,6 +38,7 @@ func deal_weapon_shoot():
|
||||
bullet.global_position = global_position
|
||||
bullet.velocity = direction * weapon_bullet_speed
|
||||
|
||||
statistics.bullet_shoot += 1
|
||||
fire_cooldown_timer.start(fire_cooldown_duration)
|
||||
|
||||
func _on_dash_cooled_down():
|
||||
|
71
scripts/statistics.gd
Normal file
@ -0,0 +1,71 @@
|
||||
class_name Statistics
|
||||
|
||||
extends Node
|
||||
|
||||
signal wave_finished
|
||||
signal wave_started
|
||||
|
||||
var time_started
|
||||
var time_survived
|
||||
|
||||
var wave_passed: int
|
||||
var in_wave_gap: bool
|
||||
|
||||
var enemies_defeated: int
|
||||
var bullet_shoot: int
|
||||
|
||||
@export var wave_gap_duration = 10
|
||||
@export var wave_duration = 10
|
||||
@export var wave_multiplier = 1.5
|
||||
|
||||
@export var wave_timer: Timer
|
||||
@export var wave_gap_timer: Timer
|
||||
|
||||
func _ready():
|
||||
time_started = Time.get_ticks_msec()
|
||||
time_survived = null
|
||||
|
||||
wave_passed = 0
|
||||
enemies_defeated = 0
|
||||
bullet_shoot = 0
|
||||
|
||||
_on_wave_gap_passed()
|
||||
|
||||
func _on_game_over():
|
||||
time_survived = get_time_survived()
|
||||
|
||||
func get_current_wave():
|
||||
return wave_passed + 1
|
||||
|
||||
func get_current_wave_time():
|
||||
if in_wave_gap:
|
||||
return get_current_wave_duration() - $WaveGapTimer.time_left
|
||||
else:
|
||||
return get_current_wave_duration() - $WaveTimer.time_left
|
||||
|
||||
func get_current_wave_duration():
|
||||
if in_wave_gap:
|
||||
return wave_gap_duration
|
||||
else:
|
||||
return wave_duration + wave_multiplier * wave_passed
|
||||
|
||||
func get_time_survived():
|
||||
if time_survived == null:
|
||||
return Time.get_ticks_msec() - time_started
|
||||
else:
|
||||
return time_survived
|
||||
|
||||
func _on_enemy_defeated():
|
||||
enemies_defeated += 1
|
||||
|
||||
func _on_wave_passed():
|
||||
wave_passed += 1
|
||||
in_wave_gap = true
|
||||
wave_finished.emit()
|
||||
wave_gap_timer.start(wave_gap_duration)
|
||||
|
||||
func _on_wave_gap_passed():
|
||||
in_wave_gap = false
|
||||
wave_started.emit()
|
||||
wave_timer.wait_time = get_current_wave_duration()
|
||||
wave_timer.start()
|
@ -2,6 +2,6 @@ extends Sprite2D
|
||||
|
||||
@export var regeneration_progress = 0.5
|
||||
|
||||
func _process(delta):
|
||||
func _process(_wdelta):
|
||||
set_modulate(Color(1, 1, 1, regeneration_progress))
|
||||
rotation_degrees += 1
|
||||
|
6
scripts/ui/finish_screen.gd
Normal file
@ -0,0 +1,6 @@
|
||||
extends Control
|
||||
|
||||
@export var stats: Statistics
|
||||
|
||||
func _show():
|
||||
visible = true
|
25
scripts/ui/stats_overlay.gd
Normal file
@ -0,0 +1,25 @@
|
||||
extends Control
|
||||
|
||||
@export var stats: Statistics
|
||||
|
||||
@export var survived_indicator: Label
|
||||
|
||||
@export var wave_indicator: Label
|
||||
@export var wave_progress: ProgressBar
|
||||
|
||||
var wave_stylebox = StyleBoxFlat.new()
|
||||
var wave_gap_stylebox = StyleBoxFlat.new()
|
||||
|
||||
func _ready():
|
||||
wave_stylebox.bg_color = Color("84ba7a")
|
||||
wave_gap_stylebox.bg_color = Color("89a1e5")
|
||||
|
||||
func _process(_delta):
|
||||
survived_indicator.text = "%.2fs" % (stats.get_time_survived() / 1000.0)
|
||||
wave_indicator.text = "%d" % stats.get_current_wave()
|
||||
|
||||
if stats.in_wave_gap:
|
||||
wave_progress.add_theme_stylebox_override("fill", wave_gap_stylebox)
|
||||
else:
|
||||
wave_progress.add_theme_stylebox_override("fill", wave_stylebox)
|
||||
wave_progress.value = stats.get_current_wave_time() / stats.get_current_wave_duration() * 100
|