From 2dc365736ff09bbed651e776030b4aec32cffd17 Mon Sep 17 00:00:00 2001 From: Zacharie Guet Date: Fri, 5 Sep 2025 15:11:29 +0200 Subject: [PATCH] #57 rework des inputs et actions --- common/game_data/scripts/terrain_data.gd | 14 +- .../resources/items/default_seed.tres | 4 +- .../resources/items/default_shovel.tres | 4 +- common/inventory/scripts/inventory.gd | 8 + common/inventory/scripts/item.gd | 11 +- common/inventory/scripts/items/seed.gd | 18 +- common/inventory/scripts/items/shovel.gd | 51 ++-- common/inventory/scripts/tool_item.gd | 10 - common/inventory/scripts/tool_item.gd.uid | 1 - .../interactables/compost/scripts/compost.gd | 2 +- entities/player/scripts/action_area.gd | 41 --- entities/player/scripts/action_area.gd.uid | 1 - entities/player/scripts/player.gd | 233 +++++++++------ game.tscn | 16 +- gui/game/game_gui.tscn | 267 ++++++++++++------ gui/game/scripts/game_gui.gd | 23 +- gui/pointer/pointer.tscn | 25 +- gui/pointer/scripts/action_zone.gd | 17 ++ gui/pointer/scripts/action_zone.gd.uid | 1 + gui/pointer/scripts/pointer.gd | 86 ++++-- project.godot | 15 +- 21 files changed, 490 insertions(+), 358 deletions(-) delete mode 100644 common/inventory/scripts/tool_item.gd delete mode 100644 common/inventory/scripts/tool_item.gd.uid delete mode 100644 entities/player/scripts/action_area.gd delete mode 100644 entities/player/scripts/action_area.gd.uid create mode 100644 gui/pointer/scripts/action_zone.gd create mode 100644 gui/pointer/scripts/action_zone.gd.uid diff --git a/common/game_data/scripts/terrain_data.gd b/common/game_data/scripts/terrain_data.gd index 851bc6d..f606d43 100644 --- a/common/game_data/scripts/terrain_data.gd +++ b/common/game_data/scripts/terrain_data.gd @@ -67,10 +67,16 @@ func get_contamination(point : Vector2) -> float: Vector2(point) / float(TERRAIN_IMAGE_GAME_FACTOR) - Vector2.ONE / 2 ) - return contamination.get_pixel( - int(round(pixel_point.x)), - int(round(pixel_point.y)) - ).r + if ( + pixel_point.x > 0 + and pixel_point.y > 0 + and pixel_point.x < contamination.get_width() + and pixel_point.y < contamination.get_height()): + return contamination.get_pixel( + int(round(pixel_point.x)), + int(round(pixel_point.y)) + ).r + return 0 func get_decontamination_coverage() -> float: return ImageTools.get_color_coverage(contamination) diff --git a/common/inventory/resources/items/default_seed.tres b/common/inventory/resources/items/default_seed.tres index 8ba6235..a5cdb61 100644 --- a/common/inventory/resources/items/default_seed.tres +++ b/common/inventory/resources/items/default_seed.tres @@ -5,7 +5,9 @@ [resource] script = ExtResource("2_mgcdi") -plant_type = "" name = "Boule" +description = "" icon = ExtResource("1_dy25s") +use_zone_radius = 5 +use_energy = 1 metadata/_custom_type_script = "uid://bypjcvlc15gsm" diff --git a/common/inventory/resources/items/default_shovel.tres b/common/inventory/resources/items/default_shovel.tres index c5deee3..ef749ce 100644 --- a/common/inventory/resources/items/default_shovel.tres +++ b/common/inventory/resources/items/default_shovel.tres @@ -5,9 +5,9 @@ [resource] script = ExtResource("1_28h2r") -area_width = 50.0 -area_distance = 50.0 name = "Shovel" description = "Can dig burried seed, and transform mature plants to seeds." icon = ExtResource("1_7g3xd") +use_zone_radius = 50 +use_energy = 1 metadata/_custom_type_script = "uid://dya38x1h1uiyg" diff --git a/common/inventory/scripts/inventory.gd b/common/inventory/scripts/inventory.gd index e420584..afcf6dd 100644 --- a/common/inventory/scripts/inventory.gd +++ b/common/inventory/scripts/inventory.gd @@ -45,6 +45,13 @@ func get_item(ind: int = 0) -> Item: return null; return items[ind] +func has_item(item : Item) -> bool: + return item in items + +func remove_item(item : Item): + items.erase(item) + emit_signal("inventory_changed", self) + func pop_item(ind: int = 0) -> Item: var item_removed: Item = items.pop_at(ind) emit_signal("inventory_changed", self) @@ -55,3 +62,4 @@ func swap_items(item_to_add: Item, ind_to_get: int = 0) -> Item: items[ind_to_get] = item_to_add emit_signal("inventory_changed", self) return item_to_get + diff --git a/common/inventory/scripts/item.gd b/common/inventory/scripts/item.gd index 6c956de..fd95917 100644 --- a/common/inventory/scripts/item.gd +++ b/common/inventory/scripts/item.gd @@ -4,21 +4,20 @@ class_name Item @export var name: String @export_multiline var description: String @export var icon: Texture2D +@export var use_zone_radius: int = 5 +@export var use_energy: int = 1 func is_one_time_use(): return false -func can_use(_player : Player) -> bool: +func can_use(_player : Player, zone: Area2D) -> bool: return false -func use_text(_player) -> String: +func use_text() -> String: return "" func use_requirement_text() -> String: return "" -func use(_player : Player): +func use(_player : Player, zone: Area2D): return false - -func generate_action_area(_player) -> ActionArea: - return null diff --git a/common/inventory/scripts/items/seed.gd b/common/inventory/scripts/items/seed.gd index 6feea97..4086b56 100644 --- a/common/inventory/scripts/items/seed.gd +++ b/common/inventory/scripts/items/seed.gd @@ -13,23 +13,15 @@ class_name Seed func _init(_plant_type : PlantType = null): plant_type = _plant_type -func generate_action_area(player : Player) -> ActionArea: - return ActionArea.new( - player, - 10 - ) - -func use_text(_player) -> String: +func use_text() -> String: return "Plant " + plant_type.name func is_one_time_use(): return true -func can_use(player : Player) -> bool: - return not player.planet.is_there_contamination(player.action_area.global_position) +func can_use(player : Player, zone : Area2D) -> bool: + return not player.planet.is_there_contamination(zone.global_position) -func use(player : Player) -> bool: - if not can_use(player): - return false +func use(player : Player, zone : Area2D) -> bool: player.play_sfx("dig") - return player.planet.plant(plant_type, player.action_area.global_position) + return player.planet.plant(plant_type, zone.global_position) diff --git a/common/inventory/scripts/items/shovel.gd b/common/inventory/scripts/items/shovel.gd index 51cfff7..cf7f498 100644 --- a/common/inventory/scripts/items/shovel.gd +++ b/common/inventory/scripts/items/shovel.gd @@ -1,35 +1,32 @@ -extends ToolItem +extends Item class_name Shovel const USE_INTERVAL = 0.15 -func use_text(_player) -> String: - return "Dig" +func use_text() -> String: + return "Dig" -func can_use(player : Player) -> bool: - var areas = player.action_area.get_overlapping_areas() - for area in areas : - if area is Plant or area is UndergroundLoot: - return true - return false +func can_use(_player : Player, zone : Area2D) -> bool: + var areas = zone.get_overlapping_areas() + for area in areas : + if area is Plant or area is UndergroundLoot: + return true + return false -func use(player : Player) -> bool: - if not can_use(player): - return false - - dig( - player.action_area.get_overlapping_areas(), - player - ) - - return true +func use(player : Player, zone : Area2D) -> bool: + dig( + zone.get_overlapping_areas(), + player + ) + + return true func dig(areas: Array[Area2D], player: Player): - for area in areas : - if area is Plant: - player.play_sfx("harvest") - area.harvest() - if area is UndergroundLoot: - player.play_sfx("dig") - area.dig() - await player.get_tree().create_timer(USE_INTERVAL).timeout \ No newline at end of file + for area in areas : + if area is Plant: + player.play_sfx("harvest") + area.harvest() + if area is UndergroundLoot: + player.play_sfx("dig") + area.dig() + await player.get_tree().create_timer(USE_INTERVAL).timeout diff --git a/common/inventory/scripts/tool_item.gd b/common/inventory/scripts/tool_item.gd deleted file mode 100644 index 6184131..0000000 --- a/common/inventory/scripts/tool_item.gd +++ /dev/null @@ -1,10 +0,0 @@ -extends Item -class_name ToolItem - -@export var area_width: float = 50 - -func generate_action_area(player : Player) -> ActionArea: - return ActionArea.new( - player, - area_width - ) \ No newline at end of file diff --git a/common/inventory/scripts/tool_item.gd.uid b/common/inventory/scripts/tool_item.gd.uid deleted file mode 100644 index 509c80e..0000000 --- a/common/inventory/scripts/tool_item.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://jom8ulyopso diff --git a/entities/interactables/compost/scripts/compost.gd b/entities/interactables/compost/scripts/compost.gd index c07d57a..3252dd3 100644 --- a/entities/interactables/compost/scripts/compost.gd +++ b/entities/interactables/compost/scripts/compost.gd @@ -26,7 +26,7 @@ func interact(p : Player) -> bool: return false p.play_sfx("harvest") - p.delete_item() + p.delete_item(p.inventory.get_item()) fill_value += value_per_seed if fill_value >= 1.: $AnimationPlayer.play("empty") diff --git a/entities/player/scripts/action_area.gd b/entities/player/scripts/action_area.gd deleted file mode 100644 index 9c4f267..0000000 --- a/entities/player/scripts/action_area.gd +++ /dev/null @@ -1,41 +0,0 @@ -extends Area2D -class_name ActionArea - -const OPACITY = 0.4 -const ACTIVATED_COLOR = Color.TURQUOISE -const DEACTIVATED_COLOR = Color.REBECCA_PURPLE - -var collision_shape : CollisionShape2D = null -var area_width : float -var area_max_distance : float -var player : Player - -var activated : bool = false - -func _init( - _player: Player, - _area_width : float = 40, -): - player = _player - area_width = _area_width - -func _ready(): - collision_shape = CollisionShape2D.new() - collision_shape.shape = CircleShape2D.new() - collision_shape.shape.radius = area_width - add_child(collision_shape) - -func _process(_delta): - var target_position = get_global_mouse_position() - player.global_position - if Vector2.ONE.distance_to(target_position) > player.max_reach: - target_position = Vector2.ZERO.direction_to(target_position)*player.max_reach - - position = target_position - queue_redraw() - -func _draw(): - draw_circle( - Vector2.ZERO, - area_width, - Color((ACTIVATED_COLOR if activated else DEACTIVATED_COLOR), OPACITY) - ) diff --git a/entities/player/scripts/action_area.gd.uid b/entities/player/scripts/action_area.gd.uid deleted file mode 100644 index 4ab279b..0000000 --- a/entities/player/scripts/action_area.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://btmwjrscevcb1 diff --git a/entities/player/scripts/player.gd b/entities/player/scripts/player.gd index 16867c0..5d0eb70 100644 --- a/entities/player/scripts/player.gd +++ b/entities/player/scripts/player.gd @@ -1,46 +1,32 @@ extends CharacterBody2D class_name Player -const MAX_REACH_CIRCLE_OPACITY = 0.1 +const MAX_REACH = 100 signal player_updated(player: Player) -signal action_tried_without_energy -signal action_not_permitted signal upgraded var planet : Planet # mis à jour par la classe Planet @export var speed = 350 -@onready var inventory : Inventory = Inventory.new() - var max_energy : int = 3 -var max_reach : int = 100 : - set(v): - max_reach = v - queue_redraw() +var has_just_received_instruction : bool = false # pour récupérer les zones dans les action_area, une frame doit être passée depuis la création de la zone var controlling_player : bool = true : set(v): controlling_player = v velocity = Vector2.ZERO -var target_interactable : Interactable = null # mis à jour par la classe Interactable +var instruction : Instruction = null -var can_use_item : bool = false : - set(v): - var old = can_use_item - can_use_item = v - if old != can_use_item: - print("emit") - player_updated.emit(self) var energy : int = max_energy : set(v): energy = v player_updated.emit(self) -var action_area : ActionArea = null : - set(v): - action_area = v - queue_redraw() + +@onready var inventory : Inventory = Inventory.new() +@onready var preview_zone : Area2D = null +@onready var action_zone : Area2D = null func _ready(): player_updated.emit(self) @@ -50,7 +36,7 @@ func _ready(): # Méthode déclenchée par la classe planet func _start_pass_day(): controlling_player = false - target_interactable = null + instruction = null # Méthode déclenchée par la classe planet func _pass_day(): @@ -61,100 +47,93 @@ func _end_pass_day(): controlling_player = true func _process(_delta): - get_input() - move_and_slide() - -func _on_inventory_updated(_inventory: Inventory): - emit_signal("player_updated", self) - -func _draw(): - if action_area: - draw_arc( - Vector2.ZERO, - max_reach, - 0., - 2*PI, - 30, - Color(Color.WHITE,MAX_REACH_CIRCLE_OPACITY), - 1 - ) - -func get_input(): if controlling_player: var old_velocity=velocity calculate_direction() - can_use_item = inventory.get_item() and inventory.get_item().can_use(self) - if action_area: - action_area.activated = can_use_item - if target_interactable and target_interactable in $InteractArea2D.get_overlapping_areas(): - if target_interactable.can_interact(self): - Pointer.stop_inspect_entity(target_interactable) - target_interactable.interact(self) - target_interactable = null - if Input.is_action_just_pressed("action"): - try_use_item() - if Input.is_action_just_pressed("drop") and inventory.get_item(): - drop_item() + if instruction and instruction.can_be_done(self) and not has_just_received_instruction: + instruction.do(self) + instruction = null + move_preview_zone(get_global_mouse_position()) + + has_just_received_instruction = false + + # Sound if old_velocity.length()==0 and velocity.length()!=0: play_sfx("move") + else: + velocity = Vector2.ZERO + move_and_slide() + +func _on_inventory_updated(_inventory: Inventory): + if inventory.get_item(): + setup_preview_zone(inventory.get_item().use_zone_radius) + emit_signal("player_updated", self) func calculate_direction(): var input_direction: Vector2 = Input.get_vector("move_left", "move_right", "move_up", "move_down") if input_direction.length() != 0: - target_interactable = null - - if target_interactable: - input_direction = self.global_position.direction_to(target_interactable.global_position) + instruction = null + + if instruction: + input_direction = self.global_position.direction_to(instruction.position) velocity = input_direction * speed if input_direction.x: $Sprite.flip_h = (input_direction.x < 0) -func try_use_item(): - if energy == 0: - action_tried_without_energy.emit() - elif not can_use_item: - action_not_permitted.emit() - if energy > 0 and can_use_item: - use_item() + +func can_interact(interactable : Interactable): + return interactable.can_interact(self) + +func try_interact(interactable : Interactable): + has_just_received_instruction = true + instruction = InteractableInstruction.new( + interactable + ) + +func try_move(move_to : Vector2): + instruction = MoveInstruction.new(move_to) func get_item(item : Item): - remove_action_area() inventory.set_item(item) - var new_action_area = item.generate_action_area(self) - if new_action_area != null : - add_action_area(new_action_area) play_sfx("pick") func drop_item(): var item_to_drop = inventory.pop_item() planet.drop_item(item_to_drop, global_position) - remove_action_area() play_sfx("drop") -func delete_item(): - inventory.set_item(null) - remove_action_area() +func delete_item(item: Item): + inventory.remove_item(item) -func use_item(): - var item : Item = inventory.get_item() - var is_item_used = item.use(self) - if is_item_used: - energy -= 1 - if item.is_one_time_use(): - delete_item() +func try_use_item(item : Item, use_position : Vector2): + has_just_received_instruction = true + setup_action_zone(use_position, item.use_zone_radius) + instruction = ItemActionInstruction.new( + use_position, + item + ) -func add_action_area(area : ActionArea): - action_area = area - add_child(action_area) +func preview_can_use_item(item : Item) -> bool: + return can_use_item_on_zone(item, preview_zone) -func remove_action_area(): - if (action_area): - remove_child(action_area) - action_area.queue_free() - action_area = null +func can_use_item_on_zone(item : Item, zone: Area2D) -> bool: + return ( + inventory.has_item(item) + and (energy - item.use_energy) >= 0 + and item.can_use(self, zone) + ) + +func use_item(item : Item): + print(action_zone.get_overlapping_areas()) + if can_use_item_on_zone(item, action_zone): + var is_item_used = item.use(self, action_zone) + if is_item_used: + energy -= item.use_energy + if item.is_one_time_use(): + delete_item(item) func upgrade(): max_energy += 1 @@ -164,6 +143,44 @@ func upgrade(): func recharge(amount : int = max_energy): energy = min(energy + amount, max_energy) +func generate_action_area(radius : int = 0) -> Area2D: + var area2D = Area2D.new() + var collision_shape = CollisionShape2D.new() + var circle_shape = CircleShape2D.new() + + circle_shape.radius = radius + collision_shape.shape = circle_shape + area2D.add_child(collision_shape) + + get_parent().add_child(area2D) + + return area2D + +func setup_preview_zone(zone_radius : int) -> Area2D: + if preview_zone: + preview_zone.queue_free() + preview_zone = generate_action_area(zone_radius) + return preview_zone + +func setup_action_zone(zone_position : Vector2, zone_radius : int) -> Area2D: + if action_zone: + action_zone.queue_free() + action_zone = generate_action_area(zone_radius) + action_zone.global_position = zone_position + return action_zone + +func move_preview_zone(zone_position : Vector2): + if preview_zone: + preview_zone.global_position = zone_position + +func detect_area_in_preview_zone() -> Array: + return preview_zone.get_overlapping_areas() + +func detect_area_in_action_zone() -> Array: + if action_zone: + return action_zone.get_overlapping_areas() + return [] + func play_sfx(sound : String): match sound: "dig": @@ -176,3 +193,45 @@ func play_sfx(sound : String): $Audio/AudioStreamPlayer_drop.play() "move": $Audio/AudioStreamPlayer_movement.play() + +class Instruction: + + var position : Vector2 + + func _init(_pos : Vector2): + position = _pos + + func can_be_done(player : Player): + return player.global_position.distance_to(position) < 10 + + func do(_player : Player): + pass + +class MoveInstruction extends Instruction: + pass + +class ItemActionInstruction extends Instruction: + var item = Item + + func _init(_pos : Vector2, _item : Item): + position = _pos + item = _item + + func can_be_done(player : Player): + return player.global_position.distance_to(position) < player.MAX_REACH + + func do(player : Player): + player.use_item(item) + +class InteractableInstruction extends Instruction: + var interactable = Interactable + + func _init(_interactable : Interactable): + interactable = _interactable + position = interactable.global_position + + func can_be_done(player : Player): + return player.global_position.distance_to(position) < player.MAX_REACH + + func do(player : Player): + interactable.interact(player) diff --git a/game.tscn b/game.tscn index 81cff71..1a41898 100644 --- a/game.tscn +++ b/game.tscn @@ -20,32 +20,38 @@ atlas = ExtResource("8_boyg6") region = Rect2(1140, 345, 141, 128) -[sub_resource type="Resource" id="Resource_lc2xo"] +[sub_resource type="Resource" id="Resource_7sc4i"] script = ExtResource("10_hb5m1") plant_type = ExtResource("9_e36ub") name = "Chardi" description = "This plant remove a lot of contamination around when it becomes mature." icon = SubResource("AtlasTexture_qt76e") +use_zone_radius = 5 +use_energy = 1 metadata/_custom_type_script = "uid://bypjcvlc15gsm" -[sub_resource type="Resource" id="Resource_215e1"] +[sub_resource type="Resource" id="Resource_80cx4"] script = ExtResource("10_hb5m1") plant_type = ExtResource("9_e36ub") name = "Chardi" description = "This plant remove a lot of contamination around when it becomes mature." icon = SubResource("AtlasTexture_qt76e") +use_zone_radius = 5 +use_energy = 1 metadata/_custom_type_script = "uid://bypjcvlc15gsm" [sub_resource type="AtlasTexture" id="AtlasTexture_sri3b"] atlas = ExtResource("8_boyg6") region = Rect2(1697, 331, 125, 158) -[sub_resource type="Resource" id="Resource_7sc4i"] +[sub_resource type="Resource" id="Resource_e8heu"] script = ExtResource("10_hb5m1") plant_type = ExtResource("11_x5p1p") name = "Maias" description = "This gorgeous flower produce a lot of seeds." icon = SubResource("AtlasTexture_sri3b") +use_zone_radius = 5 +use_energy = 1 metadata/_custom_type_script = "uid://bypjcvlc15gsm" [node name="Game" type="Node2D"] @@ -81,7 +87,7 @@ position = Vector2(3, 458) position = Vector2(0, -154) [node name="Planet" parent="." node_paths=PackedStringArray("import_entities_from_node") instance=ExtResource("6_e8heu")] -loot_items = Array[ExtResource("7_rvswv")]([SubResource("Resource_lc2xo"), SubResource("Resource_215e1"), SubResource("Resource_7sc4i")]) +loot_items = Array[ExtResource("7_rvswv")]([SubResource("Resource_7sc4i"), SubResource("Resource_80cx4"), SubResource("Resource_e8heu")]) import_entities_from_node = NodePath("../Entities") [node name="Camera" parent="." node_paths=PackedStringArray("following") instance=ExtResource("12_qhcbd")] @@ -89,8 +95,6 @@ position = Vector2(2.22, 0) following = NodePath("../Entities/Player") [connection signal="pause_asked" from="CanvasLayer/RootGui" to="CanvasLayer/Pause" method="_on_root_gui_pause_asked"] -[connection signal="action_not_permitted" from="Entities/Player" to="CanvasLayer/RootGui" method="_on_player_action_not_permitted"] -[connection signal="action_tried_without_energy" from="Entities/Player" to="CanvasLayer/RootGui" method="_on_player_action_tried_without_energy"] [connection signal="player_updated" from="Entities/Player" to="CanvasLayer/RootGui" method="_on_player_updated"] [connection signal="upgraded" from="Entities/Player" to="CanvasLayer/RootGui" method="_on_player_upgraded"] [connection signal="day_limit_exceed" from="Planet" to="CanvasLayer/Win" method="_on_planet_day_limit_exceed"] diff --git a/gui/game/game_gui.tscn b/gui/game/game_gui.tscn index ca9f934..2a8fe75 100644 --- a/gui/game/game_gui.tscn +++ b/gui/game/game_gui.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=21 format=3 uid="uid://12nak7amd1uq"] +[gd_scene load_steps=30 format=3 uid="uid://12nak7amd1uq"] [ext_resource type="Script" uid="uid://cqao7n800qy40" path="res://gui/game/scripts/game_gui.gd" id="1_udau0"] [ext_resource type="Theme" uid="uid://bgcmd213j6gk1" path="res://gui/ressources/default_theme.tres" id="2_nq5i2"] @@ -10,6 +10,53 @@ [ext_resource type="FontFile" uid="uid://cpnsnrqhfkj3k" path="res://gui/ressources/fonts/spincycle_ot.otf" id="8_n4kem"] [ext_resource type="Texture2D" uid="uid://b5cuxgisrsfgt" path="res://gui/game/pause/assets/icons/player-pause.svg" id="9_2wykm"] +[sub_resource type="Gradient" id="Gradient_id0t5"] +interpolation_mode = 1 +offsets = PackedFloat32Array(0, 0.115169, 0.41573, 0.620786, 0.924157) +colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_ykapk"] +gradient = SubResource("Gradient_id0t5") +fill_to = Vector2(1, 1) +repeat = 1 + +[sub_resource type="Animation" id="Animation_p6blc"] +resource_name = "default" +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.5, 1.03333), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Color(0.950568, 0, 0.346412, 1), Color(0.999996, 0.39403, 0.49625, 1), Color(0.950568, 0, 0.346412, 1)] +} + +[sub_resource type="Animation" id="Animation_l73to"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(0.950568, 0, 0.346412, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_l3q4a"] +_data = { +&"RESET": SubResource("Animation_l73to"), +&"default": SubResource("Animation_p6blc") +} + [sub_resource type="AtlasTexture" id="AtlasTexture_ek73b"] atlas = ExtResource("7_n4kem") region = Rect2(76, 75, 124, 135) @@ -21,6 +68,15 @@ font_size = 20 [sub_resource type="LabelSettings" id="LabelSettings_n4kem"] font_size = 12 +[sub_resource type="Gradient" id="Gradient_2wykm"] +offsets = PackedFloat32Array(0, 0.279476, 1) +colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_id0t5"] +gradient = SubResource("Gradient_2wykm") +fill = 1 +fill_from = Vector2(0.5, 0.5) + [sub_resource type="Animation" id="Animation_iyvkh"] length = 0.001 tracks/0/type = "value" @@ -38,66 +94,14 @@ tracks/0/keys = { tracks/1/type = "value" tracks/1/imported = false tracks/1/enabled = true -tracks/1/path = NodePath("MarginContainer/PlayerInfo/EnergyInfo:offset_left") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [-44.0] -} -tracks/2/type = "value" -tracks/2/imported = false -tracks/2/enabled = true -tracks/2/path = NodePath("Effect:modulate") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [Color(1, 1, 1, 0)] -} -tracks/3/type = "value" -tracks/3/imported = false -tracks/3/enabled = true -tracks/3/path = NodePath("MarginContainer/PlayerInfo/EnergyInfo:offset_bottom") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [12.5] -} - -[sub_resource type="Animation" id="Animation_n4kem"] -resource_name = "no_energy_left" -length = 0.5 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("MarginContainer/PlayerInfo/EnergyInfo:offset_left") -tracks/0/interp = 2 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 0.0333333, 0.1, 0.166667, 0.233333, 0.3, 0.366667, 0.433333, 0.5), -"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1), -"update": 0, -"values": [-44.0, -40.0, -44.0, -48.0, -44.0, -40.0, -44.0, -40.0, -44.0] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true tracks/1/path = NodePath("Effect:modulate") tracks/1/interp = 1 tracks/1/loop_wrap = true tracks/1/keys = { -"times": PackedFloat32Array(0, 0.1, 0.266667), -"transitions": PackedFloat32Array(1, 1, 1), +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), "update": 0, -"values": [Color(0.866667, 0.152941, 0.337255, 0), Color(0.866667, 0.152941, 0.337255, 0.392157), Color(0.866667, 0.152941, 0.337255, 0)] +"values": [Color(1, 1, 1, 0)] } [sub_resource type="Animation" id="Animation_id0t5"] @@ -131,52 +135,86 @@ tracks/0/keys = { "values": [Color(0.0627451, 0.0588235, 0.168627, 0), Color(0.0627451, 0.0588235, 0.168627, 1), Color(0.0627451, 0.0588235, 0.168627, 1), Color(0.0627451, 0.0588235, 0.168627, 0)] } +[sub_resource type="AnimationLibrary" id="AnimationLibrary_n4kem"] +_data = { +&"RESET": SubResource("Animation_iyvkh"), +&"not_permitted": SubResource("Animation_id0t5"), +&"pass_day": SubResource("Animation_ykapk") +} + [sub_resource type="Animation" id="Animation_2wykm"] resource_name = "upgrade" +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.2, 0.9), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Color(0.6, 0.580392, 0, 0), Color(0.600196, 0.581106, 0, 0.392157), Color(0.6, 0.580392, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_l3q4a"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_nhqnj"] +_data = { +&"RESET": SubResource("Animation_l3q4a"), +&"upgrade": SubResource("Animation_2wykm") +} + +[sub_resource type="Animation" id="Animation_w16yr"] +resource_name = "no_energy_left_appear" length = 0.5 tracks/0/type = "value" tracks/0/imported = false tracks/0/enabled = true -tracks/0/path = NodePath("Effect:modulate") +tracks/0/path = NodePath("NoEnergyLeft:position") tracks/0/interp = 2 tracks/0/loop_wrap = true tracks/0/keys = { -"times": PackedFloat32Array(0, 0.133333, 0.5), -"transitions": PackedFloat32Array(1, 1, 1), +"times": PackedFloat32Array(0.0666667, 0.5), +"transitions": PackedFloat32Array(1, 1), "update": 0, -"values": [Color(0.67451, 0.52549, 0.203922, 0), Color(0.67451, 0.52549, 0.203922, 0.572549), Color(0.67451, 0.52549, 0.203922, 0)] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("MarginContainer/PlayerInfo/EnergyInfo:offset_bottom") -tracks/1/interp = 2 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0, 0.233333, 0.5), -"transitions": PackedFloat32Array(1, 1, 1), -"update": 0, -"values": [12.5, -32.0, 12.5] +"values": [Vector2(0, -100), Vector2(0, 0)] } -[sub_resource type="AnimationLibrary" id="AnimationLibrary_n4kem"] +[sub_resource type="Animation" id="Animation_mbdxg"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("NoEnergyLeft:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(0, -100)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_p0xoq"] _data = { -&"RESET": SubResource("Animation_iyvkh"), -&"no_energy_left": SubResource("Animation_n4kem"), -&"not_permitted": SubResource("Animation_id0t5"), -&"pass_day": SubResource("Animation_ykapk"), -&"upgrade": SubResource("Animation_2wykm") +&"RESET": SubResource("Animation_mbdxg"), +&"no_energy_left_appear": SubResource("Animation_w16yr") } -[sub_resource type="Gradient" id="Gradient_2wykm"] -offsets = PackedFloat32Array(0, 0.279476, 1) -colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1) - -[sub_resource type="GradientTexture2D" id="GradientTexture2D_id0t5"] -gradient = SubResource("Gradient_2wykm") -fill = 1 -fill_from = Vector2(0.5, 0.5) - [node name="RootGui" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -189,6 +227,40 @@ size_flags_vertical = 3 mouse_filter = 1 script = ExtResource("1_udau0") +[node name="NoEnergyLeft" type="VBoxContainer" parent="."] +unique_name_in_owner = true +visible = false +modulate = Color(0.950568, 0, 0.346412, 1) +layout_mode = 1 +anchors_preset = 10 +anchor_right = 1.0 +offset_top = -100.0 +offset_bottom = 2.0 +grow_horizontal = 2 +theme = ExtResource("2_nq5i2") +theme_override_constants/separation = 12 + +[node name="TextureRect" type="TextureRect" parent="NoEnergyLeft"] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 +texture = SubResource("GradientTexture2D_ykapk") +expand_mode = 1 +stretch_mode = 1 + +[node name="Label" type="Label" parent="NoEnergyLeft"] +layout_mode = 2 +theme = ExtResource("2_nq5i2") +text = "No energy left" +label_settings = ExtResource("4_ujg5r") +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="BlinkAnimation" type="AnimationPlayer" parent="NoEnergyLeft"] +libraries = { +&"": SubResource("AnimationLibrary_l3q4a") +} +autoplay = "default" + [node name="MarginContainer" type="MarginContainer" parent="."] layout_mode = 1 anchors_preset = 15 @@ -345,11 +417,6 @@ grow_vertical = 2 mouse_filter = 2 color = Color(0.0627451, 0.0588235, 0.168627, 0) -[node name="AnimationPlayer" type="AnimationPlayer" parent="."] -libraries = { -&"": SubResource("AnimationLibrary_n4kem") -} - [node name="GridContainer" type="GridContainer" parent="."] layout_mode = 0 offset_right = 40.0 @@ -366,4 +433,20 @@ grow_vertical = 2 mouse_filter = 2 texture = SubResource("GradientTexture2D_id0t5") +[node name="PassDayAnimation" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_n4kem") +} + +[node name="EffectAnimation" type="AnimationPlayer" parent="."] +root_node = NodePath("../Effect") +libraries = { +&"": SubResource("AnimationLibrary_nhqnj") +} + +[node name="NoEnergyLeftAnimation" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_p0xoq") +} + [connection signal="pressed" from="MarginContainer/TopRightContent/Pause" to="." method="_on_pause_pressed"] diff --git a/gui/game/scripts/game_gui.gd b/gui/game/scripts/game_gui.gd index 4792e64..289e8a5 100644 --- a/gui/game/scripts/game_gui.gd +++ b/gui/game/scripts/game_gui.gd @@ -7,6 +7,8 @@ func _on_player_updated(player:Player): %EnergyCount.text = str(player.energy) + "/" + str(player.max_energy) %EnergyInfo.modulate = Color.WHITE if player.energy > 0 else Color.RED + update_no_energy_left_info(player.energy) + %ItemInfo.visible = player.inventory.get_item() != null if player.inventory.get_item(): var item : Item = player.inventory.get_item() @@ -34,14 +36,17 @@ func _on_pause_pressed(): func _on_player_upgraded(): - $AnimationPlayer.play("upgrade") - - -func _on_player_action_not_permitted(): - $AnimationPlayer.play("not_permitted") + $EffectAnimation.play("upgrade") func _on_planet_pass_day_started(planet): - $AnimationPlayer.speed_scale = 1/(planet.PASS_DAY_ANIMATION_TIME) - $AnimationPlayer.play("pass_day") - await $AnimationPlayer.animation_finished - $AnimationPlayer.speed_scale = 1 + $PassDayAnimation.speed_scale = 1/(planet.PASS_DAY_ANIMATION_TIME) + $PassDayAnimation.play("pass_day") + await $PassDayAnimation.animation_finished + $PassDayAnimation.speed_scale = 1 + +func update_no_energy_left_info(energy): + if energy == 0 and not %NoEnergyLeft.visible: + %NoEnergyLeft.visible = true + $NoEnergyLeftAnimation.play("no_energy_left_appear") + elif energy != 0 and %NoEnergyLeft.visible: + %NoEnergyLeft.visible = false diff --git a/gui/pointer/pointer.tscn b/gui/pointer/pointer.tscn index 2d24ba2..66c7364 100644 --- a/gui/pointer/pointer.tscn +++ b/gui/pointer/pointer.tscn @@ -4,7 +4,7 @@ [ext_resource type="Texture2D" uid="uid://bspffyprdywgc" path="res://gui/pointer/assets/cursors/pointer.svg" id="2_q4bvb"] [ext_resource type="AudioStream" uid="uid://bym03qp4n6vep" path="res://gui/pointer/assets/sounds/click.wav" id="3_kj0cm"] [ext_resource type="Texture2D" uid="uid://djb52fosgmv4j" path="res://gui/pointer/assets/icons/left_click.svg" id="3_pshoq"] -[ext_resource type="Texture2D" uid="uid://y3083o1fhgn0" path="res://gui/pointer/assets/icons/right_click.svg" id="4_b4uwv"] +[ext_resource type="Script" uid="uid://c2en2hc6a7ils" path="res://gui/pointer/scripts/action_zone.gd" id="4_pshoq"] [node name="Pointer" type="Node"] process_mode = 3 @@ -37,37 +37,26 @@ z_index = 1 layout_mode = 2 text = "Item" -[node name="Interact" type="HBoxContainer" parent="CanvasLayer/Inspector/Container"] +[node name="Action" type="HBoxContainer" parent="CanvasLayer/Inspector/Container"] unique_name_in_owner = true modulate = Color(1, 1, 0.168627, 1) layout_mode = 2 -[node name="TextureRect" type="TextureRect" parent="CanvasLayer/Inspector/Container/Interact"] +[node name="TextureRect" type="TextureRect" parent="CanvasLayer/Inspector/Container/Action"] layout_mode = 2 texture = ExtResource("3_pshoq") -[node name="InspectorInteractionText" type="Label" parent="CanvasLayer/Inspector/Container/Interact"] +[node name="ActionText" type="Label" parent="CanvasLayer/Inspector/Container/Action"] unique_name_in_owner = true z_index = 1 layout_mode = 2 text = "Take" horizontal_alignment = 1 -[node name="Use" type="HBoxContainer" parent="CanvasLayer/Inspector/Container"] +[node name="ActionZone" type="Sprite2D" parent="CanvasLayer/Inspector"] unique_name_in_owner = true -modulate = Color(1, 1, 0.168627, 1) -layout_mode = 2 - -[node name="TextureRect" type="TextureRect" parent="CanvasLayer/Inspector/Container/Use"] -layout_mode = 2 -texture = ExtResource("4_b4uwv") - -[node name="InspectorUseText" type="Label" parent="CanvasLayer/Inspector/Container/Use"] -unique_name_in_owner = true -z_index = 1 -layout_mode = 2 -text = "Gloubi" -horizontal_alignment = 1 +position = Vector2(0, -1) +script = ExtResource("4_pshoq") [node name="Audio" type="Node" parent="."] diff --git a/gui/pointer/scripts/action_zone.gd b/gui/pointer/scripts/action_zone.gd new file mode 100644 index 0000000..71a9018 --- /dev/null +++ b/gui/pointer/scripts/action_zone.gd @@ -0,0 +1,17 @@ +extends Sprite2D +class_name ActionZone + +const OPACITY = 0.4 +const ACTIVATED_COLOR = Color.TURQUOISE +const DEACTIVATED_COLOR = Color.REBECCA_PURPLE + + +var radius : int = 0 +var active : bool = false + +func _draw(): + draw_circle( + Vector2.ZERO, + radius, + Color((ACTIVATED_COLOR if active else DEACTIVATED_COLOR), OPACITY) + ) \ No newline at end of file diff --git a/gui/pointer/scripts/action_zone.gd.uid b/gui/pointer/scripts/action_zone.gd.uid new file mode 100644 index 0000000..11c4e81 --- /dev/null +++ b/gui/pointer/scripts/action_zone.gd.uid @@ -0,0 +1 @@ +uid://c2en2hc6a7ils diff --git a/gui/pointer/scripts/pointer.gd b/gui/pointer/scripts/pointer.gd index be01ea8..f0c6675 100644 --- a/gui/pointer/scripts/pointer.gd +++ b/gui/pointer/scripts/pointer.gd @@ -3,36 +3,62 @@ extends Node @export var default_cursor : Texture2D var inspected_entity : InspectableEntity = null -var player : Player :# renseigné par Player - set(v): - # if player: - # player.player_updated.disconnect(update_inspector) - player = v - player.player_updated.connect( - func(p): update_inspector() - ) +var player : Player # renseigné par Player +var can_interact : bool = false +var current_selected_item : Item = null +var can_use_item : bool = false func _ready(): Input.set_custom_mouse_cursor(default_cursor) %InspectorText.visible = false - %Interact.visible = false - %Use.visible = false + %Action.visible = false func _input(_event): - if Input.is_action_just_pressed("interact"): - $Audio/Click.play() - if ( - player != null - and inspected_entity - and inspected_entity is Interactable - ): - var interactable = inspected_entity as Interactable - if interactable.can_interact(player): - player.target_interactable = interactable + if player: + if Input.is_action_just_pressed("move"): + player.try_move( + player.get_global_mouse_position() + ) + if Input.is_action_just_pressed("drop"): + player.drop_item() + + if Input.is_action_just_pressed("action"): + if can_interact: + var interactable = inspected_entity as Interactable + player.try_interact(interactable) + elif can_use_item: + player.try_use_item( + player.inventory.get_item(), + player.get_global_mouse_position() + ) func _process(_delta): %Inspector.position = get_viewport().get_mouse_position() + if player: + can_interact = ( + inspected_entity + and inspected_entity is Interactable + and player.can_interact(inspected_entity) + ) + + current_selected_item = player.inventory.get_item() + + can_use_item = ( + current_selected_item + and player.preview_can_use_item(current_selected_item) + ) + + if current_selected_item: + %ActionZone.radius = current_selected_item.use_zone_radius + %ActionZone.active = can_use_item + else: + %ActionZone.radius = 0 + + %ActionZone.queue_redraw() + + update_inspector() + func inspect_entity(entity : InspectableEntity): if inspected_entity and inspected_entity != entity: inspected_entity.inspected = false @@ -41,24 +67,22 @@ func inspect_entity(entity : InspectableEntity): update_inspector() func update_inspector(): - print("updated") - %InspectorText.visible = inspected_entity != null if inspected_entity: %InspectorText.text = inspected_entity.inspected_text() if player: - %Interact.visible = inspected_entity and inspected_entity is Interactable and inspected_entity.can_interact(player) - if inspected_entity and inspected_entity is Interactable and inspected_entity.can_interact(player): - %InspectorInteractionText.text = inspected_entity.interact_text() + if can_interact and inspected_entity and inspected_entity is Interactable: + %Action.visible = true + %ActionText.text = inspected_entity.interact_text() + elif can_use_item and current_selected_item: + %Action.visible = true + %ActionText.text = current_selected_item.use_text() + else: + %Action.visible = false - %Use.visible = player.can_use_item - if player.inventory.get_item() and player.can_use_item: - %InspectorUseText.text = player.inventory.get_item().use_text(player) else: - %Interact.visible = false - %Use.visible = false - + %Action.visible = false func stop_inspect_entity(entity : InspectableEntity): entity.inspected = false diff --git a/project.godot b/project.godot index dc167a9..f253d77 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Seeding Planets" config/description="Seeding planets is a survival, managment and cosy game in which you play a little gardener robot." -config/version="proto-1.2" +config/version="proto-2.0" run/main_scene="uid://c5bruelvqbm1k" config/features=PackedStringArray("4.4", "Forward Plus") config/icon="uid://df0y0s666ui4h" @@ -48,15 +48,9 @@ move_down={ , 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) ] } -interact={ -"deadzone": 0.2, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(190, 22),"global_position":Vector2(199, 70),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) -] -} action={ "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(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(76, 12),"global_position":Vector2(85, 60),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(112, 17),"global_position":Vector2(121, 65),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) ] } drop={ @@ -69,6 +63,11 @@ pause={ "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":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +move={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(231, 25),"global_position":Vector2(240, 73),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} [rendering]