diff --git a/project/main-scenes/island.tscn b/project/main-scenes/island.tscn index 7ca3b5b..ce13cb8 100644 --- a/project/main-scenes/island.tscn +++ b/project/main-scenes/island.tscn @@ -43,6 +43,25 @@ unique_name_in_owner = true layout_mode = 2 text = "INV" +[node name="HealthBar" type="ProgressBar" parent="Camera2D/CanvasLayer/VBoxContainer"] +modulate = Color(0.787561, 0.0888135, 0.00437393, 1) +custom_minimum_size = Vector2(150, 15) +layout_mode = 2 +show_percentage = false + +[node name="FoodBar" type="ProgressBar" parent="Camera2D/CanvasLayer/VBoxContainer"] +modulate = Color(0.166826, 0.552224, 0.153144, 1) +custom_minimum_size = Vector2(0, 15) +layout_mode = 2 +show_percentage = false + +[node name="TemperatureBar" type="ProgressBar" parent="Camera2D/CanvasLayer/VBoxContainer"] +modulate = Color(0.0235294, 0.0392157, 1, 1) +custom_minimum_size = Vector2(0, 15) +layout_mode = 2 +max_value = 50.0 +show_percentage = false + [node name="Tileset" type="Node2D" parent="."] script = ExtResource("1_k0rw8") @@ -63,7 +82,7 @@ tile_map_data = PackedByteArray("AAAQAA4AAwAAAAAAAAA=") tile_set = ExtResource("1_vlccq") [node name="TemperatureLayer" type="TileMapLayer" parent="Tileset"] -tile_map_data = PackedByteArray("AAAAAAAAAgABAAAAAAA=") +tile_map_data = PackedByteArray("AAAAAAAAAgABAAAAAAAsAAYAAgABAAAAAAApAAYAAgABAAAAAAAqAAYAAgABAAAAAAArAAYAAgABAAAAAAAtAAYAAgABAAAAAAAuAAYAAgABAAAAAAAvAAYAAgABAAAAAAAwAAYAAgABAAAAAAAwAAcAAgABAAAAAAAvAAcAAgABAAAAAAAuAAcAAgABAAAAAAAtAAcAAgABAAAAAAAsAAcAAgABAAAAAAArAAcAAgABAAAAAAAqAAcAAgABAAAAAAAqAAgAAgABAAAAAAAqAAkAAgABAAAAAAArAAkAAgABAAAAAAAsAAkAAgABAAAAAAAtAAkAAgABAAAAAAAuAAkAAgABAAAAAAAuAAgAAgABAAAAAAAvAAgAAgABAAAAAAAwAAgAAgABAAAAAAAtAAgAAgABAAAAAAAsAAgAAgABAAAAAAArAAgAAgABAAAAAAA=") tile_set = ExtResource("1_vlccq") [node name="NavigationVisualization" type="TileMapLayer" parent="Tileset"] diff --git a/project/scripts/global/GameManager.gd b/project/scripts/global/GameManager.gd index ac8759b..1831f7f 100644 --- a/project/scripts/global/GameManager.gd +++ b/project/scripts/global/GameManager.gd @@ -5,46 +5,78 @@ extends Node @onready var player: PlayerManager = $PlayerManager @onready var camera: CameraController = $Camera2D as CameraController @onready var game_ticker: Timer = $GameTick +@onready var health_bar: ProgressBar = $Camera2D/CanvasLayer/VBoxContainer/HealthBar +@onready var food_bar: ProgressBar = $Camera2D/CanvasLayer/VBoxContainer/FoodBar +@onready var temperature_bar: ProgressBar = $Camera2D/CanvasLayer/VBoxContainer/TemperatureBar +@onready var temperature_layer: Node2D = $Tileset/TemperatureLayer var tilemap_navigation: TilemapNavigation = TilemapNavigation.new() func _ready() -> void: - tilemap_navigation.world = world - tilemap_navigation.player = player - player.game_manager = self - world.camp_manager.game_manager = self - world.step_visualizer.game_manager = self - world.step_visualizer.world = world + tilemap_navigation.world = world + tilemap_navigation.player = player + player.game_manager = self + world.camp_manager.game_manager = self + world.step_visualizer.game_manager = self + world.step_visualizer.world = world + health_bar.value = player.max_health + food_bar.value = player.max_food + temperature_bar.value = player.temperature_endure + update_bars() # game_ticker.start() func _process(delta: float) -> void: - if Input.is_action_just_pressed("key_1"): - camera.go_to_zooming(Vector2(517.469787597656, 289.846008300781), 1.771561) - if Input.is_action_just_pressed("key_2"): - camera.go_to_zooming(Vector2(789.883972167969, 450.102813720703), 0.56015348434448) - if Input.is_action_just_pressed("key_9"): - world.camp_manager.campfire_light() - world.camp_manager.sleep_effect() - world.camp_manager.campfire_extinguish() - if Input.is_action_just_pressed("force_game_tick"): - _on_game_tick_timeout() + if Input.is_action_just_pressed("key_1"): + camera.go_to_zooming(Vector2(517.469787597656, 289.846008300781), 1.771561) + if Input.is_action_just_pressed("key_2"): + camera.go_to_zooming(Vector2(789.883972167969, 450.102813720703), 0.56015348434448) + if Input.is_action_just_pressed("key_9"): + world.camp_manager.campfire_light() + world.camp_manager.sleep_effect() + world.camp_manager.campfire_extinguish() + if Input.is_action_just_pressed("force_game_tick"): + _on_game_tick_timeout() + if Input.is_action_just_pressed("key_6"): + toggle_temperature_layer() func player_health_depleted(): - # TODO - pass + # TODO + pass func _on_game_tick_timeout() -> void: - var timer_on_game_tick_timeout: PerformanceTimer = PerformanceTimer.new() - timer_on_game_tick_timeout.display_name = "game tick duration" - tilemap_navigation.game_tick_start() - world.step_visualizer.game_tick_start() - player.game_tick() - tilemap_navigation.game_tick_end() - world.step_visualizer.game_tick_end() - timer_on_game_tick_timeout.stop() + var timer_on_game_tick_timeout: PerformanceTimer = PerformanceTimer.new() + timer_on_game_tick_timeout.display_name = "game tick duration" + tilemap_navigation.game_tick_start() + world.step_visualizer.game_tick_start() + player.game_tick() + tilemap_navigation.game_tick_end() + world.step_visualizer.game_tick_end() + timer_on_game_tick_timeout.stop() + update_bars() + +func update_bars() -> void: + if health_bar != null: + health_bar.max_value = player.max_health + health_bar.value = clamp(player.health, 0, player.max_health) + + if food_bar != null: + food_bar.max_value = player.max_food + food_bar.value = clamp(player.food, 0, player.max_food) + + if temperature_bar != null: + var temperature_value = player.temperature_endure - player.temperature_timer + temperature_bar.max_value = player.temperature_endure + temperature_bar.value = clamp(temperature_value, 0, player.temperature_endure) + +func toggle_temperature_layer() -> void: + if temperature_layer != null: + temperature_layer.visible = not temperature_layer.visible + print("TemperatureLayer visibility:", temperature_layer.visible) + else: + print("TemperatureLayer is null!") diff --git a/project/scripts/player/PlayerManager.gd b/project/scripts/player/PlayerManager.gd index ceca2fc..012bf2f 100644 --- a/project/scripts/player/PlayerManager.gd +++ b/project/scripts/player/PlayerManager.gd @@ -3,7 +3,9 @@ extends Node @onready var inventory_label: Label = %InventoryLabel +@export var max_health: int = 100 # food system +@export var max_food: int = 100 @export var food_damage: int = 1 @export var food_addon_per_berry: int = 100 @export var food_critical_threshold: int = 50 @@ -19,203 +21,203 @@ var game_manager: GameManager = null var last_board_position: Vector2i = Vector2i(0, 0) var board_position: Vector2i = Vector2i(0, 0): - set(value): - last_board_position = board_position - board_position = value - update_board() + set(value): + last_board_position = board_position + board_position = value + update_board() @onready var behavior_tree: BehaviorTree = $BehaviorTree -var food: int = 0 +var food: int = max_food # var water: int = 0 var temperature_timer: int = 0 -var health: int = 0 +var health: int = max_health # var inventory_slot: Vector2i = tilemap_types.EMPTY: - set(value): - inventory_slot = value - update_board() + set(value): + inventory_slot = value + update_board() func _ready() -> void: - call_deferred("defer_ready") + call_deferred("defer_ready") func defer_ready() -> void: - behavior_tree.game_manager = game_manager - var player_start_position: Array[Vector2i] = game_manager.world.tilemap_player.get_cells_by_type(tilemap_types.PLAYER_DOWN) - if len(player_start_position) > 0: - board_position = player_start_position[0] - else: - push_error("No player start position found on tilemap") - update_board() + behavior_tree.game_manager = game_manager + var player_start_position: Array[Vector2i] = game_manager.world.tilemap_player.get_cells_by_type(tilemap_types.PLAYER_DOWN) + if len(player_start_position) > 0: + board_position = player_start_position[0] + else: + push_error("No player start position found on tilemap") + update_board() func _process(delta: float) -> void: - if Input.is_action_just_pressed("key_3"): - game_manager.camera.go_to_zooming(game_manager.world.tilemap_player.cell_to_local(board_position), 2) - if Input.is_action_just_pressed("key_5"): - pick_up_item(Vector2i(5, 8)) - pick_up_item(Vector2i(9, 9)) - if Input.is_action_just_pressed("key_4"): - var nearest: Vector2i = find_nearest_object([game_manager.world.tilemap_types.OBJECT_I_TREE_FULL]) - # nearest.x = nearest.x - 1 - walk_towards(nearest) + if Input.is_action_just_pressed("key_3"): + game_manager.camera.go_to_zooming(game_manager.world.tilemap_player.cell_to_local(board_position), 2) + if Input.is_action_just_pressed("key_5"): + pick_up_item(Vector2i(5, 8)) + pick_up_item(Vector2i(9, 9)) + if Input.is_action_just_pressed("key_4"): + var nearest: Vector2i = find_nearest_object([game_manager.world.tilemap_types.OBJECT_I_TREE_FULL]) + # nearest.x = nearest.x - 1 + walk_towards(nearest) # SECTION: board access/mangement func update_board() -> void: - game_manager.world.tilemap_player.clear_cells() - # decide what direction the player is facing tilemap_types.PLAYER_DOWN, ... - var direction: Vector2i = find_direction(last_board_position, board_position) - game_manager.world.tilemap_player.set_cell(board_position, tilemap_types.player_sprite_from_direction(direction)) - if inventory_slot and inventory_slot != tilemap_types.EMPTY: - inventory_label.text = str(inventory_slot) - else: - inventory_label.text = "empty" + game_manager.world.tilemap_player.clear_cells() + # decide what direction the player is facing tilemap_types.PLAYER_DOWN, ... + var direction: Vector2i = find_direction(last_board_position, board_position) + game_manager.world.tilemap_player.set_cell(board_position, tilemap_types.player_sprite_from_direction(direction)) + if inventory_slot and inventory_slot != tilemap_types.EMPTY: + inventory_label.text = str(inventory_slot) + else: + inventory_label.text = "empty" # SECTION: inventory system func pick_up_item(tilemap_pos: Vector2i) -> void: - var pick_up_cell: TileData = game_manager.world.tilemap_interactive.get_cell(tilemap_pos) - if not pick_up_cell: - push_warning("Player trying to pick up item that does not exist at ", tilemap_pos) - return + var pick_up_cell: TileData = game_manager.world.tilemap_interactive.get_cell(tilemap_pos) + if not pick_up_cell: + push_warning("Player trying to pick up item that does not exist at ", tilemap_pos) + return - var pick_up_item_type: Vector2i = game_manager.world.tilemap_interactive.tilemap.get_cell_atlas_coords(tilemap_pos) + var pick_up_item_type: Vector2i = game_manager.world.tilemap_interactive.tilemap.get_cell_atlas_coords(tilemap_pos) - # check if tile will transform into another tile upon pickup - var tile_after_pickup_transform = null - var tile_drop_item: Vector2i = inventory_slot - if tilemap_types.OBJECT_I_FILLED_BUSH == pick_up_item_type: - tile_after_pickup_transform = tilemap_types.OBJECT_I_EMPTY_BUSH - pick_up_item_type = tilemap_types.OBJECT_I_BERRY - tile_drop_item = tilemap_types.OBJECT_I_BERRY + # check if tile will transform into another tile upon pickup + var tile_after_pickup_transform = null + var tile_drop_item: Vector2i = inventory_slot + if tilemap_types.OBJECT_I_FILLED_BUSH == pick_up_item_type: + tile_after_pickup_transform = tilemap_types.OBJECT_I_EMPTY_BUSH + pick_up_item_type = tilemap_types.OBJECT_I_BERRY + tile_drop_item = tilemap_types.OBJECT_I_BERRY - # check if the inventory slot is empty - if inventory_slot == tilemap_types.EMPTY: - inventory_slot = pick_up_item_type - if tile_after_pickup_transform: - game_manager.world.tilemap_interactive.set_cell(tilemap_pos, tile_after_pickup_transform) - else: - game_manager.world.tilemap_interactive.clear_cell(tilemap_pos) - print("Picked up item: ", pick_up_item_type) - EventsTracker.track(EventsTracker.Event.PLAYER_PICKED_UP_ITEM, {"item": pick_up_item_type}) + # check if the inventory slot is empty + if inventory_slot == tilemap_types.EMPTY: + inventory_slot = pick_up_item_type + if tile_after_pickup_transform: + game_manager.world.tilemap_interactive.set_cell(tilemap_pos, tile_after_pickup_transform) + else: + game_manager.world.tilemap_interactive.clear_cell(tilemap_pos) + print("Picked up item: ", pick_up_item_type) + EventsTracker.track(EventsTracker.Event.PLAYER_PICKED_UP_ITEM, {"item": pick_up_item_type}) - else: - # inventory is full, swap the item - print("Inventory is full. Swapping item: ", inventory_slot, " with item: ", pick_up_item_type) - EventsTracker.track(EventsTracker.Event.PLAYER_DROPPED_ITEM, {"item": inventory_slot}) - EventsTracker.track(EventsTracker.Event.PLAYER_PICKED_UP_ITEM, {"item": pick_up_item_type}) - if tile_after_pickup_transform: - game_manager.world.tilemap_interactive.set_cell(tilemap_pos, tile_after_pickup_transform) - var drop_location: Vector2i = game_manager.world.find_item_drop_location(tilemap_pos) - if drop_location != tilemap_types.EMPTY: - game_manager.world.tilemap_interactive.set_cell(drop_location, tile_drop_item) - else: - push_warning("Could not find valid drop position for ", inventory_slot) - else: - game_manager.world.tilemap_interactive.set_cell(tilemap_pos, tile_drop_item) - inventory_slot = pick_up_item_type + else: + # inventory is full, swap the item + print("Inventory is full. Swapping item: ", inventory_slot, " with item: ", pick_up_item_type) + EventsTracker.track(EventsTracker.Event.PLAYER_DROPPED_ITEM, {"item": inventory_slot}) + EventsTracker.track(EventsTracker.Event.PLAYER_PICKED_UP_ITEM, {"item": pick_up_item_type}) + if tile_after_pickup_transform: + game_manager.world.tilemap_interactive.set_cell(tilemap_pos, tile_after_pickup_transform) + var drop_location: Vector2i = game_manager.world.find_item_drop_location(tilemap_pos) + if drop_location != tilemap_types.EMPTY: + game_manager.world.tilemap_interactive.set_cell(drop_location, tile_drop_item) + else: + push_warning("Could not find valid drop position for ", inventory_slot) + else: + game_manager.world.tilemap_interactive.set_cell(tilemap_pos, tile_drop_item) + inventory_slot = pick_up_item_type # SECTION: player movement func walk_towards(position: Vector2i) -> void: - var path: Array[Vector2i] = game_manager.tilemap_navigation.find_path(board_position, position) - walk_along(path) + var path: Array[Vector2i] = game_manager.tilemap_navigation.find_path(board_position, position) + walk_along(path) func walk_along(path: Array[Vector2i]) -> void: - if len(path) > 1: - var next_position: Vector2i = path[1] - var direction: Vector2i = find_direction(board_position, next_position) - move_player(direction) - game_manager.tilemap_navigation.chosen_path = path - else: - push_warning("walk_along path is empty") + if len(path) > 1: + var next_position: Vector2i = path[1] + var direction: Vector2i = find_direction(board_position, next_position) + move_player(direction) + game_manager.tilemap_navigation.chosen_path = path + else: + push_warning("walk_along path is empty") func move_player(direction: Vector2i) -> void: - var new_position: Vector2 = board_position + direction - if game_manager.world.is_walkable(new_position): - board_position = new_position - else: - push_warning("Player trying to move to non-walkable position, prevented ", new_position) + var new_position: Vector2 = board_position + direction + if game_manager.world.is_walkable(new_position): + board_position = new_position + else: + push_warning("Player trying to move to non-walkable position, prevented ", new_position) func find_nearest_object(object_collection: Array[Vector2i]) -> Vector2i: - var object_positions: Array[Vector2i] = [] + var object_positions: Array[Vector2i] = [] - for obj in object_collection: - object_positions.append_array(game_manager.world.tilemap_interactive.get_cells_by_type(obj)) + for obj in object_collection: + object_positions.append_array(game_manager.world.tilemap_interactive.get_cells_by_type(obj)) - if object_positions.size() == 0: - push_warning("No " + str(object_collection) + " found!") - return tilemap_types.NO_TILE_FOUND + if object_positions.size() == 0: + push_warning("No " + str(object_collection) + " found!") + return tilemap_types.NO_TILE_FOUND - var closest_object: Vector2i = tilemap_types.NO_TILE_FOUND - var shortest_distance: float = 99999999 + var closest_object: Vector2i = tilemap_types.NO_TILE_FOUND + var shortest_distance: float = 99999999 - for position in object_positions: - var distance: float = game_manager.tilemap_navigation.manhattan_distance(board_position, position) - if closest_object == tilemap_types.NO_TILE_FOUND or distance < shortest_distance: - closest_object = position - shortest_distance = distance + for position in object_positions: + var distance: float = game_manager.tilemap_navigation.manhattan_distance(board_position, position) + if closest_object == tilemap_types.NO_TILE_FOUND or distance < shortest_distance: + closest_object = position + shortest_distance = distance - print("Find nearest " + str(object_collection) + " at:", closest_object) - return closest_object + print("Find nearest " + str(object_collection) + " at:", closest_object) + return closest_object func find_direction(pos_a: Vector2i, pos_b: Vector2i) -> Vector2i: - var direction: Vector2i = Vector2i(0, 0) - if pos_a.x < pos_b.x: - direction.x = 1 - elif pos_a.x > pos_b.x: - direction.x = -1 + var direction: Vector2i = Vector2i(0, 0) + if pos_a.x < pos_b.x: + direction.x = 1 + elif pos_a.x > pos_b.x: + direction.x = -1 - if pos_a.y < pos_b.y: - direction.y = 1 - elif pos_a.y > pos_b.y: - direction.y = -1 + if pos_a.y < pos_b.y: + direction.y = 1 + elif pos_a.y > pos_b.y: + direction.y = -1 - return direction + return direction # SECTION: game tick func tick_handle_temperature(cell_temperature: int): - if cell_temperature == 0: - temperature_timer = 0 - elif temperature_timer > temperature_endure: - temperature_timer += cell_temperature - health -= temperature_damage + if cell_temperature == 0: + temperature_timer = 0 + elif temperature_timer > temperature_endure: + temperature_timer += cell_temperature + health -= temperature_damage func tick_handle_food(): - if food > 0: - food -= 1 - if food <= 0: - health -= food_damage + if food > 0: + food -= 1 + if food <= 0: + health -= food_damage func game_tick() -> void: - behavior_tree.game_tick() + behavior_tree.game_tick() - var player_positon_array: Array[Vector2i] = game_manager.world.tilemap_player.get_cells_by_type(tilemap_types.PLAYER_DOWN) - if len(player_positon_array) > 0: - var player_positon: Vector2i = player_positon_array[0] - var cell_temperature: int = game_manager.world.tilemap_temperature.get_custom_data(player_positon, "temperature", 0) as int - tick_handle_temperature(cell_temperature) - else: - push_error("No player found on tilemap") + var player_positon_array: Array[Vector2i] = game_manager.world.tilemap_player.get_cells_by_type(tilemap_types.PLAYER_DOWN) + if len(player_positon_array) > 0: + var player_positon: Vector2i = player_positon_array[0] + var cell_temperature: int = game_manager.world.tilemap_temperature.get_custom_data(player_positon, "temperature", 0) as int + tick_handle_temperature(cell_temperature) + else: + push_error("No player found on tilemap") - tick_handle_food() + tick_handle_food() - if health < 0: - game_manager.player_health_depleted() + if health < 0: + game_manager.player_health_depleted() - update_board() + update_board() diff --git a/project/scripts/player/tree/impl/game/inventory/TaskEatFoodFromInventory.gd b/project/scripts/player/tree/impl/game/inventory/TaskEatFoodFromInventory.gd index 9b6f62e..c452c5e 100644 --- a/project/scripts/player/tree/impl/game/inventory/TaskEatFoodFromInventory.gd +++ b/project/scripts/player/tree/impl/game/inventory/TaskEatFoodFromInventory.gd @@ -2,15 +2,15 @@ class_name TaskEatFoodFromInventory extends Task func run(blackboard: Dictionary) -> void: - var player: PlayerManager = blackboard["player"] + var player: PlayerManager = blackboard["player"] - if player.inventory_slot != tilemap_types.OBJECT_I_BERRY: - status = FAILURE - status_reason = "Inventory does not contain berry" - return + if player.inventory_slot != tilemap_types.OBJECT_I_BERRY: + status = FAILURE + status_reason = "Inventory does not contain berry" + return - player.inventory_slot = tilemap_types.EMPTY - player.food += player.food_addon_per_berry + player.inventory_slot = tilemap_types.EMPTY + player.food = player.max_food - status = SUCCESS - status_reason = "Ate berry, player now has " + str(player.food) + " food" + status = SUCCESS + status_reason = "Ate berry, player now has " + str(player.food) + " food"