diff --git a/assets/attacker.svg b/assets/attacker.svg new file mode 100644 index 0000000..cc4ca21 --- /dev/null +++ b/assets/attacker.svg @@ -0,0 +1,7 @@ + + Tower + + + \ No newline at end of file diff --git a/assets/attacker.svg.import b/assets/attacker.svg.import new file mode 100644 index 0000000..1992951 --- /dev/null +++ b/assets/attacker.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://p3urintydjlo" +path="res://.godot/imported/attacker.svg-150f6909959cc42ad50b11689a4301db.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/attacker.svg" +dest_files=["res://.godot/imported/attacker.svg-150f6909959cc42ad50b11689a4301db.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 diff --git a/assets/bullet.svg b/assets/bullet.svg new file mode 100644 index 0000000..c036713 --- /dev/null +++ b/assets/bullet.svg @@ -0,0 +1,7 @@ + + Tower + + + \ No newline at end of file diff --git a/assets/bullet.svg.import b/assets/bullet.svg.import new file mode 100644 index 0000000..98100fb --- /dev/null +++ b/assets/bullet.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://voltvmrkr73s" +path="res://.godot/imported/bullet.svg-63ca26e6536cc1d6a6067a48f66d9b99.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/bullet.svg" +dest_files=["res://.godot/imported/bullet.svg-63ca26e6536cc1d6a6067a48f66d9b99.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 diff --git a/assets/tower_forceground.svg.import b/assets/tower_forceground.svg.import index 8a40759..5d191f3 100644 --- a/assets/tower_forceground.svg.import +++ b/assets/tower_forceground.svg.import @@ -2,7 +2,7 @@ importer="texture" type="CompressedTexture2D" -uid="uid://dq3gmuse32md2" +uid="uid://b4a5wo7y6orr0" path="res://.godot/imported/tower_forceground.svg-9f6d44720ea623d40c26c9524e3dd5b1.ctex" metadata={ "vram_texture": false diff --git a/project.godot b/project.godot index d6091c3..0694de8 100644 --- a/project.godot +++ b/project.godot @@ -49,3 +49,14 @@ skill_dash={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) ] } +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) +] +} + +[layer_names] + +2d_physics/layer_1="Player" +2d_physics/layer_2="Hostile" +2d_physics/layer_3="Bullet" diff --git a/scenes/farms/enemy_farm.tscn b/scenes/farms/enemy_farm.tscn new file mode 100644 index 0000000..99fee40 --- /dev/null +++ b/scenes/farms/enemy_farm.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=2 format=3 uid="uid://cy2xpilh8v7vx"] + +[ext_resource type="Script" path="res://scripts/enemy_farm.gd" id="1_66qev"] + +[node name="EnemyFarm" type="Node2D" node_paths=PackedStringArray("common_parent")] +script = ExtResource("1_66qev") +common_parent = NodePath(".") + +[node name="RespawnTimer" type="Timer" parent="."] +autostart = true + +[connection signal="timeout" from="RespawnTimer" to="." method="spawn"] diff --git a/scenes/main.tscn b/scenes/main.tscn index 6901ac7..3102a3c 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -1,10 +1,33 @@ -[gd_scene load_steps=3 format=3 uid="uid://l4mybb2dw107"] +[gd_scene load_steps=6 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"] + +[sub_resource type="Curve2D" id="Curve2D_gwd20"] +_data = { +"points": PackedVector2Array(0, 0, 0, 0, -309, -271, 0, 0, 0, 0, -309, 850, 0, 0, 0, 0, 1369, 849, 0, 0, 0, 0, 1368, -272, 0, 0, 0, 0, -309, -271) +} +point_count = 5 [node name="Main" type="Node2D"] -[node name="Player" parent="." instance=ExtResource("1_nq1ke")] +[node name="EnemyFarm" parent="." node_paths=PackedStringArray("path_follow", "common_target") instance=ExtResource("3_ogjsq")] +path_follow = NodePath("../EnemySpawnPath/EnemySpawnPoint") +target = ExtResource("3_jg22m") +common_target = NodePath("../Player") + +[node name="BulletFarm" type="Node2D" parent="."] + +[node name="Player" parent="." node_paths=PackedStringArray("weapon_bullet_parent") instance=ExtResource("1_nq1ke")] +weapon_bullet_parent = NodePath("../BulletFarm") [node name="Tower" parent="." instance=ExtResource("2_betjv")] + +[node name="EnemySpawnPath" type="Path2D" parent="."] +curve = SubResource("Curve2D_gwd20") + +[node name="EnemySpawnPoint" type="PathFollow2D" parent="EnemySpawnPath"] +position = Vector2(-309, -271) +rotation = 1.5708 diff --git a/scenes/objects/attacker.tscn b/scenes/objects/attacker.tscn new file mode 100644 index 0000000..a469515 --- /dev/null +++ b/scenes/objects/attacker.tscn @@ -0,0 +1,19 @@ +[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="Script" path="res://scripts/attacker.gd" id="1_d7hg4"] + +[node name="Attacker" type="CharacterBody2D"] +collision_layer = 2 +collision_mask = 7 +script = ExtResource("1_d7hg4") + +[node name="AttackerSprite" type="Sprite2D" parent="."] +position = Vector2(5.96046e-08, -12) +scale = Vector2(0.1, 0.1) +texture = ExtResource("1_56wxx") + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."] +position = Vector2(3.55271e-15, -12) +scale = Vector2(0.2, 0.2) +polygon = PackedVector2Array(2.08165e-12, -222, -256, 222, 256, 222) diff --git a/scenes/objects/bullet.tscn b/scenes/objects/bullet.tscn new file mode 100644 index 0000000..0147d94 --- /dev/null +++ b/scenes/objects/bullet.tscn @@ -0,0 +1,27 @@ +[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"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_r7dy5"] +size = Vector2(8, 24) + +[node name="Bullet" type="CharacterBody2D"] +collision_layer = 4 +collision_mask = 2 +script = ExtResource("1_7ic61") + +[node name="BulletSprite" type="Sprite2D" parent="."] +position = Vector2(2.08165e-12, 2.08165e-12) +rotation = 1.5708 +scale = Vector2(0.25, 0.25) +texture = ExtResource("1_tytsj") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +rotation = 1.5708 +shape = SubResource("RectangleShape2D_r7dy5") + +[node name="DisposeTimer" type="Timer" parent="."] +autostart = true + +[connection signal="timeout" from="DisposeTimer" to="." method="_on_timed_out"] diff --git a/scenes/objects/player.tscn b/scenes/objects/player.tscn index a27259d..d02ba69 100644 --- a/scenes/objects/player.tscn +++ b/scenes/objects/player.tscn @@ -1,17 +1,25 @@ -[gd_scene load_steps=4 format=3 uid="uid://cwkcf8h5rspoh"] +[gd_scene load_steps=5 format=3 uid="uid://cwkcf8h5rspoh"] -[ext_resource type="Script" path="res://scripts/PlayerMovement.gd" id="1_e1gjl"] +[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="PackedScene" uid="uid://h4fxpxqc6bpt" path="res://scenes/objects/bullet.tscn" id="2_v83ov"] [sub_resource type="CircleShape2D" id="CircleShape2D_k56cq"] radius = 52.0096 -[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("dash_cooldown_timer")] -script = ExtResource("1_e1gjl") +[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("dash_cooldown_timer", "weapon_bullet_parent", "fire_cooldown_timer")] +collision_mask = 3 +script = ExtResource("1_sa7t7") dash_cooldown_timer = NodePath("DashCooldown") +weapon_bullet_scene = ExtResource("2_v83ov") +weapon_bullet_parent = NodePath("") +fire_cooldown_timer = NodePath("ShootCooldown") [node name="DashCooldown" type="Timer" parent="."] +[node name="ShootCooldown" type="Timer" parent="."] +wait_time = 0.2 + [node name="PlayerSprite" type="Sprite2D" parent="."] position = Vector2(1.90735e-06, 1.78814e-06) scale = Vector2(0.1, 0.1) @@ -20,4 +28,5 @@ texture = ExtResource("2_3pad2") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource("CircleShape2D_k56cq") -[connection signal="timeout" from="DashCooldown" to="." method="_on_cooled_down"] +[connection signal="timeout" from="DashCooldown" to="." method="_on_dash_cooled_down"] +[connection signal="timeout" from="ShootCooldown" to="." method="_on_fire_cooled_down"] diff --git a/scenes/objects/tower.tscn b/scenes/objects/tower.tscn index 1f5ae79..8b8c385 100644 --- a/scenes/objects/tower.tscn +++ b/scenes/objects/tower.tscn @@ -1,17 +1,23 @@ -[gd_scene load_steps=4 format=3 uid="uid://cxlgt8h33u7os"] +[gd_scene load_steps=5 format=3 uid="uid://cxlgt8h33u7os"] -[ext_resource type="Script" path="res://scripts/Tower.gd" id="1_58egr"] +[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="Script" path="res://scripts/tower_health_display.gd" id="3_ijb8h"] [sub_resource type="CircleShape2D" id="CircleShape2D_7mogk"] radius = 129.139 -[node name="Tower" type="Area2D"] -script = ExtResource("1_58egr") +[node name="Tower" type="Area2D" node_paths=PackedStringArray("sprite")] +collision_mask = 3 +script = ExtResource("1_d5o8q") +sprite = NodePath("TowerSprite") [node name="TowerSprite" type="Sprite2D" parent="."] scale = Vector2(0.25, 0.25) texture = ExtResource("2_ynj1l") +script = ExtResource("3_ijb8h") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource("CircleShape2D_7mogk") + +[connection signal="body_entered" from="." to="." method="_on_someone_entered"] diff --git a/scripts/PlayerMovement.gd b/scripts/PlayerMovement.gd deleted file mode 100644 index 0a59507..0000000 --- a/scripts/PlayerMovement.gd +++ /dev/null @@ -1,29 +0,0 @@ -extends CharacterBody2D - -@export var speed = 1200 -@export var speed_multiplier = 20 -@export var friction = 0.9 - -@export var dash_cooldown_duration = 1.0 -@export var dash_cooldown_timer: Timer - -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) - velocity = velocity * friction - - var is_dash = Input.is_action_pressed("skill_dash") - if is_dash && dash_cooldown_timer.is_stopped(): - velocity *= speed_multiplier - dash_cooldown_timer.start(dash_cooldown_duration) - -func _on_cooled_down(): - dash_cooldown_timer.stop() - -func _ready(): - var screen_size = get_viewport_rect().size - position = Vector2(screen_size.x / 2, screen_size.y / 2) - -func _physics_process(delta): - deal_move(delta) - move_and_slide() diff --git a/scripts/Tower.gd b/scripts/Tower.gd index d42fdac..7c4c990 100644 --- a/scripts/Tower.gd +++ b/scripts/Tower.gd @@ -1,5 +1,35 @@ extends Area2D -func _ready(): +signal tower_broken + +@export var sprite: Sprite2D + +@export var max_health = 100 +@export var max_energy = 20 + +var health: float +var energy: float + +func move_to_center(): var screen_size = get_viewport_rect().size position = Vector2(screen_size.x / 2, screen_size.y / 2) + +func take_damage(amount: float): + health -= amount + if health <= 0: + tower_broken.emit() + get_tree().paused = true + +func _ready(): + move_to_center() + + health = max_health + energy = max_energy + +func _process(_delta): + sprite.regeneration_progress = health / max_health + +func _on_someone_entered(body): + if body is Enemy: + take_damage(body.damage) + body.queue_free() diff --git a/scripts/attacker.gd b/scripts/attacker.gd new file mode 100644 index 0000000..7527094 --- /dev/null +++ b/scripts/attacker.gd @@ -0,0 +1,17 @@ +extends Enemy + +@export var speed = 800 +@export var friction = 0.9 + +@export var target: Node2D + +func deal_move(delta): + if target: + var angle = get_angle_to(target.position) + var direction = Vector2(cos(angle), sin(angle)) + velocity = velocity.move_toward(direction * speed, speed * delta) + velocity = velocity * friction + +func _physics_process(delta): + deal_move(delta) + move_and_slide() diff --git a/scripts/bullet.gd b/scripts/bullet.gd new file mode 100644 index 0000000..3ff4f46 --- /dev/null +++ b/scripts/bullet.gd @@ -0,0 +1,15 @@ +extends CharacterBody2D + +@export var damage = 12.0 + +func _physics_process(delta): + var collision = move_and_collide(velocity * delta) + + if collision: + var collider = collision.get_collider() + if collider is Enemy: + collider.take_damage(damage) + queue_free() + +func _on_timed_out(): + queue_free() diff --git a/scripts/enemy.gd b/scripts/enemy.gd new file mode 100644 index 0000000..6abd6b2 --- /dev/null +++ b/scripts/enemy.gd @@ -0,0 +1,16 @@ +class_name Enemy + +extends CharacterBody2D + +@export var damage = 8.0 +@export var max_health = 20 + +var health: float + +func _ready(): + health = max_health + +func take_damage(amount: float): + health -= amount + if health <= 0: + queue_free() diff --git a/scripts/enemy_farm.gd b/scripts/enemy_farm.gd new file mode 100644 index 0000000..4199672 --- /dev/null +++ b/scripts/enemy_farm.gd @@ -0,0 +1,23 @@ +extends Node2D + +@export var common_parent: Node2D +@export var path_follow: PathFollow2D + +@export var target: PackedScene +@export var common_target: Node2D + +func spawn(): + var instance = target.instantiate() + + # Randomize + path_follow.progress_ratio = randi() + instance.position = path_follow.position + + var target_scale = randf_range(0.2, 0.95) + instance.scale = Vector2(target_scale, target_scale) + instance.speed = randi_range(800, 1400) + + instance.target = common_target + + # Add into common parent + common_parent.add_child(instance) diff --git a/scripts/player.gd b/scripts/player.gd new file mode 100644 index 0000000..8547add --- /dev/null +++ b/scripts/player.gd @@ -0,0 +1,54 @@ +extends CharacterBody2D + +@export var speed = 1200 +@export var speed_multiplier = 20 +@export var friction = 0.9 + +@export var dash_cooldown_duration = 1.0 +@export var dash_cooldown_timer: Timer + +@export var weapon_bullet_speed = 3200 +@export var weapon_bullet_scene: PackedScene +@export var weapon_bullet_parent: Node2D + +@export var fire_cooldown_duration = 0.2 +@export var fire_cooldown_timer: Timer + +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) + velocity = velocity * friction + + var is_dash = Input.is_action_pressed("skill_dash") + if is_dash && dash_cooldown_timer.is_stopped(): + velocity *= speed_multiplier + dash_cooldown_timer.start(dash_cooldown_duration) + +func deal_weapon_shoot(): + var is_shooting = Input.is_action_pressed("weapon_fire") + if is_shooting && fire_cooldown_timer.is_stopped(): + var mouse_position = get_global_mouse_position() + var direction = (mouse_position - position).normalized() + var bullet = weapon_bullet_scene.instantiate() + bullet.rotation = direction.angle() + weapon_bullet_parent.add_child(bullet) + + bullet.global_position = global_position + bullet.velocity = direction * weapon_bullet_speed + + fire_cooldown_timer.start(fire_cooldown_duration) + +func _on_dash_cooled_down(): + dash_cooldown_timer.stop() + +func _on_fire_cooled_down(): + fire_cooldown_timer.stop() + +func _ready(): + var screen_size = get_viewport_rect().size + position = Vector2(screen_size.x / 2, screen_size.y / 2) + +func _physics_process(delta): + deal_move(delta) + deal_weapon_shoot() + move_and_slide() diff --git a/scripts/tower_health_display.gd b/scripts/tower_health_display.gd new file mode 100644 index 0000000..8808f2c --- /dev/null +++ b/scripts/tower_health_display.gd @@ -0,0 +1,7 @@ +extends Sprite2D + +@export var regeneration_progress = 0.5 + +func _process(delta): + set_modulate(Color(1, 1, 1, regeneration_progress)) + rotation_degrees += 1