diff --git a/buildings/building.gd b/buildings/building.gd index d7321fe..7c8c604 100644 --- a/buildings/building.gd +++ b/buildings/building.gd @@ -26,6 +26,9 @@ func _ready() -> void: for enemy in enemies: var oldpos = enemy.position; enemy.position = grid.get_world_position(location, oldpos) + if "location" in enemy: enemy.location = location + Vector2i(floor(oldpos.x/300), ceil(-oldpos.y/300)) + if "offset" in enemy: + enemy.offset = Global.vec_mod(oldpos, 300) if enemy is Platform or enemy is Trap or enemy is Item: objects.append(enemy) if "building" in enemy: enemy.building = self diff --git a/buildings/room_giant_leech.tscn b/buildings/room_giant_leech.tscn index 354370b..5b8fe7d 100644 --- a/buildings/room_giant_leech.tscn +++ b/buildings/room_giant_leech.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://oflm2yjjwhf"] +[gd_scene load_steps=11 format=3 uid="uid://oflm2yjjwhf"] [ext_resource type="Script" uid="uid://b2ji03ekijjnn" path="res://buildings/building.gd" id="1_ivy1q"] [ext_resource type="Shader" uid="uid://c7gb1nqwvkr37" path="res://buildings/building.gdshader" id="2_yuthg"] @@ -7,6 +7,7 @@ [ext_resource type="Texture2D" uid="uid://3weywjfsapax" path="res://buildings/Building 2x1 downside.png" id="5_hu6aj"] [ext_resource type="PackedScene" uid="uid://5nb7pf8g1ck" path="res://enemies/leech/giant_leech.tscn" id="8_r3b86"] [ext_resource type="PackedScene" uid="uid://4l3elvxpghw8" path="res://utils/platform.tscn" id="8_y6yyb"] +[ext_resource type="PackedScene" uid="uid://bhhhvaqhm3ctc" path="res://petal.tscn" id="9_dasjy"] [ext_resource type="PackedScene" uid="uid://xj0of571aur1" path="res://items/generic/item_spawn.tscn" id="9_jmdjr"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_pfkkr"] @@ -63,6 +64,9 @@ position = Vector2(300, -200) [node name="Giant_Leech" parent="EnemyList" instance=ExtResource("8_r3b86")] position = Vector2(400, -340) +[node name="Petal" parent="EnemyList" instance=ExtResource("9_dasjy")] +position = Vector2(511, -172) + [node name="DebugSprite" type="Sprite2D" parent="."] visible = false position = Vector2(300, -150) diff --git a/buildings/room_pedastal.tscn b/buildings/room_pedastal.tscn index f4f997d..a2d09da 100644 --- a/buildings/room_pedastal.tscn +++ b/buildings/room_pedastal.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://6y637jp2tbma"] +[gd_scene load_steps=11 format=3 uid="uid://6y637jp2tbma"] [ext_resource type="Script" uid="uid://b2ji03ekijjnn" path="res://buildings/building.gd" id="1_w5m4l"] [ext_resource type="Shader" uid="uid://c7gb1nqwvkr37" path="res://buildings/building.gdshader" id="2_wod1l"] @@ -8,6 +8,7 @@ [ext_resource type="PackedScene" uid="uid://4l3elvxpghw8" path="res://utils/platform.tscn" id="6_caaff"] [ext_resource type="PackedScene" uid="uid://xj0of571aur1" path="res://items/generic/item_spawn.tscn" id="7_elmbw"] [ext_resource type="PackedScene" uid="uid://dpv1w56yr1xue" path="res://traps/morning_star.tscn" id="8_1cnhw"] +[ext_resource type="PackedScene" uid="uid://bhhhvaqhm3ctc" path="res://petal.tscn" id="9_1cnhw"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_qnfc1"] resource_local_to_scene = true @@ -61,6 +62,9 @@ position = Vector2(39, -552) [node name="Ghost2" parent="EnemyList" instance=ExtResource("5_rh5oo")] position = Vector2(301, -39) +[node name="Petal" parent="EnemyList" instance=ExtResource("9_1cnhw")] +position = Vector2(260, -525) + [node name="DebugSprite" type="Sprite2D" parent="."] visible = false position = Vector2(150, -300) diff --git a/buildings/room_pedastal_mean.tscn b/buildings/room_pedastal_mean.tscn index b99b096..0f5bc9b 100644 --- a/buildings/room_pedastal_mean.tscn +++ b/buildings/room_pedastal_mean.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://dt827qxyycg8n"] +[gd_scene load_steps=11 format=3 uid="uid://dt827qxyycg8n"] [ext_resource type="Script" uid="uid://b2ji03ekijjnn" path="res://buildings/building.gd" id="1_pww4b"] [ext_resource type="Shader" uid="uid://c7gb1nqwvkr37" path="res://buildings/building.gdshader" id="2_qsju2"] @@ -8,6 +8,7 @@ [ext_resource type="PackedScene" uid="uid://xj0of571aur1" path="res://items/generic/item_spawn.tscn" id="7_sr858"] [ext_resource type="PackedScene" uid="uid://h3caql0b6vft" path="res://traps/bear_trap.tscn" id="8_pww4b"] [ext_resource type="PackedScene" uid="uid://dpv1w56yr1xue" path="res://traps/morning_star.tscn" id="8_ta0fd"] +[ext_resource type="PackedScene" uid="uid://bhhhvaqhm3ctc" path="res://petal.tscn" id="9_qsju2"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_qnfc1"] resource_local_to_scene = true @@ -53,6 +54,9 @@ position = Vector2(39, -552) [node name="BearTrap" parent="EnemyList" instance=ExtResource("8_pww4b")] position = Vector2(165, -7) +[node name="Petal" parent="EnemyList" instance=ExtResource("9_qsju2")] +position = Vector2(86, -397) + [node name="DebugSprite" type="Sprite2D" parent="."] visible = false position = Vector2(150, -300) diff --git a/main.tscn b/main.tscn index 0e31ad6..18115bd 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=18 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"] @@ -15,8 +15,6 @@ [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"] @@ -106,23 +104,6 @@ colors = Array[Color]([Color(0, 0.6441987, 0.6693053, 1), Color(0.90588236, 0.15 script = ExtResource("10_efxa6") boss = ExtResource("11_efxa6") -[node name="Vine" parent="." instance=ExtResource("17_yaehf")] - -[node name="Bud" parent="Vine" node_paths=PackedStringArray("vine") instance=ExtResource("16_2cqfq")] -position = Vector2(1320, -3484) -vine = NodePath("..") -location = Vector2(46, 1) -offset = Vector2(150, 150) - -[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"] diff --git a/petal.gd b/petal.gd new file mode 100644 index 0000000..9b3c3b1 --- /dev/null +++ b/petal.gd @@ -0,0 +1,18 @@ +extends Node2D +@onready var grid : Grid = get_tree().get_root().get_node("main/Earth/Grid") +@export var location : Vector2 +@export var offset : Vector2 +@export var vine_resource : PackedScene +var vine : Vine + +func _ready() -> void: + await get_tree().create_timer(1).timeout + vine = vine_resource.instantiate() + vine.petal_location = Global.vec_mod(location, grid.num_collumns) + vine.petal_offset = offset + get_parent().call_deferred("add_child",vine) + await get_tree().create_timer(1).timeout + vine.init_random() + +func _on_interaction() -> void: + vine.activate() diff --git a/petal.gd.uid b/petal.gd.uid new file mode 100644 index 0000000..082b5c3 --- /dev/null +++ b/petal.gd.uid @@ -0,0 +1 @@ +uid://coi26l4ndnaw0 diff --git a/petal.tscn b/petal.tscn new file mode 100644 index 0000000..3d8265f --- /dev/null +++ b/petal.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=7 format=3 uid="uid://bhhhvaqhm3ctc"] + +[ext_resource type="Texture2D" uid="uid://d15c1exwtp7sc" path="res://vines_petals/bud_open.png" id="1_05pvv"] +[ext_resource type="Script" uid="uid://coi26l4ndnaw0" path="res://petal.gd" id="1_ybtdj"] +[ext_resource type="PackedScene" uid="uid://b7o82cdfwuqd1" path="res://vines_petals/vine.tscn" id="2_4btcp"] +[ext_resource type="PackedScene" uid="uid://ds21d77ruuk4y" path="res://utils/interactable_area.tscn" id="2_ybtdj"] +[ext_resource type="PackedScene" uid="uid://chs0u61f45nau" path="res://utils/earth_aligner.tscn" id="5_uxqeq"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_4btcp"] +radius = 64.381676 + +[node name="Petal" type="Node2D"] +script = ExtResource("1_ybtdj") +vine_resource = ExtResource("2_4btcp") + +[node name="BudOpen" type="Sprite2D" parent="."] +modulate = Color(18.892157, 1.8483434, 18.892157, 1) +scale = Vector2(5, 5) +texture = ExtResource("1_05pvv") + +[node name="InteractableArea" parent="." instance=ExtResource("2_ybtdj")] + +[node name="CollisionShape2D" type="CollisionShape2D" parent="InteractableArea"] +position = Vector2(-1, 12) +shape = SubResource("CircleShape2D_4btcp") + +[node name="EarthAligner" parent="." instance=ExtResource("5_uxqeq")] + +[connection signal="interaction" from="InteractableArea" to="." method="_on_interaction"] diff --git a/player/player.gd b/player/player.gd index ba766ff..6606bee 100644 --- a/player/player.gd +++ b/player/player.gd @@ -80,6 +80,7 @@ func _physics_process(delta: float) -> void: func _process(delta: float) -> void: manage_iframes(delta) manage_movement_options() + manage_interaction() manage_active(delta) manage_animation() manage_attack(delta) @@ -103,13 +104,18 @@ func manage_attack(delta : float): func manage_active(_delta : float): if(active_item != null and Input.is_action_just_pressed("item") and active_item_cooldown.is_stopped()): active_item.trigger_activation() - if(Input.is_action_just_pressed("drop_item")): + if(Input.is_action_just_pressed("drop_item") and active_item != null): active_item.remove() func manage_movement_options() -> void: if(is_on_floor()): air_jumps_current = air_jumps_max +func manage_interaction(): + 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): diff --git a/player/player.tscn b/player/player.tscn index 0f6e2cf..d5023d4 100644 --- a/player/player.tscn +++ b/player/player.tscn @@ -113,4 +113,13 @@ pitch_scale = 1.62 stream = ExtResource("17_tqiix") volume_db = -12.0 +[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="AnimatedSprite2D" to="." method="_on_attack_end"] diff --git a/project.godot b/project.godot index e7ae270..00b120a 100644 --- a/project.godot +++ b/project.godot @@ -88,6 +88,13 @@ journal={ , 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) +] +} [layer_names] @@ -96,6 +103,7 @@ journal={ 2d_physics/layer_4="SolidGround" 2d_physics/layer_5="EnemyHurtBoxNonTrap" 2d_physics/layer_6="TrulySolidGround" +2d_physics/layer_7="InteractionArea" [rendering] diff --git a/utils/global.gd b/utils/global.gd index 5b8efe4..98c6a61 100644 --- a/utils/global.gd +++ b/utils/global.gd @@ -4,3 +4,6 @@ static var next_dmg_id : int = 0 : get: next_dmg_id += 1 return next_dmg_id + +static func vec_mod(vec : Vector2, modulus : float): + return Vector2(fposmod(vec.x, modulus), fposmod(vec.y, modulus)) diff --git a/utils/interactable_area.gd b/utils/interactable_area.gd new file mode 100644 index 0000000..02e7896 --- /dev/null +++ b/utils/interactable_area.gd @@ -0,0 +1,16 @@ +extends Area2D + +@export var oneshot = true +@export var cooldown = 10 +var already_used = false + +func _ready() -> void: + $Cooldown.wait_time = cooldown + +signal interaction + +func interact(): + if not $Cooldown.time_left > 0 and not (oneshot and already_used): + already_used = true + $Cooldown.start() + interaction.emit() diff --git a/utils/interactable_area.gd.uid b/utils/interactable_area.gd.uid new file mode 100644 index 0000000..ec66fbb --- /dev/null +++ b/utils/interactable_area.gd.uid @@ -0,0 +1 @@ +uid://bgp6nutttqhpb diff --git a/utils/interactable_area.tscn b/utils/interactable_area.tscn new file mode 100644 index 0000000..14db836 --- /dev/null +++ b/utils/interactable_area.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://ds21d77ruuk4y"] + +[ext_resource type="Script" uid="uid://bgp6nutttqhpb" path="res://utils/interactable_area.gd" id="1_rua2f"] + +[node name="InteractableArea" type="Area2D"] +collision_layer = 64 +script = ExtResource("1_rua2f") + +[node name="Cooldown" type="Timer" parent="."] diff --git a/vines_petals/bud.gd b/vines_petals/bud.gd index 2612a77..c637516 100644 --- a/vines_petals/bud.gd +++ b/vines_petals/bud.gd @@ -1,6 +1,7 @@ class_name Bud extends VineNode signal opened var img_path +@export var depth : int func _on_opened(): $AnimatedSprite2D.play("open") @@ -11,16 +12,13 @@ func _on_opened(): func spread(): for dir in [Vector2.UP, Vector2.DOWN, Vector2.RIGHT, Vector2.LEFT]: - if not vine.vine_locations.has(vec_mod(location + dir, grid.num_collumns)): - vine.vine_locations.append(vec_mod(location + dir, grid.num_collumns)) + if not vine.vine_locations.has(Global.vec_mod(location + dir, grid.num_collumns)): grow_to_next_bud(dir) func grow_to_next_bud(dir): - var target_offset = Vector2(randf_range(60, 240), randf_range(90, 270)) + var target_offset = vine.random_offset() + var target = Global.vec_mod(location + dir, grid.num_collumns) var pos1 = grid.get_world_position(location, offset) - var pos2 = grid.get_world_position(location + dir, target_offset) + var pos2 = grid.get_world_position(target, target_offset) var num_seg = floor((pos1-pos2).length() / 96) - await vine.grow_vine_sequence(location, offset, location + dir, target_offset, num_seg, true) - -func vec_mod(vec : Vector2, modulus : float): - return Vector2(fposmod(vec.x, modulus), fposmod(vec.y, modulus)) + await vine.grow_vine_sequence(location, offset, target, target_offset, num_seg, depth, true, false) diff --git a/vines_petals/vine.gd b/vines_petals/vine.gd index 7aa7046..ed6fff7 100644 --- a/vines_petals/vine.gd +++ b/vines_petals/vine.gd @@ -1,21 +1,35 @@ class_name Vine extends Node2D -var petal_location : Vector2 +@export var petal_location : Vector2 +@export var petal_offset : Vector2 @export var vine_locations : Array[Vector2] @export var bud_resource : PackedScene -@onready var grid : Grid = get_tree().get_root().get_node("main/Earth/Grid") -var img_path = "res://vines_petals/vine_active_green.png" +@onready var grid : Grid +var img_path_inactive = "res://vines_petals/vine_inactive.png" +@export var img_path_active = "res://vines_petals/vine_active_green.png" +var active_depth = -1 +var fully_active = false +var vine_data = [] +var max_depth = 150 +var vine_end_data = [] -func draw_vine(pos1 : Vector2, pos2 : Vector2): +func draw_vine(pos1 : Vector2, pos2 : Vector2, depth : int): var sprite = Sprite2D.new() get_tree().get_root().get_node("main").add_child(sprite) - sprite.texture = ResourceLoader.load(img_path) + if active_depth >= depth: + sprite.texture = ResourceLoader.load(img_path_active) + else: + sprite.texture = ResourceLoader.load(img_path_inactive) + while depth + 1 > vine_data.size(): + vine_data.append([]) + vine_data[depth].append(sprite) sprite.position = (pos1 + pos2)/2.0 sprite.rotation = (pos1 - pos2).angle() + PI/2 sprite.scale *= (pos1 - pos2).length() * 1 / sprite.texture.get_width() sprite.scale.x = 3 sprite.z_index = -1 -func grow_vine_sequence(location1 : Vector2, offset1 : Vector2, location2: Vector2, offset2 : Vector2, num_segments: int, grow_bud = false): +func grow_vine_sequence(location1 : Vector2, offset1 : Vector2, location2: Vector2, offset2 : Vector2, num_segments: int, depth: int, grow_bud = false, quick_spawn = false): + depth = min(depth, max_depth) var pos1 = grid.get_world_position(location1, offset1) var pos2 = grid.get_world_position(location2, offset2) var positions = [] @@ -30,10 +44,21 @@ func grow_vine_sequence(location1 : Vector2, offset1 : Vector2, location2: Vecto positions.append(center + offset) positions.append(pos2) for i in range(num_segments): - draw_vine(positions[i], positions[i+1]) - await get_tree().create_timer(0.2).timeout - if grow_bud and location2.y > 0: - spawn_bud(location2, offset2) + draw_vine(positions[i], positions[i+1], depth + i + 1) + if not quick_spawn: + await get_tree().create_timer(0.2).timeout + if active_depth >= depth + num_segments: + if grow_bud and location2.y > 0 and location2.y <= grid.max_bud_height: + spawn_bud(location2, offset2, depth + num_segments) + else: + if location2.y > 0 and location2.y <= grid.max_bud_height: + for i in range(vine_end_data.size()): + if vine_end_data[i].location == location1: + vine_end_data.remove_at(i) + break + vine_end_data.append({"location": location2, "offset": offset2, "depth": depth+num_segments}) + grid.vines_per_node[location2.x][location2.y].append(self) + vine_locations.append(Global.vec_mod(location2, grid.num_collumns)) func generate_random_offsets(segment_count, max_second_derivative): var differences = [] @@ -55,9 +80,50 @@ func generate_random_offsets(segment_count, max_second_derivative): next_val += differences[i] return ret -func spawn_bud(location, offset): +func spawn_bud(location, offset, depth): var bud = bud_resource.instantiate() bud.location = location bud.offset = offset bud.vine = self + bud.depth = depth get_tree().get_root().get_node("main").add_child(bud) + +func activate(): + update_active_depth() + +func update_active_depth(): + if active_depth < max_depth: + await get_tree().create_timer(0.15).timeout + active_depth += 1 + if vine_data.size() > active_depth: + for sprite in vine_data[active_depth]: + sprite.texture = ResourceLoader.load(img_path_active) + for data in vine_end_data: + if data.depth == active_depth: + spawn_bud(data.location, data.offset, data.depth) + update_active_depth() + +func init_random(): + grid = get_tree().get_root().get_node("main/Earth/Grid") + grid.vines_per_node[petal_location.x][petal_location.y].append(self) + vine_locations.append(petal_location) + vine_end_data.append({"location": petal_location, "offset": petal_offset, "depth": 0}) + for i in range(randi_range(2,2)): + var end = vine_end_data.pick_random() + var branches_count = 0 + for branch in range(ceil(randf() * 4)): + var dir = [Vector2.UP, Vector2.DOWN, Vector2.RIGHT, Vector2.LEFT].pick_random() + var target = Global.vec_mod(end.location + dir, grid.num_collumns) + if target.y <= grid.max_bud_height + 1 and grid.vines_per_node[target.x][target.y].is_empty(): + if not (target.y <= 0 or target.y > grid.max_bud_height): + branches_count += 1 + var target_offset = random_offset() + var pos1 = grid.get_world_position(end.location, end.offset) + var pos2 = grid.get_world_position(target, target_offset) + var num_seg = floor((pos1-pos2).length() / 96) + grow_vine_sequence(end.location, end.offset, target, target_offset, num_seg, end.depth, true, true) + if i==0 and branches_count == 1: + vine_end_data.append({"location": petal_location, "offset": petal_offset, "depth": 0}) + +func random_offset(): + return 0*Vector2(randf_range(60, 240), randf_range(90, 270)) diff --git a/world/grid.gd b/world/grid.gd index 4e55172..c66da37 100644 --- a/world/grid.gd +++ b/world/grid.gd @@ -10,6 +10,16 @@ class_name Grid extends Node2D var buildings : Array[Building] = [] +var max_bud_height = 8 +var vines_per_node : Array = [] + +func _ready() -> void: + for i in range(num_collumns): + var arr = [] + for j in range(max_bud_height + 2): + arr.append([]) + vines_per_node.append(arr) + func _draw() -> void: if !debug: return