Compare commits
61 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6dead4cc61 | |||
| 77464c39d7 | |||
| 8ec8ea59ba | |||
| 40a80801e7 | |||
| b2aa7b2907 | |||
| b4dbd50a8f | |||
| b75e6be470 | |||
| 8ca085192d | |||
| 808ffb337e | |||
| 930d9e6d8e | |||
| 248b1915b6 | |||
| 1ea01c30d6 | |||
| 42ea2d3d75 | |||
| 49d48da550 | |||
| 8786d30936 | |||
| 8f2a1146f0 | |||
| 07b5114f23 | |||
| de06759514 | |||
| cabc547b51 | |||
| 5b880fa1ac | |||
| 0072a5e2e3 | |||
| c2649a6032 | |||
| 14e7fc057f | |||
| 2a346363eb | |||
| d9dae634ef | |||
| 20dea147ba | |||
| a404950b92 | |||
| b2c54a0e14 | |||
| 01ee8f051f | |||
| 75194e1700 | |||
| 8c11ee3000 | |||
| 60e32002c1 | |||
| b3b6998e14 | |||
| c558f31583 | |||
| 28640e94c6 | |||
| c33d892cf0 | |||
| 786444e789 | |||
| a042bb1282 | |||
| 2acc452f19 | |||
| a1208fa8a4 | |||
| d3a46ee779 | |||
| c2104f2d24 | |||
| be1e8a658f | |||
| 8d642f694d | |||
| f790694373 | |||
| 5e2ca5be83 | |||
| c73dd1dbd6 | |||
| 8e9f7723d9 | |||
| 7687844ea6 | |||
| 7186482a3f | |||
| 7451279024 | |||
| e2ccf87792 | |||
| f6d2c22e84 | |||
| 85f7d32f71 | |||
| 697e5ad9e4 | |||
| 9b05276ad6 | |||
| 2d2b63fd74 | |||
| beb0b697ea | |||
| 8740b632a1 | |||
| f98c89ef94 | |||
| e37c27a280 |
|
|
@ -1,5 +0,0 @@
|
|||
extends Node2D
|
||||
|
||||
#func _process(delta: float) -> void:
|
||||
#for p : Parallax2D in get_children():
|
||||
#p.scroll_offset += Vector2.RIGHT * 100 * delta * p.scroll_scale
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://c6q1tgl7kag67
|
||||
13
background/bg_image.gd
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
extends TextureRect
|
||||
|
||||
@export var colors : Array[Color] = [Color(0.3, 1, 1) * 0.7, Color(1, 0.6, 0.6) * 0.7, Color(1, 1, 1) * 0.7]
|
||||
|
||||
# Modulate the background with an interpolation of the colors in the list,
|
||||
# depending on the players position on the earth.
|
||||
func _process(_delta: float) -> void:
|
||||
var index : int = floor((%Player.position.angle() + PI)/ TAU * colors.size())
|
||||
var diff = (%Player.position.angle() + PI)/ TAU * colors.size() - index
|
||||
self.modulate = linear_color_interpolation(colors[index], colors[(index + 1) % colors.size()], diff)
|
||||
|
||||
func linear_color_interpolation(c1 : Color, c2 : Color, t : float):
|
||||
return c1 + (c2 - c1) * t
|
||||
1
background/bg_image.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://gul4u5tw1vxk
|
||||
|
|
@ -2,7 +2,7 @@ class_name Building extends Node2D
|
|||
|
||||
@export var location : Vector2i # x is the angle, y is the height in the grid
|
||||
@export var dimension : Vector2i = Vector2(2, 1) # same as above
|
||||
@onready var grid : Grid = get_parent()
|
||||
@export var blocks_area = true
|
||||
|
||||
var objects = []
|
||||
var destroyed = false
|
||||
|
|
@ -10,32 +10,14 @@ var destroyed = false
|
|||
# make sure location is set before adding a building to the scene tree
|
||||
# also make sure that the buildings are instantiated as children of the grid
|
||||
func _ready() -> void:
|
||||
assert(grid != null)
|
||||
var angle = location.x * TAU / grid.num_collumns; # currently assumes anchor is bottom left
|
||||
var height = grid.ground_radius + location.y * grid.cell_height;
|
||||
position = height * Vector2.from_angle(angle)
|
||||
global_position = Grid.get_world_position(location)
|
||||
|
||||
grid.buildings.append(self)
|
||||
if blocks_area:
|
||||
Grid.buildings.append(self)
|
||||
|
||||
await get_tree().create_timer(0.2).timeout
|
||||
if get_node_or_null("EnemyList") != null:
|
||||
var enemies = $EnemyList.get_children()
|
||||
|
||||
$EnemyList.reparent(get_tree().get_root().get_node("main"), false)
|
||||
|
||||
for enemy in enemies:
|
||||
var oldpos = enemy.position;
|
||||
enemy.position = get_world_position(oldpos)
|
||||
if enemy is Platform or enemy is Trap or enemy is Item:
|
||||
objects.append(enemy)
|
||||
if "building" in enemy: enemy.building = self
|
||||
if(enemy.has_method("init_at_horizontal_distortion")):
|
||||
enemy.init_at_horizontal_distortion(enemy.position.length() / grid.ground_radius)
|
||||
|
||||
func get_world_position (local_position: Vector2) -> Vector2:
|
||||
var height = grid.ground_radius + location.y * grid.cell_height - local_position.y
|
||||
var angle = (location.x + local_position.x / grid.cell_height) * TAU / grid.num_collumns
|
||||
return height * Vector2.from_angle(angle)
|
||||
if get_node_or_null("ObjectList") != null:
|
||||
var obj_list = $ObjectList
|
||||
Grid.call_deferred("place_object_list", obj_list, self)
|
||||
|
||||
func overlaps(other : Building):
|
||||
# heights don't overlap
|
||||
|
|
@ -43,16 +25,17 @@ func overlaps(other : Building):
|
|||
if location.y + dimension.y <= other.location.y: return false # other is above
|
||||
|
||||
# angles overlap. We can now assume heights overlap
|
||||
var relative_other_loc = (other.location.x - location.x + grid.num_collumns) % grid.num_collumns
|
||||
var relative_other_loc = (other.location.x - location.x + Grid.num_collumns) % Grid.num_collumns
|
||||
if dimension.x > relative_other_loc: return true
|
||||
if relative_other_loc + other.dimension.x > grid.num_collumns: return true
|
||||
if relative_other_loc + other.dimension.x > Grid.num_collumns: return true
|
||||
|
||||
# If we get here, angles do not overlap
|
||||
return false
|
||||
|
||||
func destroy():
|
||||
if not destroyed:
|
||||
grid.buildings.remove_at(grid.buildings.find(self))
|
||||
# On destruction, the building is removed from the list and destroyed together with all its objects.
|
||||
Grid.buildings.remove_at(Grid.buildings.find(self))
|
||||
for object in objects:
|
||||
if object != null and not ("collected" in object and object.collected):
|
||||
object.queue_free()
|
||||
|
|
|
|||
|
|
@ -31,36 +31,36 @@ texture = ExtResource("5_012sa")
|
|||
script = ExtResource("4_505qw")
|
||||
grid_offset = Vector2i(0, -1)
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="MorningStar" parent="EnemyList" instance=ExtResource("6_qwyfo")]
|
||||
[node name="MorningStar" parent="ObjectList" instance=ExtResource("6_qwyfo")]
|
||||
position = Vector2(238, -149)
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("8_evf2t")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("8_evf2t")]
|
||||
visible = false
|
||||
position = Vector2(75, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("8_evf2t")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("8_evf2t")]
|
||||
visible = false
|
||||
position = Vector2(225, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform3" parent="EnemyList" instance=ExtResource("8_evf2t")]
|
||||
[node name="Platform3" parent="ObjectList" instance=ExtResource("8_evf2t")]
|
||||
visible = false
|
||||
position = Vector2(375, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform4" parent="EnemyList" instance=ExtResource("8_evf2t")]
|
||||
[node name="Platform4" parent="ObjectList" instance=ExtResource("8_evf2t")]
|
||||
visible = false
|
||||
position = Vector2(525, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform5" parent="EnemyList" instance=ExtResource("8_evf2t")]
|
||||
[node name="Platform5" parent="ObjectList" instance=ExtResource("8_evf2t")]
|
||||
position = Vector2(431, -150)
|
||||
scale = Vector2(2.688, 3)
|
||||
|
||||
[node name="BearTrap" parent="EnemyList" instance=ExtResource("9_c7qov")]
|
||||
[node name="BearTrap" parent="ObjectList" instance=ExtResource("9_c7qov")]
|
||||
position = Vector2(270, -9)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -31,36 +31,36 @@ texture = ExtResource("5_hu6aj")
|
|||
script = ExtResource("4_2shqy")
|
||||
grid_offset = Vector2i(0, -1)
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("8_y6yyb")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("8_y6yyb")]
|
||||
visible = false
|
||||
position = Vector2(75, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("8_y6yyb")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("8_y6yyb")]
|
||||
visible = false
|
||||
position = Vector2(225, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform3" parent="EnemyList" instance=ExtResource("8_y6yyb")]
|
||||
[node name="Platform3" parent="ObjectList" instance=ExtResource("8_y6yyb")]
|
||||
visible = false
|
||||
position = Vector2(375, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform4" parent="EnemyList" instance=ExtResource("8_y6yyb")]
|
||||
[node name="Platform4" parent="ObjectList" instance=ExtResource("8_y6yyb")]
|
||||
visible = false
|
||||
position = Vector2(525, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform5" parent="EnemyList" instance=ExtResource("8_y6yyb")]
|
||||
[node name="Platform5" parent="ObjectList" instance=ExtResource("8_y6yyb")]
|
||||
position = Vector2(300, -150)
|
||||
scale = Vector2(2.688, 3)
|
||||
|
||||
[node name="ItemSpawn" parent="EnemyList" instance=ExtResource("9_jmdjr")]
|
||||
[node name="ItemSpawn" parent="ObjectList" instance=ExtResource("9_jmdjr")]
|
||||
position = Vector2(300, -200)
|
||||
|
||||
[node name="Giant_Leech" parent="EnemyList" instance=ExtResource("8_r3b86")]
|
||||
[node name="Giant_Leech" parent="ObjectList" instance=ExtResource("8_r3b86")]
|
||||
position = Vector2(400, -340)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -25,25 +25,25 @@ scale = Vector2(25, 25)
|
|||
texture = ExtResource("3_uv7v8")
|
||||
script = ExtResource("4_bl5jt")
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="Ghost" parent="EnemyList" instance=ExtResource("5_23fi7")]
|
||||
[node name="Ghost" parent="ObjectList" instance=ExtResource("5_23fi7")]
|
||||
position = Vector2(150, -300)
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("6_e6j05")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("6_e6j05")]
|
||||
visible = false
|
||||
position = Vector2(75, -595)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("6_e6j05")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("6_e6j05")]
|
||||
visible = false
|
||||
position = Vector2(225, -595)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform3" parent="EnemyList" instance=ExtResource("6_e6j05")]
|
||||
[node name="Platform3" parent="ObjectList" instance=ExtResource("6_e6j05")]
|
||||
position = Vector2(290, -431)
|
||||
|
||||
[node name="Platform4" parent="EnemyList" instance=ExtResource("6_e6j05")]
|
||||
[node name="Platform4" parent="ObjectList" instance=ExtResource("6_e6j05")]
|
||||
position = Vector2(62, -184)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -27,38 +27,38 @@ scale = Vector2(25, 25)
|
|||
texture = ExtResource("3_elmbw")
|
||||
script = ExtResource("4_1cnhw")
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="Ghost" parent="EnemyList" instance=ExtResource("5_rh5oo")]
|
||||
[node name="Ghost" parent="ObjectList" instance=ExtResource("5_rh5oo")]
|
||||
position = Vector2(-38, -481)
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("6_caaff")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("6_caaff")]
|
||||
visible = false
|
||||
position = Vector2(75, -595)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("6_caaff")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("6_caaff")]
|
||||
visible = false
|
||||
position = Vector2(225, -595)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform3" parent="EnemyList" instance=ExtResource("6_caaff")]
|
||||
[node name="Platform3" parent="ObjectList" instance=ExtResource("6_caaff")]
|
||||
position = Vector2(5, -251)
|
||||
|
||||
[node name="Platform4" parent="EnemyList" instance=ExtResource("6_caaff")]
|
||||
[node name="Platform4" parent="ObjectList" instance=ExtResource("6_caaff")]
|
||||
position = Vector2(286, -138)
|
||||
|
||||
[node name="Platform5" parent="EnemyList" instance=ExtResource("6_caaff")]
|
||||
[node name="Platform5" parent="ObjectList" instance=ExtResource("6_caaff")]
|
||||
position = Vector2(269, -435)
|
||||
scale = Vector2(2.49, 3.1)
|
||||
|
||||
[node name="ItemSpawn" parent="EnemyList" instance=ExtResource("7_elmbw")]
|
||||
[node name="ItemSpawn" parent="ObjectList" instance=ExtResource("7_elmbw")]
|
||||
position = Vector2(149, -645)
|
||||
|
||||
[node name="MorningStar" parent="EnemyList" instance=ExtResource("8_1cnhw")]
|
||||
[node name="MorningStar" parent="ObjectList" instance=ExtResource("8_1cnhw")]
|
||||
position = Vector2(39, -552)
|
||||
|
||||
[node name="Ghost2" parent="EnemyList" instance=ExtResource("5_rh5oo")]
|
||||
[node name="Ghost2" parent="ObjectList" instance=ExtResource("5_rh5oo")]
|
||||
position = Vector2(301, -39)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -27,30 +27,30 @@ scale = Vector2(25, 25)
|
|||
texture = ExtResource("3_0yjll")
|
||||
script = ExtResource("4_ri5b7")
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("6_kom4b")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("6_kom4b")]
|
||||
visible = false
|
||||
position = Vector2(75, -595)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("6_kom4b")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("6_kom4b")]
|
||||
visible = false
|
||||
position = Vector2(225, -595)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform5" parent="EnemyList" instance=ExtResource("6_kom4b")]
|
||||
[node name="Platform5" parent="ObjectList" instance=ExtResource("6_kom4b")]
|
||||
position = Vector2(85, -287)
|
||||
scale = Vector2(2.49, 3.1)
|
||||
|
||||
[node name="ItemSpawn" parent="EnemyList" instance=ExtResource("7_sr858")]
|
||||
[node name="ItemSpawn" parent="ObjectList" instance=ExtResource("7_sr858")]
|
||||
position = Vector2(149, -645)
|
||||
rarity_bonus = 0.5
|
||||
|
||||
[node name="MorningStar" parent="EnemyList" instance=ExtResource("8_ta0fd")]
|
||||
[node name="MorningStar" parent="ObjectList" instance=ExtResource("8_ta0fd")]
|
||||
position = Vector2(39, -552)
|
||||
|
||||
[node name="BearTrap" parent="EnemyList" instance=ExtResource("8_pww4b")]
|
||||
[node name="BearTrap" parent="ObjectList" instance=ExtResource("8_pww4b")]
|
||||
position = Vector2(165, -7)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -33,42 +33,42 @@ texture = ExtResource("5_pfkkr")
|
|||
script = ExtResource("4_xr4t5")
|
||||
grid_offset = Vector2i(0, -1)
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="MorningStar" parent="EnemyList" instance=ExtResource("5_xr4t5")]
|
||||
[node name="MorningStar" parent="ObjectList" instance=ExtResource("5_xr4t5")]
|
||||
position = Vector2(397, -3)
|
||||
|
||||
[node name="Ghost" parent="EnemyList" instance=ExtResource("7_35wcg")]
|
||||
[node name="Ghost" parent="ObjectList" instance=ExtResource("7_35wcg")]
|
||||
position = Vector2(118, -125)
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("8_sifiv")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("8_sifiv")]
|
||||
visible = false
|
||||
position = Vector2(75, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("8_sifiv")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("8_sifiv")]
|
||||
visible = false
|
||||
position = Vector2(225, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform3" parent="EnemyList" instance=ExtResource("8_sifiv")]
|
||||
[node name="Platform3" parent="ObjectList" instance=ExtResource("8_sifiv")]
|
||||
visible = false
|
||||
position = Vector2(375, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform4" parent="EnemyList" instance=ExtResource("8_sifiv")]
|
||||
[node name="Platform4" parent="ObjectList" instance=ExtResource("8_sifiv")]
|
||||
visible = false
|
||||
position = Vector2(525, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform5" parent="EnemyList" instance=ExtResource("8_sifiv")]
|
||||
[node name="Platform5" parent="ObjectList" instance=ExtResource("8_sifiv")]
|
||||
position = Vector2(300, -150)
|
||||
scale = Vector2(2.688, 3)
|
||||
|
||||
[node name="ItemSpawn" parent="EnemyList" instance=ExtResource("9_i1qmw")]
|
||||
[node name="ItemSpawn" parent="ObjectList" instance=ExtResource("9_i1qmw")]
|
||||
position = Vector2(300, -200)
|
||||
|
||||
[node name="Leech" parent="EnemyList" instance=ExtResource("10_ibnxs")]
|
||||
[node name="Leech" parent="ObjectList" instance=ExtResource("10_ibnxs")]
|
||||
position = Vector2(240, -340)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -33,39 +33,39 @@ texture = ExtResource("5_v4fh6")
|
|||
script = ExtResource("4_h84o2")
|
||||
grid_offset = Vector2i(0, -1)
|
||||
|
||||
[node name="EnemyList" type="Node2D" parent="."]
|
||||
[node name="ObjectList" type="Node2D" parent="."]
|
||||
|
||||
[node name="Platform" parent="EnemyList" instance=ExtResource("6_me65q")]
|
||||
[node name="Platform" parent="ObjectList" instance=ExtResource("6_me65q")]
|
||||
visible = false
|
||||
position = Vector2(75, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform2" parent="EnemyList" instance=ExtResource("6_me65q")]
|
||||
[node name="Platform2" parent="ObjectList" instance=ExtResource("6_me65q")]
|
||||
visible = false
|
||||
position = Vector2(225, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform3" parent="EnemyList" instance=ExtResource("6_me65q")]
|
||||
[node name="Platform3" parent="ObjectList" instance=ExtResource("6_me65q")]
|
||||
visible = false
|
||||
position = Vector2(375, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="Platform4" parent="EnemyList" instance=ExtResource("6_me65q")]
|
||||
[node name="Platform4" parent="ObjectList" instance=ExtResource("6_me65q")]
|
||||
visible = false
|
||||
position = Vector2(525, -295)
|
||||
collision_layer = 41
|
||||
|
||||
[node name="ItemSpawn" parent="EnemyList" instance=ExtResource("7_crruu")]
|
||||
[node name="ItemSpawn" parent="ObjectList" instance=ExtResource("7_crruu")]
|
||||
position = Vector2(137, -329)
|
||||
rarity_bonus = 0.25
|
||||
|
||||
[node name="BearTrap" parent="EnemyList" instance=ExtResource("8_fkxmk")]
|
||||
[node name="BearTrap" parent="ObjectList" instance=ExtResource("8_fkxmk")]
|
||||
position = Vector2(465, -301)
|
||||
|
||||
[node name="Ghost" parent="EnemyList" instance=ExtResource("9_6hrl3")]
|
||||
[node name="Ghost" parent="ObjectList" instance=ExtResource("9_6hrl3")]
|
||||
position = Vector2(301, -49)
|
||||
|
||||
[node name="Leech" parent="EnemyList" instance=ExtResource("10_7e5ul")]
|
||||
[node name="Leech" parent="ObjectList" instance=ExtResource("10_7e5ul")]
|
||||
position = Vector2(176, -340)
|
||||
|
||||
[node name="DebugSprite" type="Sprite2D" parent="."]
|
||||
|
|
|
|||
BIN
enemies/Elite.pdn
Normal file
BIN
enemies/Elite_Body.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
enemies/Elite_Head.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
|
@ -1,26 +1,35 @@
|
|||
extends Node2D
|
||||
|
||||
|
||||
var moving = false
|
||||
@onready var player = get_tree().get_root().get_node("main/Player")
|
||||
@onready var target = player.position
|
||||
var speed = 500
|
||||
|
||||
# The target is set on initialization and never updated.
|
||||
@onready var target = player.position
|
||||
|
||||
var reached = false
|
||||
signal target_reached
|
||||
|
||||
func _ready() -> void:
|
||||
|
||||
# Wait one second before firing
|
||||
await get_tree().create_timer(1).timeout
|
||||
moving = true
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
|
||||
# Fire towards the center of the cross
|
||||
if moving:
|
||||
position += (target - global_position).normalized().rotated(-get_parent().rotation) * speed * delta
|
||||
|
||||
# When reaching the center, inform parent node
|
||||
if((global_position - target).length() < 40):
|
||||
moving = false
|
||||
if not reached:
|
||||
target_reached.emit()
|
||||
reached = true
|
||||
|
||||
# Damage the player on contact
|
||||
if has_node("Area2D") and $Area2D.overlaps_body(player):
|
||||
player.hurt(1, global_position-player.position)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ var angular_speed = TAU/8
|
|||
var lifetime = 5
|
||||
|
||||
var ready_blobs = 0
|
||||
var num_blobs = 4
|
||||
|
||||
var num_blobs = 0
|
||||
|
||||
var particles_ended = false
|
||||
|
||||
|
|
@ -13,16 +14,20 @@ func _on_target_reached():
|
|||
ready_blobs += 1
|
||||
|
||||
func _ready() -> void:
|
||||
# Count those children that have a "target reached" signal and connect them.
|
||||
for child in get_children():
|
||||
if "target_reached" in child:
|
||||
num_blobs += 1
|
||||
child.connect("target_reached", _on_target_reached)
|
||||
$SplashSound.play()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
# Once all child blobs have reached their target, start moving as one while slowly rotating.
|
||||
if ready_blobs == num_blobs:
|
||||
position += (player.position - position).normalized() * speed * delta
|
||||
rotate(angular_speed * delta)
|
||||
lifetime -= delta
|
||||
# In the end, clear all child blobs, then the rest.
|
||||
if lifetime < 0 and not particles_ended:
|
||||
particles_ended = true
|
||||
for child in get_children():
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
extends CharacterBody2D
|
||||
@onready var earthaligner = $EarthAligner
|
||||
@onready var player = get_tree().get_root().get_node("main/Player")
|
||||
var moves = ["slam", "wave", "water_rise", "splash"]
|
||||
@export var big_blob : PackedScene
|
||||
@onready var water : Water = get_tree().get_root().get_node("main/Water")
|
||||
|
||||
# How often water has been risen.
|
||||
var risen = 0
|
||||
|
||||
# Managing idle behavior between attacks.
|
||||
var attack_ready = true
|
||||
var idle_dir : Vector2 = Vector2.ZERO
|
||||
var idle_dir_remaining = 0
|
||||
var idle_move = true
|
||||
var target_pos = Vector2.ZERO
|
||||
|
||||
|
||||
var damage = 1
|
||||
var dead = false
|
||||
signal grounded
|
||||
signal slam_step_finished
|
||||
|
||||
func choose_next_move() -> String:
|
||||
# Water rises at 75% and 50% of remaining HP.
|
||||
if $EnemyHurtbox.hp <= 3 * $EnemyHurtbox.max_hp / 4 and risen == 0:
|
||||
risen += 1
|
||||
return "water_rise"
|
||||
|
|
@ -24,10 +30,15 @@ func choose_next_move() -> String:
|
|||
return "water_rise"
|
||||
|
||||
var pool = ["splash"]
|
||||
if not (position.length() - water.radius < 300 and randf()<0.75):
|
||||
|
||||
# Heavily decrease slam probability if boss height is low.
|
||||
if not (position.length() - water.radius < 450 and randf()<0.75):
|
||||
pool.append("slam")
|
||||
|
||||
# Heavily decrease wave probability if player is very high up.
|
||||
if not (player.position.length() > water.radius + 900 and randf()<0.75):
|
||||
pool.append("wave")
|
||||
|
||||
return ["slam", "wave", "splash"].pick_random()
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
|
|
@ -38,7 +49,7 @@ func _process(_delta: float) -> void:
|
|||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if dead: return
|
||||
up_direction = earthaligner.global_from_local(Vector2.UP)
|
||||
up_direction = $EarthAligner.up
|
||||
if(is_on_floor()):
|
||||
grounded.emit()
|
||||
if idle_move: move_idle(delta)
|
||||
|
|
@ -47,59 +58,67 @@ func _physics_process(delta: float) -> void:
|
|||
move_and_slide()
|
||||
|
||||
func move_idle(delta : float):
|
||||
# Pick a random target roughly above the player's head every 0.5 seconds.
|
||||
idle_dir_remaining -= delta
|
||||
if(idle_dir_remaining <= 0):
|
||||
target_pos = player.position + player.earth_aligner.global_from_local(Vector2.UP) * 400
|
||||
target_pos = player.position + player.get_node("EarthAligner").up * 400
|
||||
target_pos += randf_range(0, max(200, (target_pos - global_position).length())*0.25) * Vector2.from_angle(randf_range(0,TAU))
|
||||
idle_dir = (target_pos - global_position).normalized()* max(200, (target_pos - global_position).length()) * 0.4
|
||||
idle_dir_remaining = 0.5
|
||||
velocity = idle_dir
|
||||
|
||||
func slam():
|
||||
# Move up, Slam Down, Repeat. Afterwards, linger for a moment.
|
||||
# The slam destroys buildings.
|
||||
idle_move = false
|
||||
velocity = up_direction * 500
|
||||
await get_tree().create_timer(0.6).timeout
|
||||
damage = 2
|
||||
velocity = up_direction * -1500
|
||||
await grounded
|
||||
$SoundSlam.play()
|
||||
destroy_below()
|
||||
await slam_step()
|
||||
damage = 1
|
||||
velocity = up_direction * 500
|
||||
await get_tree().create_timer(0.3).timeout
|
||||
damage = 2
|
||||
velocity = up_direction * -1500
|
||||
await grounded
|
||||
$SoundSlam.play()
|
||||
destroy_below()
|
||||
damage = 1
|
||||
await slam_step()
|
||||
velocity = up_direction * 35
|
||||
await get_tree().create_timer(3).timeout
|
||||
idle_move = true
|
||||
attack_ready = true
|
||||
|
||||
func slam_step():
|
||||
# End a downslam after ground is reached or 1.5 seconds have passed.
|
||||
# Then destroy buildings hit.
|
||||
damage = 2
|
||||
velocity = up_direction * -1500
|
||||
grounded.connect(func(): slam_step_finished.emit())
|
||||
get_tree().create_timer(1.5).timeout.connect(func(): slam_step_finished.emit())
|
||||
await slam_step_finished
|
||||
$SoundSlam.play()
|
||||
destroy_below()
|
||||
damage = 1
|
||||
|
||||
func destroy_below():
|
||||
if dead: return
|
||||
for body in $DestructionChecker.get_overlapping_bodies():
|
||||
if(body.has_method("destroy")): body.destroy()
|
||||
|
||||
func wave():
|
||||
|
||||
var angle = atan2(player.position.y, player.position.x)
|
||||
# Raise a wave from the water at the boundary of the screen and move it towards the center.
|
||||
var angle = player.position.angle()
|
||||
var dir = randi_range(0, 1) * 2 - 1
|
||||
var speed = 3000/water.radius_base
|
||||
water.create_tsunami(angle - speed * dir*TAU/30, dir, speed)
|
||||
var speed = 3000 / water.radius_base
|
||||
water.create_tsunami(angle - speed * dir * TAU/30, dir, speed)
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
$Wave.play()
|
||||
await get_tree().create_timer(3.5).timeout
|
||||
attack_ready = true
|
||||
|
||||
func water_rise():
|
||||
# Increase the water level by 1 room height.
|
||||
water.rise_water()
|
||||
await get_tree().create_timer(5).timeout
|
||||
attack_ready = true
|
||||
|
||||
func splash():
|
||||
# Form four small blobs around the player which merge into one.
|
||||
var blob_instance = big_blob.instantiate()
|
||||
get_tree().get_root().get_node("main").add_child(blob_instance)
|
||||
blob_instance.position = player.position
|
||||
|
|
@ -109,16 +128,17 @@ func splash():
|
|||
|
||||
|
||||
func die():
|
||||
# Clear everything else, then wait for Audio Players to make sure sounds are not cut off.
|
||||
dead = true
|
||||
for child in get_children():
|
||||
if not child is AudioStreamPlayer2D:
|
||||
child.queue_free()
|
||||
$DeathSound.play()
|
||||
await $DeathSound.finished
|
||||
await get_tree().create_timer(3).timeout
|
||||
await get_tree().create_timer(1).timeout
|
||||
get_tree().change_scene_to_file("res://ui/victory_screen/victory_screen.tscn")
|
||||
queue_free()
|
||||
|
||||
func _on_enemy_hurtbox_damage_taken(_damage, _dir) -> void:
|
||||
func _on_enemy_hurtbox_damage_taken(_damage, _dir, _id) -> void:
|
||||
if dead: return
|
||||
$AudioStreamPlayer2D.play()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ func _ready() -> void:
|
|||
pass
|
||||
|
||||
func _on_water_water_reached_max_height() -> void:
|
||||
# The boss spawns once the water has risen to its maximum height.
|
||||
var node = boss.instantiate()
|
||||
add_sibling(node)
|
||||
node.position = %Player.position + %Player.earth_aligner.local_from_global(Vector2.UP) * 1000;
|
||||
node.position = %Player.position + %Player.get_node("EarthAligner").up * 1000;
|
||||
queue_free()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
extends Area2D
|
||||
|
||||
# Attach this to an object to make it destructible
|
||||
func destroy():
|
||||
get_parent().queue_free()
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
extends Area2D
|
||||
@onready var earth_aligner = $EarthAligner
|
||||
@onready var player : CharacterBody2D = get_tree().get_root().get_node_or_null("main/Player")
|
||||
var target : CharacterBody2D
|
||||
|
||||
# Base stats
|
||||
var speed = 100
|
||||
var damage = 1
|
||||
var player : CharacterBody2D
|
||||
var target : CharacterBody2D
|
||||
var current_knockback = Vector2.ZERO
|
||||
var knockback_weight = 800
|
||||
|
||||
# Aggro range determines at which distance the ghost targets the player,
|
||||
# Chase range determines at which distance the ghost stops pursuing the player.
|
||||
var aggro_range = 900
|
||||
var chase_range = 1400
|
||||
|
||||
var current_knockback = Vector2.ZERO
|
||||
var knockback_weight = 800
|
||||
|
||||
func _ready() -> void:
|
||||
player = get_tree().get_root().get_node_or_null("main/Player")
|
||||
$AnimatedSprite2D.play("default")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
|
|
@ -19,28 +22,32 @@ func _process(delta: float) -> void:
|
|||
return
|
||||
|
||||
var dist = (position - player.position).length()
|
||||
# Set target based on aggression range and whether target is already set
|
||||
if(dist > chase_range):
|
||||
target = null
|
||||
elif(target == null and dist <= aggro_range):
|
||||
target = player
|
||||
|
||||
# Move towards the target at constant speed
|
||||
if(target!=null):
|
||||
var motion = -(position - target.position).normalized() * speed
|
||||
self.position += motion * delta * min(1, dist/(motion.length()*delta))
|
||||
|
||||
|
||||
|
||||
# Process knockback
|
||||
self.position += current_knockback * delta
|
||||
current_knockback = current_knockback/pow(1.3, 60*delta)
|
||||
|
||||
|
||||
if(self.overlaps_body(player)):
|
||||
player.hurt(damage, self.global_position-player.global_position)
|
||||
|
||||
func _on_death():
|
||||
# First free all other children, then wait for Death Sound to finish
|
||||
for child in get_children():
|
||||
if not child is AudioStreamPlayer2D:
|
||||
child.queue_free()
|
||||
await $AudioStreamPlayer2D.finished
|
||||
await $HurtSound.finished
|
||||
self.queue_free()
|
||||
|
||||
func _on_damage_taken(_damage : int, dir: Vector2, _id):
|
||||
current_knockback = - dir * knockback_weight
|
||||
$AudioStreamPlayer2D.play()
|
||||
$HurtSound.play()
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ script = ExtResource("1_6attn")
|
|||
[node name="EnemyHurtbox" parent="." node_paths=PackedStringArray("canvasItem") instance=ExtResource("2_34o1m")]
|
||||
max_hp = 50
|
||||
canvasItem = NodePath("..")
|
||||
id_block_time = 0.2
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="EnemyHurtbox"]
|
||||
scale = Vector2(6, 6)
|
||||
|
|
@ -52,7 +53,7 @@ shape = SubResource("CircleShape2D_6attn")
|
|||
|
||||
[node name="EarthAligner" parent="." instance=ExtResource("3_obmiq")]
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||
[node name="HurtSound" type="AudioStreamPlayer2D" parent="."]
|
||||
stream = ExtResource("7_eqcb8")
|
||||
volume_db = 15.0
|
||||
|
||||
|
|
|
|||
|
|
@ -49,20 +49,20 @@ scale = Vector2(2, 2)
|
|||
|
||||
[node name="EarthAligner" parent="." instance=ExtResource("3_vk62e")]
|
||||
|
||||
[node name="RayCast2D" type="Area2D" parent="."]
|
||||
[node name="StepChecker" type="Area2D" parent="."]
|
||||
position = Vector2(248, 31.2)
|
||||
collision_layer = 0
|
||||
collision_mask = 8
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RayCast2D"]
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="StepChecker"]
|
||||
position = Vector2(0, 25)
|
||||
shape = SubResource("RectangleShape2D_cq6dk")
|
||||
|
||||
[node name="RayCast2D2" type="Area2D" parent="."]
|
||||
[node name="GroundSensor" type="Area2D" parent="."]
|
||||
collision_layer = 0
|
||||
collision_mask = 8
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RayCast2D2"]
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="GroundSensor"]
|
||||
position = Vector2(0, 25)
|
||||
shape = SubResource("RectangleShape2D_cq6dk")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
extends EnemyHurtbox
|
||||
# The distance from one end to the other while standing
|
||||
@export var broadth = 250
|
||||
@export var move_dir = -1
|
||||
@export var angular_speed = 0.25
|
||||
var move_dir = [-1, 1].pick_random()
|
||||
const angular_speed = 0.25
|
||||
|
||||
# The angle from the base to the moving end
|
||||
var angle = 0.0 if move_dir == 1 else PI
|
||||
|
||||
@onready var segments : Array[Node] = $Segments.get_children()
|
||||
|
|
@ -10,25 +13,37 @@ var dead = false
|
|||
|
||||
func _process(delta: float) -> void:
|
||||
if dead: return
|
||||
if not $RayCast2D2.has_overlapping_bodies():
|
||||
position += 200 * delta * $EarthAligner.global_from_local(Vector2.DOWN)
|
||||
# Fall slowly while not grounded
|
||||
if not $GroundSensor.has_overlapping_bodies():
|
||||
position += 200 * delta * $EarthAligner.down
|
||||
|
||||
var y = position.length()
|
||||
var ratio = - move_dir * broadth / (2 * y)
|
||||
|
||||
# Due to the curvature of the ground, the leech can not just prescribe a semicircle.
|
||||
# 2 * rot_angle determines how much further than 180° the moving leg has to move.
|
||||
# This agrees with the angle of the arc spanned by the leeches standing ends.
|
||||
var rot_angle = - 2 * asin(ratio)
|
||||
angle -= TAU * delta * angular_speed * move_dir
|
||||
|
||||
# Once the rotation has finished, the other leg is used as the leeches center.
|
||||
# The leeches position has to be updated accordingly.
|
||||
if(angle > PI + abs(rot_angle) / 2 or angle < - abs(rot_angle) / 2):
|
||||
angle = fmod(angle + PI, PI)
|
||||
position = position.rotated(rot_angle)
|
||||
if dead:
|
||||
return
|
||||
|
||||
# StepChecker determines whether there is ground for the next step.
|
||||
# Place the StepChecker on the side of the next step to be made.
|
||||
if(move_dir == 1 and angle < 1 or move_dir == -1 and angle > PI - 1):
|
||||
$RayCast2D.global_position = position.rotated(rot_angle)
|
||||
$RayCast2D.rotation = rot_angle
|
||||
$StepChecker.global_position = position.rotated(rot_angle)
|
||||
$StepChecker.rotation = rot_angle
|
||||
|
||||
# At some point of the movement, check whether there is ground to step on, turn around otherwise.
|
||||
if(move_dir == 1 and angle < 0.5 or move_dir == -1 and angle > PI - 0.5):
|
||||
if(not $RayCast2D.has_overlapping_bodies()):
|
||||
if(not $StepChecker.has_overlapping_bodies()):
|
||||
move_dir *= -1
|
||||
if dead:
|
||||
return
|
||||
|
||||
# Update the position and rotation according to the end's position
|
||||
for i in range(segment_count):
|
||||
var segment_pos_data = calculate_segment_location_and_rotation(i)
|
||||
if not is_instance_valid(segments[i]):
|
||||
|
|
@ -38,7 +53,11 @@ func _process(delta: float) -> void:
|
|||
|
||||
func calculate_segment_location_and_rotation (i) -> Dictionary:
|
||||
var aerial_end_location = Vector2.from_angle(-angle) * broadth
|
||||
|
||||
# Compute the gravicenter of the standing end, the moving end and the apex of the movement.
|
||||
var gravicenter = (aerial_end_location + Vector2(0, -broadth) + Vector2.ZERO) / 3
|
||||
|
||||
# Compute the circle through the above gravicenter, the standing end and the moving end.
|
||||
var ax = gravicenter.x
|
||||
var ay = gravicenter.y
|
||||
var bx = aerial_end_location.x
|
||||
|
|
@ -48,31 +67,46 @@ func calculate_segment_location_and_rotation (i) -> Dictionary:
|
|||
var d = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by))
|
||||
var ux = ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d
|
||||
var uy = ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d
|
||||
var center = Vector2(ux, uy)
|
||||
var radius = center.length()
|
||||
var circum_center = Vector2(ux, uy)
|
||||
var radius = circum_center.length()
|
||||
|
||||
# Determine the direction of the correct arc between the standing and the moving end
|
||||
var switch_arc_dir = false
|
||||
# When the moving end crosses above the standing end, the circumcenter jumps
|
||||
# from one side of the leech to the other, reverting the direction of the arc
|
||||
if ux < 0:
|
||||
switch_arc_dir = !switch_arc_dir
|
||||
if center.angle() > 1:
|
||||
|
||||
# For sufficiently large size of circum_center.angle() it can happen that
|
||||
# the sign of the (circum_center - aerial_end_location).angle() flips while
|
||||
# that of circum_center.angle() doesn't, which has to be counteracted.
|
||||
if circum_center.angle() > 1:
|
||||
switch_arc_dir = !switch_arc_dir
|
||||
|
||||
var angle1 = - PI + center.angle()
|
||||
var angle2 = - PI + (center-aerial_end_location).angle()
|
||||
var angle1 = - PI + circum_center.angle()
|
||||
var angle2 = - PI + (circum_center - aerial_end_location).angle()
|
||||
if(switch_arc_dir):
|
||||
angle1 += TAU
|
||||
|
||||
if radius < 10000000:
|
||||
return {"position": center + radius * Vector2.from_angle((i * angle1 + (segment_count - 1 - i) * angle2)/(segment_count - 1)),
|
||||
"rotation": (i * angle1 + (segment_count - 1 - i) * angle2)/ (segment_count - 1) + sign(ux) * PI/2}
|
||||
|
||||
else:
|
||||
# In the edge case where the leech is almost a straight line, the circum_center
|
||||
# and radius approach infty, leading to numerical errors producing flickering.
|
||||
# This is ruled out by treating these cases as actual straight lines.
|
||||
if radius > 1000000:
|
||||
return {"position" : Vector2.UP * broadth * i / (segment_count - 1),
|
||||
"rotation" : 3 * PI / 2}
|
||||
|
||||
# Otherwise, the segments are distributed regularly along the arc.
|
||||
else:
|
||||
var arc_angle = (i * angle1 + (segment_count - 1 - i) * angle2)/(segment_count - 1)
|
||||
return {"position": circum_center + radius * Vector2.from_angle(arc_angle),
|
||||
"rotation": arc_angle + sign(ux) * PI/2}
|
||||
|
||||
|
||||
func _on_damage_taken(_damage, _dir, _id):
|
||||
$AudioStreamPlayer2D.play()
|
||||
|
||||
func _on_death():
|
||||
# Free all other children while waiting for the death sound to play.
|
||||
dead = true
|
||||
for child in get_children():
|
||||
if not child is AudioStreamPlayer2D:
|
||||
|
|
|
|||
|
|
@ -39,20 +39,20 @@ scale = Vector2(-1, -1)
|
|||
|
||||
[node name="EarthAligner" parent="." instance=ExtResource("3_0r7dp")]
|
||||
|
||||
[node name="RayCast2D" type="Area2D" parent="."]
|
||||
[node name="StepChecker" type="Area2D" parent="."]
|
||||
position = Vector2(248, 31.2)
|
||||
collision_layer = 0
|
||||
collision_mask = 8
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RayCast2D"]
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="StepChecker"]
|
||||
position = Vector2(0, 14.8)
|
||||
shape = SubResource("RectangleShape2D_cq6dk")
|
||||
|
||||
[node name="RayCast2D2" type="Area2D" parent="."]
|
||||
[node name="GroundSensor" type="Area2D" parent="."]
|
||||
collision_layer = 0
|
||||
collision_mask = 8
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RayCast2D2"]
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="GroundSensor"]
|
||||
position = Vector2(0, 8.8)
|
||||
shape = SubResource("RectangleShape2D_cq6dk")
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@ extends Area2D
|
|||
@onready var player = get_tree().get_root().get_node_or_null("main/Player")
|
||||
var damage = 1
|
||||
|
||||
#signal segment_damaged
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if (player != null and overlaps_body(player)):
|
||||
player.hurt(damage, self.global_position-player.global_position)
|
||||
|
||||
# Forward taken damage to the parent leech.
|
||||
func _on_hurtbox_damaged(dmg : int, dir : Vector2, id):
|
||||
#segment_damaged.emit(dmg, dir)
|
||||
get_parent().get_parent().hurt(dmg, dir, id)
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
class_name ActiveItem extends Item
|
||||
|
||||
@export var sprite : Texture2D
|
||||
|
||||
func collect() -> bool:
|
||||
if (player.active_item == null):
|
||||
player.active_item = self
|
||||
actually_collect()
|
||||
|
||||
return true
|
||||
return false
|
||||
|
||||
func actually_collect():
|
||||
pass
|
||||
|
||||
func activate():
|
||||
assert(false)
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 770 B |
|
|
@ -1,23 +0,0 @@
|
|||
extends ActiveItem
|
||||
var cooldown = 1.5
|
||||
var dash_time = 0.15
|
||||
var dashing = 0
|
||||
var dash_dir
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
super(delta)
|
||||
if dashing > 0:
|
||||
dashing -= delta
|
||||
player.reset_to_velocity = player.earth_aligner.local_from_global(dash_dir)
|
||||
|
||||
|
||||
func actually_collect():
|
||||
player.set_cooldown(cooldown)
|
||||
|
||||
func activate():
|
||||
$DashSound.play()
|
||||
player.activate_cooldown()
|
||||
player.air_jumps_current = min(player.air_jumps_current + 1, player.air_jumps_max)
|
||||
dashing = dash_time
|
||||
dash_dir = player.earth_aligner.global_from_local(Vector2.RIGHT * player.facing * 1600)
|
||||
player.inv_time = max(player.inv_time, dash_time)
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
extends ActiveItem
|
||||
var cooldown = 10
|
||||
|
||||
func actually_collect():
|
||||
player.set_cooldown(cooldown)
|
||||
|
||||
|
||||
func activate():
|
||||
$UpdashSound.play()
|
||||
player.activate_cooldown()
|
||||
player.reset_to_velocity = Vector2(0,1)
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
player.reset_to_velocity = Vector2(0, -2400)
|
||||
BIN
items/consumables/bow/arrow.png
Normal file
|
After Width: | Height: | Size: 875 B |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bavoghl2pxs83"
|
||||
path="res://.godot/imported/arror.png-9ea2fbd842e6807dfd42e9ceed411fd2.ctex"
|
||||
path="res://.godot/imported/arrow.png-2cffe6fabf19679230c231a1fd8a329e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/active_items/bow/arror.png"
|
||||
dest_files=["res://.godot/imported/arror.png-9ea2fbd842e6807dfd42e9ceed411fd2.ctex"]
|
||||
source_file="res://items/consumables/bow/arrow.png"
|
||||
dest_files=["res://.godot/imported/arrow.png-2cffe6fabf19679230c231a1fd8a329e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://dfva4dhflxglr"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bglrm0bb4nla" path="res://items/active_items/bow/arrow.gd" id="1_lxthq"]
|
||||
[ext_resource type="Texture2D" uid="uid://bavoghl2pxs83" path="res://items/active_items/bow/arror.png" id="2_ilsew"]
|
||||
[ext_resource type="Script" uid="uid://bglrm0bb4nla" path="res://items/consumables/bow/arrow.gd" id="1_lxthq"]
|
||||
[ext_resource type="Texture2D" uid="uid://bavoghl2pxs83" path="res://items/consumables/bow/arrow.png" id="2_ilsew"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_tfcgf"]
|
||||
size = Vector2(20, 5)
|
||||
9
items/consumables/bow/arrow_icon.tscn
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://bu3j6ambrybd2"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://bavoghl2pxs83" path="res://items/consumables/bow/arrow.png" id="1_7lvex"]
|
||||
|
||||
[node name="TextureRect" type="TextureRect"]
|
||||
custom_minimum_size = Vector2(0, 3)
|
||||
texture = ExtResource("1_7lvex")
|
||||
expand_mode = 3
|
||||
stretch_mode = 3
|
||||
|
|
@ -1,18 +1,21 @@
|
|||
extends ActiveItem
|
||||
@export var cooldown = 1
|
||||
@export var cooldown = 0.3
|
||||
@export var arrow_scene : PackedScene
|
||||
|
||||
|
||||
func actually_collect():
|
||||
player.set_cooldown(cooldown)
|
||||
|
||||
|
||||
func activate():
|
||||
player.activate_cooldown()
|
||||
|
||||
# Spawn an arrow on activation
|
||||
var arrow : Area2D = arrow_scene.instantiate()
|
||||
get_tree().get_root().add_child(arrow)
|
||||
arrow.position = player.position
|
||||
arrow.rotation = player.rotation
|
||||
arrow.direction = player.earth_aligner.global_from_local(Vector2(player.facing, 0))
|
||||
arrow.direction = player.get_node("EarthAligner").right * player.facing
|
||||
|
||||
# Make sure the arrow sprite faces the right direction
|
||||
if(player.facing == -1):
|
||||
arrow.get_node("Sprite2D").scale.x = - arrow.get_node("Sprite2D").scale.x
|
||||
$SoundBowRelease.play()
|
||||
|
Before Width: | Height: | Size: 967 B After Width: | Height: | Size: 967 B |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d01h01le82gyh"
|
||||
path="res://.godot/imported/bow.png-5c21d924e7ed46a9ae9ef92089b84a58.ctex"
|
||||
path="res://.godot/imported/bow.png-7ca2f79a3aaf0404b0d2a5f64b2c7b38.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/active_items/bow/bow.png"
|
||||
dest_files=["res://.godot/imported/bow.png-5c21d924e7ed46a9ae9ef92089b84a58.ctex"]
|
||||
source_file="res://items/consumables/bow/bow.png"
|
||||
dest_files=["res://.godot/imported/bow.png-7ca2f79a3aaf0404b0d2a5f64b2c7b38.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
[gd_scene load_steps=9 format=3 uid="uid://ddn025xnjngko"]
|
||||
[gd_scene load_steps=10 format=3 uid="uid://ddn025xnjngko"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bkcip66at5sug" path="res://items/active_items/bow/bow.gd" id="1_xppub"]
|
||||
[ext_resource type="PackedScene" uid="uid://dfva4dhflxglr" path="res://items/active_items/bow/arrow.tscn" id="2_0id2q"]
|
||||
[ext_resource type="Texture2D" uid="uid://d01h01le82gyh" path="res://items/active_items/bow/bow.png" id="3_vkelq"]
|
||||
[ext_resource type="Script" uid="uid://bkcip66at5sug" path="res://items/consumables/bow/bow.gd" id="1_xppub"]
|
||||
[ext_resource type="PackedScene" uid="uid://dfva4dhflxglr" path="res://items/consumables/bow/arrow.tscn" id="2_0id2q"]
|
||||
[ext_resource type="Texture2D" uid="uid://d01h01le82gyh" path="res://items/consumables/bow/bow.png" id="3_vkelq"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="4_0id2q"]
|
||||
[ext_resource type="PackedScene" uid="uid://bu3j6ambrybd2" path="res://items/consumables/bow/arrow_icon.tscn" id="4_2dslu"]
|
||||
[ext_resource type="AudioStream" uid="uid://bg1w0fyeyys2p" path="res://sounds/item-equip-6904.mp3" id="5_gfbg0"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="5_o1smo"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="5_o1smo"]
|
||||
[ext_resource type="AudioStream" uid="uid://10ljbd4djqgb" path="res://sounds/263675__porkmuncher__bow_release_cut.wav" id="7_o1smo"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_gllxn"]
|
||||
|
|
@ -17,6 +18,8 @@ collision_mask = 4
|
|||
script = ExtResource("1_xppub")
|
||||
arrow_scene = ExtResource("2_0id2q")
|
||||
sprite = ExtResource("3_vkelq")
|
||||
uses_left_icon = ExtResource("4_2dslu")
|
||||
uses = 5
|
||||
icon = ExtResource("3_vkelq")
|
||||
item_name = "Bow"
|
||||
|
||||
|
|
@ -28,7 +31,6 @@ scale = Vector2(2.17, 3.5)
|
|||
shape = SubResource("CircleShape2D_gllxn")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.583047, 0.321422, 0.988413, 1)
|
||||
position = Vector2(8, 2)
|
||||
scale = Vector2(1.5, 1.5)
|
||||
texture = ExtResource("5_o1smo")
|
||||
|
|
@ -3,6 +3,6 @@ extends Item
|
|||
|
||||
func collect() -> bool:
|
||||
if(player.current_hp < player.max_hp):
|
||||
player.current_hp = min(player.max_hp, player.current_hp + heal_amount)
|
||||
player.current_hp += heal_amount
|
||||
return true
|
||||
return false
|
||||
|
Before Width: | Height: | Size: 928 B After Width: | Height: | Size: 928 B |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dog2yksitfgu1"
|
||||
path="res://.godot/imported/heal_item.png-fd96dcbc8e00ec13b19c3e58ef0188e6.ctex"
|
||||
path="res://.godot/imported/heal_item.png-8a8830bfa8056f0430b6f7daf94a6634.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/immediate_items/heal_item/heal_item.png"
|
||||
dest_files=["res://.godot/imported/heal_item.png-fd96dcbc8e00ec13b19c3e58ef0188e6.ctex"]
|
||||
source_file="res://items/consumables/heal_item/heal_item.png"
|
||||
dest_files=["res://.godot/imported/heal_item.png-8a8830bfa8056f0430b6f7daf94a6634.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://b00185vygcka1"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b43fudwi47qfd" path="res://items/immediate_items/heal_item/heal_item.gd" id="1_3vbv8"]
|
||||
[ext_resource type="Texture2D" uid="uid://dog2yksitfgu1" path="res://items/immediate_items/heal_item/heal_item.png" id="2_bqles"]
|
||||
[ext_resource type="Script" uid="uid://b43fudwi47qfd" path="res://items/consumables/heal_item/heal_item.gd" id="1_3vbv8"]
|
||||
[ext_resource type="Texture2D" uid="uid://dog2yksitfgu1" path="res://items/consumables/heal_item/heal_item.png" id="2_bqles"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="2_evqwq"]
|
||||
[ext_resource type="Texture2D" uid="uid://djfc7sdc8wxp6" path="res://player/Heart_cut.png" id="3_fvuym"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="4_sr4am"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="4_sr4am"]
|
||||
[ext_resource type="AudioStream" uid="uid://b37akn7hmk2r3" path="res://sounds/471834__keshafilm__health-pickup.wav" id="5_1ujdq"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_hvhjo"]
|
||||
|
|
@ -21,7 +21,6 @@ scale = Vector2(2.4, 3.36)
|
|||
shape = SubResource("CircleShape2D_hvhjo")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
position = Vector2(1, -1)
|
||||
scale = Vector2(1.2, 1.2)
|
||||
texture = ExtResource("4_sr4am")
|
||||
|
||||
36
items/consumables/horizontal_dash/horizontal_dash.gd
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
extends ActiveItem
|
||||
@export var cooldown = 0.2
|
||||
var dash_time = 0.15
|
||||
var dash_timer : SceneTreeTimer
|
||||
var dash_velocity
|
||||
var dash_speed = 1600
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
super(delta)
|
||||
# While the dash is active, move the player in the
|
||||
# (absolute!) direction fixed at the start of the dash
|
||||
if dash_timer != null and dash_timer.time_left > 0:
|
||||
player.reset_to_velocity = player.get_node("EarthAligner").local_from_global(dash_velocity)
|
||||
|
||||
func actually_collect():
|
||||
player.set_cooldown(cooldown)
|
||||
|
||||
func activate():
|
||||
$DashSound.play()
|
||||
player.activate_cooldown()
|
||||
# The dash refills one air jump if possible and provides iframes.
|
||||
player.air_jumps_current += 1
|
||||
dash_timer = get_tree().create_timer(dash_time)
|
||||
dash_velocity = player.get_node("EarthAligner").right * player.facing * dash_speed
|
||||
player.get_node("IFrames").start(dash_time)
|
||||
|
||||
func remove(reset_player_active = true):
|
||||
# If the item is removed during the dash, clear the active item slot,
|
||||
# but only remove the item from the scene afterwards.
|
||||
if(dash_timer != null):
|
||||
if reset_player_active:
|
||||
player.active_item = null
|
||||
await dash_timer.timeout
|
||||
super(false)
|
||||
else:
|
||||
super()
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://dy17xhg1yrl0o"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://jq326dmuaj22" path="res://items/active_items/horizontal_dash/horizontal_dash.gd" id="1_ktd5x"]
|
||||
[ext_resource type="Texture2D" uid="uid://cnn3tadylge8y" path="res://items/active_items/horizontal_dash/horizontaldash.png" id="3_ktd5x"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="3_vqrqe"]
|
||||
[ext_resource type="Script" uid="uid://jq326dmuaj22" path="res://items/consumables/horizontal_dash/horizontal_dash.gd" id="1_ktd5x"]
|
||||
[ext_resource type="Texture2D" uid="uid://cnn3tadylge8y" path="res://items/consumables/horizontal_dash/horizontaldash.png" id="3_ktd5x"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="3_vqrqe"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="4_gtuhj"]
|
||||
[ext_resource type="AudioStream" uid="uid://bg1w0fyeyys2p" path="res://sounds/item-equip-6904.mp3" id="5_5y0ew"]
|
||||
[ext_resource type="AudioStream" uid="uid://ds0yw3au0quae" path="res://sounds/whoosh.mp3" id="6_a6gm0"]
|
||||
|
|
@ -32,7 +32,6 @@ scale = Vector2(1, 4)
|
|||
shape = SubResource("CircleShape2D_ktd5x")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.725757, 0.519822, 5.77569e-07, 1)
|
||||
position = Vector2(-2, 14)
|
||||
scale = Vector2(1.2, 1.2)
|
||||
texture = ExtResource("3_vqrqe")
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cnn3tadylge8y"
|
||||
path="res://.godot/imported/horizontaldash.png-3a6880e60346d9b8d19d47557212a382.ctex"
|
||||
path="res://.godot/imported/horizontaldash.png-9fe6fddd3110882a6c56740b08ea51eb.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/active_items/horizontal_dash/horizontaldash.png"
|
||||
dest_files=["res://.godot/imported/horizontaldash.png-3a6880e60346d9b8d19d47557212a382.ctex"]
|
||||
source_file="res://items/consumables/horizontal_dash/horizontaldash.png"
|
||||
dest_files=["res://.godot/imported/horizontaldash.png-9fe6fddd3110882a6c56740b08ea51eb.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
24
items/consumables/updash/updash.gd
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
extends ActiveItem
|
||||
var cooldown = 10
|
||||
var timer : SceneTreeTimer
|
||||
|
||||
func actually_collect():
|
||||
player.set_cooldown(cooldown)
|
||||
|
||||
func activate():
|
||||
$UpdashSound.play()
|
||||
player.activate_cooldown()
|
||||
# Drop the player for a moment, then boost upwards.
|
||||
player.reset_to_velocity = Vector2(0,1)
|
||||
timer = get_tree().create_timer(0.1)
|
||||
await timer.timeout
|
||||
player.reset_to_velocity = Vector2(0, -2400)
|
||||
|
||||
func remove(reset_player_active = true):
|
||||
# If the item is removed during the dash startup, clear the active item slot,
|
||||
# but only remove the item from the scene afterwards.
|
||||
if reset_player_active:
|
||||
player.active_item = null
|
||||
if timer != null and timer.time_left > 0:
|
||||
await timer.timeout
|
||||
super(false)
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dxcfkdhl4g24c"
|
||||
path="res://.godot/imported/updash.png-ddc6856a4b101f20557ef85572ee190a.ctex"
|
||||
path="res://.godot/imported/updash.png-6cf7335cc7a138df6d0425e524bb4bb8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/active_items/updash/updash.png"
|
||||
dest_files=["res://.godot/imported/updash.png-ddc6856a4b101f20557ef85572ee190a.ctex"]
|
||||
source_file="res://items/consumables/updash/updash.png"
|
||||
dest_files=["res://.godot/imported/updash.png-6cf7335cc7a138df6d0425e524bb4bb8.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://ewe36lqcjojk"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bbwsc2a2hd0ow" path="res://items/active_items/updash/updash.gd" id="1_ghbl6"]
|
||||
[ext_resource type="Texture2D" uid="uid://dxcfkdhl4g24c" path="res://items/active_items/updash/updash.png" id="3_a5yxq"]
|
||||
[ext_resource type="Script" uid="uid://bbwsc2a2hd0ow" path="res://items/consumables/updash/updash.gd" id="1_ghbl6"]
|
||||
[ext_resource type="Texture2D" uid="uid://dxcfkdhl4g24c" path="res://items/consumables/updash/updash.png" id="3_a5yxq"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="3_ktv3s"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="3_ssiqx"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="3_ssiqx"]
|
||||
[ext_resource type="AudioStream" uid="uid://bg1w0fyeyys2p" path="res://sounds/item-equip-6904.mp3" id="5_ssiqx"]
|
||||
[ext_resource type="AudioStream" uid="uid://ds0yw3au0quae" path="res://sounds/whoosh.mp3" id="6_mbe12"]
|
||||
|
||||
|
|
@ -17,25 +17,22 @@ icon = ExtResource("3_a5yxq")
|
|||
item_name = "Upward Boost"
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
visible = false
|
||||
position = Vector2(0, 19)
|
||||
scale = Vector2(3, 2)
|
||||
scale = Vector2(3.3, 2.2)
|
||||
shape = SubResource("CircleShape2D_ghbl6")
|
||||
|
||||
[node name="CollisionShape2D2" type="CollisionShape2D" parent="."]
|
||||
visible = false
|
||||
position = Vector2(0, -4)
|
||||
scale = Vector2(1, 4)
|
||||
scale = Vector2(1.1, 4.4)
|
||||
shape = SubResource("CircleShape2D_ghbl6")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.583047, 0.321422, 0.988413, 1)
|
||||
position = Vector2(0, 15)
|
||||
scale = Vector2(1.2, 1.2)
|
||||
scale = Vector2(1.4, 1.4)
|
||||
texture = ExtResource("3_ssiqx")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
scale = Vector2(1.6, 1.6)
|
||||
scale = Vector2(1.8, 1.8)
|
||||
texture = ExtResource("3_a5yxq")
|
||||
|
||||
[node name="EarthAligner" parent="." instance=ExtResource("3_ktv3s")]
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d4mrbgfl7jpqq"
|
||||
path="res://.godot/imported/ItemShine.png-41425a3fac8f6530e2b2e4df0c180258.ctex"
|
||||
path="res://.godot/imported/ItemShine.png-034066fd9fe20ff0370bbee7c72c08ef.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/ItemShine.png"
|
||||
dest_files=["res://.godot/imported/ItemShine.png-41425a3fac8f6530e2b2e4df0c180258.ctex"]
|
||||
source_file="res://items/generic/ItemShine.png"
|
||||
dest_files=["res://.godot/imported/ItemShine.png-034066fd9fe20ff0370bbee7c72c08ef.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
52
items/generic/active_item.gd
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
class_name ActiveItem extends Item
|
||||
|
||||
@onready var active_item_uses = get_tree().get_root().get_node_or_null("main/UIOverlay/ActiveItemUses")
|
||||
|
||||
@export var sprite : Texture2D
|
||||
@export var uses_left_icon : PackedScene
|
||||
@export var uses = 1:
|
||||
set(new_uses):
|
||||
uses = new_uses
|
||||
refresh_uses_ui()
|
||||
|
||||
func refresh_uses_ui():
|
||||
# Set the amount and type of child nodes active_item_uses has according to num_uses.
|
||||
if active_item_uses != null:
|
||||
while active_item_uses.get_children().size() > uses:
|
||||
active_item_uses.remove_child(active_item_uses.get_child(0))
|
||||
if uses_left_icon != null:
|
||||
while active_item_uses.get_children().size() < uses:
|
||||
active_item_uses.add_child(uses_left_icon.instantiate())
|
||||
|
||||
# Called when the active item is touched. It will only be collected if
|
||||
# the player has space, in which case actually_collect() is called.
|
||||
func collect() -> bool:
|
||||
if (player.active_item == null or (player.active_item.item_name == item_name and player.active_item.uses < uses)):
|
||||
player.active_item = self
|
||||
uses = uses
|
||||
actually_collect()
|
||||
return true
|
||||
return false
|
||||
|
||||
# Intended to be overridden by item classes.
|
||||
func actually_collect():
|
||||
pass
|
||||
|
||||
func trigger_activation():
|
||||
activate()
|
||||
if uses != -1:
|
||||
uses -= 1
|
||||
if uses == 0:
|
||||
remove()
|
||||
|
||||
# Intended to be overridden by item classes.
|
||||
func activate():
|
||||
pass
|
||||
|
||||
# When removed, also removes the reference from the player and removes the uses.
|
||||
func remove(reset_player_active = true):
|
||||
if player.active_item == self:
|
||||
uses = 0
|
||||
if reset_player_active:
|
||||
player.active_item = null
|
||||
self.queue_free()
|
||||
|
|
@ -6,6 +6,8 @@ var collected = false
|
|||
|
||||
func _process(_delta: float) -> void:
|
||||
if(is_instance_valid(player) and overlaps_body(player)):
|
||||
# Attempt to collect the item. If successful, play the collect animation
|
||||
# and attach the item to the player.
|
||||
if(self.has_method("collect") and collect()):
|
||||
set_deferred("monitoring", false)
|
||||
set_deferred("monitorable", false)
|
||||
|
|
@ -13,10 +15,12 @@ func _process(_delta: float) -> void:
|
|||
collect_animation()
|
||||
collected = true
|
||||
|
||||
# Placeholder for a proper animation.
|
||||
func collect_animation():
|
||||
self.visible = false
|
||||
if self.has_node("AudioStreamPlayer2D"): $AudioStreamPlayer2D.play()
|
||||
|
||||
# Intended to be overridden by item classes.
|
||||
func collect():
|
||||
push_error("Please specify item collection behavior")
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
[gd_resource type="Resource" script_class="ItemPool" load_steps=11 format=3 uid="uid://m6yj45qvoecs"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://b00185vygcka1" path="res://items/immediate_items/heal_item/heal_item.tscn" id="1_2l6sh"]
|
||||
[ext_resource type="PackedScene" uid="uid://wc7kgtomy6xm" path="res://items/permanent_items/extrajump/extrajump.tscn" id="2_rli0f"]
|
||||
[ext_resource type="PackedScene" uid="uid://gwctb2xqsbj" path="res://items/immediate_items/healthup/healthup.tscn" id="3_g002j"]
|
||||
[ext_resource type="PackedScene" uid="uid://ewe36lqcjojk" path="res://items/active_items/updash/updash.tscn" id="4_vpswe"]
|
||||
[ext_resource type="PackedScene" uid="uid://ddn025xnjngko" path="res://items/active_items/bow/bow.tscn" id="5_jwi73"]
|
||||
[ext_resource type="PackedScene" uid="uid://bbpf28ohayd8n" path="res://items/permanent_items/backslash/backslash.tscn" id="6_73uum"]
|
||||
[ext_resource type="PackedScene" uid="uid://b00185vygcka1" path="res://items/consumables/heal_item/heal_item.tscn" id="1_rli0f"]
|
||||
[ext_resource type="PackedScene" uid="uid://dy17xhg1yrl0o" path="res://items/consumables/horizontal_dash/horizontal_dash.tscn" id="2_g002j"]
|
||||
[ext_resource type="PackedScene" uid="uid://ddn025xnjngko" path="res://items/consumables/bow/bow.tscn" id="3_vpswe"]
|
||||
[ext_resource type="PackedScene" uid="uid://ewe36lqcjojk" path="res://items/consumables/updash/updash.tscn" id="4_jwi73"]
|
||||
[ext_resource type="PackedScene" uid="uid://gwctb2xqsbj" path="res://items/rare_items/healthup/healthup.tscn" id="5_73uum"]
|
||||
[ext_resource type="Script" uid="uid://bgbqefa6h7ckv" path="res://items/generic/item_pool.gd" id="6_rli0f"]
|
||||
[ext_resource type="PackedScene" uid="uid://bpgo1djj8f1rg" path="res://items/permanent_items/high_jump/high_jump.tscn" id="7_k6eth"]
|
||||
[ext_resource type="PackedScene" uid="uid://bwtdls58ajair" path="res://items/permanent_items/upslash/upslash.tscn" id="8_8cxou"]
|
||||
[ext_resource type="PackedScene" uid="uid://dy17xhg1yrl0o" path="res://items/active_items/horizontal_dash/horizontal_dash.tscn" id="9_esvgx"]
|
||||
[ext_resource type="PackedScene" uid="uid://bbpf28ohayd8n" path="res://items/unique_items/backslash/backslash.tscn" id="7_k6eth"]
|
||||
[ext_resource type="PackedScene" uid="uid://bpgo1djj8f1rg" path="res://items/unique_items/high_jump/high_jump.tscn" id="8_8cxou"]
|
||||
[ext_resource type="PackedScene" uid="uid://bwtdls58ajair" path="res://items/unique_items/upslash/upslash.tscn" id="9_esvgx"]
|
||||
[ext_resource type="PackedScene" uid="uid://wc7kgtomy6xm" path="res://items/unique_items/extrajump/extrajump.tscn" id="10_l52h1"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("6_rli0f")
|
||||
common = Array[PackedScene]([ExtResource("1_2l6sh")])
|
||||
rare = Array[PackedScene]([ExtResource("3_g002j"), ExtResource("2_rli0f"), ExtResource("4_vpswe"), ExtResource("5_jwi73")])
|
||||
unique = Array[PackedScene]([ExtResource("6_73uum"), ExtResource("7_k6eth"), ExtResource("8_8cxou"), ExtResource("9_esvgx")])
|
||||
common = Array[PackedScene]([ExtResource("1_rli0f"), ExtResource("1_rli0f"), ExtResource("1_rli0f"), ExtResource("2_g002j"), ExtResource("3_vpswe"), ExtResource("4_jwi73")])
|
||||
rare = Array[PackedScene]([ExtResource("5_73uum")])
|
||||
unique = Array[PackedScene]([ExtResource("7_k6eth"), ExtResource("8_8cxou"), ExtResource("9_esvgx"), ExtResource("10_l52h1"), ExtResource("5_73uum"), ExtResource("5_73uum"), ExtResource("5_73uum")])
|
||||
|
|
|
|||
|
|
@ -1,35 +1,55 @@
|
|||
class_name ItemSpawn extends Node2D
|
||||
|
||||
static var item_pool : ItemPool = ResourceLoader.load("res://items/generic/item_pool.tres","ItemPool",ResourceLoader.CACHE_MODE_IGNORE)
|
||||
static var item_pool = ResourceLoader.load("res://items/generic/item_pool.tres","",ResourceLoader.CACHE_MODE_IGNORE)
|
||||
|
||||
@export var rarity_bonus : float = 0
|
||||
@export var guarantee_rare : bool = false
|
||||
|
||||
@export var unique_base_chance = 0.08
|
||||
@export var rare_base_chance = .16
|
||||
@export var unique_bonus_multiplier = .025
|
||||
@export var rare_bonus_multiplier = .1
|
||||
@export var unique_base_chance = 0.24
|
||||
@export var rare_base_chance = 0
|
||||
@export var unique_bonus_multiplier = .05
|
||||
@export var rare_bonus_multiplier = 0
|
||||
|
||||
@export var spawn_petal = true
|
||||
@export var petal_scene : PackedScene = ResourceLoader.load("res://vines_petals/petal.tscn")
|
||||
|
||||
var packed_item_scene : PackedScene
|
||||
|
||||
var remove_after_spawn = false
|
||||
|
||||
# Choose the item pool this spawn location draws from
|
||||
func choose_pool() -> Array[PackedScene]:
|
||||
spawn_petal = false
|
||||
var unique_chance = unique_base_chance + unique_bonus_multiplier * rarity_bonus
|
||||
var rare_chance = rare_base_chance + rare_bonus_multiplier * rarity_bonus
|
||||
|
||||
var random = randf()
|
||||
if random < unique_chance && item_pool.unique.size() > 0:
|
||||
# Unique items are removed from the pool when picked
|
||||
remove_after_spawn = true
|
||||
return item_pool.unique
|
||||
elif random < unique_chance + rare_chance || guarantee_rare:
|
||||
return item_pool.rare
|
||||
return item_pool.common
|
||||
|
||||
|
||||
# Places a petal holding this item
|
||||
func instantiate_petal(item):
|
||||
var petal : Petal = petal_scene.instantiate()
|
||||
get_parent().call_deferred("add_child", petal)
|
||||
petal.item = item
|
||||
petal.global_position = global_position
|
||||
|
||||
func _ready():
|
||||
# Pick a random pool and a random item from it, then remove it if unique.
|
||||
var pool = choose_pool()
|
||||
var index = randi_range(0, pool.size() - 1)
|
||||
var packed_scene : PackedScene = pool[index]
|
||||
packed_item_scene = pool[index]
|
||||
if remove_after_spawn:
|
||||
item_pool.unique.remove_at(index)
|
||||
var object = packed_scene.instantiate()
|
||||
|
||||
# Place the item, possibly inside a petal
|
||||
if packed_item_scene == null: return
|
||||
var object = packed_item_scene.instantiate()
|
||||
add_child.call_deferred(object)
|
||||
object.reparent.call_deferred(get_parent())
|
||||
if spawn_petal: instantiate_petal(object)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://xj0of571aur1"]
|
||||
[gd_scene load_steps=4 format=3 uid="uid://xj0of571aur1"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b8em61mqgdi58" path="res://items/generic/item_spawn.gd" id="1_ms6tn"]
|
||||
[ext_resource type="PackedScene" uid="uid://bhhhvaqhm3ctc" path="res://vines_petals/petal.tscn" id="2_5to52"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="3_5pwuf"]
|
||||
|
||||
[node name="ItemSpawn" type="Node2D"]
|
||||
script = ExtResource("1_ms6tn")
|
||||
petal_scene = ExtResource("2_5to52")
|
||||
metadata/_custom_type_script = "uid://b8em61mqgdi58"
|
||||
|
||||
[node name="EarthAligner" parent="." instance=ExtResource("3_5pwuf")]
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
extends Item
|
||||
|
||||
func collect():
|
||||
player.jump_strength = 1600
|
||||
$SoundCollect.play()
|
||||
return true
|
||||
|
|
@ -4,5 +4,5 @@ extends Item
|
|||
|
||||
func collect() -> bool:
|
||||
player.max_hp += max_health_increase
|
||||
player.current_hp = min(player.max_hp, player.current_hp + heal_amount)
|
||||
player.current_hp += max_health_increase
|
||||
return true
|
||||
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cp4uia4l6j5nt"
|
||||
path="res://.godot/imported/healthup.png-154169bafb62b18f75d6b0b15f585161.ctex"
|
||||
path="res://.godot/imported/healthup.png-2c1ab3085e0e24d17f4f5b1fcfed814f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/immediate_items/healthup/healthup.png"
|
||||
dest_files=["res://.godot/imported/healthup.png-154169bafb62b18f75d6b0b15f585161.ctex"]
|
||||
source_file="res://items/rare_items/healthup/healthup.png"
|
||||
dest_files=["res://.godot/imported/healthup.png-2c1ab3085e0e24d17f4f5b1fcfed814f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://gwctb2xqsbj"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ce6fxbjarlvtk" path="res://items/immediate_items/healthup/healthup.gd" id="1_ivtxh"]
|
||||
[ext_resource type="Texture2D" uid="uid://cp4uia4l6j5nt" path="res://items/immediate_items/healthup/healthup.png" id="2_gb062"]
|
||||
[ext_resource type="Script" uid="uid://ce6fxbjarlvtk" path="res://items/rare_items/healthup/healthup.gd" id="1_ivtxh"]
|
||||
[ext_resource type="Texture2D" uid="uid://cp4uia4l6j5nt" path="res://items/rare_items/healthup/healthup.png" id="2_gb062"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="2_lolop"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="3_gb062"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="3_gb062"]
|
||||
[ext_resource type="AudioStream" uid="uid://b37akn7hmk2r3" path="res://sounds/471834__keshafilm__health-pickup.wav" id="6_uq82b"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_rlcnv"]
|
||||
|
|
@ -23,12 +23,12 @@ shape = SubResource("CircleShape2D_rlcnv")
|
|||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.583047, 0.321422, 0.988413, 1)
|
||||
position = Vector2(1, -1)
|
||||
scale = Vector2(1.2, 1.2)
|
||||
scale = Vector2(1.4, 1.4)
|
||||
texture = ExtResource("3_gb062")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
position = Vector2(4, -3)
|
||||
scale = Vector2(1.1, 1.1)
|
||||
scale = Vector2(1.5, 1.5)
|
||||
texture = ExtResource("2_gb062")
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||
|
|
@ -3,6 +3,7 @@ extends Item
|
|||
@export var sword : PackedScene
|
||||
|
||||
func collect() -> bool:
|
||||
# Give the player a new sword facing towards th back.
|
||||
var sword_instance = sword.instantiate()
|
||||
player.add_child(sword_instance)
|
||||
sword_instance.facing_mult = -1
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c7mrm8uel7r36"
|
||||
path="res://.godot/imported/backslash.png-627b3c40a1c8a6f83dc2a8bbc2d29adb.ctex"
|
||||
path="res://.godot/imported/backslash.png-d9537e0b7044cf5f7b1de9b329c0275d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/permanent_items/backslash/backslash.png"
|
||||
dest_files=["res://.godot/imported/backslash.png-627b3c40a1c8a6f83dc2a8bbc2d29adb.ctex"]
|
||||
source_file="res://items/unique_items/backslash/backslash.png"
|
||||
dest_files=["res://.godot/imported/backslash.png-d9537e0b7044cf5f7b1de9b329c0275d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://bbpf28ohayd8n"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://blg876atd71cg" path="res://items/permanent_items/backslash/backslash.gd" id="1_s4bdx"]
|
||||
[ext_resource type="Script" uid="uid://blg876atd71cg" path="res://items/unique_items/backslash/backslash.gd" id="1_s4bdx"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="2_kiuxs"]
|
||||
[ext_resource type="PackedScene" uid="uid://d3e3kuyeh6mr1" path="res://player/sword.tscn" id="2_u6vk4"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="4_legpc"]
|
||||
[ext_resource type="Texture2D" uid="uid://c7mrm8uel7r36" path="res://items/permanent_items/backslash/backslash.png" id="5_qg660"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="4_legpc"]
|
||||
[ext_resource type="Texture2D" uid="uid://c7mrm8uel7r36" path="res://items/unique_items/backslash/backslash.png" id="5_qg660"]
|
||||
[ext_resource type="AudioStream" uid="uid://pdd0sy3p4y0d" path="res://sounds/750240__universfield__coin-drop.mp3" id="6_qg660"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_hvhjo"]
|
||||
|
|
@ -18,18 +18,17 @@ item_name = "Second Blade"
|
|||
[node name="EarthAligner" parent="." instance=ExtResource("2_kiuxs")]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
visible = false
|
||||
scale = Vector2(7, 7)
|
||||
scale = Vector2(4, 4)
|
||||
shape = SubResource("CircleShape2D_hvhjo")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.725757, 0.519822, 5.77569e-07, 1)
|
||||
scale = Vector2(2.5, 2.5)
|
||||
scale = Vector2(1.4, 1.4)
|
||||
texture = ExtResource("4_legpc")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
position = Vector2(-3, -2)
|
||||
scale = Vector2(2.4, 2.4)
|
||||
scale = Vector2(1.6, 1.6)
|
||||
texture = ExtResource("5_qg660")
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dicx1uk4187dq"
|
||||
path="res://.godot/imported/extrajump.png-b4900058bcc784042b34649841ea8810.ctex"
|
||||
path="res://.godot/imported/extrajump.png-05dd8382741d643c60de1808878c2a6e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/permanent_items/extrajump/extrajump.png"
|
||||
dest_files=["res://.godot/imported/extrajump.png-b4900058bcc784042b34649841ea8810.ctex"]
|
||||
source_file="res://items/unique_items/extrajump/extrajump.png"
|
||||
dest_files=["res://.godot/imported/extrajump.png-05dd8382741d643c60de1808878c2a6e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://wc7kgtomy6xm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bnr7cpjuvy6xj" path="res://items/permanent_items/extrajump/extrajump.gd" id="1_t7gtn"]
|
||||
[ext_resource type="Script" uid="uid://bnr7cpjuvy6xj" path="res://items/unique_items/extrajump/extrajump.gd" id="1_t7gtn"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="2_70c5v"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="3_hw3fr"]
|
||||
[ext_resource type="Texture2D" uid="uid://dicx1uk4187dq" path="res://items/permanent_items/extrajump/extrajump.png" id="3_t7gtn"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="3_hw3fr"]
|
||||
[ext_resource type="Texture2D" uid="uid://dicx1uk4187dq" path="res://items/unique_items/extrajump/extrajump.png" id="3_t7gtn"]
|
||||
[ext_resource type="AudioStream" uid="uid://pdd0sy3p4y0d" path="res://sounds/750240__universfield__coin-drop.mp3" id="5_kn13r"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hw3fr"]
|
||||
|
|
@ -22,7 +22,7 @@ position = Vector2(1.90735e-06, 0.999999)
|
|||
shape = SubResource("RectangleShape2D_hw3fr")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.583047, 0.321422, 0.988413, 1)
|
||||
modulate = Color(0.7254902, 0.52156866, 0, 1)
|
||||
position = Vector2(0, 2)
|
||||
scale = Vector2(1.5, 1.5)
|
||||
texture = ExtResource("3_hw3fr")
|
||||
7
items/unique_items/high_jump/high_jump.gd
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
extends Item
|
||||
|
||||
func collect():
|
||||
player.ground_jump_strength = 1600
|
||||
player.air_jump_strength = 1400
|
||||
$SoundCollect.play()
|
||||
return true
|
||||
|
Before Width: | Height: | Size: 868 B After Width: | Height: | Size: 868 B |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c6pyyfgkhytu5"
|
||||
path="res://.godot/imported/high_jump.png-1048e30a3bfeaa9531008ef81208b49f.ctex"
|
||||
path="res://.godot/imported/high_jump.png-1067a48863a7f4045d2fdd5833c9cc16.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/permanent_items/high_jump/high_jump.png"
|
||||
dest_files=["res://.godot/imported/high_jump.png-1048e30a3bfeaa9531008ef81208b49f.ctex"]
|
||||
source_file="res://items/unique_items/high_jump/high_jump.png"
|
||||
dest_files=["res://.godot/imported/high_jump.png-1067a48863a7f4045d2fdd5833c9cc16.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://bpgo1djj8f1rg"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cq6h2iven3rly" path="res://items/permanent_items/high_jump/high_jump.gd" id="1_7gixi"]
|
||||
[ext_resource type="Script" uid="uid://cq6h2iven3rly" path="res://items/unique_items/high_jump/high_jump.gd" id="1_7gixi"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="2_s7mjt"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="3_ui5no"]
|
||||
[ext_resource type="Texture2D" uid="uid://c6pyyfgkhytu5" path="res://items/permanent_items/high_jump/high_jump.png" id="4_7gixi"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="3_ui5no"]
|
||||
[ext_resource type="Texture2D" uid="uid://c6pyyfgkhytu5" path="res://items/unique_items/high_jump/high_jump.png" id="4_7gixi"]
|
||||
[ext_resource type="AudioStream" uid="uid://pdd0sy3p4y0d" path="res://sounds/750240__universfield__coin-drop.mp3" id="5_s7mjt"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_bya24"]
|
||||
|
|
@ -23,12 +23,12 @@ shape = SubResource("CircleShape2D_bya24")
|
|||
|
||||
[node name="SpriteGlint" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.725757, 0.519822, 5.77569e-07, 1)
|
||||
scale = Vector2(2.5, 2.5)
|
||||
scale = Vector2(1.4, 1.4)
|
||||
texture = ExtResource("3_ui5no")
|
||||
|
||||
[node name="SpriteItem" type="Sprite2D" parent="."]
|
||||
texture_filter = 1
|
||||
scale = Vector2(4, 4)
|
||||
scale = Vector2(2.4, 2.4)
|
||||
texture = ExtResource("4_7gixi")
|
||||
|
||||
[node name="SoundCollect" type="AudioStreamPlayer2D" parent="."]
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
|
@ -3,15 +3,15 @@
|
|||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bhsmtgdpbxq46"
|
||||
path="res://.godot/imported/upslash.png-284818e0c0e6551e342cba63442fd5f7.ctex"
|
||||
path="res://.godot/imported/upslash.png-80aa495c6e97ba4b13b5c25052544db0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://items/permanent_items/upslash/upslash.png"
|
||||
dest_files=["res://.godot/imported/upslash.png-284818e0c0e6551e342cba63442fd5f7.ctex"]
|
||||
source_file="res://items/unique_items/upslash/upslash.png"
|
||||
dest_files=["res://.godot/imported/upslash.png-80aa495c6e97ba4b13b5c25052544db0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://bwtdls58ajair"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cyql6o6m4xrv3" path="res://items/permanent_items/upslash/upslash.gd" id="1_vv4qh"]
|
||||
[ext_resource type="Script" uid="uid://cyql6o6m4xrv3" path="res://items/unique_items/upslash/upslash.gd" id="1_vv4qh"]
|
||||
[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="3_ayb0v"]
|
||||
[ext_resource type="Texture2D" uid="uid://bhsmtgdpbxq46" path="res://items/permanent_items/upslash/upslash.png" id="4_4ynxq"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/ItemShine.png" id="4_35mg8"]
|
||||
[ext_resource type="Texture2D" uid="uid://bhsmtgdpbxq46" path="res://items/unique_items/upslash/upslash.png" id="4_4ynxq"]
|
||||
[ext_resource type="Texture2D" uid="uid://d4mrbgfl7jpqq" path="res://items/generic/ItemShine.png" id="4_35mg8"]
|
||||
[ext_resource type="AudioStream" uid="uid://pdd0sy3p4y0d" path="res://sounds/750240__universfield__coin-drop.mp3" id="6_5tj4p"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_hvhjo"]
|
||||
|
|
@ -16,18 +16,17 @@ item_name = "Upward Slash"
|
|||
[node name="EarthAligner" parent="." instance=ExtResource("3_ayb0v")]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
visible = false
|
||||
scale = Vector2(7, 7)
|
||||
scale = Vector2(3.5, 3.5)
|
||||
shape = SubResource("CircleShape2D_hvhjo")
|
||||
|
||||
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||
modulate = Color(0.725757, 0.519822, 5.77569e-07, 1)
|
||||
scale = Vector2(2.5, 2.5)
|
||||
scale = Vector2(1.4, 1.4)
|
||||
texture = ExtResource("4_35mg8")
|
||||
|
||||
[node name="Sprite2D3" type="Sprite2D" parent="."]
|
||||
position = Vector2(0, -18)
|
||||
scale = Vector2(2.8, 2.8)
|
||||
position = Vector2(0, -9.000003)
|
||||
scale = Vector2(1.6, 1.6)
|
||||
texture = ExtResource("4_4ynxq")
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||
13
main.tscn
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=15 format=3 uid="uid://cxo6bq26huau7"]
|
||||
[gd_scene load_steps=16 format=3 uid="uid://cxo6bq26huau7"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cmaovvr15b3qk" path="res://player/player.tscn" id="2_1bvp3"]
|
||||
[ext_resource type="Texture2D" uid="uid://d3fpq76anm4t7" path="res://world/Background Prototype/Background prototype.png" id="3_kek77"]
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
[ext_resource type="Script" uid="uid://cpaskpj67pnaj" path="res://enemies/boss/boss_spawner.gd" id="10_efxa6"]
|
||||
[ext_resource type="PackedScene" uid="uid://cqn67nwyrtq3k" path="res://ui/journal/journal.tscn" id="10_w48qg"]
|
||||
[ext_resource type="PackedScene" uid="uid://cpe4s6vsn0ujd" path="res://enemies/boss/boss.tscn" id="11_efxa6"]
|
||||
[ext_resource type="Script" uid="uid://gul4u5tw1vxk" path="res://background/bg_image.gd" id="13_vivmo"]
|
||||
|
||||
[node name="main" type="Node2D"]
|
||||
|
||||
|
|
@ -54,6 +55,14 @@ texture = ExtResource("4_ycdy4")
|
|||
offset_right = 96.0
|
||||
offset_bottom = 96.0
|
||||
|
||||
[node name="ActiveItemUses" type="VBoxContainer" parent="UIOverlay"]
|
||||
unique_name_in_owner = true
|
||||
offset_left = 1863.0
|
||||
offset_top = 25.0
|
||||
offset_right = 1895.0
|
||||
offset_bottom = 120.0
|
||||
alignment = 2
|
||||
|
||||
[node name="ItemUI" parent="UIOverlay" node_paths=PackedStringArray("player") instance=ExtResource("6_4c57u")]
|
||||
player = NodePath("../../Player")
|
||||
|
||||
|
|
@ -87,6 +96,8 @@ anchor_bottom = 1.0
|
|||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
texture = ExtResource("3_kek77")
|
||||
script = ExtResource("13_vivmo")
|
||||
colors = Array[Color]([Color(0, 0.6441987, 0.6693053, 1), Color(0.90588236, 0.15686275, 0.21176471, 0.60784316), Color(0.69803923, 0.69803923, 0.69803923, 1)])
|
||||
|
||||
[node name="BossSpawner" type="Node" parent="."]
|
||||
script = ExtResource("10_efxa6")
|
||||
|
|
|
|||
129
main.tscn13002292799.tmp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
[gd_scene load_steps=18 format=3 uid="uid://cxo6bq26huau7"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cmaovvr15b3qk" path="res://player/player.tscn" id="2_1bvp3"]
|
||||
[ext_resource type="Texture2D" uid="uid://d3fpq76anm4t7" path="res://world/Background Prototype/Background prototype.png" id="3_kek77"]
|
||||
[ext_resource type="PackedScene" uid="uid://jjoyj1ldafkf" path="res://world/earth.tscn" id="3_lquwl"]
|
||||
[ext_resource type="Script" uid="uid://colvx6wq0e8n7" path="res://world/building_generator.gd" id="4_1bvp3"]
|
||||
[ext_resource type="PackedScene" uid="uid://snvs7fty1l5a" path="res://ui/initial_text/initial_text.tscn" id="4_dg77c"]
|
||||
[ext_resource type="Texture2D" uid="uid://c6bd4kakb1tr3" path="res://utils/empty.png" id="4_ycdy4"]
|
||||
[ext_resource type="PackedScene" uid="uid://73g8y37skebh" path="res://ui/item_ui/item_ui.tscn" id="6_4c57u"]
|
||||
[ext_resource type="PackedScene" uid="uid://cjsrtswk4vgf2" path="res://ui/healthbar/healthbar.tscn" id="6_7mycd"]
|
||||
[ext_resource type="PackedScene" uid="uid://dpdn2php3ydsv" path="res://ui/death_screen/death_screen.tscn" id="7_5vw27"]
|
||||
[ext_resource type="Script" uid="uid://3k6r3jnko4hg" path="res://utils/show_fps.gd" id="8_5vw27"]
|
||||
[ext_resource type="PackedScene" uid="uid://ca5ndobertnp4" path="res://water/water.tscn" id="10_4c57u"]
|
||||
[ext_resource type="Script" uid="uid://cpaskpj67pnaj" path="res://enemies/boss/boss_spawner.gd" id="10_efxa6"]
|
||||
[ext_resource type="PackedScene" uid="uid://cqn67nwyrtq3k" path="res://ui/journal/journal.tscn" id="10_w48qg"]
|
||||
[ext_resource type="PackedScene" uid="uid://cpe4s6vsn0ujd" path="res://enemies/boss/boss.tscn" id="11_efxa6"]
|
||||
[ext_resource type="Script" uid="uid://gul4u5tw1vxk" path="res://bg_image.gd" id="13_vivmo"]
|
||||
[ext_resource type="PackedScene" uid="uid://dhxnae8wbhp3u" path="res://vines_petals/bud.tscn" id="16_2cqfq"]
|
||||
[ext_resource type="PackedScene" uid="uid://b7o82cdfwuqd1" path="res://vines_petals/vine.tscn" id="17_yaehf"]
|
||||
|
||||
[node name="main" type="Node2D"]
|
||||
|
||||
[node name="Earth" parent="." instance=ExtResource("3_lquwl")]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("2_1bvp3")]
|
||||
unique_name_in_owner = true
|
||||
position = Vector2(578, -3017)
|
||||
scale = Vector2(3, 3)
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="Player"]
|
||||
position = Vector2(0, -50)
|
||||
ignore_rotation = false
|
||||
|
||||
[node name="Debug_Camera" type="Camera2D" parent="."]
|
||||
scale = Vector2(41.02, 41.02)
|
||||
zoom = Vector2(0.12, 0.12)
|
||||
|
||||
[node name="Building Generator" type="Node" parent="."]
|
||||
script = ExtResource("4_1bvp3")
|
||||
initial_buildings = 10
|
||||
|
||||
[node name="Timer" type="Timer" parent="Building Generator"]
|
||||
wait_time = 3.0
|
||||
autostart = true
|
||||
|
||||
[node name="UIOverlay" type="CanvasLayer" parent="."]
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="UIOverlay"]
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
texture = ExtResource("4_ycdy4")
|
||||
|
||||
[node name="InitialText" parent="UIOverlay" instance=ExtResource("4_dg77c")]
|
||||
|
||||
[node name="Healthbar" parent="UIOverlay" instance=ExtResource("6_7mycd")]
|
||||
offset_right = 96.0
|
||||
offset_bottom = 96.0
|
||||
|
||||
[node name="ActiveItemUses" type="VBoxContainer" parent="UIOverlay"]
|
||||
unique_name_in_owner = true
|
||||
offset_left = 1863.0
|
||||
offset_top = 25.0
|
||||
offset_right = 1895.0
|
||||
offset_bottom = 120.0
|
||||
alignment = 2
|
||||
|
||||
[node name="ItemUI" parent="UIOverlay" node_paths=PackedStringArray("player") instance=ExtResource("6_4c57u")]
|
||||
player = NodePath("../../Player")
|
||||
|
||||
[node name="DeathScreen" parent="UIOverlay" instance=ExtResource("7_5vw27")]
|
||||
visible = false
|
||||
|
||||
[node name="FPS" type="Label" parent="UIOverlay"]
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -40.0
|
||||
offset_bottom = 23.0
|
||||
grow_horizontal = 0
|
||||
script = ExtResource("8_5vw27")
|
||||
|
||||
[node name="Journal" parent="UIOverlay" instance=ExtResource("10_w48qg")]
|
||||
visible = false
|
||||
|
||||
[node name="Water" parent="." instance=ExtResource("10_4c57u")]
|
||||
unique_name_in_owner = true
|
||||
z_index = 15
|
||||
position = Vector2(102, 0)
|
||||
|
||||
[node name="Background" type="CanvasLayer" parent="."]
|
||||
layer = -1
|
||||
|
||||
[node name="ColorRect" type="TextureRect" parent="Background"]
|
||||
modulate = Color(0.544974, 0.544974, 0.544974, 1)
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
texture = ExtResource("3_kek77")
|
||||
script = ExtResource("13_vivmo")
|
||||
colors = Array[Color]([Color(0, 0.6441987, 0.6693053, 1), Color(0.90588236, 0.15686275, 0.21176471, 0.60784316), Color(0.69803923, 0.69803923, 0.69803923, 1)])
|
||||
|
||||
[node name="BossSpawner" type="Node" parent="."]
|
||||
script = ExtResource("10_efxa6")
|
||||
boss = ExtResource("11_efxa6")
|
||||
|
||||
[node name="Vine" parent="." instance=ExtResource("17_yaehf")]
|
||||
|
||||
[node name="Bud" parent="Vine" instance=ExtResource("16_2cqfq")]
|
||||
position = Vector2(271, -3293)
|
||||
|
||||
[node name="Node2D2" type="Node2D" parent="Vine"]
|
||||
position = Vector2(963, -3171)
|
||||
|
||||
[node name="Node2D4" type="Node2D" parent="Vine"]
|
||||
position = Vector2(1035, -3518)
|
||||
|
||||
[node name="Node2D5" type="Node2D" parent="Vine"]
|
||||
position = Vector2(1551, -2955)
|
||||
|
||||
[connection signal="active_item_changed" from="Player" to="UIOverlay/ItemUI" method="_on_player_active_item_changed"]
|
||||
[connection signal="health_changed" from="Player" to="UIOverlay/Healthbar" method="_on_player_health_changed"]
|
||||
[connection signal="max_hp_changed" from="Player" to="UIOverlay/Healthbar" method="_on_player_max_hp_changed"]
|
||||
[connection signal="player_died" from="Player" to="UIOverlay/DeathScreen" method="_on_player_player_died"]
|
||||
[connection signal="timeout" from="Building Generator/Timer" to="Building Generator" method="_on_timer_timeout"]
|
||||
[connection signal="visibility_changed" from="UIOverlay/DeathScreen" to="Player" method="_on_death_screen_visibility_changed"]
|
||||
[connection signal="water_reached_max_height" from="Water" to="BossSpawner" method="_on_water_water_reached_max_height"]
|
||||
200
player/player.gd
|
|
@ -1,10 +1,4 @@
|
|||
class_name Player extends CharacterBody2D
|
||||
# Child Nodes
|
||||
@onready var camera : Camera2D = $Camera2D;
|
||||
@onready var anim_sprite : AnimatedSprite2D = $AnimatedSprite2D;
|
||||
@onready var earth_aligner : Node2D = $EarthAligner;
|
||||
@onready var sword : Area2D = $Sword;
|
||||
@onready var active_item_cooldown : Timer = $ActiveItemCooldown
|
||||
|
||||
@export var double_jump_animation : PackedScene
|
||||
|
||||
|
|
@ -18,38 +12,50 @@ var gravity = 100;
|
|||
|
||||
# Movement
|
||||
var facing = -1;
|
||||
var hspeed = 150;
|
||||
var jump_strength = 1200;
|
||||
var base_hspeed = 150.0;
|
||||
var ground_jump_strength = 1400;
|
||||
var air_jump_strength = 1100;
|
||||
var air_jumps_max = 1;
|
||||
var air_jumps_current = 1;
|
||||
var air_jumps_current = 1:
|
||||
set(air_jumps_new):
|
||||
air_jumps_current = min(air_jumps_new, air_jumps_max)
|
||||
|
||||
# HP and Iframes
|
||||
signal health_changed(new_health : int)
|
||||
signal max_hp_changed(new_max_hp : int)
|
||||
signal player_died
|
||||
|
||||
var hit_iframes = 0.8
|
||||
var current_hp = 5:
|
||||
set(new_hp):
|
||||
current_hp = new_hp
|
||||
health_changed.emit(current_hp)
|
||||
var max_hp = 5:
|
||||
# HP can't be increased above Max HP or reduced below 0
|
||||
# When reduced to 0, the player dies.
|
||||
new_hp = min(new_hp, max_hp)
|
||||
if new_hp <= 0:
|
||||
new_hp = 0
|
||||
die()
|
||||
if new_hp != current_hp:
|
||||
current_hp = new_hp
|
||||
health_changed.emit(current_hp)
|
||||
@export var max_hp = 5:
|
||||
# When Max HP is reduced below current health, current health is adjusted.
|
||||
set(new_max_hp):
|
||||
max_hp = new_max_hp
|
||||
if max_hp <= 0:
|
||||
max_hp = 0
|
||||
if current_hp > max_hp:
|
||||
current_hp = max_hp
|
||||
max_hp_changed.emit(max_hp)
|
||||
var hit_invulnerability = 0.8
|
||||
var inv_time = 0;
|
||||
var dead = false;
|
||||
|
||||
# Received Knockback
|
||||
var reset_to_velocity = Vector2.ZERO
|
||||
var knockback_strength = 1500
|
||||
var damage_knockup = 500
|
||||
@export var friction = 0.5
|
||||
|
||||
# Attack Handling
|
||||
var atk_cooldown = 0.5
|
||||
var atk_timer = 0
|
||||
var can_upslash = false
|
||||
|
||||
signal attack
|
||||
|
||||
# Active Item
|
||||
|
|
@ -61,53 +67,61 @@ var active_item : ActiveItem = null:
|
|||
|
||||
|
||||
func set_cooldown(cooldown):
|
||||
active_item_cooldown.wait_time = cooldown
|
||||
$ActiveItemCooldown.wait_time = cooldown
|
||||
|
||||
func activate_cooldown():
|
||||
active_item_cooldown.start()
|
||||
$ActiveItemCooldown.start()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# Update the Health Bar initially
|
||||
max_hp_changed.emit(max_hp)
|
||||
health_changed.emit(current_hp)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
# Velocity management uses the physics framework, hence runs at fix 60FPS
|
||||
manage_velocity(delta)
|
||||
move_and_slide()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
manage_iframes(delta)
|
||||
func _process(_delta: float) -> void:
|
||||
# All non-velocity management can run without FPS cap
|
||||
update_vine_statuses()
|
||||
manage_movement_options()
|
||||
manage_active(delta)
|
||||
manage_interaction()
|
||||
manage_animation()
|
||||
manage_attack(delta)
|
||||
if handle_input:
|
||||
manage_active()
|
||||
manage_attack()
|
||||
|
||||
func manage_iframes(delta: float):
|
||||
if(inv_time > 0):
|
||||
inv_time = max(0, inv_time-delta)
|
||||
func manage_attack():
|
||||
# If an attack is possible, a signal is sent which the weapon can connect to
|
||||
if(Input.is_action_just_pressed("attack") and $AttackCooldown.time_left <= 0):
|
||||
if Input.is_action_pressed("up") and can_upslash:
|
||||
attack.emit("up")
|
||||
else:
|
||||
attack.emit("horizontal")
|
||||
$Sprite.play("attack")
|
||||
$SwordSwingAudio.play()
|
||||
$AttackCooldown.start()
|
||||
|
||||
func manage_attack(delta : float):
|
||||
atk_timer = max(0, atk_timer-delta)
|
||||
if handle_input:
|
||||
if(Input.is_action_just_pressed("attack") and atk_timer <= 0):
|
||||
if Input.is_action_pressed("up") and can_upslash:
|
||||
attack.emit("up")
|
||||
else:
|
||||
attack.emit("horizontal")
|
||||
$AnimatedSprite2D.play("attack")
|
||||
$SwordSwingAudio.play()
|
||||
atk_timer = atk_cooldown
|
||||
|
||||
func manage_active(_delta : float):
|
||||
if(active_item != null and Input.is_action_just_pressed("item") and active_item_cooldown.is_stopped()):
|
||||
active_item.activate()
|
||||
if(Input.is_action_just_pressed("drop_item")):
|
||||
active_item = null
|
||||
func manage_active():
|
||||
# Activate or remove items. Cooldown + use management is handled by the item.
|
||||
if(active_item != null and Input.is_action_just_pressed("item") and $ActiveItemCooldown.is_stopped()):
|
||||
active_item.trigger_activation()
|
||||
if(Input.is_action_just_pressed("drop_item") and active_item != null):
|
||||
active_item.remove()
|
||||
|
||||
func manage_movement_options() -> void:
|
||||
# Reset Air Jumps when grounded
|
||||
if(is_on_floor()):
|
||||
air_jumps_current = air_jumps_max
|
||||
|
||||
func manage_interaction():
|
||||
# Interacts with all overlapping interactables on button press
|
||||
if Input.is_action_just_pressed("interact"):
|
||||
for area in $InteractBox.get_overlapping_areas():
|
||||
if area.has_method("interact"): area.interact()
|
||||
|
||||
func manage_animation() -> void:
|
||||
var walk_dir = 0
|
||||
if(handle_input):
|
||||
|
|
@ -116,56 +130,81 @@ func manage_animation() -> void:
|
|||
if(Input.is_action_pressed("move_left")):
|
||||
walk_dir -= 1
|
||||
|
||||
if(walk_dir != 0):
|
||||
# Set the direction the player faces
|
||||
if walk_dir != 0:
|
||||
facing = walk_dir
|
||||
anim_sprite.scale.x = - abs(anim_sprite.scale.x) * facing
|
||||
if(is_on_floor() and not $AnimatedSprite2D.is_playing()):
|
||||
anim_sprite.play("walk")
|
||||
$Sprite.scale.x = - abs($Sprite.scale.x) * facing
|
||||
|
||||
# Play the walk or idle animation when appropriate
|
||||
if(walk_dir != 0):
|
||||
if(is_on_floor() and not $Sprite.is_playing()):
|
||||
$Sprite.play("walk")
|
||||
else:
|
||||
if anim_sprite.animation == "walk":
|
||||
anim_sprite.stop()
|
||||
if $Sprite.animation == "walk":
|
||||
$Sprite.stop()
|
||||
|
||||
|
||||
func manage_velocity(delta: float) -> void:
|
||||
up_direction = (position - earth_center).normalized();
|
||||
var old_local_velocity = earth_aligner.local_from_global(velocity)
|
||||
var local_velocity = Vector2(old_local_velocity.x/pow(1.7,60*delta), old_local_velocity.y);
|
||||
up_direction = $EarthAligner.up
|
||||
# Convert the current velocity into local coordinates, then compute changes there.
|
||||
# This is important for capped values such as fall speed.
|
||||
var old_local_velocity = $EarthAligner.local_from_global(velocity)
|
||||
# Apply friction horizontally, exponentially. Factor 1 - friction per frame at 60FPS.
|
||||
var local_velocity = Vector2(old_local_velocity.x * pow(1 - friction,60*delta), old_local_velocity.y);
|
||||
local_velocity += Vector2(0, gravity)
|
||||
|
||||
if handle_input:
|
||||
# Apply Slow Status if present.
|
||||
var hspeed = base_hspeed if not Status.affects("Slow", self) else base_hspeed * get_node("Slow").params.slow_factor
|
||||
|
||||
# Change the local velocity by the movement speed, or more if moving in the opposite direction,
|
||||
# for more responsive turning around.
|
||||
if(Input.is_action_pressed("move_right")):
|
||||
local_velocity += Vector2(hspeed, 0)
|
||||
if local_velocity.x > - 3 * hspeed:
|
||||
local_velocity += Vector2(hspeed, 0)
|
||||
else:
|
||||
local_velocity += Vector2(2 * hspeed, 0)
|
||||
if(Input.is_action_pressed("move_left")):
|
||||
local_velocity += Vector2(-hspeed, 0)
|
||||
|
||||
if local_velocity.x < 3 * hspeed:
|
||||
local_velocity += Vector2(-hspeed, 0)
|
||||
else:
|
||||
local_velocity += Vector2(-2 * hspeed, 0)
|
||||
|
||||
if(Input.is_action_just_pressed("jump") and (is_on_floor() or air_jumps_current > 0)):
|
||||
var dropped = false
|
||||
if(not is_on_floor()):
|
||||
air_jumps_current -= 1;
|
||||
play_double_jump_animation()
|
||||
elif (Input.is_action_pressed("drop")):
|
||||
dropped = true
|
||||
self.position += earth_aligner.global_from_local(Vector2(0,12))
|
||||
if(not dropped):
|
||||
local_velocity.y = -jump_strength
|
||||
# If the player holds drop, just move through the platform
|
||||
if Input.is_action_pressed("drop"):
|
||||
self.position += 12 * $EarthAligner.down
|
||||
else:
|
||||
# Otherwise, either jump from the ground or perform a double jump.
|
||||
if is_on_floor():
|
||||
local_velocity.y = -ground_jump_strength
|
||||
else:
|
||||
air_jumps_current -= 1;
|
||||
play_double_jump_animation()
|
||||
local_velocity.y = -air_jump_strength
|
||||
|
||||
if(local_velocity.y > max_fall_speed):
|
||||
local_velocity.y = max_fall_speed
|
||||
|
||||
if(reset_to_velocity != Vector2.ZERO):
|
||||
local_velocity = reset_to_velocity
|
||||
# When knockback is applied, momentum is reset to the knockback value instead.
|
||||
if(reset_to_velocity.x != 0):
|
||||
local_velocity.x = reset_to_velocity.x
|
||||
if(reset_to_velocity.y != 0):
|
||||
local_velocity.y = reset_to_velocity.y
|
||||
reset_to_velocity = Vector2.ZERO
|
||||
velocity = earth_aligner.global_from_local(local_velocity)
|
||||
|
||||
# Return to world coordinates and apply the changes to velocity.
|
||||
velocity = $EarthAligner.global_from_local(local_velocity)
|
||||
|
||||
|
||||
func hurt(dmg: int, dir: Vector2 = Vector2.ZERO):
|
||||
if(inv_time <= 0):
|
||||
# If the player has no iframes, apply knockback and damage and start iframes.
|
||||
if $IFrames.time_left <= 0:
|
||||
if Status.affects("Vulnerable", self): dmg += 1
|
||||
$AudioStreamPlayer2D.play()
|
||||
current_hp -= dmg
|
||||
if(current_hp <= 0):
|
||||
die()
|
||||
inv_time = hit_invulnerability
|
||||
reset_to_velocity = Vector2(-sign(earth_aligner.local_from_global(dir).x)*knockback_strength, -damage_knockup)
|
||||
$IFrames.start(hit_iframes)
|
||||
reset_to_velocity = Vector2(-sign($EarthAligner.local_from_global(dir).x)*knockback_strength, -damage_knockup)
|
||||
return true
|
||||
return false
|
||||
|
||||
|
|
@ -174,18 +213,29 @@ func die():
|
|||
player_died.emit()
|
||||
dead = true
|
||||
|
||||
# Connected to the signal marking the end of an attack.
|
||||
# Returns to default animation.
|
||||
func _on_attack_end():
|
||||
if($AnimatedSprite2D.animation != "idle"):
|
||||
$AnimatedSprite2D.play("idle")
|
||||
$AnimatedSprite2D.stop()
|
||||
if($Sprite.animation != "idle"):
|
||||
$Sprite.play("idle")
|
||||
$Sprite.stop()
|
||||
|
||||
# Take away player control while the Death Screen is active.
|
||||
func _on_death_screen_visibility_changed() -> void:
|
||||
handle_input = !handle_input
|
||||
|
||||
func play_double_jump_animation() -> void:
|
||||
# Instantiate a sprite which plays a double jump animation, then deletes itself.
|
||||
$AirJumpAudio.play()
|
||||
var node = double_jump_animation.instantiate()
|
||||
add_child(node)
|
||||
node.position = Vector2(0, 5)
|
||||
node.scale = .5 * Vector2.ONE
|
||||
node.reparent(get_parent())
|
||||
|
||||
# If there is any vine nearby, gain the corresponding statusses.
|
||||
func update_vine_statuses():
|
||||
var location = Grid.get_location_from_world_pos(global_position)
|
||||
for vine : Vine in Grid.get_vines_at(location):
|
||||
if vine.active_depth > 0: #TODO: Properly manage procedural activation
|
||||
Status.apply(vine.status_name, self, 0.1, vine.status_params)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ position = Vector2(0.2, 6)
|
|||
scale = Vector2(0.7, 0.72)
|
||||
shape = SubResource("RectangleShape2D_e7oew")
|
||||
|
||||
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
|
||||
[node name="Sprite" type="AnimatedSprite2D" parent="."]
|
||||
scale = Vector2(0.37, 0.37)
|
||||
sprite_frames = SubResource("SpriteFrames_dw050")
|
||||
animation = &"attack"
|
||||
|
|
@ -100,6 +100,14 @@ animation = &"attack"
|
|||
[node name="ActiveItemCooldown" type="Timer" parent="."]
|
||||
one_shot = true
|
||||
|
||||
[node name="IFrames" type="Timer" parent="."]
|
||||
wait_time = 0.8
|
||||
one_shot = true
|
||||
|
||||
[node name="AttackCooldown" type="Timer" parent="."]
|
||||
wait_time = 0.35
|
||||
one_shot = true
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||
stream = ExtResource("11_2ieo8")
|
||||
volume_db = 15.0
|
||||
|
|
@ -113,4 +121,13 @@ pitch_scale = 1.62
|
|||
stream = ExtResource("17_tqiix")
|
||||
volume_db = -12.0
|
||||
|
||||
[connection signal="animation_finished" from="AnimatedSprite2D" to="." method="_on_attack_end"]
|
||||
[node name="InteractBox" type="Area2D" parent="."]
|
||||
collision_layer = 0
|
||||
collision_mask = 64
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="InteractBox"]
|
||||
position = Vector2(0.2, 6)
|
||||
scale = Vector2(0.7, 0.72)
|
||||
shape = SubResource("RectangleShape2D_e7oew")
|
||||
|
||||
[connection signal="animation_finished" from="Sprite" to="." method="_on_attack_end"]
|
||||
|
|
|
|||
|
|
@ -1,36 +1,50 @@
|
|||
extends Area2D
|
||||
var anim_sprite: AnimatedSprite2D
|
||||
var slash_duration = 0.1
|
||||
var slash_timer = 0
|
||||
var damage = 20
|
||||
var facing = -1
|
||||
var facing_mult = 1
|
||||
var dmg_id
|
||||
var swing_knockback = 1000
|
||||
var apply_swing_knockback = true
|
||||
|
||||
func _ready() -> void:
|
||||
anim_sprite = $AnimatedSprite2D
|
||||
get_parent().attack.connect(swing)
|
||||
|
||||
func swing(dir_str) -> void:
|
||||
# Each swing is a new damage instance
|
||||
dmg_id = Global.next_dmg_id
|
||||
facing = - get_parent().facing * facing_mult
|
||||
facing = get_parent().facing * facing_mult
|
||||
# Adjust the orientation depending on direction of the player,
|
||||
# direction of the sword and whether it was an upward strike
|
||||
if dir_str == "up":
|
||||
scale.x = abs(scale.x)
|
||||
scale.y = abs(scale.y) * facing
|
||||
rotation = PI/2
|
||||
scale.y = abs(scale.y) * -facing
|
||||
rotation = PI/2 * facing_mult
|
||||
else:
|
||||
scale.x = abs(scale.x) * facing
|
||||
scale.x = abs(scale.x) * -facing
|
||||
scale.y = abs(scale.y)
|
||||
rotation = 0
|
||||
anim_sprite.visible = true
|
||||
await get_tree().create_timer(0.01).timeout
|
||||
slash_timer = slash_duration
|
||||
|
||||
# Sprite is visible during swing
|
||||
$Sprite.visible = true
|
||||
|
||||
# Wait for the physics to register the new orientation of the sword before starting the swing
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
# Upslashes do not knockback you when you hit
|
||||
if dir_str == "up":
|
||||
apply_swing_knockback = false
|
||||
$SlashTimer.start()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if slash_timer > 0:
|
||||
slash_timer = max(0, slash_timer-delta)
|
||||
if(slash_timer == 0):
|
||||
anim_sprite.visible = false
|
||||
func end_slash():
|
||||
# Reset swing-specific values to default
|
||||
$Sprite.visible = false
|
||||
apply_swing_knockback = true
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if $SlashTimer.time_left > 0:
|
||||
# Hurt all overlapping enemies
|
||||
for area in get_overlapping_areas():
|
||||
var hurt_dir = -get_parent().earth_aligner.global_from_local(Vector2(-facing, 0)).rotated(facing*rotation)
|
||||
area.hurt(damage, hurt_dir, dmg_id)
|
||||
var hurt_dir = -get_parent().get_node("EarthAligner").global_from_local(Vector2(facing, 0)).rotated(-facing*rotation)
|
||||
if area.hurt(damage, hurt_dir, dmg_id) and apply_swing_knockback:
|
||||
get_parent().reset_to_velocity += Vector2(swing_knockback * -facing, 0)
|
||||
apply_swing_knockback = false
|
||||
|
|
|
|||
|
|
@ -28,9 +28,15 @@ rotation = 1.5708
|
|||
scale = Vector2(-0.635, -1.1)
|
||||
shape = SubResource("CapsuleShape2D_e4ynd")
|
||||
|
||||
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
|
||||
[node name="Sprite" type="AnimatedSprite2D" parent="."]
|
||||
visible = false
|
||||
modulate = Color(1, 1, 1, 0.6862745)
|
||||
position = Vector2(-25.644447, 0.61333346)
|
||||
scale = Vector2(-0.385, 0.231)
|
||||
sprite_frames = SubResource("SpriteFrames_fahsa")
|
||||
|
||||
[node name="SlashTimer" type="Timer" parent="."]
|
||||
wait_time = 0.1
|
||||
one_shot = true
|
||||
|
||||
[connection signal="timeout" from="SlashTimer" to="." method="end_slash"]
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ run/main_scene="uid://dpkr8yoobtej6"
|
|||
config/features=PackedStringArray("4.5", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
Grid="*res://world/grid.tscn"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=1920
|
||||
|
|
@ -31,52 +35,68 @@ move_right={
|
|||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
move_left={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
jump={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
attack={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(356, 29),"global_position":Vector2(365, 77),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
drop={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null)
|
||||
]
|
||||
}
|
||||
item={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":88,"key_label":0,"unicode":120,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(297, 25),"global_position":Vector2(306, 73),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
drop_item={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":121,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":3,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
up={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
|
||||
]
|
||||
}
|
||||
journal={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":74,"key_label":0,"unicode":106,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
interact={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":86,"key_label":0,"unicode":118,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +107,7 @@ journal={
|
|||
2d_physics/layer_4="SolidGround"
|
||||
2d_physics/layer_5="EnemyHurtBoxNonTrap"
|
||||
2d_physics/layer_6="TrulySolidGround"
|
||||
2d_physics/layer_7="InteractionArea"
|
||||
|
||||
[rendering]
|
||||
|
||||
|
|
|
|||
58
statusses/status.gd
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Status inherits from Timer: The time until the status expires.
|
||||
class_name Status extends Timer
|
||||
var params = {}
|
||||
const default_parameters = {
|
||||
# Vulnerable: Player Status. Increases Damage taken by 1 per Hit
|
||||
"Vulnerable": {},
|
||||
# Slow: Player Status. Decreases movement speed by speed_factor.
|
||||
# Can theoretically also be used to increase speed.
|
||||
"Slow": {
|
||||
"slow_factor": 0.6
|
||||
}
|
||||
}
|
||||
|
||||
func _ready() -> void:
|
||||
timeout.connect(expire)
|
||||
one_shot = true
|
||||
|
||||
# Applies the given Status as a child to the target node for the given duration.
|
||||
# Was intended to work through statusses inheriting from Status, but Godot inheritance interacts terribly with static things.
|
||||
# If that status is already present on the node, duration is reset and reapply is called.
|
||||
static func apply(status_name : String, target : Node, duration : float, params_in : Dictionary = {}):
|
||||
if not target.has_node(status_name):
|
||||
var child = Status.new()
|
||||
child.name = status_name
|
||||
child.params = get_default_parameters(status_name).duplicate(true)
|
||||
child.params.merge(params_in.duplicate(true))
|
||||
target.add_child(child)
|
||||
child.start(duration)
|
||||
else:
|
||||
var child : Status = target.get_node(status_name)
|
||||
child.reapply(duration)
|
||||
|
||||
# Checks whether the target is affected by the given status.
|
||||
static func affects(status_name : String, target : Node) -> bool:
|
||||
return target.has_node(status_name)
|
||||
|
||||
# Returns the status on the target, or null if the status is not present.
|
||||
static func get_status(status_name : String, target : Node) -> Status:
|
||||
if affects(status_name, target):
|
||||
return target.get_node(status_name)
|
||||
else:
|
||||
return null
|
||||
|
||||
# By default, reapplying a status resets the duration and merges the new parameters into the given ones.
|
||||
func reapply(duration_new : float, params_new : Dictionary = {}):
|
||||
self.start(max(duration_new, time_left))
|
||||
merge_params(params_new)
|
||||
|
||||
# Controls the override behavior of each status
|
||||
func merge_params(params_new):
|
||||
if name == "Slow" and params.has("slow_factor") and params_new.has("slow_factor"):
|
||||
params.slow_factor = min(params.slow_factor, params_new.slow_factor)
|
||||
|
||||
func expire():
|
||||
queue_free()
|
||||
|
||||
static func get_default_parameters(status_name : String) -> Dictionary:
|
||||
return default_parameters.get(status_name, {})
|
||||
1
statusses/status.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://c574sege4i20i
|
||||
|
|
@ -6,25 +6,23 @@ extends Trap
|
|||
var closed = false
|
||||
|
||||
func damage_target(target: CollisionObject2D):
|
||||
# Checks whether the player or an enemy has been hit
|
||||
if(target.get_collision_layer_value(3)):
|
||||
target.hurt(player_damage, Vector2.ZERO)
|
||||
else:
|
||||
target.hurt(enemy_damage, Vector2.ZERO)
|
||||
|
||||
|
||||
# Bear Traps are static, hence it is sufficient to check for others entering the trap
|
||||
func _on_area_2d_area_entered(area: Area2D) -> void:
|
||||
if not closed:
|
||||
damage_target(area)
|
||||
closed = true
|
||||
$AnimatedSprite2D.play("close")
|
||||
await $AnimatedSprite2D.animation_finished
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
queue_free()
|
||||
|
||||
close_on(area)
|
||||
|
||||
func _on_area_2d_body_entered(body: Node2D) -> void:
|
||||
close_on(body)
|
||||
|
||||
# Play the animation and assign the damage
|
||||
func close_on(target):
|
||||
if not closed:
|
||||
damage_target(body)
|
||||
damage_target(target)
|
||||
closed = true
|
||||
$AnimatedSprite2D.play("close")
|
||||
await $AnimatedSprite2D.animation_finished
|
||||
|
|
|
|||