├── .gitignore ├── LICENSE ├── concept-plain.svg ├── concept.svg ├── source ├── Actors │ ├── Enemies │ │ ├── CutoutCharacter.tscn │ │ ├── Enemy.gd │ │ ├── Enemy.tscn │ │ ├── ToughEnemy.tscn │ │ ├── particle.svg │ │ └── particle.svg.import │ └── Player │ │ ├── Player.gd │ │ └── Player.tscn ├── Areas │ └── AsteroidSurface │ │ ├── rocks-and-craters.svg │ │ ├── rocks-and-craters.svg.import │ │ ├── sand.svg │ │ ├── sand.svg.import │ │ ├── tileset.tres │ │ ├── walkable-path.svg │ │ └── walkable-path.svg.import ├── Game.gd ├── Game.tscn ├── Levels │ ├── AStarGrid │ │ ├── AStarGrid.gd │ │ └── AStarGrid.tscn │ ├── EventsPlayer.gd │ ├── Level.gd │ ├── Level.tscn │ ├── Level1.tscn │ ├── Level2.tscn │ ├── TowerPlacer │ │ ├── TowerPlacer.gd │ │ ├── TowerPlacer.tscn │ │ ├── grid-cell.svg │ │ └── grid-cell.svg.import │ └── Waves │ │ ├── Wave.gd │ │ ├── Wave1.tscn │ │ ├── Wave2.tscn │ │ ├── Wave3.tscn │ │ └── Wave4.tscn ├── Objects │ ├── EnemySpawn │ │ ├── enemy-spawn.svg │ │ └── enemy-spawn.svg.import │ ├── HitBox │ │ ├── HitBoxArea2D.gd │ │ └── HitBoxArea2D.tscn │ ├── HurtBox │ │ ├── HurtBoxArea2D.gd │ │ └── HurtBoxArea2D.tscn │ ├── PlayerBase │ │ ├── CutoutPlayerBase.tscn │ │ ├── CutoutSprites.gd │ │ ├── PlayerBase.gd │ │ ├── PlayerBase.tscn │ │ ├── player-base.svg │ │ └── player-base.svg.import │ ├── SelectableArea2D │ │ ├── SelectableArea2D.gd │ │ └── SelectableArea2D.tscn │ ├── Towers │ │ ├── BombTower.tscn │ │ ├── RifleTower.tscn │ │ ├── Tower.gd │ │ ├── Tower.tscn │ │ └── Upgrades │ │ │ ├── FireRangeUpgrade.gd │ │ │ └── Upgrade.gd │ ├── WaveSpawner2D │ │ ├── WaveSpawner2D.gd │ │ └── WaveSpawner2D.tscn │ └── Weapon2D │ │ ├── Bullets │ │ ├── BombBullet.tscn │ │ ├── Bullet.gd │ │ └── Bullet.tscn │ │ ├── RangePreview │ │ ├── RangePreview.gd │ │ ├── RangePreview.tscn │ │ ├── range-preview.svg │ │ └── range-preview.svg.import │ │ ├── Weapon2D.gd │ │ └── Weapon2D.tscn ├── Screens │ ├── EndScreen.gd │ └── EndScreen.tscn ├── UI │ ├── Theme │ │ ├── Montserrat-ExtraBold.ttf │ │ ├── background_stylebox.tres │ │ ├── button_font.tres │ │ ├── foreground_stylebox.tres │ │ ├── main_font.tres │ │ └── main_theme.tres │ ├── UICooldownBar │ │ ├── UICooldownBar.gd │ │ ├── UICooldownBar.tscn │ │ ├── clock-tic.png │ │ ├── clock-tic.png.import │ │ ├── clock.png │ │ ├── clock.png.import │ │ ├── cooldown-bar-over.png │ │ ├── cooldown-bar-over.png.import │ │ ├── cooldown-bar-progress.png │ │ ├── cooldown-bar-progress.png.import │ │ ├── cooldown-bar-under.png │ │ └── cooldown-bar-under.png.import │ ├── UIGoldPanel.gd │ ├── UIGoldPanel.tscn │ ├── UIHealthBar │ │ ├── UIHealthBar.tscn │ │ ├── UITimedHealthBar.gd │ │ ├── UITimedHealthBar.tscn │ │ ├── heart.svg │ │ └── heart.svg.import │ ├── UIScreenOverlay.gd │ ├── UIScreenOverlay.tscn │ ├── UITowerShop │ │ ├── UITowerPurchaseButton.gd │ │ ├── UITowerPurchaseButton.tscn │ │ ├── UITowerShop.gd │ │ ├── UITowerShop.tscn │ │ ├── tower-icon-disabled.svg │ │ ├── tower-icon-disabled.svg.import │ │ ├── tower-icon-focused.svg │ │ ├── tower-icon-focused.svg.import │ │ ├── tower-icon-hover.svg │ │ ├── tower-icon-hover.svg.import │ │ ├── tower-icon-normal.svg │ │ ├── tower-icon-normal.svg.import │ │ ├── tower-icon-pressed.svg │ │ └── tower-icon-pressed.svg.import │ ├── UIUnit │ │ ├── UIUnit.gd │ │ └── UIUnit.tscn │ └── UIUpgradeShop │ │ ├── UIUpgradeButton.gd │ │ ├── UIUpgradeButton.tscn │ │ ├── UIUpgradeShop.gd │ │ └── UIUpgradeShop.tscn ├── VFX │ ├── Explosions │ │ ├── Explosion.tscn │ │ ├── SmallExplosion.tscn │ │ ├── explosion_gradient.tres │ │ ├── puff.png │ │ ├── puff.png.import │ │ ├── puff_smooth.png │ │ ├── puff_smooth.png.import │ │ ├── scraps_gradient.tres │ │ ├── sparkle.png │ │ ├── sparkle.png.import │ │ ├── white_glowing_circle.png │ │ └── white_glowing_circle.png.import │ └── PathPreview.tscn ├── default_env.tres ├── icon.png ├── icon.png.import ├── project.godot ├── sprite-sheet.svg └── sprite-sheet.svg.import └── start-project ├── Actors └── Enemies │ ├── CutoutCharacter.tscn │ ├── particle.svg │ └── particle.svg.import ├── Areas └── AsteroidSurface │ ├── rocks-and-craters.svg │ ├── rocks-and-craters.svg.import │ ├── sand.svg │ ├── sand.svg.import │ ├── tileset.tres │ ├── walkable-path.svg │ └── walkable-path.svg.import ├── Objects ├── PlayerBase │ ├── CutoutPlayerBase.tscn │ └── CutoutSprites.gd └── Weapon2D │ └── RangePreview │ ├── RangePreview.gd │ ├── RangePreview.tscn │ ├── range-preview.svg │ └── range-preview.svg.import ├── Screens ├── EndScreen.gd └── EndScreen.tscn ├── UI ├── Theme │ ├── Montserrat-ExtraBold.ttf │ ├── background_stylebox.tres │ ├── button_font.tres │ ├── foreground_stylebox.tres │ ├── main_font.tres │ └── main_theme.tres ├── UICooldownBar │ ├── UICooldownBar.gd │ ├── UICooldownBar.tscn │ ├── clock-tic.png │ ├── clock-tic.png.import │ ├── clock.png │ ├── clock.png.import │ ├── cooldown-bar-over.png │ ├── cooldown-bar-over.png.import │ ├── cooldown-bar-progress.png │ ├── cooldown-bar-progress.png.import │ ├── cooldown-bar-under.png │ └── cooldown-bar-under.png.import ├── UIGoldPanel │ ├── UIGoldPanel.gd │ └── UIGoldPanel.tscn ├── UIHealthBar │ ├── UIHealthBar.tscn │ ├── UITimedHealthBar.gd │ ├── UITimedHealthBar.tscn │ ├── heart.svg │ └── heart.svg.import ├── UIScreenOverlay │ ├── UIScreenOverlay.gd │ └── UIScreenOverlay.tscn ├── UITowerShop │ ├── tower-icon-disabled.svg │ ├── tower-icon-disabled.svg.import │ ├── tower-icon-focused.svg │ ├── tower-icon-focused.svg.import │ ├── tower-icon-hover.svg │ ├── tower-icon-hover.svg.import │ ├── tower-icon-normal.svg │ ├── tower-icon-normal.svg.import │ ├── tower-icon-pressed.svg │ └── tower-icon-pressed.svg.import └── UIUnit │ ├── UIUnit.gd │ └── UIUnit.tscn ├── VFX ├── Explosion │ ├── Explosion.tscn │ ├── SmallExplosion.tscn │ ├── explosion_gradient.tres │ ├── puff.png │ ├── puff.png.import │ ├── puff_smooth.png │ ├── puff_smooth.png.import │ ├── scraps_gradient.tres │ ├── sparkle.png │ ├── sparkle.png.import │ ├── white_glowing_circle.png │ └── white_glowing_circle.png.import └── PathPreview.tscn ├── default_env.tres ├── grid-cell.svg ├── grid-cell.svg.import ├── icon.png ├── icon.png.import ├── project.godot ├── sprite-sheet.svg └── sprite-sheet.svg.import /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Godot-specific ignores 3 | .import/ 4 | export.cfg 5 | export_presets.cfg 6 | 7 | # Mono-specific ignores 8 | .mono/ 9 | data_*/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 GDQuest 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /source/Actors/Enemies/Enemy.gd: -------------------------------------------------------------------------------- 1 | class_name Enemy 2 | extends PathFollow2D 3 | 4 | signal died(gold_amount) 5 | 6 | # Movement speed in pixels per second. 7 | export var speed := 64.0 8 | # Amount of gold earned upon killing this enemy. 9 | export var gold_value := 50 10 | 11 | export var max_health := 15 12 | onready var health := max_health setget set_health 13 | 14 | onready var _ui_pivot := $UIPivot 15 | onready var _health_bar := $UIPivot/HealthBar 16 | onready var _anim_player := $AnimationPlayer 17 | onready var _cutout_anim_player := $CutoutCharacter/AnimationPlayer 18 | 19 | 20 | func _ready() -> void: 21 | set_physics_process(false) 22 | 23 | _ui_pivot.set_as_toplevel(true) 24 | 25 | _health_bar.max_value = max_health 26 | _health_bar.value = health 27 | 28 | 29 | func _physics_process(delta: float) -> void: 30 | offset += speed * delta 31 | 32 | if unit_offset >= 1.0: 33 | set_physics_process(false) 34 | disappear() 35 | 36 | 37 | func move() -> void: 38 | set_physics_process(true) 39 | _cutout_anim_player.play("move") 40 | 41 | 42 | func disappear() -> void: 43 | _anim_player.play("disappear") 44 | 45 | 46 | func die() -> void: 47 | emit_signal("died", gold_value) 48 | disappear() 49 | 50 | 51 | func set_health(value: int) -> void: 52 | health = clamp(value, 0, max_health) 53 | _health_bar.value = health 54 | 55 | if health < 1: 56 | die() 57 | 58 | 59 | func _on_HurtBoxArea2D_hit_landed(damage: int) -> void: 60 | set_health(health - damage) 61 | -------------------------------------------------------------------------------- /source/Actors/Enemies/ToughEnemy.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://Actors/Enemies/Enemy.tscn" type="PackedScene" id=1] 4 | 5 | [sub_resource type="CircleShape2D" id=1] 6 | radius = 48.0 7 | 8 | [node name="Enemy" instance=ExtResource( 1 )] 9 | speed = 128.0 10 | gold_value = 75 11 | max_health = 12 12 | 13 | [node name="CutoutCharacter" parent="." index="0"] 14 | scale = Vector2( 1.2, 1.2 ) 15 | 16 | [node name="Sprite" parent="CutoutCharacter" index="1"] 17 | region_rect = Rect2( 384, 64, 57, 57 ) 18 | 19 | [node name="Sprite2" parent="CutoutCharacter" index="2"] 20 | region_rect = Rect2( 384, 64, 57, 57 ) 21 | 22 | [node name="Sprite3" parent="CutoutCharacter" index="3"] 23 | region_rect = Rect2( 384, 64, 57, 57 ) 24 | 25 | [node name="Sprite4" parent="CutoutCharacter" index="4"] 26 | region_rect = Rect2( 384, 64, 57, 57 ) 27 | 28 | [node name="HurtBoxArea2D" parent="." index="1"] 29 | armor = 2 30 | 31 | [node name="CollisionShape2D" parent="HitBoxArea2D" index="0"] 32 | position = Vector2( 0, -28 ) 33 | 34 | [node name="CollisionShape2D" parent="VisibleArea2D" index="0"] 35 | shape = SubResource( 1 ) 36 | 37 | [editable path="CutoutCharacter"] 38 | -------------------------------------------------------------------------------- /source/Actors/Enemies/particle.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /source/Actors/Enemies/particle.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/particle.svg-6a2c10808518a648f8e5ec8f4688e443.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Actors/Enemies/particle.svg" 13 | dest_files=[ "res://.import/particle.svg-6a2c10808518a648f8e5ec8f4688e443.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Actors/Player/Player.gd: -------------------------------------------------------------------------------- 1 | class_name Player 2 | extends Node 3 | 4 | signal gold_changed(gold_amount) 5 | 6 | export var gold := 100 setget set_gold 7 | 8 | 9 | func set_gold(new_amount: int) -> void: 10 | gold = max(0, new_amount) 11 | emit_signal("gold_changed", gold) 12 | -------------------------------------------------------------------------------- /source/Actors/Player/Player.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://Actors/Player/Player.gd" type="Script" id=1] 4 | 5 | 6 | [node name="Player" type="Node"] 7 | script = ExtResource( 1 ) 8 | gold = 1000 9 | -------------------------------------------------------------------------------- /source/Areas/AsteroidSurface/rocks-and-craters.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/rocks-and-craters.svg-d039ad5957be00f78334d088af06d900.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Areas/AsteroidSurface/rocks-and-craters.svg" 13 | dest_files=[ "res://.import/rocks-and-craters.svg-d039ad5957be00f78334d088af06d900.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Areas/AsteroidSurface/sand.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sand.svg-8176aa2958b49ade8514e76ba5a92581.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Areas/AsteroidSurface/sand.svg" 13 | dest_files=[ "res://.import/sand.svg-8176aa2958b49ade8514e76ba5a92581.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Areas/AsteroidSurface/tileset.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="TileSet" load_steps=5 format=2] 2 | 3 | [ext_resource path="res://Levels/TowerPlacer/grid-cell.svg" type="Texture" id=1] 4 | [ext_resource path="res://Areas/AsteroidSurface/rocks-and-craters.svg" type="Texture" id=2] 5 | [ext_resource path="res://Areas/AsteroidSurface/walkable-path.svg" type="Texture" id=3] 6 | [ext_resource path="res://Areas/AsteroidSurface/sand.svg" type="Texture" id=4] 7 | 8 | [resource] 9 | 0/name = "grid-cell.svg 0" 10 | 0/texture = ExtResource( 1 ) 11 | 0/tex_offset = Vector2( 0, 0 ) 12 | 0/modulate = Color( 1, 1, 1, 1 ) 13 | 0/region = Rect2( 0, 0, 64, 64 ) 14 | 0/tile_mode = 0 15 | 0/occluder_offset = Vector2( 0, 0 ) 16 | 0/navigation_offset = Vector2( 0, 0 ) 17 | 0/shape_offset = Vector2( 0, 0 ) 18 | 0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 19 | 0/shape_one_way = false 20 | 0/shape_one_way_margin = 0.0 21 | 0/shapes = [ ] 22 | 0/z_index = 0 23 | 1/name = "Non Placeable Cells" 24 | 1/texture = ExtResource( 2 ) 25 | 1/tex_offset = Vector2( 0, 0 ) 26 | 1/modulate = Color( 1, 1, 1, 1 ) 27 | 1/region = Rect2( 0, 0, 192, 192 ) 28 | 1/tile_mode = 2 29 | 1/autotile/icon_coordinate = Vector2( 1, 1 ) 30 | 1/autotile/tile_size = Vector2( 64, 64 ) 31 | 1/autotile/spacing = 0 32 | 1/autotile/occluder_map = [ ] 33 | 1/autotile/navpoly_map = [ ] 34 | 1/autotile/priority_map = [ ] 35 | 1/autotile/z_index_map = [ ] 36 | 1/occluder_offset = Vector2( 0, 0 ) 37 | 1/navigation_offset = Vector2( 0, 0 ) 38 | 1/shape_offset = Vector2( 0, 0 ) 39 | 1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 40 | 1/shape_one_way = false 41 | 1/shape_one_way_margin = 0.0 42 | 1/shapes = [ ] 43 | 1/z_index = 0 44 | 2/name = "Enemy Walking Path" 45 | 2/texture = ExtResource( 3 ) 46 | 2/tex_offset = Vector2( 0, 0 ) 47 | 2/modulate = Color( 1, 1, 1, 1 ) 48 | 2/region = Rect2( 0, 0, 384, 384 ) 49 | 2/tile_mode = 1 50 | 2/autotile/bitmask_mode = 1 51 | 2/autotile/bitmask_flags = [ Vector2( 0, 1 ), 48, Vector2( 0, 2 ), 56, Vector2( 0, 3 ), 432, Vector2( 0, 4 ), 438, Vector2( 0, 5 ), 54, Vector2( 1, 0 ), 144, Vector2( 1, 1 ), 186, Vector2( 1, 2 ), 18, Vector2( 1, 3 ), 504, Vector2( 1, 4 ), 511, Vector2( 1, 5 ), 63, Vector2( 2, 1 ), 24, Vector2( 2, 2 ), 146, Vector2( 2, 3 ), 216, Vector2( 2, 4 ), 219, Vector2( 2, 5 ), 27, Vector2( 3, 0 ), 176, Vector2( 3, 1 ), 50, Vector2( 3, 2 ), 184, Vector2( 3, 3 ), 178, Vector2( 3, 4 ), 16, Vector2( 4, 0 ), 152, Vector2( 4, 1 ), 26, Vector2( 4, 2 ), 58, Vector2( 4, 3 ), 154 ] 52 | 2/autotile/icon_coordinate = Vector2( 3, 4 ) 53 | 2/autotile/tile_size = Vector2( 64, 64 ) 54 | 2/autotile/spacing = 0 55 | 2/autotile/occluder_map = [ ] 56 | 2/autotile/navpoly_map = [ ] 57 | 2/autotile/priority_map = [ ] 58 | 2/autotile/z_index_map = [ ] 59 | 2/occluder_offset = Vector2( 0, 0 ) 60 | 2/navigation_offset = Vector2( 0, 0 ) 61 | 2/shape_offset = Vector2( 0, 0 ) 62 | 2/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 63 | 2/shape_one_way = false 64 | 2/shape_one_way_margin = 0.0 65 | 2/shapes = [ ] 66 | 2/z_index = 0 67 | 3/name = "Tower Placeable Cell" 68 | 3/texture = ExtResource( 4 ) 69 | 3/tex_offset = Vector2( 0, 0 ) 70 | 3/modulate = Color( 1, 1, 1, 1 ) 71 | 3/region = Rect2( 0, 0, 64, 64 ) 72 | 3/tile_mode = 0 73 | 3/occluder_offset = Vector2( 0, 0 ) 74 | 3/navigation_offset = Vector2( 0, 0 ) 75 | 3/shape_offset = Vector2( 0, 0 ) 76 | 3/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 77 | 3/shape_one_way = false 78 | 3/shape_one_way_margin = 0.0 79 | 3/shapes = [ ] 80 | 3/z_index = 0 81 | -------------------------------------------------------------------------------- /source/Areas/AsteroidSurface/walkable-path.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/walkable-path.svg-ecaa9a460c48ad8740e02db5f09971a1.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Areas/AsteroidSurface/walkable-path.svg" 13 | dest_files=[ "res://.import/walkable-path.svg-ecaa9a460c48ad8740e02db5f09971a1.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Game.gd: -------------------------------------------------------------------------------- 1 | # Initializes the user interface, forwarding it the data it needs from the game world. 2 | extends Node 3 | 4 | export(String, FILE, "*tscn") var end_screen_path = "res://Screens/EndScreen.tscn" 5 | 6 | onready var _player := $Player 7 | onready var _level := $Level 8 | onready var _hud := $UILayer/UI/HUD 9 | onready var _tower_shop := $UILayer/UI/HUD/UITowerShop 10 | onready var _screen_overlay := $UILayer/UI/UIScreenOverlay 11 | onready var _mouse_barrier := $UILayer/UI/MouseBarrier 12 | onready var _retry_button := $UILayer/UI/HUD/RetryButton 13 | onready var _start_button := $UILayer/UI/HUD/StartWaveButton 14 | onready var _gold_panel := $UILayer/UI/HUD/UIGoldPanel 15 | onready var _upgrade_shop := $UILayer/UI/HUD/UIUpgradeShop 16 | 17 | 18 | func _ready() -> void: 19 | _tower_shop.player = _player 20 | _gold_panel.player = _player 21 | _upgrade_shop.player = _player 22 | _setup_level() 23 | _level.start() 24 | 25 | 26 | func _setup_level() -> void: 27 | _level.connect("base_destroyed", self, "_on_Level_base_destroyed") 28 | _level.connect("finished", self, "_on_Level_finished") 29 | _level.connect("gold_earned", self, "_on_Level_gold_earned") 30 | _level.connect("round_finished", self, "_on_Level_round_finished") 31 | 32 | _level.tower_placer.connect("tower_placed", _tower_shop, "_on_TowerPlacer_tower_placed") 33 | _level.tower_placer.connect("tower_placed", _upgrade_shop, "_on_TowerPlacer_tower_placed") 34 | _tower_shop.connect("tower_purchased", _level.tower_placer, "add_new_tower") 35 | 36 | 37 | func _load_next_level() -> void: 38 | var next_level: Node = load(_level.next_level_path).instance() 39 | _level.queue_free() 40 | _level = next_level 41 | add_child(_level) 42 | _setup_level() 43 | _level.start() 44 | 45 | 46 | func _toggle_interface() -> void: 47 | _hud.visible = not _hud.visible 48 | _toggle_mouse_barrier() 49 | 50 | 51 | # Prevents mouse interactions in play mode 52 | func _toggle_mouse_barrier() -> void: 53 | _mouse_barrier.visible = not _hud.visible 54 | 55 | 56 | func _on_StartWaveButton_pressed() -> void: 57 | # Enters in the "play mode". In play mode, players become passive to the 58 | # game's event. Interface becomes invisible and the Level starts. 59 | _toggle_interface() 60 | get_tree().call_group("selected", "set_selected", false) 61 | yield(_screen_overlay.play_wave_start(), "completed") 62 | _level.start() 63 | 64 | 65 | func _on_Level_round_finished() -> void: 66 | # Enters in the "plan mode". In plan mode, players can take actions and plan 67 | # their Tower Layout for the next wave. Interface becomes visible again. 68 | _toggle_interface() 69 | _level.show_walkable_path() 70 | 71 | 72 | # Lose condition 73 | func _on_Level_base_destroyed() -> void: 74 | _start_button.hide() 75 | _tower_shop.hide() 76 | _retry_button.show() 77 | yield(_screen_overlay.play_lost(), "completed") 78 | _toggle_interface() 79 | 80 | 81 | # Win condition 82 | func _on_Level_finished() -> void: 83 | yield(_screen_overlay.play_win(), "completed") 84 | if _level.next_level_path: 85 | _load_next_level() 86 | else: 87 | var end_screen: Node = load(end_screen_path).instance() 88 | end_screen.player_score = _player.gold 89 | var packed_scene := PackedScene.new() 90 | packed_scene.pack(end_screen) 91 | get_tree().change_scene_to(packed_scene) 92 | 93 | 94 | func _on_RetryButton_pressed() -> void: 95 | get_tree().reload_current_scene() 96 | 97 | 98 | func _on_Level_gold_earned(gold_amount) -> void: 99 | _player.gold += gold_amount 100 | -------------------------------------------------------------------------------- /source/Game.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=2] 2 | 3 | [ext_resource path="res://UI/UITowerShop/UITowerShop.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Levels/Level1.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://Game.gd" type="Script" id=3] 6 | [ext_resource path="res://UI/UIGoldPanel.tscn" type="PackedScene" id=4] 7 | [ext_resource path="res://UI/UIScreenOverlay.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://Actors/Player/Player.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://UI/UIUpgradeShop/UIUpgradeShop.tscn" type="PackedScene" id=7] 10 | 11 | [node name="Game" type="Node"] 12 | script = ExtResource( 3 ) 13 | 14 | [node name="Player" parent="." instance=ExtResource( 6 )] 15 | 16 | [node name="UILayer" type="CanvasLayer" parent="."] 17 | 18 | [node name="UI" type="Control" parent="UILayer"] 19 | anchor_right = 1.0 20 | anchor_bottom = 1.0 21 | mouse_filter = 2 22 | __meta__ = { 23 | "_edit_use_anchors_": false 24 | } 25 | 26 | [node name="HUD" type="Control" parent="UILayer/UI"] 27 | visible = false 28 | anchor_right = 1.0 29 | anchor_bottom = 1.0 30 | mouse_filter = 2 31 | __meta__ = { 32 | "_edit_use_anchors_": false 33 | } 34 | 35 | [node name="StartWaveButton" type="Button" parent="UILayer/UI/HUD"] 36 | anchor_left = 0.5 37 | anchor_top = 1.0 38 | anchor_right = 0.5 39 | anchor_bottom = 1.0 40 | margin_left = 256.0 41 | margin_top = -184.0 42 | margin_right = 448.0 43 | margin_bottom = -120.0 44 | text = "Start!" 45 | __meta__ = { 46 | "_edit_use_anchors_": false 47 | } 48 | 49 | [node name="RetryButton" type="Button" parent="UILayer/UI/HUD"] 50 | visible = false 51 | anchor_left = 0.5 52 | anchor_top = 0.5 53 | anchor_right = 0.5 54 | anchor_bottom = 0.5 55 | margin_left = -96.0 56 | margin_top = -32.0 57 | margin_right = 96.0 58 | margin_bottom = 32.0 59 | text = "Retry" 60 | __meta__ = { 61 | "_edit_use_anchors_": false 62 | } 63 | 64 | [node name="UIGoldPanel" parent="UILayer/UI/HUD" instance=ExtResource( 4 )] 65 | anchor_left = 0.5 66 | anchor_top = 1.0 67 | anchor_right = 0.5 68 | anchor_bottom = 1.0 69 | margin_left = -108.0 70 | margin_top = -56.0 71 | margin_right = 108.0 72 | margin_bottom = 0.0 73 | 74 | [node name="UITowerShop" parent="UILayer/UI/HUD" instance=ExtResource( 1 )] 75 | margin_top = -248.0 76 | margin_bottom = -64.0 77 | 78 | [node name="UIUpgradeShop" parent="UILayer/UI/HUD" instance=ExtResource( 7 )] 79 | 80 | [node name="MouseBarrier" type="Control" parent="UILayer/UI"] 81 | visible = false 82 | anchor_right = 1.0 83 | anchor_bottom = 1.0 84 | __meta__ = { 85 | "_edit_use_anchors_": false 86 | } 87 | 88 | [node name="UIScreenOverlay" parent="UILayer/UI" instance=ExtResource( 5 )] 89 | 90 | [node name="Level" parent="." instance=ExtResource( 2 )] 91 | 92 | [connection signal="pressed" from="UILayer/UI/HUD/StartWaveButton" to="." method="_on_StartWaveButton_pressed"] 93 | [connection signal="pressed" from="UILayer/UI/HUD/RetryButton" to="." method="_on_RetryButton_pressed"] 94 | -------------------------------------------------------------------------------- /source/Levels/AStarGrid/AStarGrid.gd: -------------------------------------------------------------------------------- 1 | # Calculates a set of walkable positions between the start_point and the goal_point 2 | extends TileMap 3 | 4 | const DIRECTIONS := [ 5 | Vector2.UP, 6 | Vector2.LEFT, 7 | Vector2.RIGHT, 8 | Vector2.DOWN 9 | ] 10 | 11 | export var start_point := Vector2.ZERO 12 | export var goal_point := Vector2.ZERO 13 | export var offset := Vector2(32, 32) 14 | 15 | var walkable_cells: PoolVector2Array 16 | 17 | var _astar := AStar2D.new() 18 | var _start_id := 0 19 | var _goal_id := 0 20 | 21 | 22 | func get_walkable_path() -> PoolVector2Array: 23 | var walkable_path := PoolVector2Array() 24 | 25 | var astar_path = _get_astar_path() 26 | for cell in astar_path: 27 | var point := map_to_world(cell) 28 | walkable_path.append(to_global(point) + offset) 29 | return walkable_path 30 | 31 | 32 | func _get_astar_path() -> PoolVector2Array: 33 | var astar_path: PoolVector2Array 34 | 35 | _create_astar_points() 36 | _connect_neighbor_cells() 37 | 38 | # Creates a walkable path from the start_point to the goal_point 39 | astar_path = _astar.get_point_path(_start_id, _goal_id) 40 | return astar_path 41 | 42 | 43 | func _create_astar_points() -> void: 44 | # Sets cells ID by iteration order 45 | var cell_id := 0 46 | for cell in walkable_cells: 47 | _astar.add_point(cell_id, cell) 48 | 49 | # Store the start and goal point IDs 50 | if cell == world_to_map(start_point): 51 | _start_id = cell_id 52 | if cell == world_to_map(goal_point): 53 | _goal_id = cell_id 54 | 55 | cell_id += 1 56 | 57 | 58 | func _connect_neighbor_cells(): 59 | # Turn the walkable_cells in an Array to find its elements indices 60 | var walkable_cells_array := Array(walkable_cells) 61 | 62 | for point in _astar.get_points(): 63 | var cell = _astar.get_point_position(point) 64 | for direction in DIRECTIONS: 65 | var neighbor_cell_id = walkable_cells_array.find(cell + direction) 66 | # Skip cells that weren't found 67 | if neighbor_cell_id == -1: 68 | continue 69 | _astar.connect_points(point, neighbor_cell_id) 70 | -------------------------------------------------------------------------------- /source/Levels/AStarGrid/AStarGrid.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://Levels/AStarGrid/AStarGrid.gd" type="Script" id=1] 4 | 5 | [node name="AStarGrid" type="TileMap"] 6 | position = Vector2( 32, 32 ) 7 | format = 1 8 | script = ExtResource( 1 ) 9 | -------------------------------------------------------------------------------- /source/Levels/EventsPlayer.gd: -------------------------------------------------------------------------------- 1 | extends AnimationPlayer 2 | 3 | export var current_event = 0 4 | 5 | func play_event(event_index := current_event) -> void: 6 | var events_list: Array = get_animation_list() 7 | var animation_count := events_list.size() 8 | if event_index >= animation_count: 9 | return 10 | play(events_list[event_index]) 11 | 12 | 13 | func play_current_event() -> void: 14 | play_event() 15 | current_event += 1 16 | -------------------------------------------------------------------------------- /source/Levels/Level.gd: -------------------------------------------------------------------------------- 1 | # Controls Wave's flow and TowerPlacement 2 | extends Node2D 3 | 4 | signal finished 5 | signal round_finished 6 | signal base_destroyed 7 | signal gold_earned(gold_amount) 8 | 9 | const TOWER_PLACEABLE_CELLS_ID := 3 10 | const ENEMY_WALK_PATH_CELLS_ID := 2 11 | 12 | export(String, FILE, "*.tscn") var next_level_path 13 | 14 | onready var tower_placer := $TowerPlacer 15 | onready var _tilemap := $TileMap 16 | onready var _astar_grid := $AStarGrid 17 | onready var _wave_spawner := $WaveSpawner2D 18 | onready var _events_player := $EventsPlayer 19 | onready var _path_preview := $PathPreview 20 | onready var _player_base := $GoalPoint/PlayerBase 21 | 22 | 23 | func _ready() -> void: 24 | _setup() 25 | 26 | 27 | func start() -> void: 28 | _path_preview.fade_out() 29 | _events_player.play_current_event() 30 | 31 | 32 | func finish() -> void: 33 | if _player_base.health > 0: 34 | emit_signal("finished") 35 | 36 | 37 | func spawn_wave() -> void: 38 | var wave = _wave_spawner.spawn() 39 | wave.connect("finished", self, "_on_Wave_finished") 40 | _setup_wave_path(wave) 41 | 42 | for enemy in wave.get_children(): 43 | enemy.connect("died", self, "_on_Enemy_died") 44 | 45 | wave.start() 46 | 47 | 48 | func start_round() -> void: 49 | if _events_player.current_event >= _events_player.get_animation_list().size(): 50 | finish() 51 | return 52 | emit_signal("round_finished") 53 | 54 | 55 | func _setup() -> void: 56 | tower_placer.setup_available_cells(_tilemap.get_used_cells_by_id(TOWER_PLACEABLE_CELLS_ID)) 57 | _astar_grid.walkable_cells = _tilemap.get_used_cells_by_id(ENEMY_WALK_PATH_CELLS_ID) 58 | _astar_grid.start_point = $StartPoint.position 59 | _astar_grid.goal_point = $GoalPoint.position 60 | show_walkable_path() 61 | 62 | 63 | func show_walkable_path(walking_path := _astar_grid.get_walkable_path()) -> void: 64 | _path_preview.clear_points() 65 | _path_preview.points = walking_path 66 | _path_preview.fade_in() 67 | 68 | 69 | func _setup_wave_path(wave: Wave) -> void: 70 | wave.set_movement_path(_astar_grid.get_walkable_path()) 71 | 72 | 73 | func _on_Wave_finished() -> void: 74 | start_round() 75 | 76 | 77 | func _on_PlayerBase_destroyed(): 78 | emit_signal("base_destroyed") 79 | 80 | 81 | func _on_Enemy_died(gold_earned: int) -> void: 82 | emit_signal("gold_earned", gold_earned) 83 | 84 | 85 | func _on_round_finished() -> void: 86 | start() 87 | -------------------------------------------------------------------------------- /source/Levels/TowerPlacer/TowerPlacer.gd: -------------------------------------------------------------------------------- 1 | # Allows the player to interactively place a tower on the game grid. 2 | # Keeps track of free and occupied cells. 3 | class_name TowerPlacer 4 | extends TileMap 5 | 6 | signal tower_placed(tower) 7 | 8 | # The ID of the tiles where players can place a tower. 9 | const AVAILABLE_CELL_ID := 0 10 | const INVALID_CELL_ID := 1 11 | 12 | onready var _visual_grid := $VisualGrid 13 | 14 | var _current_cell := Vector2.ZERO 15 | var _current_tower: Tower 16 | 17 | 18 | func _ready() -> void: 19 | set_process_unhandled_input(false) 20 | 21 | 22 | func _unhandled_input(event: InputEvent) -> void: 23 | if event is InputEventMouseMotion: 24 | _snap_tower_to_grid() 25 | if event.is_action_pressed("tower_placement"): 26 | _place_tower() 27 | 28 | 29 | func setup_available_cells(cells_array: PoolVector2Array) -> void: 30 | for cell in cells_array: 31 | set_cell_placeable(cell) 32 | 33 | 34 | func add_new_tower(tower: Tower) -> void: 35 | if _current_tower: 36 | _current_tower.queue_free() 37 | 38 | add_child(tower) 39 | _current_tower = tower 40 | 41 | set_process_unhandled_input(true) 42 | _visual_grid.visible = true 43 | 44 | _snap_tower_to_grid() 45 | 46 | 47 | func set_cell_unplaceable(cell: Vector2) -> void: 48 | set_cellv(cell, INVALID_CELL_ID) 49 | 50 | 51 | func set_cell_placeable(cell: Vector2) -> void: 52 | set_cellv(cell, AVAILABLE_CELL_ID) 53 | 54 | 55 | func is_cell_placeable(cell: Vector2) -> bool: 56 | return get_cellv(cell) == AVAILABLE_CELL_ID 57 | 58 | 59 | func _place_tower() -> void: 60 | set_process_unhandled_input(false) 61 | _visual_grid.visible = false 62 | 63 | if not is_cell_placeable(_current_cell): 64 | _current_tower.queue_free() 65 | _current_tower = null 66 | return 67 | set_cell_unplaceable(_current_cell) 68 | 69 | emit_signal("tower_placed", _current_tower) 70 | _current_tower.connect("sold", self, "_on_Tower_sold") 71 | _current_tower = null 72 | 73 | 74 | func _snap_tower_to_grid() -> void: 75 | _current_cell = world_to_map(get_global_mouse_position()) 76 | _current_tower.global_position = map_to_world(_current_cell) 77 | if not is_cell_placeable(_current_cell): 78 | _current_tower.modulate = Color(1, 0.375, 0.375) 79 | else: 80 | _current_tower.modulate = Color.white 81 | 82 | 83 | func _on_Tower_sold(_price: int, place: Vector2) -> void: 84 | set_cell_placeable(world_to_map(place)) 85 | -------------------------------------------------------------------------------- /source/Levels/TowerPlacer/grid-cell.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /source/Levels/TowerPlacer/grid-cell.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/grid-cell.svg-44e798e11443aec844dd0cfbbb04cd83.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Levels/TowerPlacer/grid-cell.svg" 13 | dest_files=[ "res://.import/grid-cell.svg-44e798e11443aec844dd0cfbbb04cd83.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Levels/Waves/Wave.gd: -------------------------------------------------------------------------------- 1 | class_name Wave 2 | extends Path2D 3 | 4 | signal starting 5 | signal started 6 | signal finished 7 | 8 | # The time interval between each BasicEnemy first movement, used to 9 | # create a gap between enemies by delaying the start of their movement 10 | export var enemy_time_interval := 0.5 11 | 12 | 13 | func _ready() -> void: 14 | enemy_time_interval = max(0.1, enemy_time_interval) 15 | 16 | 17 | func start() -> void: 18 | emit_signal("starting") 19 | setup_enemies() 20 | move_enemies() 21 | 22 | 23 | func setup_enemies() -> void: 24 | for enemy in get_children(): 25 | enemy.unit_offset = 0.0 26 | enemy.connect("tree_exited", self, "_on_Enemy_tree_exited") 27 | 28 | 29 | func move_enemies() -> void: 30 | for enemy in get_children(): 31 | yield(get_tree().create_timer(enemy_time_interval), "timeout") 32 | enemy.move() 33 | emit_signal("started") 34 | 35 | 36 | func set_movement_path(movement_path: PoolVector2Array) -> void: 37 | curve.clear_points() 38 | for point in movement_path: 39 | curve.add_point(point) 40 | 41 | 42 | func is_wave_finished() -> bool: 43 | return get_child_count() < 1 44 | 45 | 46 | func _on_Enemy_tree_exited() -> void: 47 | if is_wave_finished(): 48 | emit_signal("finished") 49 | queue_free() 50 | -------------------------------------------------------------------------------- /source/Levels/Waves/Wave1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://Levels/Waves/Wave.gd" type="Script" id=1] 4 | [ext_resource path="res://Actors/Enemies/Enemy.tscn" type="PackedScene" id=2] 5 | 6 | 7 | 8 | [sub_resource type="Curve2D" id=1] 9 | _data = { 10 | "points": PoolVector2Array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 512, 0 ) 11 | } 12 | 13 | [node name="Wave" type="Path2D"] 14 | self_modulate = Color( 0.501961, 0.6, 1, 0.701961 ) 15 | curve = SubResource( 1 ) 16 | script = ExtResource( 1 ) 17 | 18 | [node name="BasicEnemy" parent="." instance=ExtResource( 2 )] 19 | 20 | [node name="BasicEnemy2" parent="." instance=ExtResource( 2 )] 21 | 22 | [node name="BasicEnemy3" parent="." instance=ExtResource( 2 )] 23 | -------------------------------------------------------------------------------- /source/Levels/Waves/Wave2.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://Levels/Waves/Wave.gd" type="Script" id=1] 4 | [ext_resource path="res://Actors/Enemies/Enemy.tscn" type="PackedScene" id=2] 5 | 6 | [sub_resource type="Curve2D" id=1] 7 | _data = { 8 | "points": PoolVector2Array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 0 ) 9 | } 10 | 11 | [node name="Wave" type="Path2D"] 12 | curve = SubResource( 1 ) 13 | script = ExtResource( 1 ) 14 | 15 | [node name="BasicEnemy" parent="." instance=ExtResource( 2 )] 16 | 17 | [node name="BasicEnemy2" parent="." instance=ExtResource( 2 )] 18 | 19 | [node name="BasicEnemy3" parent="." instance=ExtResource( 2 )] 20 | 21 | [node name="BasicEnemy4" parent="." instance=ExtResource( 2 )] 22 | 23 | [node name="BasicEnemy5" parent="." instance=ExtResource( 2 )] 24 | -------------------------------------------------------------------------------- /source/Levels/Waves/Wave3.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://Levels/Waves/Wave.gd" type="Script" id=1] 4 | [ext_resource path="res://Actors/Enemies/Enemy.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://Actors/Enemies/ToughEnemy.tscn" type="PackedScene" id=3] 6 | 7 | [sub_resource type="Curve2D" id=1] 8 | _data = { 9 | "points": PoolVector2Array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 0 ) 10 | } 11 | 12 | [node name="Wave" type="Path2D"] 13 | curve = SubResource( 1 ) 14 | script = ExtResource( 1 ) 15 | 16 | [node name="BasicEnemy" parent="." instance=ExtResource( 2 )] 17 | 18 | [node name="ToughEnemy" parent="." instance=ExtResource( 3 )] 19 | 20 | [node name="BasicEnemy2" parent="." instance=ExtResource( 2 )] 21 | 22 | [node name="ToughEnemy2" parent="." instance=ExtResource( 3 )] 23 | 24 | [node name="BasicEnemy3" parent="." instance=ExtResource( 2 )] 25 | -------------------------------------------------------------------------------- /source/Levels/Waves/Wave4.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://Levels/Waves/Wave.gd" type="Script" id=1] 4 | [ext_resource path="res://Actors/Enemies/Enemy.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://Actors/Enemies/ToughEnemy.tscn" type="PackedScene" id=3] 6 | 7 | [sub_resource type="Curve2D" id=1] 8 | _data = { 9 | "points": PoolVector2Array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 0 ) 10 | } 11 | 12 | [node name="Wave" type="Path2D"] 13 | curve = SubResource( 1 ) 14 | script = ExtResource( 1 ) 15 | 16 | [node name="ToughEnemy" parent="." instance=ExtResource( 3 )] 17 | 18 | [node name="Enemy" parent="." instance=ExtResource( 2 )] 19 | 20 | [node name="ToughEnemy2" parent="." instance=ExtResource( 3 )] 21 | 22 | [node name="Enemy2" parent="." instance=ExtResource( 2 )] 23 | 24 | [node name="ToughEnemy3" parent="." instance=ExtResource( 3 )] 25 | -------------------------------------------------------------------------------- /source/Objects/EnemySpawn/enemy-spawn.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/enemy-spawn.svg-8a0224ff5ee8c87ffcda5d22e0c2f2db.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Objects/EnemySpawn/enemy-spawn.svg" 13 | dest_files=[ "res://.import/enemy-spawn.svg-8a0224ff5ee8c87ffcda5d22e0c2f2db.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Objects/HitBox/HitBoxArea2D.gd: -------------------------------------------------------------------------------- 1 | # Represents a Hit dealt from the attacker perspective 2 | class_name HitBoxArea2D 3 | extends Area2D 4 | 5 | enum Teams { PLAYER, ENEMY } 6 | export (Teams) var team := Teams.PLAYER 7 | 8 | export var damage := 1 9 | export var can_hit_multiple := false 10 | 11 | 12 | func apply_hit(hurt_box: HurtBoxArea2D) -> void: 13 | if team == hurt_box.team: 14 | return 15 | hurt_box.get_hurt(damage) 16 | set_deferred("monitoring", can_hit_multiple) 17 | 18 | 19 | func _on_area_entered(area: Area2D) -> void: 20 | apply_hit(area) 21 | -------------------------------------------------------------------------------- /source/Objects/HitBox/HitBoxArea2D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://Objects/HitBox/HitBoxArea2D.gd" type="Script" id=1] 4 | 5 | [node name="HitBoxArea2D" type="Area2D"] 6 | monitorable = false 7 | collision_layer = 0 8 | collision_mask = 2 9 | script = ExtResource( 1 ) 10 | [connection signal="area_entered" from="." to="." method="_on_area_entered"] 11 | -------------------------------------------------------------------------------- /source/Objects/HurtBox/HurtBoxArea2D.gd: -------------------------------------------------------------------------------- 1 | # Represents a Hit dealt from the target perspective 2 | class_name HurtBoxArea2D 3 | extends Area2D 4 | 5 | signal hit_landed(damage) 6 | 7 | enum Teams { PLAYER, ENEMY } 8 | export (Teams) var team := Teams.PLAYER 9 | 10 | export var armor := 0 11 | 12 | 13 | func get_hurt(damage: int) -> void: 14 | var final_damage := damage - armor 15 | emit_signal("hit_landed", final_damage) 16 | -------------------------------------------------------------------------------- /source/Objects/HurtBox/HurtBoxArea2D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://Objects/HurtBox/HurtBoxArea2D.gd" type="Script" id=1] 4 | 5 | [node name="HurtBoxArea2D" type="Area2D"] 6 | monitoring = false 7 | collision_layer = 2 8 | collision_mask = 0 9 | script = ExtResource( 1 ) 10 | -------------------------------------------------------------------------------- /source/Objects/PlayerBase/CutoutSprites.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | 4 | onready var _anim_player := $AnimationPlayer 5 | 6 | func play(animation: String) -> void: 7 | _anim_player.play(animation) 8 | -------------------------------------------------------------------------------- /source/Objects/PlayerBase/PlayerBase.gd: -------------------------------------------------------------------------------- 1 | # The Player's main building. 2 | extends Node2D 3 | 4 | signal destroyed 5 | 6 | export var max_health := 10 7 | var health := max_health setget set_health 8 | 9 | onready var _sprites := $Sprites 10 | onready var _interface := $Interface 11 | onready var _ui_health_bar := $Interface/HealthBar 12 | onready var _health_bar := $HealthBar 13 | onready var _hurt_box := $HurtBoxArea2D 14 | 15 | 16 | func _ready() -> void: 17 | health = max_health 18 | 19 | # Share the Interface/HealthBar's values with the HealthBar 20 | # to keep them synced 21 | _ui_health_bar.share(_health_bar) 22 | 23 | _ui_health_bar.max_value = max_health 24 | _ui_health_bar.value = health 25 | 26 | 27 | func set_health(value: int) -> void: 28 | health = clamp(value, 0, max_health) 29 | 30 | _ui_health_bar.value = health 31 | 32 | if health < 1: 33 | _destroy() 34 | 35 | 36 | func _destroy() -> void: 37 | emit_signal("destroyed") 38 | _sprites.play("Explode") 39 | 40 | # Make a deferred call to prevent errors 41 | _hurt_box.set_deferred("monitorable", false) 42 | 43 | 44 | func _on_HurtBoxArea2D_hit_landed(damage: int) -> void: 45 | set_health(health - damage) 46 | 47 | 48 | func _on_SelectableArea2D_selection_changed(selected: bool) -> void: 49 | if selected: 50 | _interface.appear() 51 | else: 52 | _interface.disappear() 53 | -------------------------------------------------------------------------------- /source/Objects/PlayerBase/PlayerBase.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=9 format=2] 2 | 3 | [ext_resource path="res://Objects/PlayerBase/CutoutPlayerBase.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Objects/HurtBox/HurtBoxArea2D.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://Objects/SelectableArea2D/SelectableArea2D.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://Objects/PlayerBase/PlayerBase.gd" type="Script" id=4] 7 | [ext_resource path="res://UI/UIHealthBar/UIHealthBar.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://UI/UIUnit/UIUnit.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://UI/UIHealthBar/UITimedHealthBar.tscn" type="PackedScene" id=8] 10 | 11 | [sub_resource type="RectangleShape2D" id=1] 12 | extents = Vector2( 64, 34 ) 13 | 14 | [node name="PlayerBase" type="Node2D"] 15 | script = ExtResource( 4 ) 16 | 17 | [node name="Sprites" parent="." instance=ExtResource( 1 )] 18 | 19 | [node name="HurtBoxArea2D" parent="." instance=ExtResource( 2 )] 20 | position = Vector2( 0, 10 ) 21 | 22 | [node name="CollisionShape2D" type="CollisionShape2D" parent="HurtBoxArea2D"] 23 | position = Vector2( 0, -8 ) 24 | shape = SubResource( 1 ) 25 | 26 | [node name="SelectableArea2D" parent="." instance=ExtResource( 3 )] 27 | 28 | [node name="CollisionShape2D" type="CollisionShape2D" parent="SelectableArea2D"] 29 | position = Vector2( 0, 2 ) 30 | shape = SubResource( 1 ) 31 | 32 | [node name="Interface" parent="." instance=ExtResource( 6 )] 33 | 34 | [node name="HealthBar" parent="Interface" instance=ExtResource( 5 )] 35 | margin_left = -88.0 36 | margin_top = -72.0 37 | margin_right = 84.0 38 | margin_bottom = -54.0 39 | 40 | [node name="HealthBar" parent="." instance=ExtResource( 8 )] 41 | margin_left = -88.0 42 | margin_top = -72.0 43 | margin_right = 84.0 44 | margin_bottom = -54.0 45 | step = 1.0 46 | [connection signal="hit_landed" from="HurtBoxArea2D" to="." method="_on_HurtBoxArea2D_hit_landed"] 47 | [connection signal="selection_changed" from="SelectableArea2D" to="." method="_on_SelectableArea2D_selection_changed"] 48 | -------------------------------------------------------------------------------- /source/Objects/PlayerBase/player-base.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/player-base.svg-e6615df4603076c80a8bc8470eef80ce.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Objects/PlayerBase/player-base.svg" 13 | dest_files=[ "res://.import/player-base.svg-e6615df4603076c80a8bc8470eef80ce.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Objects/SelectableArea2D/SelectableArea2D.gd: -------------------------------------------------------------------------------- 1 | # Communicates selection states at individual level. 2 | class_name SelectableArea2D 3 | extends Area2D 4 | 5 | signal selection_changed(selected) 6 | 7 | export var select_action := "select" 8 | 9 | var selected := false setget set_selected 10 | 11 | 12 | func _ready() -> void: 13 | set_process_unhandled_input(false) 14 | 15 | 16 | func _input_event(_viewport: Object, event: InputEvent, _shape_idx: int) -> void: 17 | if event.is_action_pressed(select_action): 18 | set_selected(not selected) 19 | 20 | 21 | func _unhandled_input(event: InputEvent) -> void: 22 | if event.is_action_pressed(select_action): 23 | set_selected(false) 24 | set_process_unhandled_input(false) 25 | 26 | 27 | func set_selected(select: bool) -> void: 28 | selected = select 29 | if selected: 30 | add_to_group("selected") 31 | else: 32 | remove_from_group("selected") 33 | emit_signal("selection_changed", selected) 34 | 35 | 36 | func _on_mouse_entered() -> void: 37 | set_process_unhandled_input(false) 38 | 39 | 40 | func _on_mouse_exited() -> void: 41 | set_process_unhandled_input(selected) 42 | -------------------------------------------------------------------------------- /source/Objects/SelectableArea2D/SelectableArea2D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://Objects/SelectableArea2D/SelectableArea2D.gd" type="Script" id=1] 4 | 5 | [node name="SelectableArea2D" type="Area2D"] 6 | monitoring = false 7 | collision_mask = 0 8 | script = ExtResource( 1 ) 9 | 10 | [connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"] 11 | [connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"] 12 | -------------------------------------------------------------------------------- /source/Objects/Towers/BombTower.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://Objects/Towers/Tower.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Objects/Weapon2D/Bullets/BombBullet.tscn" type="PackedScene" id=2] 5 | 6 | [sub_resource type="CircleShape2D" id=1] 7 | resource_local_to_scene = true 8 | radius = 128.0 9 | 10 | [node name="Tower" instance=ExtResource( 1 )] 11 | cost = 500 12 | 13 | [node name="Weapon2D" parent="." index="1"] 14 | bullet_scene = ExtResource( 2 ) 15 | fire_range = 128.0 16 | fire_cooldown = 3.0 17 | 18 | [node name="Sprite" parent="Weapon2D" index="0"] 19 | offset = Vector2( 36, 0 ) 20 | region_rect = Rect2( 190, 217, 50, 28 ) 21 | 22 | [node name="BulletSpawnPosition2D" parent="Weapon2D" index="1"] 23 | position = Vector2( 60, 0 ) 24 | 25 | [node name="CollisionShape2D" parent="Weapon2D/RangeArea2D" index="0"] 26 | shape = SubResource( 1 ) 27 | 28 | [editable path="Weapon2D"] 29 | -------------------------------------------------------------------------------- /source/Objects/Towers/RifleTower.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://Objects/Towers/Tower.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Objects/Towers/Upgrades/FireRangeUpgrade.gd" type="Script" id=3] 5 | 6 | [node name="Tower" instance=ExtResource( 1 )] 7 | 8 | [node name="FireRangeUpgrade" type="Node" parent="Upgrades" index="0"] 9 | script = ExtResource( 3 ) 10 | display_name = "Fire Range" 11 | description = "Increases the tower's reach." 12 | -------------------------------------------------------------------------------- /source/Objects/Towers/Tower.gd: -------------------------------------------------------------------------------- 1 | class_name Tower 2 | extends Node2D 3 | 4 | signal sold(price, place) 5 | signal selected(selected) 6 | 7 | export var cost := 100 8 | 9 | onready var _weapon := $Weapon2D 10 | onready var _interface := $Interface 11 | onready var _cooldown_bar := $UICooldownBar 12 | onready var _selection := $SelectableArea2D 13 | onready var _upgrades := $Upgrades 14 | 15 | 16 | func _ready() -> void: 17 | _weapon.show_range() 18 | for upgrade in _upgrades.get_children(): 19 | upgrade.weapon = _weapon 20 | upgrade.connect("applied", self, "_on_Upgrade_applied") 21 | 22 | 23 | func show_interface() -> void: 24 | _weapon.show_range() 25 | _interface.appear() 26 | 27 | 28 | func hide_interface() -> void: 29 | _weapon.hide_range() 30 | _interface.disappear() 31 | 32 | 33 | func get_upgrades() -> Array: 34 | return _upgrades.get_children() 35 | 36 | 37 | func _on_SelectableArea2D_selection_changed(selected) -> void: 38 | if selected: 39 | show_interface() 40 | else: 41 | hide_interface() 42 | emit_signal("selected", selected) 43 | 44 | 45 | func _on_SellButton_pressed() -> void: 46 | emit_signal("sold", cost / 2, position) 47 | queue_free() 48 | 49 | 50 | func _on_Weapon2D_fired() -> void: 51 | _cooldown_bar.start(_weapon.fire_cooldown) 52 | 53 | 54 | func _on_Upgrade_applied(upgrade_cost: int) -> void: 55 | cost += upgrade_cost 56 | -------------------------------------------------------------------------------- /source/Objects/Towers/Tower.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=9 format=2] 2 | 3 | [ext_resource path="res://Objects/Weapon2D/Weapon2D.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Objects/SelectableArea2D/SelectableArea2D.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://Objects/Towers/Tower.gd" type="Script" id=3] 6 | [ext_resource path="res://sprite-sheet.svg" type="Texture" id=4] 7 | [ext_resource path="res://UI/UIUnit/UIUnit.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://UI/UICooldownBar/UICooldownBar.tscn" type="PackedScene" id=6] 9 | 10 | [sub_resource type="CircleShape2D" id=1] 11 | resource_local_to_scene = true 12 | radius = 128.0 13 | 14 | [sub_resource type="RectangleShape2D" id=2] 15 | extents = Vector2( 32, 32 ) 16 | 17 | [node name="Tower" type="Node2D"] 18 | script = ExtResource( 3 ) 19 | 20 | [node name="BaseSprite" type="Sprite" parent="."] 21 | texture = ExtResource( 4 ) 22 | offset = Vector2( 32, 32 ) 23 | region_enabled = true 24 | region_rect = Rect2( 192, 64, 73, 64 ) 25 | 26 | [node name="Weapon2D" parent="." instance=ExtResource( 1 )] 27 | position = Vector2( 32, 36 ) 28 | fire_range = 192.0 29 | 30 | [node name="CollisionShape2D" parent="Weapon2D/RangeArea2D" index="0"] 31 | shape = SubResource( 1 ) 32 | 33 | [node name="GlassSprite" type="Sprite" parent="."] 34 | texture = ExtResource( 4 ) 35 | offset = Vector2( 32, 38 ) 36 | region_enabled = true 37 | region_rect = Rect2( 272, 89, 26, 27 ) 38 | 39 | [node name="SelectableArea2D" parent="." instance=ExtResource( 2 )] 40 | position = Vector2( 32, 32 ) 41 | z_index = -1 42 | 43 | [node name="CollisionShape2D" type="CollisionShape2D" parent="SelectableArea2D"] 44 | shape = SubResource( 2 ) 45 | 46 | [node name="Interface" parent="." instance=ExtResource( 5 )] 47 | margin_left = 32.0 48 | margin_top = 40.0 49 | margin_right = 32.0 50 | margin_bottom = 40.0 51 | 52 | [node name="SellButton" type="Button" parent="Interface"] 53 | anchor_left = 0.5 54 | anchor_top = 1.0 55 | anchor_right = 0.5 56 | anchor_bottom = 1.0 57 | margin_left = -72.0 58 | margin_top = 32.0 59 | margin_right = 72.0 60 | margin_bottom = 70.0 61 | rect_pivot_offset = Vector2( 72, 16 ) 62 | text = "Sell" 63 | __meta__ = { 64 | "_edit_use_anchors_": false 65 | } 66 | 67 | [node name="UICooldownBar" parent="." instance=ExtResource( 6 )] 68 | margin_left = -40.0 69 | margin_top = -40.0 70 | margin_right = 104.0 71 | margin_bottom = -16.0 72 | 73 | [node name="Upgrades" type="Node" parent="."] 74 | 75 | [connection signal="fired" from="Weapon2D" to="." method="_on_Weapon2D_fired"] 76 | [connection signal="selection_changed" from="SelectableArea2D" to="." method="_on_SelectableArea2D_selection_changed"] 77 | [connection signal="pressed" from="Interface/SellButton" to="." method="_on_SellButton_pressed"] 78 | 79 | [editable path="Weapon2D"] 80 | -------------------------------------------------------------------------------- /source/Objects/Towers/Upgrades/FireRangeUpgrade.gd: -------------------------------------------------------------------------------- 1 | extends Upgrade 2 | 3 | 4 | func _apply() -> void: 5 | weapon.fire_range += value 6 | weapon.show_range() 7 | -------------------------------------------------------------------------------- /source/Objects/Towers/Upgrades/Upgrade.gd: -------------------------------------------------------------------------------- 1 | class_name Upgrade 2 | extends Node 3 | 4 | signal applied(cost) 5 | 6 | export var display_name := "Upgrade name" 7 | export(String, MULTILINE) var description := "Upgrade description" 8 | export var cost := 100 9 | export var cost_multiplier := 1.2 10 | export var value := 100.0 11 | 12 | var weapon: Weapon2D 13 | 14 | 15 | func apply() -> void: 16 | _apply() 17 | cost *= cost_multiplier 18 | emit_signal("applied", cost) 19 | 20 | 21 | # Virtual method, override in children according to upgrade effect 22 | func _apply() -> void: 23 | pass 24 | -------------------------------------------------------------------------------- /source/Objects/WaveSpawner2D/WaveSpawner2D.gd: -------------------------------------------------------------------------------- 1 | # Spawns enemy waves. 2 | class_name WaveSpawner2D 3 | extends Position2D 4 | 5 | signal spawned(spawn) 6 | 7 | export var spawn_scene: PackedScene 8 | 9 | 10 | func spawn() -> Node2D: 11 | var spawn: Node2D = spawn_scene.instance() 12 | 13 | add_child(spawn) 14 | spawn.set_as_toplevel(true) 15 | spawn.global_position = global_position 16 | 17 | emit_signal("spawned", spawn) 18 | return spawn 19 | -------------------------------------------------------------------------------- /source/Objects/WaveSpawner2D/WaveSpawner2D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://Objects/WaveSpawner2D/WaveSpawner2D.gd" type="Script" id=1] 4 | 5 | [node name="WaveSpawner2D" type="Position2D"] 6 | script = ExtResource( 1 ) 7 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/Bullets/BombBullet.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=2] 2 | 3 | [ext_resource path="res://Objects/Weapon2D/Bullets/Bullet.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://VFX/Explosions/Explosion.tscn" type="PackedScene" id=4] 5 | 6 | [sub_resource type="CircleShape2D" id=1] 7 | radius = 64.1249 8 | 9 | [sub_resource type="Animation" id=2] 10 | resource_name = "Explode" 11 | length = 3.0 12 | tracks/0/type = "animation" 13 | tracks/0/path = NodePath("Explosion/AnimationPlayer") 14 | tracks/0/interp = 1 15 | tracks/0/loop_wrap = true 16 | tracks/0/imported = false 17 | tracks/0/enabled = true 18 | tracks/0/keys = { 19 | "clips": PoolStringArray( "Explode" ), 20 | "times": PoolRealArray( 0 ) 21 | } 22 | tracks/1/type = "value" 23 | tracks/1/path = NodePath("HitBoxArea2D/CollisionShape2D:disabled") 24 | tracks/1/interp = 1 25 | tracks/1/loop_wrap = true 26 | tracks/1/imported = false 27 | tracks/1/enabled = true 28 | tracks/1/keys = { 29 | "times": PoolRealArray( 0, 0.5 ), 30 | "transitions": PoolRealArray( 1, 1 ), 31 | "update": 1, 32 | "values": [ false, true ] 33 | } 34 | tracks/2/type = "method" 35 | tracks/2/path = NodePath(".") 36 | tracks/2/interp = 1 37 | tracks/2/loop_wrap = true 38 | tracks/2/imported = false 39 | tracks/2/enabled = true 40 | tracks/2/keys = { 41 | "times": PoolRealArray( 3 ), 42 | "transitions": PoolRealArray( 1 ), 43 | "values": [ { 44 | "args": [ ], 45 | "method": "queue_free" 46 | } ] 47 | } 48 | 49 | [sub_resource type="Animation" id=3] 50 | resource_name = "SETUP" 51 | tracks/0/type = "value" 52 | tracks/0/path = NodePath("HitBoxArea2D/CollisionShape2D:disabled") 53 | tracks/0/interp = 1 54 | tracks/0/loop_wrap = true 55 | tracks/0/imported = false 56 | tracks/0/enabled = true 57 | tracks/0/keys = { 58 | "times": PoolRealArray( 0 ), 59 | "transitions": PoolRealArray( 1 ), 60 | "update": 1, 61 | "values": [ true ] 62 | } 63 | 64 | [node name="Bullet" instance=ExtResource( 1 )] 65 | 66 | [node name="Sprite" parent="." index="0"] 67 | scale = Vector2( 1.3, 1.3 ) 68 | region_rect = Rect2( 240, 144, 16, 16 ) 69 | 70 | [node name="Sprite2" parent="Sprite" index="0"] 71 | visible = false 72 | 73 | [node name="HitBoxArea2D" parent="." index="1"] 74 | damage = 2 75 | can_hit_multiple = true 76 | 77 | [node name="CollisionShape2D" parent="HitBoxArea2D" index="0"] 78 | shape = SubResource( 1 ) 79 | 80 | [node name="AnimationPlayer" parent="." index="3"] 81 | autoplay = "SETUP" 82 | anims/Explode = SubResource( 2 ) 83 | anims/SETUP = SubResource( 3 ) 84 | 85 | [node name="SmallExplosion" parent="." index="4"] 86 | visible = false 87 | 88 | [node name="Explosion" parent="." index="5" instance=ExtResource( 4 )] 89 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/Bullets/Bullet.gd: -------------------------------------------------------------------------------- 1 | class_name Bullet 2 | extends Node2D 3 | 4 | export var speed := 500.0 5 | 6 | onready var _tween := $Tween 7 | onready var _anim_player := $AnimationPlayer 8 | 9 | 10 | func _init() -> void: 11 | set_as_toplevel(true) 12 | 13 | 14 | func fly_to(target_global_position: Vector2) -> void: 15 | var distance := global_position.distance_to(target_global_position) 16 | var duration := distance / speed 17 | 18 | _tween.interpolate_property( 19 | self, "global_position", global_position, target_global_position, duration 20 | ) 21 | _tween.start() 22 | look_at(target_global_position) 23 | yield(_tween, "tween_all_completed") 24 | _anim_player.play("Explode") 25 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/Bullets/Bullet.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://Objects/Weapon2D/Bullets/Bullet.gd" type="Script" id=1] 4 | [ext_resource path="res://sprite-sheet.svg" type="Texture" id=2] 5 | [ext_resource path="res://Objects/HitBox/HitBoxArea2D.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://VFX/Explosions/SmallExplosion.tscn" type="PackedScene" id=4] 7 | 8 | [sub_resource type="CapsuleShape2D" id=1] 9 | radius = 8.0 10 | height = 8.0 11 | 12 | [sub_resource type="Animation" id=2] 13 | resource_name = "Explode" 14 | length = 0.1 15 | tracks/0/type = "value" 16 | tracks/0/path = NodePath("SmallExplosion:emitting") 17 | tracks/0/interp = 1 18 | tracks/0/loop_wrap = true 19 | tracks/0/imported = false 20 | tracks/0/enabled = true 21 | tracks/0/keys = { 22 | "times": PoolRealArray( 0, 0.1 ), 23 | "transitions": PoolRealArray( 1, 1 ), 24 | "update": 1, 25 | "values": [ true, false ] 26 | } 27 | tracks/1/type = "method" 28 | tracks/1/path = NodePath(".") 29 | tracks/1/interp = 1 30 | tracks/1/loop_wrap = true 31 | tracks/1/imported = false 32 | tracks/1/enabled = true 33 | tracks/1/keys = { 34 | "times": PoolRealArray( 0.1 ), 35 | "transitions": PoolRealArray( 1 ), 36 | "values": [ { 37 | "args": [ ], 38 | "method": "queue_free" 39 | } ] 40 | } 41 | 42 | [node name="Bullet" type="Node2D"] 43 | script = ExtResource( 1 ) 44 | 45 | [node name="Sprite" type="Sprite" parent="."] 46 | texture = ExtResource( 2 ) 47 | region_enabled = true 48 | region_rect = Rect2( 192, 144, 21, 18 ) 49 | 50 | [node name="Sprite2" type="Sprite" parent="Sprite"] 51 | show_behind_parent = true 52 | position = Vector2( -16, 0 ) 53 | texture = ExtResource( 2 ) 54 | region_enabled = true 55 | region_rect = Rect2( 129, 228, 27, 16 ) 56 | 57 | [node name="HitBoxArea2D" parent="." instance=ExtResource( 3 )] 58 | damage = 3 59 | 60 | [node name="CollisionShape2D" type="CollisionShape2D" parent="HitBoxArea2D"] 61 | rotation = 1.57079 62 | shape = SubResource( 1 ) 63 | 64 | [node name="Tween" type="Tween" parent="."] 65 | playback_process_mode = 0 66 | 67 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 68 | anims/Explode = SubResource( 2 ) 69 | 70 | [node name="SmallExplosion" parent="." instance=ExtResource( 4 )] 71 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/RangePreview/RangePreview.gd: -------------------------------------------------------------------------------- 1 | extends Sprite 2 | 3 | export var radius := 100.0 4 | export var tween_duration := 0.5 5 | 6 | onready var _tween := $Tween 7 | 8 | 9 | func appear() -> void: 10 | var ratio = radius / texture.get_width() 11 | var final_scale = Vector2(ratio, ratio) * 2.0 12 | 13 | _tween.stop_all() 14 | 15 | _tween.interpolate_property( 16 | self, "scale", scale, final_scale, tween_duration, Tween.TRANS_QUINT, Tween.EASE_OUT 17 | ) 18 | _tween.interpolate_property( 19 | self, "modulate", modulate, Color(1, 1, 1, 1), tween_duration) 20 | _tween.start() 21 | 22 | 23 | func disappear() -> void: 24 | if _tween.is_active(): 25 | _tween.stop_all() 26 | 27 | _tween.interpolate_property( 28 | self, "scale", scale, Vector2.ZERO, tween_duration, Tween.TRANS_BACK, Tween.EASE_IN 29 | ) 30 | _tween.interpolate_property( 31 | self, "modulate", modulate, Color(1, 1, 1, 0), tween_duration * 2.0) 32 | _tween.start() 33 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/RangePreview/RangePreview.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://Objects/Weapon2D/RangePreview/range-preview.svg" type="Texture" id=1] 4 | [ext_resource path="res://Objects/Weapon2D/RangePreview/RangePreview.gd" type="Script" id=2] 5 | 6 | [node name="RangePreview" type="Sprite"] 7 | modulate = Color( 1, 1, 1, 0 ) 8 | texture = ExtResource( 1 ) 9 | script = ExtResource( 2 ) 10 | radius = 50.0 11 | 12 | [node name="Tween" type="Tween" parent="."] 13 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/RangePreview/range-preview.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 57 | 61 | 67 | 73 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/RangePreview/range-preview.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/range-preview.svg-3ddcdc213d26cf3b747e41044dcee9ea.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Objects/Weapon2D/RangePreview/range-preview.svg" 13 | dest_files=[ "res://.import/range-preview.svg-3ddcdc213d26cf3b747e41044dcee9ea.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/Weapon2D.gd: -------------------------------------------------------------------------------- 1 | class_name Weapon2D 2 | extends Node2D 3 | 4 | signal fired() 5 | 6 | export var bullet_scene: PackedScene 7 | # Range of the weapon in pixels. 8 | export var fire_range := 128.0 setget set_fire_range 9 | # Cooldown in seconds to fire again 10 | export var fire_cooldown := 1.0 11 | 12 | onready var _bullet_spawn_position := $BulletSpawnPosition2D 13 | onready var _cooldown_timer := $CooldownTimer 14 | onready var _range_area := $RangeArea2D 15 | onready var _animation_player := $AnimationPlayer 16 | onready var _range_shape: CircleShape2D = $RangeArea2D/CollisionShape2D.shape 17 | onready var _range_preview := $RangePreview 18 | 19 | 20 | func _ready() -> void: 21 | set_fire_range(fire_range) 22 | show_range() 23 | 24 | 25 | func _physics_process(_delta: float) -> void: 26 | if not _cooldown_timer.is_stopped(): 27 | return 28 | 29 | var targets: Array = _range_area.get_overlapping_areas() 30 | if targets.empty(): 31 | return 32 | 33 | var target: Node2D = targets[0] 34 | shoot_at(target.global_position) 35 | 36 | 37 | func set_fire_range(new_range: float) -> void: 38 | fire_range = new_range 39 | if not is_inside_tree(): 40 | yield(self, "ready") 41 | _range_shape.radius = fire_range 42 | 43 | 44 | func shoot_at(target_position: Vector2) -> void: 45 | look_at(target_position) 46 | _animation_player.play("shoot") 47 | 48 | var bullet = bullet_scene.instance() 49 | add_child(bullet) 50 | bullet.global_position = _bullet_spawn_position.global_position 51 | bullet.fly_to(target_position) 52 | 53 | _cooldown_timer.start(fire_cooldown) 54 | emit_signal("fired") 55 | 56 | 57 | func show_range() -> void: 58 | _range_preview.radius = fire_range 59 | _range_preview.appear() 60 | 61 | 62 | func hide_range() -> void: 63 | _range_preview.disappear() 64 | -------------------------------------------------------------------------------- /source/Objects/Weapon2D/Weapon2D.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://Objects/Weapon2D/Weapon2D.gd" type="Script" id=1] 4 | [ext_resource path="res://sprite-sheet.svg" type="Texture" id=2] 5 | [ext_resource path="res://Objects/Weapon2D/RangePreview/RangePreview.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://Objects/Weapon2D/Bullets/Bullet.tscn" type="PackedScene" id=4] 7 | 8 | [sub_resource type="CircleShape2D" id=1] 9 | resource_local_to_scene = true 10 | radius = 128.0 11 | 12 | [sub_resource type="Animation" id=2] 13 | resource_name = "shoot" 14 | length = 0.5 15 | tracks/0/type = "value" 16 | tracks/0/path = NodePath("Sprite:position") 17 | tracks/0/interp = 1 18 | tracks/0/loop_wrap = true 19 | tracks/0/imported = false 20 | tracks/0/enabled = true 21 | tracks/0/keys = { 22 | "times": PoolRealArray( 0, 0.2, 0.5 ), 23 | "transitions": PoolRealArray( 0.5, 1, 1 ), 24 | "update": 0, 25 | "values": [ Vector2( 0, 0 ), Vector2( -16, 0 ), Vector2( 0, 0 ) ] 26 | } 27 | 28 | [node name="Weapon2D" type="Node2D"] 29 | script = ExtResource( 1 ) 30 | bullet_scene = ExtResource( 4 ) 31 | fire_range = 256.0 32 | 33 | [node name="Sprite" type="Sprite" parent="."] 34 | texture = ExtResource( 2 ) 35 | offset = Vector2( 40, 0 ) 36 | region_enabled = true 37 | region_rect = Rect2( 192, 176, 54, 18 ) 38 | 39 | [node name="BulletSpawnPosition2D" type="Position2D" parent="."] 40 | position = Vector2( 64, 0 ) 41 | 42 | [node name="RangeArea2D" type="Area2D" parent="."] 43 | collision_layer = 0 44 | collision_mask = 4 45 | 46 | [node name="CollisionShape2D" type="CollisionShape2D" parent="RangeArea2D"] 47 | shape = SubResource( 1 ) 48 | 49 | [node name="CooldownTimer" type="Timer" parent="."] 50 | process_mode = 0 51 | one_shot = true 52 | 53 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 54 | anims/shoot = SubResource( 2 ) 55 | 56 | [node name="RangePreview" parent="." instance=ExtResource( 3 )] 57 | -------------------------------------------------------------------------------- /source/Screens/EndScreen.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | export var player_score := 0 4 | 5 | onready var _label := $Panel/Label 6 | 7 | func _ready() -> void: 8 | _label.text = _label.text % player_score 9 | -------------------------------------------------------------------------------- /source/Screens/EndScreen.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/Montserrat-ExtraBold.ttf" type="DynamicFontData" id=1] 4 | [ext_resource path="res://Screens/EndScreen.gd" type="Script" id=2] 5 | 6 | [sub_resource type="DynamicFont" id=1] 7 | size = 32 8 | font_data = ExtResource( 1 ) 9 | 10 | [sub_resource type="Animation" id=2] 11 | resource_name = "Text" 12 | length = 2.5 13 | tracks/0/type = "value" 14 | tracks/0/path = NodePath("Panel:rect_scale") 15 | tracks/0/interp = 1 16 | tracks/0/loop_wrap = true 17 | tracks/0/imported = false 18 | tracks/0/enabled = true 19 | tracks/0/keys = { 20 | "times": PoolRealArray( 0, 0.2, 0.3 ), 21 | "transitions": PoolRealArray( 1, 0.5, 1 ), 22 | "update": 0, 23 | "values": [ Vector2( 0, 0 ), Vector2( 1.2, 1.2 ), Vector2( 1, 1 ) ] 24 | } 25 | tracks/1/type = "value" 26 | tracks/1/path = NodePath("Panel/Label:percent_visible") 27 | tracks/1/interp = 1 28 | tracks/1/loop_wrap = true 29 | tracks/1/imported = false 30 | tracks/1/enabled = true 31 | tracks/1/keys = { 32 | "times": PoolRealArray( 0, 0.4, 1.4, 2.5 ), 33 | "transitions": PoolRealArray( 1, 1, 1, 1 ), 34 | "update": 0, 35 | "values": [ 0.0, 0.0, 0.909091, 1.0 ] 36 | } 37 | 38 | [node name="EndScreen" type="Control"] 39 | anchor_right = 1.0 40 | anchor_bottom = 1.0 41 | script = ExtResource( 2 ) 42 | __meta__ = { 43 | "_edit_use_anchors_": false 44 | } 45 | 46 | [node name="Panel" type="Panel" parent="."] 47 | anchor_left = 0.5 48 | anchor_top = 0.5 49 | anchor_right = 0.5 50 | anchor_bottom = 0.5 51 | margin_left = -618.0 52 | margin_top = -120.0 53 | margin_right = 618.0 54 | margin_bottom = 120.0 55 | rect_scale = Vector2( 1e-05, 1e-05 ) 56 | rect_pivot_offset = Vector2( 618, 124 ) 57 | __meta__ = { 58 | "_edit_use_anchors_": false 59 | } 60 | 61 | [node name="Label" type="Label" parent="Panel"] 62 | anchor_right = 1.0 63 | anchor_bottom = 1.0 64 | custom_fonts/font = SubResource( 1 ) 65 | text = "Congratulations! We vanquished the Aster-570! 66 | As a good strategist you spent just the resources you need. 67 | 68 | Score: %s" 69 | align = 1 70 | valign = 1 71 | percent_visible = 0.0 72 | __meta__ = { 73 | "_edit_use_anchors_": false 74 | } 75 | 76 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 77 | autoplay = "Text" 78 | anims/Text = SubResource( 2 ) 79 | -------------------------------------------------------------------------------- /source/UI/Theme/Montserrat-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/UI/Theme/Montserrat-ExtraBold.ttf -------------------------------------------------------------------------------- /source/UI/Theme/background_stylebox.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=2] 2 | 3 | [resource] 4 | bg_color = Color( 0.278431, 0.231373, 0.470588, 1 ) 5 | border_width_left = 2 6 | border_width_top = 2 7 | border_width_right = 2 8 | border_width_bottom = 2 9 | border_color = Color( 1, 1, 1, 1 ) 10 | corner_radius_top_left = 8 11 | corner_radius_top_right = 8 12 | corner_radius_bottom_right = 8 13 | corner_radius_bottom_left = 8 14 | -------------------------------------------------------------------------------- /source/UI/Theme/button_font.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/Montserrat-ExtraBold.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 14 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /source/UI/Theme/foreground_stylebox.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=2] 2 | 3 | [resource] 4 | bg_color = Color( 0.235294, 0.639216, 0.439216, 1 ) 5 | border_width_left = 2 6 | border_width_top = 2 7 | border_width_right = 2 8 | border_width_bottom = 2 9 | border_color = Color( 1, 1, 1, 1 ) 10 | corner_radius_top_left = 8 11 | corner_radius_top_right = 8 12 | corner_radius_bottom_right = 8 13 | corner_radius_bottom_left = 8 14 | -------------------------------------------------------------------------------- /source/UI/Theme/main_font.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/Montserrat-ExtraBold.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 20 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /source/UI/Theme/main_theme.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Theme" load_steps=10 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/main_font.tres" type="DynamicFont" id=1] 4 | [ext_resource path="res://UI/Theme/button_font.tres" type="DynamicFont" id=2] 5 | 6 | [sub_resource type="StyleBoxFlat" id=1] 7 | bg_color = Color( 0.364706, 0.341176, 0.470588, 0.705882 ) 8 | border_width_left = 4 9 | border_width_top = 4 10 | border_width_right = 4 11 | border_width_bottom = 4 12 | 13 | [sub_resource type="StyleBoxFlat" id=2] 14 | bg_color = Color( 0.278431, 0.231373, 0.470588, 0.705882 ) 15 | border_width_left = 4 16 | border_width_top = 4 17 | border_width_right = 4 18 | border_width_bottom = 4 19 | border_color = Color( 1, 1, 1, 0.705882 ) 20 | 21 | [sub_resource type="StyleBoxFlat" id=3] 22 | bg_color = Color( 0.37888, 0.3136, 0.64, 0.705882 ) 23 | border_width_left = 4 24 | border_width_top = 4 25 | border_width_right = 4 26 | border_width_bottom = 4 27 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 28 | 29 | [sub_resource type="StyleBoxFlat" id=4] 30 | bg_color = Color( 0.278431, 0.231373, 0.470588, 0.705882 ) 31 | border_width_left = 4 32 | border_width_top = 4 33 | border_width_right = 4 34 | border_width_bottom = 4 35 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 36 | 37 | [sub_resource type="StyleBoxFlat" id=5] 38 | bg_color = Color( 0.18944, 0.1568, 0.32, 0.486275 ) 39 | border_width_left = 4 40 | border_width_top = 4 41 | border_width_right = 4 42 | border_width_bottom = 4 43 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 44 | 45 | [sub_resource type="StyleBoxLine" id=6] 46 | color = Color( 1, 1, 1, 1 ) 47 | thickness = 2 48 | 49 | [sub_resource type="StyleBoxFlat" id=7] 50 | bg_color = Color( 0.278431, 0.231373, 0.470588, 0.705882 ) 51 | border_width_left = 4 52 | border_width_top = 4 53 | border_width_right = 4 54 | border_width_bottom = 4 55 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 56 | corner_radius_top_left = 8 57 | corner_radius_top_right = 8 58 | corner_radius_bottom_right = 8 59 | corner_radius_bottom_left = 8 60 | 61 | [resource] 62 | default_font = ExtResource( 1 ) 63 | Button/colors/font_color = Color( 1, 1, 1, 1 ) 64 | Button/colors/font_color_disabled = Color( 0.607843, 0.607843, 0.607843, 1 ) 65 | Button/colors/font_color_hover = Color( 1, 1, 1, 1 ) 66 | Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) 67 | Button/constants/hseparation = 2 68 | Button/fonts/font = ExtResource( 2 ) 69 | Button/styles/disabled = SubResource( 1 ) 70 | Button/styles/focus = SubResource( 2 ) 71 | Button/styles/hover = SubResource( 3 ) 72 | Button/styles/normal = SubResource( 4 ) 73 | Button/styles/pressed = SubResource( 5 ) 74 | HSeparator/constants/separation = 4 75 | HSeparator/styles/separator = SubResource( 6 ) 76 | OptionButton/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) 77 | OptionButton/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) 78 | OptionButton/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) 79 | OptionButton/colors/font_color_pressed = Color( 1, 1, 1, 1 ) 80 | OptionButton/constants/arrow_margin = 2 81 | OptionButton/constants/hseparation = 2 82 | OptionButton/fonts/font = null 83 | OptionButton/icons/arrow = null 84 | OptionButton/styles/disabled = null 85 | OptionButton/styles/focus = null 86 | OptionButton/styles/hover = null 87 | OptionButton/styles/normal = null 88 | OptionButton/styles/pressed = null 89 | Panel/styles/panel = SubResource( 7 ) 90 | PanelContainer/styles/panel = SubResource( 7 ) 91 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/UICooldownBar.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | export var gradient: Gradient 5 | 6 | onready var _progress := $TextureProgress 7 | onready var _animator := $AnimationPlayer 8 | onready var _timer := $Timer 9 | 10 | 11 | func _ready() -> void: 12 | set_process(false) 13 | hide() 14 | 15 | 16 | func _process(delta: float) -> void: 17 | _progress.value = _timer.wait_time - _timer.time_left 18 | _progress.tint_progress = gradient.interpolate(_progress.ratio) 19 | 20 | 21 | func start(time: float) -> void: 22 | _timer.start(time) 23 | _progress.max_value = time 24 | _progress.value = 0.0 25 | _animator.playback_speed = 1.0/time 26 | _animator.play("Spin") 27 | set_process(true) 28 | show() 29 | 30 | 31 | func _on_Timer_timeout(): 32 | _animator.play("Finish") 33 | set_process(false) 34 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/UICooldownBar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=10 format=2] 2 | 3 | [ext_resource path="res://UI/UICooldownBar/cooldown-bar-progress.png" type="Texture" id=1] 4 | [ext_resource path="res://UI/UICooldownBar/cooldown-bar-over.png" type="Texture" id=2] 5 | [ext_resource path="res://UI/UICooldownBar/clock.png" type="Texture" id=3] 6 | [ext_resource path="res://UI/UICooldownBar/clock-tic.png" type="Texture" id=4] 7 | [ext_resource path="res://UI/UICooldownBar/cooldown-bar-under.png" type="Texture" id=5] 8 | [ext_resource path="res://UI/UICooldownBar/UICooldownBar.gd" type="Script" id=6] 9 | 10 | [sub_resource type="Gradient" id=1] 11 | offsets = PoolRealArray( 0.254682, 0.520599, 0.846442, 1 ) 12 | colors = PoolColorArray( 0.921569, 0.337255, 0.294118, 1, 1, 0.568627, 0.4, 1, 1, 0.709804, 0.439216, 1, 1, 1, 1, 1 ) 13 | 14 | [sub_resource type="Animation" id=2] 15 | resource_name = "Finish" 16 | length = 0.2 17 | tracks/0/type = "value" 18 | tracks/0/path = NodePath(".:visible") 19 | tracks/0/interp = 1 20 | tracks/0/loop_wrap = true 21 | tracks/0/imported = false 22 | tracks/0/enabled = true 23 | tracks/0/keys = { 24 | "times": PoolRealArray( 0.2 ), 25 | "transitions": PoolRealArray( 1 ), 26 | "update": 1, 27 | "values": [ false ] 28 | } 29 | 30 | [sub_resource type="Animation" id=3] 31 | tracks/0/type = "value" 32 | tracks/0/path = NodePath("Clock/Tic:rect_rotation") 33 | tracks/0/interp = 1 34 | tracks/0/loop_wrap = true 35 | tracks/0/imported = false 36 | tracks/0/enabled = true 37 | tracks/0/keys = { 38 | "times": PoolRealArray( 0, 1 ), 39 | "transitions": PoolRealArray( 1, 1 ), 40 | "update": 0, 41 | "values": [ 0.0, 360.0 ] 42 | } 43 | 44 | [node name="UICooldownBar" type="Control"] 45 | visible = false 46 | margin_right = 144.0 47 | margin_bottom = 24.0 48 | script = ExtResource( 6 ) 49 | __meta__ = { 50 | "_edit_use_anchors_": false 51 | } 52 | gradient = SubResource( 1 ) 53 | 54 | [node name="TextureProgress" type="TextureProgress" parent="."] 55 | anchor_left = 0.222 56 | anchor_right = 1.0 57 | anchor_bottom = 1.0 58 | margin_left = 0.0319977 59 | step = 0.01 60 | texture_under = ExtResource( 5 ) 61 | texture_over = ExtResource( 2 ) 62 | texture_progress = ExtResource( 1 ) 63 | __meta__ = { 64 | "_edit_use_anchors_": false 65 | } 66 | 67 | [node name="Clock" type="TextureRect" parent="."] 68 | anchor_right = 0.167 69 | anchor_bottom = 1.0 70 | margin_right = -0.0480022 71 | texture = ExtResource( 3 ) 72 | expand = true 73 | stretch_mode = 6 74 | __meta__ = { 75 | "_edit_use_anchors_": false 76 | } 77 | 78 | [node name="Tic" type="TextureRect" parent="Clock"] 79 | anchor_left = 0.5 80 | anchor_top = 0.5 81 | anchor_right = 0.5 82 | anchor_bottom = 0.5 83 | margin_left = -2.0 84 | margin_top = -8.0 85 | margin_right = 2.0 86 | rect_rotation = 252.0 87 | rect_pivot_offset = Vector2( 2, 8 ) 88 | texture = ExtResource( 4 ) 89 | expand = true 90 | stretch_mode = 1 91 | __meta__ = { 92 | "_edit_use_anchors_": false 93 | } 94 | 95 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 96 | anims/Finish = SubResource( 2 ) 97 | anims/Spin = SubResource( 3 ) 98 | 99 | [node name="Timer" type="Timer" parent="."] 100 | 101 | [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] 102 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/clock-tic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/UI/UICooldownBar/clock-tic.png -------------------------------------------------------------------------------- /source/UI/UICooldownBar/clock-tic.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/clock-tic.png-fcf004a0cb21e95bfb83688239d9146c.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/clock-tic.png" 13 | dest_files=[ "res://.import/clock-tic.png-fcf004a0cb21e95bfb83688239d9146c.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/UI/UICooldownBar/clock.png -------------------------------------------------------------------------------- /source/UI/UICooldownBar/clock.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/clock.png-e646f709d1c473b8f555faca30d0b0fd.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/clock.png" 13 | dest_files=[ "res://.import/clock.png-e646f709d1c473b8f555faca30d0b0fd.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/cooldown-bar-over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/UI/UICooldownBar/cooldown-bar-over.png -------------------------------------------------------------------------------- /source/UI/UICooldownBar/cooldown-bar-over.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cooldown-bar-over.png-139f0f8a8e088eb12a232c8fecc07bf6.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/cooldown-bar-over.png" 13 | dest_files=[ "res://.import/cooldown-bar-over.png-139f0f8a8e088eb12a232c8fecc07bf6.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/cooldown-bar-progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/UI/UICooldownBar/cooldown-bar-progress.png -------------------------------------------------------------------------------- /source/UI/UICooldownBar/cooldown-bar-progress.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cooldown-bar-progress.png-4efbbd0ea1e29dd11c8ddd7112fcbf44.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/cooldown-bar-progress.png" 13 | dest_files=[ "res://.import/cooldown-bar-progress.png-4efbbd0ea1e29dd11c8ddd7112fcbf44.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UICooldownBar/cooldown-bar-under.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/UI/UICooldownBar/cooldown-bar-under.png -------------------------------------------------------------------------------- /source/UI/UICooldownBar/cooldown-bar-under.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cooldown-bar-under.png-9693085f3ebee638ce0f793ec3efc232.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/cooldown-bar-under.png" 13 | dest_files=[ "res://.import/cooldown-bar-under.png-9693085f3ebee638ce0f793ec3efc232.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UIGoldPanel.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | onready var _label: Label = $Label 5 | 6 | var player: Player setget set_player 7 | 8 | func set_player(new_player: Player) -> void: 9 | player = new_player 10 | player.connect("gold_changed", self, "_update_gold_amount") 11 | _update_gold_amount(player.gold) 12 | 13 | 14 | func _update_gold_amount(new_amount: int) -> void: 15 | _label.text = "Gold: %s" % new_amount 16 | -------------------------------------------------------------------------------- /source/UI/UIGoldPanel.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/UIGoldPanel.gd" type="Script" id=2] 4 | 5 | [node name="UIGoldPanel" type="Panel"] 6 | margin_right = 224.0 7 | margin_bottom = 64.0 8 | mouse_filter = 2 9 | script = ExtResource( 2 ) 10 | __meta__ = { 11 | "_edit_use_anchors_": false 12 | } 13 | 14 | [node name="Label" type="Label" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | margin_left = 22.0 18 | margin_right = -22.0 19 | size_flags_horizontal = 3 20 | size_flags_vertical = 6 21 | text = "Gold: 1000" 22 | align = 1 23 | valign = 1 24 | __meta__ = { 25 | "_edit_use_anchors_": false 26 | } 27 | -------------------------------------------------------------------------------- /source/UI/UIHealthBar/UIHealthBar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://UI/UIHealthBar/heart.svg" type="Texture" id=1] 4 | 5 | [sub_resource type="StyleBoxFlat" id=1] 6 | bg_color = Color( 0.235294, 0.639216, 0.439216, 1 ) 7 | border_width_left = 2 8 | border_width_top = 2 9 | border_width_right = 2 10 | border_width_bottom = 2 11 | border_color = Color( 1, 1, 1, 1 ) 12 | corner_radius_top_left = 8 13 | corner_radius_top_right = 8 14 | corner_radius_bottom_right = 8 15 | corner_radius_bottom_left = 8 16 | 17 | [sub_resource type="StyleBoxFlat" id=2] 18 | bg_color = Color( 0.278431, 0.231373, 0.470588, 1 ) 19 | border_width_left = 2 20 | border_width_top = 2 21 | border_width_right = 2 22 | border_width_bottom = 2 23 | border_color = Color( 1, 1, 1, 1 ) 24 | corner_radius_top_left = 8 25 | corner_radius_top_right = 8 26 | corner_radius_bottom_right = 8 27 | corner_radius_bottom_left = 8 28 | 29 | [node name="HealthBar" type="ProgressBar"] 30 | margin_right = 172.0 31 | margin_bottom = 18.0 32 | custom_styles/fg = SubResource( 1 ) 33 | custom_styles/bg = SubResource( 2 ) 34 | step = 1.0 35 | value = 50.0 36 | percent_visible = false 37 | __meta__ = { 38 | "_edit_use_anchors_": false 39 | } 40 | 41 | [node name="TextureRect" type="TextureRect" parent="."] 42 | margin_left = -56.0 43 | margin_top = -14.0 44 | margin_right = -8.0 45 | margin_bottom = 34.0 46 | texture = ExtResource( 1 ) 47 | expand = true 48 | stretch_mode = 6 49 | __meta__ = { 50 | "_edit_use_anchors_": false 51 | } 52 | -------------------------------------------------------------------------------- /source/UI/UIHealthBar/UITimedHealthBar.gd: -------------------------------------------------------------------------------- 1 | extends ProgressBar 2 | 3 | onready var _timer := $Timer 4 | 5 | 6 | func _on_value_changed(_value: float) -> void: 7 | show() 8 | _timer.start() 9 | 10 | 11 | func _on_Timer_timeout() -> void: 12 | hide() 13 | -------------------------------------------------------------------------------- /source/UI/UIHealthBar/UITimedHealthBar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://UI/UIHealthBar/heart.svg" type="Texture" id=1] 4 | [ext_resource path="res://UI/UIHealthBar/UITimedHealthBar.gd" type="Script" id=2] 5 | 6 | [sub_resource type="StyleBoxFlat" id=1] 7 | bg_color = Color( 0.235294, 0.639216, 0.439216, 1 ) 8 | border_width_left = 2 9 | border_width_top = 2 10 | border_width_right = 2 11 | border_width_bottom = 2 12 | border_color = Color( 1, 1, 1, 1 ) 13 | corner_radius_top_left = 8 14 | corner_radius_top_right = 8 15 | corner_radius_bottom_right = 8 16 | corner_radius_bottom_left = 8 17 | 18 | [sub_resource type="StyleBoxFlat" id=2] 19 | bg_color = Color( 0.278431, 0.231373, 0.470588, 1 ) 20 | border_width_left = 2 21 | border_width_top = 2 22 | border_width_right = 2 23 | border_width_bottom = 2 24 | border_color = Color( 1, 1, 1, 1 ) 25 | corner_radius_top_left = 8 26 | corner_radius_top_right = 8 27 | corner_radius_bottom_right = 8 28 | corner_radius_bottom_left = 8 29 | 30 | [node name="UIHealthBar" type="ProgressBar"] 31 | margin_top = 6.0 32 | margin_right = 192.0 33 | margin_bottom = 24.0 34 | custom_styles/fg = SubResource( 1 ) 35 | custom_styles/bg = SubResource( 2 ) 36 | value = 50.0 37 | percent_visible = false 38 | script = ExtResource( 2 ) 39 | __meta__ = { 40 | "_edit_use_anchors_": false 41 | } 42 | 43 | [node name="TextureRect" type="TextureRect" parent="."] 44 | margin_left = -56.0 45 | margin_top = -14.0 46 | margin_right = -8.0 47 | margin_bottom = 34.0 48 | texture = ExtResource( 1 ) 49 | expand = true 50 | stretch_mode = 6 51 | __meta__ = { 52 | "_edit_use_anchors_": false 53 | } 54 | 55 | [node name="Timer" type="Timer" parent="."] 56 | wait_time = 0.5 57 | 58 | [connection signal="value_changed" from="." to="." method="_on_value_changed"] 59 | [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] 60 | -------------------------------------------------------------------------------- /source/UI/UIHealthBar/heart.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/heart.svg-49f6cf64586eb6a039065531a8f12ab4.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UIHealthBar/heart.svg" 13 | dest_files=[ "res://.import/heart.svg-49f6cf64586eb6a039065531a8f12ab4.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UIScreenOverlay.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | onready var _anim_player := $AnimationPlayer 4 | 5 | 6 | func play_win() -> void: 7 | _anim_player.play("PlayerWon") 8 | yield(_anim_player, "animation_finished") 9 | 10 | 11 | func play_lost() -> void: 12 | _anim_player.play("PlayerLost") 13 | yield(_anim_player, "animation_finished") 14 | 15 | 16 | func play_wave_start() -> void: 17 | _anim_player.play("WaveStarting") 18 | yield(_anim_player, "animation_finished") 19 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/UITowerPurchaseButton.gd: -------------------------------------------------------------------------------- 1 | extends TextureButton 2 | 3 | signal tower_purchased(tower_scene) 4 | 5 | export var tower_scene: PackedScene 6 | 7 | onready var _label := $Label 8 | 9 | var tower_cost = 0 10 | 11 | 12 | func _ready() -> void: 13 | setup_tower_data() 14 | 15 | 16 | # Instance the Tower to access its data, e.g. cost and description 17 | func setup_tower_data() -> void: 18 | var tower: Tower = tower_scene.instance() 19 | tower_cost = tower.cost 20 | _label.text = "Cost: %s" % tower_cost 21 | tower.queue_free() 22 | 23 | 24 | func _pressed() -> void: 25 | emit_signal("tower_purchased", tower_scene) 26 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/UITowerPurchaseButton.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=2] 2 | 3 | [ext_resource path="res://UI/UITowerShop/tower-icon-normal.svg" type="Texture" id=1] 4 | [ext_resource path="res://UI/UITowerShop/UITowerPurchaseButton.gd" type="Script" id=2] 5 | [ext_resource path="res://UI/UITowerShop/tower-icon-hover.svg" type="Texture" id=3] 6 | [ext_resource path="res://UI/UITowerShop/tower-icon-pressed.svg" type="Texture" id=4] 7 | [ext_resource path="res://Objects/Towers/Tower.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://UI/UITowerShop/tower-icon-disabled.svg" type="Texture" id=6] 9 | [ext_resource path="res://UI/UITowerShop/tower-icon-focused.svg" type="Texture" id=7] 10 | 11 | [node name="UITowerPurchaseButton" type="TextureButton"] 12 | margin_right = 64.0 13 | margin_bottom = 64.0 14 | rect_min_size = Vector2( 64, 64 ) 15 | size_flags_horizontal = 3 16 | size_flags_vertical = 3 17 | action_mode = 0 18 | enabled_focus_mode = 0 19 | texture_normal = ExtResource( 1 ) 20 | texture_pressed = ExtResource( 4 ) 21 | texture_hover = ExtResource( 3 ) 22 | texture_disabled = ExtResource( 6 ) 23 | texture_focused = ExtResource( 7 ) 24 | expand = true 25 | stretch_mode = 5 26 | script = ExtResource( 2 ) 27 | __meta__ = { 28 | "_edit_use_anchors_": false 29 | } 30 | tower_scene = ExtResource( 5 ) 31 | 32 | [node name="Label" type="Label" parent="."] 33 | anchor_top = 1.0 34 | anchor_right = 1.0 35 | anchor_bottom = 1.0 36 | margin_left = -40.0 37 | margin_top = 16.0 38 | margin_right = 40.0 39 | margin_bottom = 48.0 40 | text = "Cost: 100" 41 | align = 1 42 | valign = 1 43 | autowrap = true 44 | __meta__ = { 45 | "_edit_use_anchors_": false 46 | } 47 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/UITowerShop.gd: -------------------------------------------------------------------------------- 1 | class_name UITowerShop 2 | extends Panel 3 | 4 | signal tower_purchased(tower) 5 | 6 | onready var _buttons: Array = $HBoxContainer.get_children() 7 | 8 | var player: Player setget set_player 9 | 10 | 11 | func _ready() -> void: 12 | for button in _buttons: 13 | button.connect("tower_purchased", self, "_on_TowerPurchaseButton_tower_purchased") 14 | 15 | 16 | func set_player(new_player: Player) -> void: 17 | player = new_player 18 | player.connect("gold_changed", self, "_on_Player_gold_changed") 19 | 20 | 21 | func _on_TowerPurchaseButton_tower_purchased(tower_scene: PackedScene) -> void: 22 | var tower: Tower = tower_scene.instance() 23 | 24 | tower.connect("sold", self, "_on_Tower_sold") 25 | emit_signal("tower_purchased", tower) 26 | 27 | 28 | func _on_TowerPlacer_tower_placed(tower: Tower) -> void: 29 | player.gold -= tower.cost 30 | 31 | 32 | func _on_Tower_sold(price: int, _position: Vector2) -> void: 33 | player.gold += price 34 | 35 | 36 | func _on_Player_gold_changed(gold_amount: int) -> void: 37 | for button in _buttons: 38 | button.disabled = button.tower_cost > gold_amount 39 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/UITowerShop.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://Objects/Towers/BombTower.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://Objects/Towers/RifleTower.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://UI/UITowerShop/UITowerShop.gd" type="Script" id=3] 6 | [ext_resource path="res://UI/UITowerShop/UITowerPurchaseButton.tscn" type="PackedScene" id=6] 7 | 8 | [node name="UITowerShop" type="Panel"] 9 | anchor_left = 0.5 10 | anchor_top = 1.0 11 | anchor_right = 0.5 12 | anchor_bottom = 1.0 13 | margin_left = -160.0 14 | margin_top = -220.0 15 | margin_right = 160.0 16 | margin_bottom = -36.0 17 | rect_min_size = Vector2( 320, 184 ) 18 | mouse_filter = 2 19 | script = ExtResource( 3 ) 20 | __meta__ = { 21 | "_edit_use_anchors_": false 22 | } 23 | 24 | [node name="Label" type="Label" parent="."] 25 | anchor_left = 0.5 26 | anchor_top = 0.5 27 | anchor_right = 0.5 28 | anchor_bottom = 0.5 29 | margin_left = -128.0 30 | margin_top = -72.0 31 | margin_right = 128.0 32 | margin_bottom = -56.0 33 | text = "Purchase new towers" 34 | align = 1 35 | valign = 1 36 | __meta__ = { 37 | "_edit_use_anchors_": false 38 | } 39 | 40 | [node name="HBoxContainer" type="HBoxContainer" parent="."] 41 | anchor_left = 0.5 42 | anchor_top = 0.5 43 | anchor_right = 0.5 44 | anchor_bottom = 0.5 45 | margin_left = -128.0 46 | margin_top = -32.0 47 | margin_right = 128.0 48 | margin_bottom = 40.0 49 | custom_constants/separation = 16 50 | alignment = 1 51 | __meta__ = { 52 | "_edit_use_anchors_": false 53 | } 54 | 55 | [node name="UITowerPurchaseButton" parent="HBoxContainer" instance=ExtResource( 6 )] 56 | margin_right = 120.0 57 | margin_bottom = 72.0 58 | hint_tooltip = "Standard tower. Shoots bullets at a target direction. 59 | " 60 | focus_mode = 0 61 | mouse_filter = 1 62 | tower_scene = ExtResource( 2 ) 63 | 64 | [node name="UITowerPurchaseButton2" parent="HBoxContainer" instance=ExtResource( 6 )] 65 | margin_left = 136.0 66 | margin_right = 256.0 67 | margin_bottom = 72.0 68 | hint_tooltip = "Bomb tower. Shoots a bomb at a target position that hits every enemy inside its explosion area. 69 | " 70 | focus_mode = 0 71 | mouse_filter = 1 72 | tower_scene = ExtResource( 1 ) 73 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-disabled.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-disabled.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-disabled.svg-62c4df5afaef7403c38ea7613fee01a0.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-disabled.svg" 13 | dest_files=[ "res://.import/tower-icon-disabled.svg-62c4df5afaef7403c38ea7613fee01a0.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-focused.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-focused.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-focused.svg-e45f7d0f6fc6495dcb36beb0c612cd09.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-focused.svg" 13 | dest_files=[ "res://.import/tower-icon-focused.svg-e45f7d0f6fc6495dcb36beb0c612cd09.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-hover.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-hover.svg-e3374d23a1e60195dc22da7d76b6bd7c.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-hover.svg" 13 | dest_files=[ "res://.import/tower-icon-hover.svg-e3374d23a1e60195dc22da7d76b6bd7c.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-normal.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-normal.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-normal.svg-54029b396714c9a0bc62fb03ce535dbe.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-normal.svg" 13 | dest_files=[ "res://.import/tower-icon-normal.svg-54029b396714c9a0bc62fb03ce535dbe.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /source/UI/UITowerShop/tower-icon-pressed.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-pressed.svg-b6c90a05f9abb921648be57d23811288.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-pressed.svg" 13 | dest_files=[ "res://.import/tower-icon-pressed.svg-b6c90a05f9abb921648be57d23811288.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/UI/UIUnit/UIUnit.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | onready var _anim_player := $AnimationPlayer 5 | 6 | func appear() -> void: 7 | _anim_player.play("appear") 8 | 9 | 10 | func disappear() -> void: 11 | _anim_player.play("disappear") 12 | -------------------------------------------------------------------------------- /source/UI/UIUnit/UIUnit.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://UI/UIUnit/UIUnit.gd" type="Script" id=1] 4 | 5 | [sub_resource type="Animation" id=3] 6 | resource_name = "appear" 7 | length = 0.3 8 | tracks/0/type = "value" 9 | tracks/0/path = NodePath(".:rect_scale") 10 | tracks/0/interp = 1 11 | tracks/0/loop_wrap = true 12 | tracks/0/imported = false 13 | tracks/0/enabled = true 14 | tracks/0/keys = { 15 | "times": PoolRealArray( 0, 0.2, 0.3 ), 16 | "transitions": PoolRealArray( 0.5, 1, 1 ), 17 | "update": 0, 18 | "values": [ Vector2( 0, 0 ), Vector2( 1.2, 1.2 ), Vector2( 1, 1 ) ] 19 | } 20 | 21 | [sub_resource type="Animation" id=2] 22 | resource_name = "disappear" 23 | length = 0.3 24 | tracks/0/type = "value" 25 | tracks/0/path = NodePath(".:rect_scale") 26 | tracks/0/interp = 1 27 | tracks/0/loop_wrap = true 28 | tracks/0/imported = false 29 | tracks/0/enabled = true 30 | tracks/0/keys = { 31 | "times": PoolRealArray( 0, 0.1, 0.3 ), 32 | "transitions": PoolRealArray( 0.5, 0.5, 0.5 ), 33 | "update": 0, 34 | "values": [ Vector2( 1, 1 ), Vector2( 1.2, 1.2 ), Vector2( 0, 0 ) ] 35 | } 36 | 37 | [node name="Interface" type="Control"] 38 | rect_scale = Vector2( 1e-05, 1e-05 ) 39 | mouse_filter = 2 40 | script = ExtResource( 1 ) 41 | __meta__ = { 42 | "_edit_use_anchors_": false 43 | } 44 | 45 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 46 | anims/appear = SubResource( 3 ) 47 | anims/disappear = SubResource( 2 ) 48 | -------------------------------------------------------------------------------- /source/UI/UIUpgradeShop/UIUpgradeButton.gd: -------------------------------------------------------------------------------- 1 | class_name UIUpgradeButton 2 | extends Button 3 | 4 | 5 | func update_display(upgrade: Upgrade, player_gold: int) -> void: 6 | text = "%s: %sg" % [upgrade.display_name, upgrade.cost] 7 | hint_tooltip = upgrade.description 8 | disabled = player_gold < upgrade.cost 9 | -------------------------------------------------------------------------------- /source/UI/UIUpgradeShop/UIUpgradeButton.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/UIUpgradeShop/UIUpgradeButton.gd" type="Script" id=1] 4 | 5 | [node name="UIUpgradeButton" type="Button"] 6 | margin_right = 224.0 7 | margin_bottom = 34.0 8 | custom_constants/hseparation = 4 9 | text = "%s: %sg" 10 | script = ExtResource( 1 ) 11 | __meta__ = { 12 | "_edit_use_anchors_": false 13 | } 14 | -------------------------------------------------------------------------------- /source/UI/UIUpgradeShop/UIUpgradeShop.gd: -------------------------------------------------------------------------------- 1 | class_name UpgradeShop 2 | extends Control 3 | 4 | export var _upgrade_button_scene: PackedScene 5 | 6 | onready var _container := $Panel/VBoxContainer 7 | onready var _anim_player := $AnimationPlayer 8 | onready var _panel := $Panel 9 | 10 | var player: Player 11 | 12 | 13 | func appear() -> void: 14 | # Reset rotation to appear at tower's top portion 15 | rect_rotation = -90 16 | _panel.rect_rotation = 90 17 | 18 | # Rotate to always display the panel on screen. Fix cases where 19 | # players place towers near/at screen's edges 20 | if not get_viewport_rect().encloses(_panel.get_global_rect()): 21 | _fit_panel_in_view() 22 | _anim_player.play("Appear") 23 | 24 | 25 | func disappear() -> void: 26 | _anim_player.play("Disappear") 27 | 28 | 29 | func add_upgrade_button(upgrade: Upgrade) -> void: 30 | var button: UIUpgradeButton = _upgrade_button_scene.instance() 31 | button.connect("pressed", self, "_on_UIUpgradeButton_pressed", [button, upgrade]) 32 | button.update_display(upgrade, player.gold) 33 | 34 | _container.add_child(button) 35 | 36 | 37 | func _update(tower: Tower) -> void: 38 | rect_global_position = tower.global_position 39 | 40 | for child in _container.get_children(): 41 | child.queue_free() 42 | 43 | for upgrade in tower.get_upgrades(): 44 | add_upgrade_button(upgrade) 45 | 46 | 47 | # Uses rotation to ensure the interface is always in the view. 48 | func _fit_panel_in_view() -> void: 49 | var center := get_viewport_rect().size * 0.5 50 | var angle := center.angle_to_point(rect_global_position - rect_pivot_offset) 51 | # Snap angle to 45 degrees increment 52 | angle = round(angle / (PI / 4)) * (PI / 4) 53 | 54 | rect_rotation = rad2deg(angle) 55 | _panel.rect_rotation = - rect_rotation 56 | 57 | 58 | func _on_TowerPlacer_tower_placed(tower: Tower) -> void: 59 | tower.connect("selected", self, "_on_Tower_selected", [tower]) 60 | tower.connect("sold", self, "_on_Tower_sold") 61 | 62 | 63 | func _on_Tower_selected(selected: bool, tower: Tower) -> void: 64 | _update(tower) 65 | 66 | if selected: 67 | appear() 68 | else: 69 | disappear() 70 | 71 | 72 | func _on_Tower_sold(_price: int, place: Vector2) -> void: 73 | disappear() 74 | 75 | 76 | func _on_UIUpgradeButton_pressed(button: UIUpgradeButton, upgrade: Upgrade) -> void: 77 | if player.gold < upgrade.cost: 78 | return 79 | player.gold -= upgrade.cost 80 | upgrade.apply() 81 | button.update_display(upgrade, player.gold) 82 | -------------------------------------------------------------------------------- /source/UI/UIUpgradeShop/UIUpgradeShop.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://UI/UIUpgradeShop/UIUpgradeShop.gd" type="Script" id=1] 4 | [ext_resource path="res://UI/UIUpgradeShop/UIUpgradeButton.tscn" type="PackedScene" id=2] 5 | 6 | [sub_resource type="Animation" id=1] 7 | resource_name = "Appear" 8 | length = 0.3 9 | step = 0.05 10 | tracks/0/type = "value" 11 | tracks/0/path = NodePath("Panel:rect_scale") 12 | tracks/0/interp = 1 13 | tracks/0/loop_wrap = true 14 | tracks/0/imported = false 15 | tracks/0/enabled = true 16 | tracks/0/keys = { 17 | "times": PoolRealArray( 0, 0.15, 0.3 ), 18 | "transitions": PoolRealArray( 0.5, 0.5, 1 ), 19 | "update": 0, 20 | "values": [ Vector2( 1e-05, 1e-05 ), Vector2( 0.05, 1 ), Vector2( 1, 1 ) ] 21 | } 22 | 23 | [sub_resource type="Animation" id=2] 24 | resource_name = "Disappear" 25 | length = 0.3 26 | step = 0.05 27 | tracks/0/type = "value" 28 | tracks/0/path = NodePath("Panel:rect_scale") 29 | tracks/0/interp = 1 30 | tracks/0/loop_wrap = true 31 | tracks/0/imported = false 32 | tracks/0/enabled = true 33 | tracks/0/keys = { 34 | "times": PoolRealArray( 0, 0.15, 0.3 ), 35 | "transitions": PoolRealArray( 0.5, 0.5, 0.5 ), 36 | "update": 0, 37 | "values": [ Vector2( 1, 1 ), Vector2( 0.05, 1 ), Vector2( 1e-05, 1e-05 ) ] 38 | } 39 | 40 | [node name="UIUpgradeShop" type="Control"] 41 | rect_pivot_offset = Vector2( 32, 32 ) 42 | mouse_filter = 2 43 | script = ExtResource( 1 ) 44 | __meta__ = { 45 | "_edit_use_anchors_": false 46 | } 47 | _upgrade_button_scene = ExtResource( 2 ) 48 | 49 | [node name="Panel" type="Panel" parent="."] 50 | margin_left = -96.0 51 | margin_top = -350.0 52 | margin_right = 160.0 53 | margin_bottom = -30.0 54 | rect_pivot_offset = Vector2( 128, 160 ) 55 | __meta__ = { 56 | "_edit_use_anchors_": false 57 | } 58 | 59 | [node name="Label" type="Label" parent="Panel"] 60 | anchor_right = 1.0 61 | margin_left = 16.0 62 | margin_top = 16.0 63 | margin_right = -16.0 64 | margin_bottom = 64.0 65 | text = "Upgrades" 66 | align = 1 67 | valign = 1 68 | __meta__ = { 69 | "_edit_use_anchors_": false 70 | } 71 | 72 | [node name="HSeparator" type="HSeparator" parent="Panel"] 73 | anchor_left = 0.5 74 | anchor_right = 0.5 75 | margin_left = -96.0 76 | margin_top = 64.0 77 | margin_right = 96.0 78 | margin_bottom = 72.0 79 | __meta__ = { 80 | "_edit_use_anchors_": false 81 | } 82 | 83 | [node name="VBoxContainer" type="VBoxContainer" parent="Panel"] 84 | anchor_top = 1.0 85 | anchor_right = 1.0 86 | anchor_bottom = 1.0 87 | margin_left = 16.0 88 | margin_top = -240.0 89 | margin_right = -16.0 90 | margin_bottom = -16.0 91 | size_flags_horizontal = 3 92 | size_flags_vertical = 3 93 | __meta__ = { 94 | "_edit_use_anchors_": false 95 | } 96 | 97 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 98 | anims/Appear = SubResource( 1 ) 99 | anims/Disappear = SubResource( 2 ) 100 | -------------------------------------------------------------------------------- /source/VFX/Explosions/SmallExplosion.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://VFX/Explosions/white_glowing_circle.png" type="Texture" id=1] 4 | 5 | [sub_resource type="Gradient" id=1] 6 | offsets = PoolRealArray( 0.788043, 1 ) 7 | colors = PoolColorArray( 1, 1, 1, 1, 1, 1, 1, 0 ) 8 | 9 | [sub_resource type="GradientTexture" id=2] 10 | gradient = SubResource( 1 ) 11 | 12 | [sub_resource type="Curve" id=3] 13 | _data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 1, 0.954545 ), 0.0, 0.0, 0, 0 ] 14 | 15 | [sub_resource type="CurveTexture" id=4] 16 | curve = SubResource( 3 ) 17 | 18 | [sub_resource type="ParticlesMaterial" id=5] 19 | emission_shape = 1 20 | emission_sphere_radius = 20.0 21 | flag_disable_z = true 22 | spread = 180.0 23 | gravity = Vector3( 0, 0, 0 ) 24 | initial_velocity = 800.0 25 | orbit_velocity = 0.0 26 | orbit_velocity_random = 0.0 27 | damping = 2000.0 28 | scale = 0.5 29 | scale_random = 0.3 30 | scale_curve = SubResource( 4 ) 31 | color_ramp = SubResource( 2 ) 32 | 33 | [node name="SmallExplosion" type="Particles2D"] 34 | modulate = Color( 1.5, 1.5, 1.5, 1 ) 35 | self_modulate = Color( 0.34902, 0.67451, 1, 1 ) 36 | emitting = false 37 | amount = 16 38 | lifetime = 0.1 39 | explosiveness = 0.9 40 | local_coords = false 41 | process_material = SubResource( 5 ) 42 | texture = ExtResource( 1 ) 43 | -------------------------------------------------------------------------------- /source/VFX/Explosions/explosion_gradient.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="GradientTexture" load_steps=2 format=2] 2 | 3 | [sub_resource type="Gradient" id=1] 4 | offsets = PoolRealArray( 0, 0.185185, 0.533333, 0.82963, 1 ) 5 | colors = PoolColorArray( 1, 1, 1, 1, 1, 0.788235, 0.309804, 1, 0.980392, 0.419608, 0.211765, 1, 0.831373, 0.219608, 0.219608, 1, 0.831373, 0.219608, 0.219608, 0 ) 6 | 7 | [resource] 8 | gradient = SubResource( 1 ) 9 | -------------------------------------------------------------------------------- /source/VFX/Explosions/puff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/VFX/Explosions/puff.png -------------------------------------------------------------------------------- /source/VFX/Explosions/puff.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/puff.png-a97a2dbe05e458d4ca98d34a9d7f4da4.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosions/puff.png" 13 | dest_files=[ "res://.import/puff.png-a97a2dbe05e458d4ca98d34a9d7f4da4.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/VFX/Explosions/puff_smooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/VFX/Explosions/puff_smooth.png -------------------------------------------------------------------------------- /source/VFX/Explosions/puff_smooth.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/puff_smooth.png-3930a30f50be4c9c75043e5a80de9680.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosions/puff_smooth.png" 13 | dest_files=[ "res://.import/puff_smooth.png-3930a30f50be4c9c75043e5a80de9680.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/VFX/Explosions/scraps_gradient.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="GradientTexture" load_steps=2 format=2] 2 | 3 | [sub_resource type="Gradient" id=1] 4 | offsets = PoolRealArray( 0, 0.155894, 0.505017, 0.8327, 1 ) 5 | colors = PoolColorArray( 0.258824, 0.25098, 0.25098, 1, 0.722656, 0.118153, 0.118153, 1, 0.855469, 0.323879, 0.126857, 1, 1, 0.788235, 0.309804, 0.717647, 1, 1, 1, 0 ) 6 | 7 | [resource] 8 | gradient = SubResource( 1 ) 9 | -------------------------------------------------------------------------------- /source/VFX/Explosions/sparkle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/VFX/Explosions/sparkle.png -------------------------------------------------------------------------------- /source/VFX/Explosions/sparkle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sparkle.png-9b6c5a08d7289a4e0580cfb7b180137f.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosions/sparkle.png" 13 | dest_files=[ "res://.import/sparkle.png-9b6c5a08d7289a4e0580cfb7b180137f.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/VFX/Explosions/white_glowing_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/VFX/Explosions/white_glowing_circle.png -------------------------------------------------------------------------------- /source/VFX/Explosions/white_glowing_circle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/white_glowing_circle.png-18c903a04f43dc51f1b475c2128e7106.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosions/white_glowing_circle.png" 13 | dest_files=[ "res://.import/white_glowing_circle.png-18c903a04f43dc51f1b475c2128e7106.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/VFX/PathPreview.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [sub_resource type="GDScript" id=1] 4 | script/source = "extends Line2D 5 | 6 | 7 | onready var _tween := $Tween 8 | onready var _timer := $Timer 9 | 10 | func fade_out() -> void: 11 | var transparent := modulate 12 | transparent.a = 0.0 13 | _tween.interpolate_property(self, \"modulate\", modulate, transparent, 0.5) 14 | _tween.start() 15 | _timer.start(0.5 / (get_point_count() -1)) 16 | 17 | 18 | func fade_in() -> void: 19 | var opaque := modulate 20 | opaque.a = 1.0 21 | _tween.interpolate_property(self, \"modulate\", modulate, opaque, 0.5) 22 | _tween.start() 23 | 24 | 25 | func _on_Timer_timeout() -> void: 26 | if get_point_count() > 0: 27 | remove_point(get_point_count() -1) 28 | else: 29 | _timer.stop() 30 | " 31 | 32 | [sub_resource type="Animation" id=2] 33 | resource_name = "glow" 34 | loop = true 35 | step = 0.05 36 | tracks/0/type = "value" 37 | tracks/0/path = NodePath(".:modulate") 38 | tracks/0/interp = 1 39 | tracks/0/loop_wrap = true 40 | tracks/0/imported = false 41 | tracks/0/enabled = true 42 | tracks/0/keys = { 43 | "times": PoolRealArray( 0, 0.5 ), 44 | "transitions": PoolRealArray( 1, 1 ), 45 | "update": 0, 46 | "values": [ Color( 1, 1, 1, 1 ), Color( 1, 0.72549, 0.72549, 1 ) ] 47 | } 48 | 49 | [node name="PathPreview" type="Line2D"] 50 | width = 20.0 51 | default_color = Color( 1, 0.415686, 0.160784, 1 ) 52 | joint_mode = 2 53 | script = SubResource( 1 ) 54 | 55 | [node name="Tween" type="Tween" parent="."] 56 | 57 | [node name="Timer" type="Timer" parent="."] 58 | 59 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 60 | autoplay = "glow" 61 | anims/glow = SubResource( 2 ) 62 | 63 | [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] 64 | -------------------------------------------------------------------------------- /source/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /source/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/source/icon.png -------------------------------------------------------------------------------- /source/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /source/sprite-sheet.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sprite-sheet.svg-770a08d3ddf9b41899e4553fd12331ab.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprite-sheet.svg" 13 | dest_files=[ "res://.import/sprite-sheet.svg-770a08d3ddf9b41899e4553fd12331ab.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/Actors/Enemies/particle.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /start-project/Actors/Enemies/particle.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/particle.svg-6a2c10808518a648f8e5ec8f4688e443.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Actors/Enemies/particle.svg" 13 | dest_files=[ "res://.import/particle.svg-6a2c10808518a648f8e5ec8f4688e443.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/Areas/AsteroidSurface/rocks-and-craters.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/rocks-and-craters.svg-d039ad5957be00f78334d088af06d900.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Areas/AsteroidSurface/rocks-and-craters.svg" 13 | dest_files=[ "res://.import/rocks-and-craters.svg-d039ad5957be00f78334d088af06d900.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/Areas/AsteroidSurface/sand.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sand.svg-8176aa2958b49ade8514e76ba5a92581.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Areas/AsteroidSurface/sand.svg" 13 | dest_files=[ "res://.import/sand.svg-8176aa2958b49ade8514e76ba5a92581.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/Areas/AsteroidSurface/tileset.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="TileSet" load_steps=4 format=2] 2 | 3 | [ext_resource path="res://Areas/AsteroidSurface/rocks-and-craters.svg" type="Texture" id=2] 4 | [ext_resource path="res://Areas/AsteroidSurface/walkable-path.svg" type="Texture" id=3] 5 | [ext_resource path="res://Areas/AsteroidSurface/sand.svg" type="Texture" id=4] 6 | 7 | [resource] 8 | 1/name = "Non Placeable Cells" 9 | 1/texture = ExtResource( 2 ) 10 | 1/tex_offset = Vector2( 0, 0 ) 11 | 1/modulate = Color( 1, 1, 1, 1 ) 12 | 1/region = Rect2( 0, 0, 192, 192 ) 13 | 1/tile_mode = 2 14 | 1/autotile/icon_coordinate = Vector2( 1, 1 ) 15 | 1/autotile/tile_size = Vector2( 64, 64 ) 16 | 1/autotile/spacing = 0 17 | 1/autotile/occluder_map = [ ] 18 | 1/autotile/navpoly_map = [ ] 19 | 1/autotile/priority_map = [ ] 20 | 1/autotile/z_index_map = [ ] 21 | 1/occluder_offset = Vector2( 0, 0 ) 22 | 1/navigation_offset = Vector2( 0, 0 ) 23 | 1/shape_offset = Vector2( 0, 0 ) 24 | 1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 25 | 1/shape_one_way = false 26 | 1/shape_one_way_margin = 0.0 27 | 1/shapes = [ ] 28 | 1/z_index = 0 29 | 2/name = "Enemy Walking Path" 30 | 2/texture = ExtResource( 3 ) 31 | 2/tex_offset = Vector2( 0, 0 ) 32 | 2/modulate = Color( 1, 1, 1, 1 ) 33 | 2/region = Rect2( 0, 0, 384, 384 ) 34 | 2/tile_mode = 1 35 | 2/autotile/bitmask_mode = 1 36 | 2/autotile/bitmask_flags = [ Vector2( 0, 1 ), 48, Vector2( 0, 2 ), 56, Vector2( 0, 3 ), 432, Vector2( 0, 4 ), 438, Vector2( 0, 5 ), 54, Vector2( 1, 0 ), 144, Vector2( 1, 1 ), 186, Vector2( 1, 2 ), 18, Vector2( 1, 3 ), 504, Vector2( 1, 4 ), 511, Vector2( 1, 5 ), 63, Vector2( 2, 1 ), 24, Vector2( 2, 2 ), 146, Vector2( 2, 3 ), 216, Vector2( 2, 4 ), 219, Vector2( 2, 5 ), 27, Vector2( 3, 0 ), 176, Vector2( 3, 1 ), 50, Vector2( 3, 2 ), 184, Vector2( 3, 3 ), 178, Vector2( 3, 4 ), 16, Vector2( 4, 0 ), 152, Vector2( 4, 1 ), 26, Vector2( 4, 2 ), 58, Vector2( 4, 3 ), 154 ] 37 | 2/autotile/icon_coordinate = Vector2( 3, 4 ) 38 | 2/autotile/tile_size = Vector2( 64, 64 ) 39 | 2/autotile/spacing = 0 40 | 2/autotile/occluder_map = [ ] 41 | 2/autotile/navpoly_map = [ ] 42 | 2/autotile/priority_map = [ ] 43 | 2/autotile/z_index_map = [ ] 44 | 2/occluder_offset = Vector2( 0, 0 ) 45 | 2/navigation_offset = Vector2( 0, 0 ) 46 | 2/shape_offset = Vector2( 0, 0 ) 47 | 2/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 48 | 2/shape_one_way = false 49 | 2/shape_one_way_margin = 0.0 50 | 2/shapes = [ ] 51 | 2/z_index = 0 52 | 3/name = "Tower Placeable Cell" 53 | 3/texture = ExtResource( 4 ) 54 | 3/tex_offset = Vector2( 0, 0 ) 55 | 3/modulate = Color( 1, 1, 1, 1 ) 56 | 3/region = Rect2( 0, 0, 64, 64 ) 57 | 3/tile_mode = 0 58 | 3/occluder_offset = Vector2( 0, 0 ) 59 | 3/navigation_offset = Vector2( 0, 0 ) 60 | 3/shape_offset = Vector2( 0, 0 ) 61 | 3/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 62 | 3/shape_one_way = false 63 | 3/shape_one_way_margin = 0.0 64 | 3/shapes = [ ] 65 | 3/z_index = 0 66 | -------------------------------------------------------------------------------- /start-project/Areas/AsteroidSurface/walkable-path.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/walkable-path.svg-ecaa9a460c48ad8740e02db5f09971a1.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Areas/AsteroidSurface/walkable-path.svg" 13 | dest_files=[ "res://.import/walkable-path.svg-ecaa9a460c48ad8740e02db5f09971a1.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/Objects/PlayerBase/CutoutSprites.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | 4 | onready var _anim_player := $AnimationPlayer 5 | 6 | func play(animation: String) -> void: 7 | _anim_player.play(animation) 8 | -------------------------------------------------------------------------------- /start-project/Objects/Weapon2D/RangePreview/RangePreview.gd: -------------------------------------------------------------------------------- 1 | extends Sprite 2 | 3 | export var radius := 100.0 4 | export var tween_duration := 0.5 5 | 6 | onready var _tween := $Tween 7 | 8 | 9 | func appear() -> void: 10 | var ratio = radius / texture.get_width() 11 | var final_scale = Vector2(ratio, ratio) * 2.0 12 | 13 | _tween.stop_all() 14 | 15 | _tween.interpolate_property( 16 | self, "scale", scale, final_scale, tween_duration, Tween.TRANS_QUINT, Tween.EASE_OUT 17 | ) 18 | _tween.interpolate_property( 19 | self, "modulate", modulate, Color(1, 1, 1, 1), tween_duration) 20 | _tween.start() 21 | 22 | 23 | func disappear() -> void: 24 | if _tween.is_active(): 25 | _tween.stop_all() 26 | 27 | _tween.interpolate_property( 28 | self, "scale", scale, Vector2.ZERO, tween_duration, Tween.TRANS_BACK, Tween.EASE_IN 29 | ) 30 | _tween.interpolate_property( 31 | self, "modulate", modulate, Color(1, 1, 1, 0), tween_duration * 2.0) 32 | _tween.start() 33 | -------------------------------------------------------------------------------- /start-project/Objects/Weapon2D/RangePreview/RangePreview.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://Objects/Weapon2D/RangePreview/range-preview.svg" type="Texture" id=1] 4 | [ext_resource path="res://Objects/Weapon2D/RangePreview/RangePreview.gd" type="Script" id=2] 5 | 6 | [node name="RangePreview" type="Sprite"] 7 | modulate = Color( 1, 1, 1, 0 ) 8 | texture = ExtResource( 1 ) 9 | script = ExtResource( 2 ) 10 | radius = 50.0 11 | 12 | [node name="Tween" type="Tween" parent="."] 13 | -------------------------------------------------------------------------------- /start-project/Objects/Weapon2D/RangePreview/range-preview.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 57 | 61 | 67 | 73 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /start-project/Objects/Weapon2D/RangePreview/range-preview.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/range-preview.svg-3ddcdc213d26cf3b747e41044dcee9ea.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://Objects/Weapon2D/RangePreview/range-preview.svg" 13 | dest_files=[ "res://.import/range-preview.svg-3ddcdc213d26cf3b747e41044dcee9ea.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=4.0 35 | -------------------------------------------------------------------------------- /start-project/Screens/EndScreen.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | export var player_score := 0 4 | 5 | onready var _label := $Panel/Label 6 | 7 | func _ready() -> void: 8 | _label.text = _label.text % player_score 9 | -------------------------------------------------------------------------------- /start-project/Screens/EndScreen.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/Montserrat-ExtraBold.ttf" type="DynamicFontData" id=1] 4 | [ext_resource path="res://Screens/EndScreen.gd" type="Script" id=2] 5 | 6 | [sub_resource type="DynamicFont" id=1] 7 | size = 32 8 | font_data = ExtResource( 1 ) 9 | 10 | [sub_resource type="Animation" id=2] 11 | resource_name = "Text" 12 | length = 2.5 13 | tracks/0/type = "value" 14 | tracks/0/path = NodePath("Panel:rect_scale") 15 | tracks/0/interp = 1 16 | tracks/0/loop_wrap = true 17 | tracks/0/imported = false 18 | tracks/0/enabled = true 19 | tracks/0/keys = { 20 | "times": PoolRealArray( 0, 0.2, 0.3 ), 21 | "transitions": PoolRealArray( 1, 0.5, 1 ), 22 | "update": 0, 23 | "values": [ Vector2( 0, 0 ), Vector2( 1.2, 1.2 ), Vector2( 1, 1 ) ] 24 | } 25 | tracks/1/type = "value" 26 | tracks/1/path = NodePath("Panel/Label:percent_visible") 27 | tracks/1/interp = 1 28 | tracks/1/loop_wrap = true 29 | tracks/1/imported = false 30 | tracks/1/enabled = true 31 | tracks/1/keys = { 32 | "times": PoolRealArray( 0, 0.4, 1.4, 2.5 ), 33 | "transitions": PoolRealArray( 1, 1, 1, 1 ), 34 | "update": 0, 35 | "values": [ 0.0, 0.0, 0.909091, 1.0 ] 36 | } 37 | 38 | [node name="EndScreen" type="Control"] 39 | anchor_right = 1.0 40 | anchor_bottom = 1.0 41 | script = ExtResource( 2 ) 42 | __meta__ = { 43 | "_edit_use_anchors_": false 44 | } 45 | 46 | [node name="Panel" type="Panel" parent="."] 47 | anchor_left = 0.5 48 | anchor_top = 0.5 49 | anchor_right = 0.5 50 | anchor_bottom = 0.5 51 | margin_left = -618.0 52 | margin_top = -120.0 53 | margin_right = 618.0 54 | margin_bottom = 120.0 55 | rect_scale = Vector2( 1e-05, 1e-05 ) 56 | rect_pivot_offset = Vector2( 618, 124 ) 57 | __meta__ = { 58 | "_edit_use_anchors_": false 59 | } 60 | 61 | [node name="Label" type="Label" parent="Panel"] 62 | anchor_right = 1.0 63 | anchor_bottom = 1.0 64 | custom_fonts/font = SubResource( 1 ) 65 | text = "Congratulations! We vanquished the Aster-570! 66 | As a good strategist you spent just the resources you need. 67 | 68 | Score: %s" 69 | align = 1 70 | valign = 1 71 | percent_visible = 0.0 72 | __meta__ = { 73 | "_edit_use_anchors_": false 74 | } 75 | 76 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 77 | autoplay = "Text" 78 | anims/Text = SubResource( 2 ) 79 | -------------------------------------------------------------------------------- /start-project/UI/Theme/Montserrat-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/UI/Theme/Montserrat-ExtraBold.ttf -------------------------------------------------------------------------------- /start-project/UI/Theme/background_stylebox.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=2] 2 | 3 | [resource] 4 | bg_color = Color( 0.278431, 0.231373, 0.470588, 1 ) 5 | border_width_left = 2 6 | border_width_top = 2 7 | border_width_right = 2 8 | border_width_bottom = 2 9 | border_color = Color( 1, 1, 1, 1 ) 10 | corner_radius_top_left = 8 11 | corner_radius_top_right = 8 12 | corner_radius_bottom_right = 8 13 | corner_radius_bottom_left = 8 14 | -------------------------------------------------------------------------------- /start-project/UI/Theme/button_font.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/Montserrat-ExtraBold.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 14 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /start-project/UI/Theme/foreground_stylebox.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StyleBoxFlat" format=2] 2 | 3 | [resource] 4 | bg_color = Color( 0.235294, 0.639216, 0.439216, 1 ) 5 | border_width_left = 2 6 | border_width_top = 2 7 | border_width_right = 2 8 | border_width_bottom = 2 9 | border_color = Color( 1, 1, 1, 1 ) 10 | corner_radius_top_left = 8 11 | corner_radius_top_right = 8 12 | corner_radius_bottom_right = 8 13 | corner_radius_bottom_left = 8 14 | -------------------------------------------------------------------------------- /start-project/UI/Theme/main_font.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="DynamicFont" load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/Montserrat-ExtraBold.ttf" type="DynamicFontData" id=1] 4 | 5 | [resource] 6 | size = 20 7 | font_data = ExtResource( 1 ) 8 | -------------------------------------------------------------------------------- /start-project/UI/Theme/main_theme.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Theme" load_steps=10 format=2] 2 | 3 | [ext_resource path="res://UI/Theme/main_font.tres" type="DynamicFont" id=1] 4 | [ext_resource path="res://UI/Theme/button_font.tres" type="DynamicFont" id=2] 5 | 6 | [sub_resource type="StyleBoxFlat" id=1] 7 | bg_color = Color( 0.364706, 0.341176, 0.470588, 0.705882 ) 8 | border_width_left = 4 9 | border_width_top = 4 10 | border_width_right = 4 11 | border_width_bottom = 4 12 | 13 | [sub_resource type="StyleBoxFlat" id=2] 14 | bg_color = Color( 0.278431, 0.231373, 0.470588, 0.705882 ) 15 | border_width_left = 4 16 | border_width_top = 4 17 | border_width_right = 4 18 | border_width_bottom = 4 19 | border_color = Color( 1, 1, 1, 0.705882 ) 20 | 21 | [sub_resource type="StyleBoxFlat" id=3] 22 | bg_color = Color( 0.37888, 0.3136, 0.64, 0.705882 ) 23 | border_width_left = 4 24 | border_width_top = 4 25 | border_width_right = 4 26 | border_width_bottom = 4 27 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 28 | 29 | [sub_resource type="StyleBoxFlat" id=4] 30 | bg_color = Color( 0.278431, 0.231373, 0.470588, 0.705882 ) 31 | border_width_left = 4 32 | border_width_top = 4 33 | border_width_right = 4 34 | border_width_bottom = 4 35 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 36 | 37 | [sub_resource type="StyleBoxFlat" id=5] 38 | bg_color = Color( 0.18944, 0.1568, 0.32, 0.486275 ) 39 | border_width_left = 4 40 | border_width_top = 4 41 | border_width_right = 4 42 | border_width_bottom = 4 43 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 44 | 45 | [sub_resource type="StyleBoxLine" id=6] 46 | color = Color( 1, 1, 1, 1 ) 47 | thickness = 2 48 | 49 | [sub_resource type="StyleBoxFlat" id=7] 50 | bg_color = Color( 0.278431, 0.231373, 0.470588, 0.705882 ) 51 | border_width_left = 4 52 | border_width_top = 4 53 | border_width_right = 4 54 | border_width_bottom = 4 55 | border_color = Color( 0.301961, 0.65098, 1, 0.705882 ) 56 | corner_radius_top_left = 8 57 | corner_radius_top_right = 8 58 | corner_radius_bottom_right = 8 59 | corner_radius_bottom_left = 8 60 | 61 | [resource] 62 | default_font = ExtResource( 1 ) 63 | Button/colors/font_color = Color( 1, 1, 1, 1 ) 64 | Button/colors/font_color_disabled = Color( 0.607843, 0.607843, 0.607843, 1 ) 65 | Button/colors/font_color_hover = Color( 1, 1, 1, 1 ) 66 | Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) 67 | Button/constants/hseparation = 2 68 | Button/fonts/font = ExtResource( 2 ) 69 | Button/styles/disabled = SubResource( 1 ) 70 | Button/styles/focus = SubResource( 2 ) 71 | Button/styles/hover = SubResource( 3 ) 72 | Button/styles/normal = SubResource( 4 ) 73 | Button/styles/pressed = SubResource( 5 ) 74 | HSeparator/constants/separation = 4 75 | HSeparator/styles/separator = SubResource( 6 ) 76 | OptionButton/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) 77 | OptionButton/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) 78 | OptionButton/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) 79 | OptionButton/colors/font_color_pressed = Color( 1, 1, 1, 1 ) 80 | OptionButton/constants/arrow_margin = 2 81 | OptionButton/constants/hseparation = 2 82 | OptionButton/fonts/font = null 83 | OptionButton/icons/arrow = null 84 | OptionButton/styles/disabled = null 85 | OptionButton/styles/focus = null 86 | OptionButton/styles/hover = null 87 | OptionButton/styles/normal = null 88 | OptionButton/styles/pressed = null 89 | Panel/styles/panel = SubResource( 7 ) 90 | PanelContainer/styles/panel = SubResource( 7 ) 91 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/UICooldownBar.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | export var gradient: Gradient 5 | 6 | onready var _progress := $TextureProgress 7 | onready var _animator := $AnimationPlayer 8 | onready var _timer := $Timer 9 | 10 | 11 | func _ready() -> void: 12 | set_process(false) 13 | hide() 14 | 15 | 16 | func _process(delta: float) -> void: 17 | _progress.value = _timer.wait_time - _timer.time_left 18 | _progress.tint_progress = gradient.interpolate(_progress.ratio) 19 | 20 | 21 | func start(time: float) -> void: 22 | _timer.start(time) 23 | _progress.max_value = time 24 | _progress.value = 0.0 25 | _animator.playback_speed = 1.0/time 26 | _animator.play("Spin") 27 | set_process(true) 28 | show() 29 | 30 | 31 | func _on_Timer_timeout(): 32 | _animator.play("Finish") 33 | set_process(false) 34 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/UICooldownBar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=10 format=2] 2 | 3 | [ext_resource path="res://UI/UICooldownBar/cooldown-bar-progress.png" type="Texture" id=1] 4 | [ext_resource path="res://UI/UICooldownBar/cooldown-bar-over.png" type="Texture" id=2] 5 | [ext_resource path="res://UI/UICooldownBar/clock.png" type="Texture" id=3] 6 | [ext_resource path="res://UI/UICooldownBar/clock-tic.png" type="Texture" id=4] 7 | [ext_resource path="res://UI/UICooldownBar/cooldown-bar-under.png" type="Texture" id=5] 8 | [ext_resource path="res://UI/UICooldownBar/UICooldownBar.gd" type="Script" id=6] 9 | 10 | [sub_resource type="Gradient" id=1] 11 | offsets = PoolRealArray( 0.254682, 0.520599, 0.846442, 1 ) 12 | colors = PoolColorArray( 0.921569, 0.337255, 0.294118, 1, 1, 0.568627, 0.4, 1, 1, 0.709804, 0.439216, 1, 1, 1, 1, 1 ) 13 | 14 | [sub_resource type="Animation" id=2] 15 | resource_name = "Finish" 16 | length = 0.2 17 | tracks/0/type = "value" 18 | tracks/0/path = NodePath(".:visible") 19 | tracks/0/interp = 1 20 | tracks/0/loop_wrap = true 21 | tracks/0/imported = false 22 | tracks/0/enabled = true 23 | tracks/0/keys = { 24 | "times": PoolRealArray( 0.2 ), 25 | "transitions": PoolRealArray( 1 ), 26 | "update": 1, 27 | "values": [ false ] 28 | } 29 | 30 | [sub_resource type="Animation" id=3] 31 | tracks/0/type = "value" 32 | tracks/0/path = NodePath("Clock/Tic:rect_rotation") 33 | tracks/0/interp = 1 34 | tracks/0/loop_wrap = true 35 | tracks/0/imported = false 36 | tracks/0/enabled = true 37 | tracks/0/keys = { 38 | "times": PoolRealArray( 0, 1 ), 39 | "transitions": PoolRealArray( 1, 1 ), 40 | "update": 0, 41 | "values": [ 0.0, 360.0 ] 42 | } 43 | 44 | [node name="UICooldownBar" type="Control"] 45 | visible = false 46 | margin_right = 144.0 47 | margin_bottom = 24.0 48 | script = ExtResource( 6 ) 49 | __meta__ = { 50 | "_edit_use_anchors_": false 51 | } 52 | gradient = SubResource( 1 ) 53 | 54 | [node name="TextureProgress" type="TextureProgress" parent="."] 55 | anchor_left = 0.222 56 | anchor_right = 1.0 57 | anchor_bottom = 1.0 58 | margin_left = 0.0319977 59 | step = 0.01 60 | texture_under = ExtResource( 5 ) 61 | texture_over = ExtResource( 2 ) 62 | texture_progress = ExtResource( 1 ) 63 | __meta__ = { 64 | "_edit_use_anchors_": false 65 | } 66 | 67 | [node name="Clock" type="TextureRect" parent="."] 68 | anchor_right = 0.167 69 | anchor_bottom = 1.0 70 | margin_right = -0.0480022 71 | texture = ExtResource( 3 ) 72 | expand = true 73 | stretch_mode = 6 74 | __meta__ = { 75 | "_edit_use_anchors_": false 76 | } 77 | 78 | [node name="Tic" type="TextureRect" parent="Clock"] 79 | anchor_left = 0.5 80 | anchor_top = 0.5 81 | anchor_right = 0.5 82 | anchor_bottom = 0.5 83 | margin_left = -2.0 84 | margin_top = -8.0 85 | margin_right = 2.0 86 | rect_rotation = 252.0 87 | rect_pivot_offset = Vector2( 2, 8 ) 88 | texture = ExtResource( 4 ) 89 | expand = true 90 | stretch_mode = 1 91 | __meta__ = { 92 | "_edit_use_anchors_": false 93 | } 94 | 95 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 96 | anims/Finish = SubResource( 2 ) 97 | anims/Spin = SubResource( 3 ) 98 | 99 | [node name="Timer" type="Timer" parent="."] 100 | 101 | [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] 102 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/clock-tic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/UI/UICooldownBar/clock-tic.png -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/clock-tic.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/clock-tic.png-fcf004a0cb21e95bfb83688239d9146c.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/clock-tic.png" 13 | dest_files=[ "res://.import/clock-tic.png-fcf004a0cb21e95bfb83688239d9146c.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/UI/UICooldownBar/clock.png -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/clock.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/clock.png-e646f709d1c473b8f555faca30d0b0fd.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/clock.png" 13 | dest_files=[ "res://.import/clock.png-e646f709d1c473b8f555faca30d0b0fd.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/cooldown-bar-over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/UI/UICooldownBar/cooldown-bar-over.png -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/cooldown-bar-over.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cooldown-bar-over.png-139f0f8a8e088eb12a232c8fecc07bf6.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/cooldown-bar-over.png" 13 | dest_files=[ "res://.import/cooldown-bar-over.png-139f0f8a8e088eb12a232c8fecc07bf6.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/cooldown-bar-progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/UI/UICooldownBar/cooldown-bar-progress.png -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/cooldown-bar-progress.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cooldown-bar-progress.png-4efbbd0ea1e29dd11c8ddd7112fcbf44.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/cooldown-bar-progress.png" 13 | dest_files=[ "res://.import/cooldown-bar-progress.png-4efbbd0ea1e29dd11c8ddd7112fcbf44.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/cooldown-bar-under.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/UI/UICooldownBar/cooldown-bar-under.png -------------------------------------------------------------------------------- /start-project/UI/UICooldownBar/cooldown-bar-under.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/cooldown-bar-under.png-9693085f3ebee638ce0f793ec3efc232.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UICooldownBar/cooldown-bar-under.png" 13 | dest_files=[ "res://.import/cooldown-bar-under.png-9693085f3ebee638ce0f793ec3efc232.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UIGoldPanel/UIGoldPanel.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | onready var _label: Label = $Label 5 | 6 | var player: Player setget set_player 7 | 8 | func set_player(new_player: Player) -> void: 9 | player = new_player 10 | player.connect("gold_changed", self, "_update_gold_amount") 11 | _update_gold_amount(player.gold) 12 | 13 | 14 | func _update_gold_amount(new_amount: int) -> void: 15 | _label.text = "Gold: %s" % new_amount 16 | -------------------------------------------------------------------------------- /start-project/UI/UIGoldPanel/UIGoldPanel.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://UI/UIGoldPanel/UIGoldPanel.gd" type="Script" id=1] 4 | 5 | [node name="UIGoldPanel" type="Panel"] 6 | margin_right = 224.0 7 | margin_bottom = 64.0 8 | mouse_filter = 2 9 | script = ExtResource( 1 ) 10 | __meta__ = { 11 | "_edit_use_anchors_": false 12 | } 13 | 14 | [node name="Label" type="Label" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | margin_left = 22.0 18 | margin_right = -22.0 19 | size_flags_horizontal = 3 20 | size_flags_vertical = 6 21 | text = "Gold: 1000" 22 | align = 1 23 | valign = 1 24 | __meta__ = { 25 | "_edit_use_anchors_": false 26 | } 27 | -------------------------------------------------------------------------------- /start-project/UI/UIHealthBar/UIHealthBar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://UI/UIHealthBar/heart.svg" type="Texture" id=1] 4 | 5 | [sub_resource type="StyleBoxFlat" id=1] 6 | bg_color = Color( 0.235294, 0.639216, 0.439216, 1 ) 7 | border_width_left = 2 8 | border_width_top = 2 9 | border_width_right = 2 10 | border_width_bottom = 2 11 | border_color = Color( 1, 1, 1, 1 ) 12 | corner_radius_top_left = 8 13 | corner_radius_top_right = 8 14 | corner_radius_bottom_right = 8 15 | corner_radius_bottom_left = 8 16 | 17 | [sub_resource type="StyleBoxFlat" id=2] 18 | bg_color = Color( 0.278431, 0.231373, 0.470588, 1 ) 19 | border_width_left = 2 20 | border_width_top = 2 21 | border_width_right = 2 22 | border_width_bottom = 2 23 | border_color = Color( 1, 1, 1, 1 ) 24 | corner_radius_top_left = 8 25 | corner_radius_top_right = 8 26 | corner_radius_bottom_right = 8 27 | corner_radius_bottom_left = 8 28 | 29 | [node name="HealthBar" type="ProgressBar"] 30 | margin_right = 172.0 31 | margin_bottom = 18.0 32 | custom_styles/fg = SubResource( 1 ) 33 | custom_styles/bg = SubResource( 2 ) 34 | step = 1.0 35 | value = 50.0 36 | percent_visible = false 37 | __meta__ = { 38 | "_edit_use_anchors_": false 39 | } 40 | 41 | [node name="TextureRect" type="TextureRect" parent="."] 42 | margin_left = -56.0 43 | margin_top = -14.0 44 | margin_right = -8.0 45 | margin_bottom = 34.0 46 | texture = ExtResource( 1 ) 47 | expand = true 48 | stretch_mode = 6 49 | __meta__ = { 50 | "_edit_use_anchors_": false 51 | } 52 | -------------------------------------------------------------------------------- /start-project/UI/UIHealthBar/UITimedHealthBar.gd: -------------------------------------------------------------------------------- 1 | extends ProgressBar 2 | 3 | onready var _timer := $Timer 4 | 5 | 6 | func _on_value_changed(value: float) -> void: 7 | show() 8 | _timer.start() 9 | 10 | 11 | func _on_Timer_timeout() -> void: 12 | hide() 13 | -------------------------------------------------------------------------------- /start-project/UI/UIHealthBar/UITimedHealthBar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://UI/UIHealthBar/heart.svg" type="Texture" id=1] 4 | [ext_resource path="res://UI/UIHealthBar/UITimedHealthBar.gd" type="Script" id=2] 5 | 6 | [sub_resource type="StyleBoxFlat" id=1] 7 | bg_color = Color( 0.235294, 0.639216, 0.439216, 1 ) 8 | border_width_left = 2 9 | border_width_top = 2 10 | border_width_right = 2 11 | border_width_bottom = 2 12 | border_color = Color( 1, 1, 1, 1 ) 13 | corner_radius_top_left = 8 14 | corner_radius_top_right = 8 15 | corner_radius_bottom_right = 8 16 | corner_radius_bottom_left = 8 17 | 18 | [sub_resource type="StyleBoxFlat" id=2] 19 | bg_color = Color( 0.278431, 0.231373, 0.470588, 1 ) 20 | border_width_left = 2 21 | border_width_top = 2 22 | border_width_right = 2 23 | border_width_bottom = 2 24 | border_color = Color( 1, 1, 1, 1 ) 25 | corner_radius_top_left = 8 26 | corner_radius_top_right = 8 27 | corner_radius_bottom_right = 8 28 | corner_radius_bottom_left = 8 29 | 30 | [node name="HealthBar" type="ProgressBar"] 31 | margin_right = 192.0 32 | margin_bottom = 18.0 33 | custom_styles/fg = SubResource( 1 ) 34 | custom_styles/bg = SubResource( 2 ) 35 | value = 50.0 36 | percent_visible = false 37 | script = ExtResource( 2 ) 38 | __meta__ = { 39 | "_edit_use_anchors_": false 40 | } 41 | 42 | [node name="TextureRect" type="TextureRect" parent="."] 43 | margin_left = -56.0 44 | margin_top = -14.0 45 | margin_right = -8.0 46 | margin_bottom = 34.0 47 | texture = ExtResource( 1 ) 48 | expand = true 49 | stretch_mode = 6 50 | __meta__ = { 51 | "_edit_use_anchors_": false 52 | } 53 | 54 | [node name="Timer" type="Timer" parent="."] 55 | wait_time = 0.5 56 | 57 | [connection signal="value_changed" from="." to="." method="_on_value_changed"] 58 | [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] 59 | -------------------------------------------------------------------------------- /start-project/UI/UIHealthBar/heart.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/heart.svg-49f6cf64586eb6a039065531a8f12ab4.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UIHealthBar/heart.svg" 13 | dest_files=[ "res://.import/heart.svg-49f6cf64586eb6a039065531a8f12ab4.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UIScreenOverlay/UIScreenOverlay.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | onready var _anim_player := $AnimationPlayer 4 | 5 | 6 | func play_win() -> void: 7 | _anim_player.play("PlayerWon") 8 | yield(_anim_player, "animation_finished") 9 | 10 | 11 | func play_lost() -> void: 12 | _anim_player.play("PlayerLost") 13 | yield(_anim_player, "animation_finished") 14 | 15 | 16 | func play_wave_start_async() -> void: 17 | _anim_player.play("WaveStarting") 18 | yield(_anim_player, "animation_finished") 19 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-disabled.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-disabled.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-disabled.svg-62c4df5afaef7403c38ea7613fee01a0.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-disabled.svg" 13 | dest_files=[ "res://.import/tower-icon-disabled.svg-62c4df5afaef7403c38ea7613fee01a0.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-focused.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-focused.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-focused.svg-e45f7d0f6fc6495dcb36beb0c612cd09.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-focused.svg" 13 | dest_files=[ "res://.import/tower-icon-focused.svg-e45f7d0f6fc6495dcb36beb0c612cd09.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 75 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-hover.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-hover.svg-e3374d23a1e60195dc22da7d76b6bd7c.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-hover.svg" 13 | dest_files=[ "res://.import/tower-icon-hover.svg-e3374d23a1e60195dc22da7d76b6bd7c.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-normal.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-normal.svg-54029b396714c9a0bc62fb03ce535dbe.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-normal.svg" 13 | dest_files=[ "res://.import/tower-icon-normal.svg-54029b396714c9a0bc62fb03ce535dbe.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UITowerShop/tower-icon-pressed.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tower-icon-pressed.svg-b6c90a05f9abb921648be57d23811288.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://UI/UITowerShop/tower-icon-pressed.svg" 13 | dest_files=[ "res://.import/tower-icon-pressed.svg-b6c90a05f9abb921648be57d23811288.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/UI/UIUnit/UIUnit.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | onready var _anim_player := $AnimationPlayer 5 | 6 | func appear() -> void: 7 | _anim_player.play("appear") 8 | 9 | 10 | func disappear() -> void: 11 | _anim_player.play("disappear") 12 | -------------------------------------------------------------------------------- /start-project/UI/UIUnit/UIUnit.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://UI/UIUnit/UIUnit.gd" type="Script" id=1] 4 | 5 | [sub_resource type="Animation" id=1] 6 | resource_name = "appear" 7 | length = 0.3 8 | tracks/0/type = "value" 9 | tracks/0/path = NodePath(".:rect_scale") 10 | tracks/0/interp = 1 11 | tracks/0/loop_wrap = true 12 | tracks/0/imported = false 13 | tracks/0/enabled = true 14 | tracks/0/keys = { 15 | "times": PoolRealArray( 0, 0.2, 0.3 ), 16 | "transitions": PoolRealArray( 0.5, 1, 1 ), 17 | "update": 0, 18 | "values": [ Vector2( 0, 0 ), Vector2( 1.2, 1.2 ), Vector2( 1, 1 ) ] 19 | } 20 | 21 | [sub_resource type="Animation" id=2] 22 | resource_name = "disappear" 23 | length = 0.3 24 | tracks/0/type = "value" 25 | tracks/0/path = NodePath(".:rect_scale") 26 | tracks/0/interp = 1 27 | tracks/0/loop_wrap = true 28 | tracks/0/imported = false 29 | tracks/0/enabled = true 30 | tracks/0/keys = { 31 | "times": PoolRealArray( 0, 0.1, 0.3 ), 32 | "transitions": PoolRealArray( 0.5, 0.5, 0.5 ), 33 | "update": 0, 34 | "values": [ Vector2( 1, 1 ), Vector2( 1.2, 1.2 ), Vector2( 0, 0 ) ] 35 | } 36 | 37 | [node name="Interface" type="Control"] 38 | mouse_filter = 2 39 | script = ExtResource( 1 ) 40 | __meta__ = { 41 | "_edit_use_anchors_": false 42 | } 43 | 44 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 45 | anims/appear = SubResource( 1 ) 46 | anims/disappear = SubResource( 2 ) 47 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/SmallExplosion.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://VFX/Explosion/white_glowing_circle.png" type="Texture" id=1] 4 | 5 | [sub_resource type="Gradient" id=1] 6 | offsets = PoolRealArray( 0.788043, 1 ) 7 | colors = PoolColorArray( 1, 1, 1, 1, 1, 1, 1, 0 ) 8 | 9 | [sub_resource type="GradientTexture" id=2] 10 | gradient = SubResource( 1 ) 11 | 12 | [sub_resource type="Curve" id=3] 13 | _data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 1, 0.954545 ), 0.0, 0.0, 0, 0 ] 14 | 15 | [sub_resource type="CurveTexture" id=4] 16 | curve = SubResource( 3 ) 17 | 18 | [sub_resource type="ParticlesMaterial" id=5] 19 | emission_shape = 1 20 | emission_sphere_radius = 20.0 21 | flag_disable_z = true 22 | spread = 180.0 23 | gravity = Vector3( 0, 0, 0 ) 24 | initial_velocity = 800.0 25 | orbit_velocity = 0.0 26 | orbit_velocity_random = 0.0 27 | damping = 2000.0 28 | scale = 0.5 29 | scale_random = 0.3 30 | scale_curve = SubResource( 4 ) 31 | color_ramp = SubResource( 2 ) 32 | 33 | [node name="SmallExplosion" type="Particles2D"] 34 | modulate = Color( 1.5, 1.5, 1.5, 1 ) 35 | self_modulate = Color( 0.34902, 0.67451, 1, 1 ) 36 | emitting = false 37 | amount = 16 38 | lifetime = 0.1 39 | explosiveness = 0.9 40 | local_coords = false 41 | process_material = SubResource( 5 ) 42 | texture = ExtResource( 1 ) 43 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/explosion_gradient.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="GradientTexture" load_steps=2 format=2] 2 | 3 | [sub_resource type="Gradient" id=1] 4 | offsets = PoolRealArray( 0, 0.185185, 0.533333, 0.82963, 1 ) 5 | colors = PoolColorArray( 1, 1, 1, 1, 1, 0.788235, 0.309804, 1, 0.980392, 0.419608, 0.211765, 1, 0.831373, 0.219608, 0.219608, 1, 0.831373, 0.219608, 0.219608, 0 ) 6 | 7 | [resource] 8 | gradient = SubResource( 1 ) 9 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/puff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/VFX/Explosion/puff.png -------------------------------------------------------------------------------- /start-project/VFX/Explosion/puff.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/puff.png-17343d3079ec2b5a1c4066139325ca90.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosion/puff.png" 13 | dest_files=[ "res://.import/puff.png-17343d3079ec2b5a1c4066139325ca90.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/puff_smooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/VFX/Explosion/puff_smooth.png -------------------------------------------------------------------------------- /start-project/VFX/Explosion/puff_smooth.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/puff_smooth.png-54099f8c14d24d7cf3bc581ad220923b.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosion/puff_smooth.png" 13 | dest_files=[ "res://.import/puff_smooth.png-54099f8c14d24d7cf3bc581ad220923b.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/scraps_gradient.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="GradientTexture" load_steps=2 format=2] 2 | 3 | [sub_resource type="Gradient" id=1] 4 | offsets = PoolRealArray( 0, 0.155894, 0.505017, 0.8327, 1 ) 5 | colors = PoolColorArray( 0.258824, 0.25098, 0.25098, 1, 0.722656, 0.118153, 0.118153, 1, 0.855469, 0.323879, 0.126857, 1, 1, 0.788235, 0.309804, 0.717647, 1, 1, 1, 0 ) 6 | 7 | [resource] 8 | gradient = SubResource( 1 ) 9 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/sparkle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/VFX/Explosion/sparkle.png -------------------------------------------------------------------------------- /start-project/VFX/Explosion/sparkle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sparkle.png-67cbc2cee3a6c5aeb5699820face8639.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosion/sparkle.png" 13 | dest_files=[ "res://.import/sparkle.png-67cbc2cee3a6c5aeb5699820face8639.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/VFX/Explosion/white_glowing_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/VFX/Explosion/white_glowing_circle.png -------------------------------------------------------------------------------- /start-project/VFX/Explosion/white_glowing_circle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/white_glowing_circle.png-ec45a8abc7514e57582731cd4b5ff0a7.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://VFX/Explosion/white_glowing_circle.png" 13 | dest_files=[ "res://.import/white_glowing_circle.png-ec45a8abc7514e57582731cd4b5ff0a7.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/VFX/PathPreview.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [sub_resource type="GDScript" id=1] 4 | script/source = "extends Line2D 5 | 6 | 7 | onready var _tween := $Tween 8 | onready var _timer := $Timer 9 | 10 | func fade_out() -> void: 11 | var transparent := modulate 12 | transparent.a = 0.0 13 | _tween.interpolate_property(self, \"modulate\", modulate, transparent, 0.5) 14 | _tween.start() 15 | _timer.start(0.5 / (get_point_count() -1)) 16 | 17 | 18 | func fade_in() -> void: 19 | var opaque := modulate 20 | opaque.a = 1.0 21 | _tween.interpolate_property(self, \"modulate\", modulate, opaque, 0.5) 22 | _tween.start() 23 | 24 | 25 | func _on_Timer_timeout() -> void: 26 | if get_point_count() > 0: 27 | remove_point(get_point_count() -1) 28 | else: 29 | _timer.stop() 30 | " 31 | 32 | [sub_resource type="Animation" id=5] 33 | resource_name = "glow" 34 | loop = true 35 | step = 0.05 36 | tracks/0/type = "value" 37 | tracks/0/path = NodePath(".:modulate") 38 | tracks/0/interp = 1 39 | tracks/0/loop_wrap = true 40 | tracks/0/imported = false 41 | tracks/0/enabled = true 42 | tracks/0/keys = { 43 | "times": PoolRealArray( 0, 0.5 ), 44 | "transitions": PoolRealArray( 1, 1 ), 45 | "update": 0, 46 | "values": [ Color( 1, 1, 1, 1 ), Color( 1, 0.72549, 0.72549, 1 ) ] 47 | } 48 | 49 | [node name="PathPreview" type="Line2D"] 50 | width = 20.0 51 | default_color = Color( 1, 0.415686, 0.160784, 1 ) 52 | joint_mode = 2 53 | script = SubResource( 1 ) 54 | 55 | [node name="Tween" type="Tween" parent="."] 56 | 57 | [node name="Timer" type="Timer" parent="."] 58 | 59 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 60 | autoplay = "glow" 61 | anims/glow = SubResource( 5 ) 62 | [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] 63 | -------------------------------------------------------------------------------- /start-project/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /start-project/grid-cell.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /start-project/grid-cell.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/grid-cell.svg-6dc3d08e9807150ffe3b0752d9dacc85.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://grid-cell.svg" 13 | dest_files=[ "res://.import/grid-cell.svg-6dc3d08e9807150ffe3b0752d9dacc85.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdquest-demos/godot-2d-tower-defense/8d4e408cba9e9f31c06e54478bbe04943bb8b746/start-project/icon.png -------------------------------------------------------------------------------- /start-project/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /start-project/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ ] 12 | _global_script_class_icons={ 13 | } 14 | 15 | [application] 16 | 17 | config/name="Tower Defense - Start" 18 | config/description="The initial version of 2D Secrets topdown tower defense game project." 19 | config/icon="res://icon.png" 20 | 21 | [debug] 22 | 23 | gdscript/warnings/return_value_discarded=false 24 | 25 | [display] 26 | 27 | window/size/width=1920 28 | window/size/height=1080 29 | window/size/test_width=1280 30 | window/size/test_height=720 31 | window/stretch/mode="2d" 32 | window/stretch/aspect="keep_width" 33 | 34 | [gui] 35 | 36 | theme/custom="res://UI/Theme/main_theme.tres" 37 | theme/custom_font="res://UI/Theme/main_font.tres" 38 | 39 | [input] 40 | 41 | select={ 42 | "deadzone": 0.5, 43 | "events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) 44 | ] 45 | } 46 | tower_placement={ 47 | "deadzone": 0.5, 48 | "events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) 49 | ] 50 | } 51 | 52 | [input_devices] 53 | 54 | pointing/emulate_touch_from_mouse=true 55 | 56 | [layer_names] 57 | 58 | 2d_physics/layer_1="selection" 59 | 2d_physics/layer_2="combat" 60 | 2d_physics/layer_3="enemies" 61 | 62 | [rendering] 63 | 64 | 2d/snapping/use_gpu_pixel_snap=true 65 | environment/default_clear_color=Color( 0.196078, 0.160784, 0.278431, 1 ) 66 | environment/default_environment="res://default_env.tres" 67 | quality/2d/use_pixel_snap=true 68 | -------------------------------------------------------------------------------- /start-project/sprite-sheet.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/sprite-sheet.svg-770a08d3ddf9b41899e4553fd12331ab.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprite-sheet.svg" 13 | dest_files=[ "res://.import/sprite-sheet.svg-770a08d3ddf9b41899e4553fd12331ab.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | --------------------------------------------------------------------------------