diff --git a/ActionBehaviour/ActionBehaviourResource.gd b/ActionBehaviour/ActionBehaviourResource.gd index 49fe783..ea0109b 100644 --- a/ActionBehaviour/ActionBehaviourResource.gd +++ b/ActionBehaviour/ActionBehaviourResource.gd @@ -1,11 +1,11 @@ extends Resource class_name ActionBehaviour -func do_action() -> void: +func do_action(source_tile: InsectTile, action_tile: InsectTile, map: HexGrid) -> void: pass -func select_targets(source_pos: Vector4i, map: HexGrid) -> void: - pass +func get_targets(source_pos: Vector4i, map: HexGrid) -> Array[InsectTile]: + return [] # NOTE: When selecting a tile, check if there is an action behaviour # If yes: In addition to showing moveable spaces (0 for the mosquito by default) diff --git a/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd b/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd index 47cc193..81c1e79 100644 --- a/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd +++ b/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd @@ -1,8 +1,18 @@ extends ActionBehaviour class_name ActionBehaviourMosquito +func do_action(source_tile: InsectTile, action_tile: InsectTile, map: HexGrid) -> void: + pass + # GameEvents.insect_tiles_selected_for_action -func select_targets(source_pos: Vector4i, map: HexGrid): # -> Array[InsectTile]: +func get_targets(source_pos: Vector4i, map: HexGrid) -> Array[InsectTile]: + # if on the hive, i.e. layer > 0, we always move like a beetle + # so we can't use our action unless we're on layer 0 + # TODO: Update movement selection + if source_pos.w > 0: + map.debug_label(Vector3(source_pos.x, source_pos.y, source_pos.z), "TODO: Implement Beetle Movement") + return [] + var neighbours = map.get_neighbours(source_pos) # Filter out other mosquitos var possible_action_targets: Array[InsectTile] = [] @@ -10,8 +20,9 @@ func select_targets(source_pos: Vector4i, map: HexGrid): # -> Array[InsectTile]: var tile = map.get_tile(neighbour) if tile != null: # TODO: Find better way to see what tile we have... - pass - #if not tile.resource.movement_behaviour is MovementBehaviourMosquito: - # possible_action_targets.push_back(tile) + if not tile.resource.movement_behaviour is MovementBehaviourMosquito: + possible_action_targets.push_back(tile) - GameEvents.insect_tiles_selected_for_action.emit(source_pos, possible_action_targets) + #GameEvents.insect_tiles_selected_for_action.emit(source_pos, possible_action_targets) + + return possible_action_targets diff --git a/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd b/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd index 5f051f1..a0beccf 100644 --- a/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd +++ b/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd @@ -1,12 +1,24 @@ extends ActionBehaviour class_name ActionBehaviourPillbug -func select_targets(source_pos: Vector4i, map: HexGrid): # -> Array[InsectTile]: +func do_action(source_tile: InsectTile, action_tile: InsectTile, map: HexGrid) -> void: + pass + +func get_targets(source_pos: Vector4i, map: HexGrid) -> Array[InsectTile]: var neighbours = map.get_neighbours(source_pos) var possible_action_targets: Array[InsectTile] = [] + for neighbour in neighbours: var tile = map.get_tile(neighbour) if tile != null: - possible_action_targets.push_back(tile) + if not tile.is_in_stack() and tile.can_move(): + possible_action_targets.push_back(tile) - GameEvents.insect_tiles_selected_for_action.emit(source_pos, possible_action_targets) + #GameEvents.insect_tiles_selected_for_action.emit(source_pos, possible_action_targets) + + return possible_action_targets + + +# 2nd level has to be clear (move through narrow gap rule) +# We could do the following: Get neighbours in 2nd level of source (pillbug) and target +# we we have two overlapping/same neighbours, we have a narrow gap and can't move the target diff --git a/Game.gd b/Game.gd index 783f2a7..c6aa78c 100644 --- a/Game.gd +++ b/Game.gd @@ -10,7 +10,7 @@ var current_turn: int = 1 func _ready(): GameEvents.insect_tile_finished_moving.connect(_on_insect_tile_finished_moving) GameEvents.insect_tile_created.connect(_on_insect_tile_created) - + GameEvents.pass_round.connect(_on_pass_round) # since we sealed in webrtc, # and limited players to 1 in enet # this should only happen when the opponent disconnects @@ -21,6 +21,14 @@ func _ready(): GameEvents.game_started.emit() + +@rpc("any_peer", "call_local") +func pass_round() -> void: + advance_turn() + +func _on_pass_round() -> void: + pass_round.rpc() + func _on_peer_disconnected(id: int) -> void: GameData.disconnect_reason = "Connection to other peer closed unexpectedly" #Networking.disconnect_all() @@ -31,6 +39,7 @@ func _on_peer_disconnected(id: int) -> void: #Networking.disconnect_all() # get_tree().change_scene_to_file("res://UI/main_menu.tscn") + func advance_turn(): GameEvents.turn_ended.emit(current_turn, map) is_blacks_turn = !is_blacks_turn diff --git a/Game.tscn b/Game.tscn index 91c62ac..a95a960 100644 --- a/Game.tscn +++ b/Game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=23 format=3 uid="uid://bx0bbrwdr0h40"] +[gd_scene load_steps=24 format=3 uid="uid://bx0bbrwdr0h40"] [ext_resource type="Script" path="res://Game.gd" id="1_dgt1j"] [ext_resource type="Script" path="res://CameraPivot.gd" id="2_71xp1"] @@ -14,6 +14,7 @@ [ext_resource type="Script" path="res://TurnTexture.gd" id="12_kjwp8"] [ext_resource type="Script" path="res://addons/awesome_input_icons/classes/InputIconTextureRect.gd" id="13_mbmni"] [ext_resource type="Texture2D" uid="uid://20wqrthwoqr0" path="res://addons/awesome_input_icons/assets/keyboard and mouse vector/mouse_move.svg" id="14_t8b21"] +[ext_resource type="Script" path="res://UI/ActionMoveMenu.gd" id="15_gc6p8"] [sub_resource type="PlaneMesh" id="PlaneMesh_cu5ir"] material = ExtResource("5_u4p4p") @@ -250,6 +251,19 @@ offset_bottom = 40.0 layout_mode = 2 text = "Menu" +[node name="PassRoundButton" type="Button" parent="MenuButtons/VBoxContainer"] +layout_mode = 2 +text = "Pass" + +[node name="SurrenderButton" type="Button" parent="MenuButtons/VBoxContainer"] +layout_mode = 2 +text = "Surrender" + +[node name="OfferDrawButton" type="Button" parent="MenuButtons/VBoxContainer"] +layout_mode = 2 +disabled = true +text = "Offer Draw" + [node name="RulesButton" type="Button" parent="MenuButtons/VBoxContainer"] layout_mode = 2 text = "Rules" @@ -465,6 +479,65 @@ theme_override_font_sizes/font_size = 20 text = "Show/Hide controls" horizontal_alignment = 2 +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="ActionMoveMenu" type="Control" parent="CanvasLayer"] +visible = false +layout_mode = 3 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +script = ExtResource("15_gc6p8") + +[node name="PanelContainer" type="PanelContainer" parent="CanvasLayer/ActionMoveMenu"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="CanvasLayer/ActionMoveMenu/PanelContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +theme_override_constants/margin_left = 15 +theme_override_constants/margin_top = 15 +theme_override_constants/margin_right = 15 +theme_override_constants/margin_bottom = 15 + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="MoveButton" type="Button" parent="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Use action of #Name" + +[node name="ActionButton" type="Button" parent="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Move as #Name" + +[node name="HSeparator" type="HSeparator" parent="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="CancelButton" type="Button" parent="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Cancel" + [connection signal="pressed" from="MenuButtons/VBoxContainer/MenuButton" to="MenuButtons" method="_on_menu_button_pressed"] +[connection signal="pressed" from="MenuButtons/VBoxContainer/PassRoundButton" to="MenuButtons" method="_on_pass_round_button_pressed"] +[connection signal="pressed" from="MenuButtons/VBoxContainer/SurrenderButton" to="MenuButtons" method="_on_surrender_button_pressed"] +[connection signal="pressed" from="MenuButtons/VBoxContainer/OfferDrawButton" to="MenuButtons" method="_on_menu_button_pressed"] [connection signal="pressed" from="MenuButtons/VBoxContainer/RulesButton" to="MenuButtons" method="_on_rules_button_pressed"] [connection signal="pressed" from="GameOverMenu/Control/PanelContainer/VBoxContainer/Button" to="GameOverMenu" method="_on_button_pressed"] +[connection signal="pressed" from="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer/MoveButton" to="CanvasLayer/ActionMoveMenu" method="_on_move_button_pressed"] +[connection signal="pressed" from="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer/ActionButton" to="CanvasLayer/ActionMoveMenu" method="_on_action_button_pressed"] +[connection signal="pressed" from="CanvasLayer/ActionMoveMenu/PanelContainer/MarginContainer/VBoxContainer/CancelButton" to="CanvasLayer/ActionMoveMenu" method="_on_cancel_button_pressed"] diff --git a/GameOverMenu.gd b/GameOverMenu.gd index a4edd2f..d0a2c4c 100644 --- a/GameOverMenu.gd +++ b/GameOverMenu.gd @@ -22,4 +22,5 @@ func _on_game_over(black_lost: bool, white_lost: bool) -> void: func _on_button_pressed(): #WSClient.close() - get_tree().change_scene_to_file("res://main_menu.tscn") + Networking.disconnect_all() + get_tree().change_scene_to_file("res://UI/main_menu.tscn") diff --git a/Globals/GameEvents.gd b/Globals/GameEvents.gd index 6b9a51e..4af44a9 100644 --- a/Globals/GameEvents.gd +++ b/Globals/GameEvents.gd @@ -6,15 +6,21 @@ signal insect_placement_cancelled signal insect_tile_created(tile, pos) signal insect_tile_selected(tile) +signal insect_tile_selecetion_failed(tile) signal insect_tile_deselected(tile) signal insect_tile_moved(tile, to) signal insect_tile_finished_moving(tile, to) signal insect_tiles_selected_for_action(source_tile, target_tiles, action) signal insect_action_cancelled() -signal insect_action_done() # ??? Maybe? Right no we have a gameendchecker... +signal insect_action_done() # ??? Maybe? Right now we have a gameendchecker... + +signal choose_action_or_move(tile, has_action_targets, has_move_targets) +signal insect_tile_move_started(tile) +signal insect_tile_action_started(tile) # Turn started could work implicitly? We'll see... +signal pass_round signal turn_started(turn_num, map, is_blacks_turn) signal turn_ended(turn_num, map) diff --git a/HexGrid3D/HexGrid3D.gd b/HexGrid3D/HexGrid3D.gd index fb2f2a0..9bc5510 100644 --- a/HexGrid3D/HexGrid3D.gd +++ b/HexGrid3D/HexGrid3D.gd @@ -198,6 +198,7 @@ func debug_label(pos, text) -> void: var label = Label3D.new() label.billboard = BaseMaterial3D.BILLBOARD_ENABLED label.text = text + label.no_depth_test = true var p = cube_to_world_pos(pos) label.position = Vector3(p.x, 0.2, p.y) add_child(label) @@ -233,7 +234,7 @@ func can_reach(start: Vector4i, target: Vector4i, exclude: Array[Vector4i] = []) return is_cell_empty(left_coord) or is_cell_empty(right_coord) -func _on_insect_selected(button: InsectButton, is_black: bool) -> void: +func _on_insect_selected(button: InsectButton, is_black: bool) -> void: var positions = get_placeable_positions(button) for child in placement_visualizer.get_children(): @@ -289,23 +290,37 @@ func _on_insect_placed(resource: TileResource, is_black: bool, pos: Vector4i) -> place_insect_tile.rpc(resource_path, is_black, pos) func can_move(tile: InsectTile) -> bool: - return can_hive_exist_without_tile(tile) + if not can_hive_exist_without_tile(tile): + return false + + var spaces = tile.resource.movement_behaviour.get_available_spaces(tile.coordinates, self) + + if spaces.is_empty(): + return false + + return true + +func has_action_targets(tile: InsectTile) -> bool: + if tile.resource.action_behaviour == null: + return false + + var targets: Array[InsectTile] = tile.resource.action_behaviour.get_targets(tile.coordinates, self) + + return !targets.is_empty() -func _on_insect_tile_selected(tile: InsectTile) -> void: +func _on_insect_tile_action_started(tile: InsectTile) -> void: + do_action(tile) + +func _on_insect_tile_move_started(tile: InsectTile) -> void: + do_move(tile) + +func do_action(tile: InsectTile) -> void: + pass + +func do_move(tile: InsectTile) -> void: for child in placement_visualizer.get_children(): child.queue_free() - if not can_hive_exist_without_tile(tile): - print("Would break hive") - return - - if tile.resource.movement_behaviour == null: - #print("no movement behaviour") - return - - #if tile.resource.action_behaviour != null: - #tile.resource.action_behaviour.select_targets(tile.coordinates, self) - var spaces = tile.resource.movement_behaviour.get_available_spaces(tile.coordinates, self) if spaces.is_empty(): @@ -355,6 +370,26 @@ func _on_insect_tile_selected(tile: InsectTile) -> void: outline.is_black = tile.is_black placement_visualizer.add_child(outline) placements[space] = outline + +func _on_insect_tile_selected(tile: InsectTile) -> void: + # check the following: + # if the insect is selectable for an action (has action_callback data set) -> do that action + # else: + # if the unit has no action + # try moving + # else: + # show action/move panel, grey out action/or move if there are no target or can't move? + if tile.action_callback.is_valid(): + tile.action_callback.call() + return + else: + # if tile has an action + if tile.resource.action_behaviour != null: + GameEvents.choose_action_or_move.emit(tile, has_action_targets(tile), can_move(tile)) + return + + if can_move(tile): + do_move(tile) func get_tile(pos: Vector4i) -> InsectTile: return used_cells.get(pos) @@ -458,3 +493,5 @@ func _ready() -> void: GameEvents.insect_placed.connect(_on_insect_placed) GameEvents.insect_tile_selected.connect(_on_insect_tile_selected) GameEvents.insect_tile_moved.connect(_on_insect_tile_moved) + GameEvents.insect_tile_action_started.connect(_on_insect_tile_action_started) + GameEvents.insect_tile_move_started.connect(_on_insect_tile_move_started) diff --git a/HexOutline.gd b/HexOutline.gd index 6216ec3..0c98dc0 100644 --- a/HexOutline.gd +++ b/HexOutline.gd @@ -15,6 +15,8 @@ var is_moving: bool = false var map_reference: HexGrid +var is_active: bool = true + const BUILD_GHOST = preload("res://InsectTiles/BuildGhost.tscn") # Called when the node enters the scene tree for the first time. func _ready(): @@ -28,14 +30,17 @@ func _ready(): GameEvents.insect_placed.connect(_on_insect_placed) func _on_insect_tile_moved(tile: InsectTile, to: Vector4i) -> void: + is_active = false queue_free() func _on_insect_placed(resource: TileResource, is_black: bool, pos: Vector4i) -> void: + is_active = false queue_free() # Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): - if Input.is_action_just_pressed("place_tile"): +#func _process(delta): +func _input_event(camera, event, position, normal, shape_idx): + if Input.is_action_just_pressed("place_tile") and is_active: if hovered: if is_moving: GameEvents.insect_tile_moved.emit(insect_tile, coordinates) @@ -50,10 +55,8 @@ func _on_mouse_entered(): tile.is_black = is_black tile.map_reference = map_reference - add_child(tile) - func _on_input_event(camera, event, position, normal, shape_idx): pass # Replace with function body. diff --git a/InGameMenu.gd b/InGameMenu.gd index f62eabd..e02ca0e 100644 --- a/InGameMenu.gd +++ b/InGameMenu.gd @@ -35,8 +35,6 @@ func hide_panel() -> void: tween.finished.connect(_on_panel_hidden) - - func _on_panel_hidden() -> void: visible = false queue_free() diff --git a/MenuButtons.gd b/MenuButtons.gd index 20ddb53..a442532 100644 --- a/MenuButtons.gd +++ b/MenuButtons.gd @@ -2,11 +2,21 @@ extends Control const IN_GAME_MENU = preload("res://UI/InGameMenu/InGameMenu.tscn") const RULES = preload("res://UI/Rules/Rules.tscn") + +@onready var surrender_button = $VBoxContainer/SurrenderButton +@onready var pass_round_button = $VBoxContainer/PassRoundButton + +var is_blacks_turn: bool = false + # Called when the node enters the scene tree for the first time. func _ready(): - pass # Replace with function body. - - + GameEvents.turn_started.connect(_on_turn_started) + +func _on_turn_started(round_num: int, map: HexGrid, _is_blacks_turn: bool) -> void: + is_blacks_turn = _is_blacks_turn + surrender_button.disabled = GameData.is_player_black != _is_blacks_turn and not GameData.is_hot_seat + pass_round_button.disabled = GameData.is_player_black != _is_blacks_turn and not GameData.is_hot_seat + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta): pass @@ -25,3 +35,16 @@ func _on_menu_button_pressed(): get_tree().root.add_child(in_game_menu) in_game_menu.show_panel() + +@rpc("any_peer", "call_local") +func surrender() -> void: + if is_blacks_turn: + GameEvents.game_over.emit(true, false) + else: + GameEvents.game_over.emit(false, true) + +func _on_surrender_button_pressed(): + surrender.rpc() + +func _on_pass_round_button_pressed(): + GameEvents.pass_round.emit() diff --git a/MovementBehaviour/Prefabs/MovementBehaviourLadybug.gd b/MovementBehaviour/Prefabs/MovementBehaviourLadybug.gd index 91509f1..9e79caf 100644 --- a/MovementBehaviour/Prefabs/MovementBehaviourLadybug.gd +++ b/MovementBehaviour/Prefabs/MovementBehaviourLadybug.gd @@ -9,6 +9,7 @@ func simulate_move_recursive(start: Vector4i, max_num: int, exclude: Array[Vecto visited.append(start) + if max_num < 1: return [start] @@ -19,8 +20,8 @@ func simulate_move_recursive(start: Vector4i, max_num: int, exclude: Array[Vecto neighbours = map.get_empty_neighbours(start) for neighbour in neighbours: - if neighbour in visited: - continue + #if neighbour in visited: + # continue #var same_neighbours = map.get_same_neighbours(start, neighbour) #for e in exclude: @@ -28,6 +29,7 @@ func simulate_move_recursive(start: Vector4i, max_num: int, exclude: Array[Vecto #if same_neighbours.size() > 0: visited.append(neighbour) + possible.append_array(simulate_move_recursive(neighbour, max_num - 1, exclude, map, visited)) return possible @@ -36,5 +38,12 @@ func get_available_spaces(pos: Vector4i, map: HexGrid) -> Array[Vector4i]: var possible_places: Array[Vector4i] = [] possible_places = simulate_move_recursive(pos, max_movement_reach, [pos], map) - + + var possible_places_dict: Dictionary = {} + for p in possible_places: + possible_places_dict[p] = p + + possible_places.clear() + possible_places.assign(possible_places_dict.values()) + return possible_places diff --git a/MovementBehaviour/Prefabs/MovementBehaviourMosquito.gd b/MovementBehaviour/Prefabs/MovementBehaviourMosquito.gd index c4b0ae6..4758aec 100644 --- a/MovementBehaviour/Prefabs/MovementBehaviourMosquito.gd +++ b/MovementBehaviour/Prefabs/MovementBehaviourMosquito.gd @@ -2,12 +2,13 @@ extends MovementBehaviour class_name MovementBehaviourMosquito func get_available_spaces(pos: Vector4i, map: HexGrid) -> Array[Vector4i]: - var target_spaces: Array[Vector4i] = [] - - for neighbour in map.get_neighbours(pos): - if map.is_cell_empty(neighbour): - continue - - target_spaces.append_array(map.get_tile(neighbour).resource.movement_behaviour.get_available_spaces(pos, map)) - - return target_spaces + return [] + #var target_spaces: Array[Vector4i] = [] + # + #for neighbour in map.get_neighbours(pos): + #if map.is_cell_empty(neighbour): + #continue +# + #target_spaces.append_array(map.get_tile(neighbour).resource.movement_behaviour.get_available_spaces(pos, map)) +# + #return target_spaces diff --git a/Tile/Tile.gd b/Tile/Tile.gd index ea5e94c..85aeadc 100644 --- a/Tile/Tile.gd +++ b/Tile/Tile.gd @@ -6,7 +6,6 @@ var map_reference: HexGrid var is_blacks_turn: bool = false var coordinates: Vector4i -var layer: int = 0 @export var is_black: bool = false @export var resource: TileResource @@ -18,17 +17,14 @@ var hat: InsectTile = null var build_in_progress: bool = false var move_in_progress: bool = false - var deactivated: bool = false - var hovered: bool = false - var selected: bool = false -var hover_shader: ShaderMaterial = preload("res://InsectTiles/HoverShader.tres") -const SELECTION_FAILED_MAT: ShaderMaterial = preload("res://InsectTiles/SelectionFailedMat.tres") -const ACTION_SHADER = preload("res://InsectTiles/ActionShader.tres") +var hover_shader: ShaderMaterial = preload("res://InsectTiles/HoverShader.tres") +#const SELECTION_FAILED_MAT: ShaderMaterial = preload("res://InsectTiles/SelectionFailedMat.tres") +#const ACTION_SHADER = preload("res://InsectTiles/ActionShader.tres") var mat: StandardMaterial3D @@ -37,8 +33,25 @@ var tween: Tween var tweening: bool = false var selected_for_action: bool = false +var action_callback: Callable = Callable() + + var can_be_selected: bool = false +var move_round_penalty: int = 0 + +func is_in_stack() -> bool: + return hat != null or coordinates.w != 0 + +func can_move() -> bool: + # if any tile gets moved, set move_round_penalty to 2 + # on turn start subtract 1 + # we can't move if its 1, so we have to wait an additional round + # this is ued for the pillbug ability + # also if we move, we also set it to 2 + + return move_round_penalty == 0 + func is_players_turn() -> bool: return is_blacks_turn == is_black @@ -69,18 +82,45 @@ func _ready() -> void: hexagon_small.rotation.y = PI GameEvents.insect_selected.connect(_on_insect_selected) + GameEvents.insect_tile_selecetion_failed.connect(_on_selection_failed) GameEvents.insect_placed.connect(_on_insect_placed) GameEvents.insect_placement_cancelled.connect(_on_insect_placement_cancelled, CONNECT_DEFERRED) GameEvents.insect_tile_selected.connect(_on_insect_tile_selected) GameEvents.insect_tile_deselected.connect(_on_insect_tile_deselected) GameEvents.insect_tile_moved.connect(_on_insect_tile_moved) + GameEvents.insect_tiles_selected_for_action.connect(_on_tiles_selected_for_action) + GameEvents.insect_action_cancelled.connect(_on_action_cancelled) GameEvents.turn_started.connect(_on_turn_started) +func _on_action_cancelled() -> void: + selected_for_action = false + move_in_progress = false + selected = false + + if hovered: + hover() + else: + if tween != null: + tween.kill() + + tween.tween_method(tween_shader, mat.next_pass.get_shader_parameter("albedo"), Color(1, 1, 1, 0), 0.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) + + +func _on_selection_failed(tile: InsectTile) -> void: + if tile != self: + return + + # Show selection failed mat + func _on_turn_started(turn_num: int, map: HexGrid, _is_blacks_turn: bool) -> void: is_blacks_turn = _is_blacks_turn + move_round_penalty -= 1 + if move_round_penalty < 0: + move_round_penalty = 0 + can_be_selected = GameData.bees_placed.has(is_black) #print(GameData.has_bee_been_placed) if turn_num >= 7 and not GameData.bees_placed.has(is_black): @@ -89,7 +129,12 @@ func _on_turn_started(turn_num: int, map: HexGrid, _is_blacks_turn: bool) -> voi func _on_tiles_selected_for_action(source_pos: Vector4i, targets: Array[InsectTile]) -> void: if self in targets: selected_for_action = true - mat.next_pass = ACTION_SHADER + if tween != null: + tween.kill() + + tween = get_tree().create_tween() + #tween.tween_property(self, "position", Vector3(0, 0, 5), 0.5).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SPRING) + tween.tween_method(tween_shader, Color(0, 0.6, 0, 0), Color(0, 0.6, 0, 0.8), 0.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) return deactivated = true @@ -98,35 +143,49 @@ func _on_tiles_selected_for_action(source_pos: Vector4i, targets: Array[InsectTi func _on_insect_tile_moved(tile: InsectTile, to: Vector4i) -> void: move_in_progress = false selected = false + deactivated = false if tile == self: - hovered = false - if not tweening: - mat.next_pass = null + move_round_penalty == 2 func _on_insect_tile_deselected(tile: InsectTile) -> void: move_in_progress = false selected = false + deactivated = false + + if hovered: + hover() + else: + if tween != null: + tween.kill() + + #tween.tween_method(tween_shader, mat.next_pass.get_shader_parameter("albedo"), Color(1, 1, 1, 0), 0.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) func _on_insect_tile_selected(tile: InsectTile) -> void: + deactivated = true if tile == self: selected = true + return func _on_insect_placed(resource: TileResource, is_black: bool, pos: Vector4i) -> void: build_in_progress = false + deactivated = false func _on_insect_placement_cancelled() -> void: build_in_progress = false + deactivated = false func _on_insect_selected(button: InsectButton, is_black: bool) -> void: build_in_progress = true + deactivated = true -func _process(delta): +#func _process(delta): +func _input_event(camera, event, position, normal, shape_idx): if Input.is_action_just_pressed("place_tile"): - if not can_be_selected: + if deactivated: return - if deactivated: + if not can_be_selected: return if not hovered: @@ -157,18 +216,19 @@ func hover() -> void: if is_blacks_turn != is_black: return + # mat.next_pass = hover_shader.duplicate() + if tween != null: tween.kill() tween = get_tree().create_tween() #tween.tween_property(self, "position", Vector3(0, 0, 5), 0.5).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SPRING) - tween.tween_method(tween_hover_shader, Color(0, 0, 0, 0), Color(0, 0, 0, 1), 0.1).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) + tween.tween_method(tween_shader, Color(0, 0, 0, 0), Color(0, 0, 0, 1), 0.1).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) -func tween_hover_shader(color: Color) -> void: - if mat.next_pass != null: - mat.next_pass.set_shader_parameter("albedo", color) - mat.next_pass.set_shader_parameter("emission_color", color) +func tween_shader(color: Color) -> void: + mat.next_pass.set_shader_parameter("albedo", color) + mat.next_pass.set_shader_parameter("emission_color", color) func unhover() -> void: if is_blacks_turn != is_black: @@ -179,16 +239,22 @@ func unhover() -> void: tween = get_tree().create_tween() #tween.tween_property(hex, "position", Vector2(0, -16), 0.1).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SPRING) - tween.tween_method(tween_hover_shader, Color(0, 0, 0, 1), Color(0, 0, 0, 0), 0.25).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) + tween.tween_method(tween_shader, Color(0, 0, 0, 1), Color(0, 0, 0, 0), 0.25).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) func _on_mouse_entered(): - hovered = true + if hat != null: + return + hovered = true + if not deactivated and not selected_for_action: hover() func _on_mouse_exited(): + if hat != null: + return + hovered = false if not selected and not selected_for_action: diff --git a/UI/ActionMoveMenu.gd b/UI/ActionMoveMenu.gd new file mode 100644 index 0000000..78a9636 --- /dev/null +++ b/UI/ActionMoveMenu.gd @@ -0,0 +1,71 @@ +extends Control + +@onready var move_button = $PanelContainer/MarginContainer/VBoxContainer/MoveButton +@onready var action_button = $PanelContainer/MarginContainer/VBoxContainer/ActionButton + +var current_tile: InsectTile = null +var tween: Tween = null + +func show_panel() -> void: + scale = Vector2.ZERO + + visible = true + if tween != null: + tween.kill() + + tween = get_tree().create_tween() + tween.tween_property(self, "scale", Vector2(1.0, 1.0), 0.35).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SPRING) + +func hide_panel() -> void: + current_tile = null + + if tween != null: + tween.kill() + + tween = get_tree().create_tween() + tween.tween_property(self, "scale", Vector2(0.0, 0.0), 0.35).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_EXPO) + + tween.finished.connect(_on_panel_hidden) + pass + +func _on_panel_hidden() -> void: + visible = false + +# Called when the node enters the scene tree for the first time. +func _ready(): + GameEvents.choose_action_or_move.connect(_on_choose_action_or_move) + GameEvents.insect_tile_deselected.connect(_on_tile_deselected) + +func _on_tile_deselected(tile: InsectTile) -> void: + hide_panel() + + +func _on_choose_action_or_move(tile: InsectTile, has_action_targets: bool, can_move: bool) -> void: + current_tile = tile + move_button.text = "Move as %s" % tile.resource.tile_name + move_button.disabled = !can_move + + action_button.text = "Use action of %s" % tile.resource.tile_name + action_button.disabled = !has_action_targets + show_panel() + pass + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + + +func _on_action_button_pressed(): + GameEvents.insect_tile_action_started.emit(current_tile) + hide_panel() + + +func _on_move_button_pressed(): + GameEvents.insect_tile_move_started.emit(current_tile) + hide_panel() + + +func _on_cancel_button_pressed(): + GameEvents.insect_tile_deselected.emit(current_tile) + pass # Replace with function body. diff --git a/UI/BuildMenu.gd b/UI/BuildMenu.gd index 1466935..5b4931e 100644 --- a/UI/BuildMenu.gd +++ b/UI/BuildMenu.gd @@ -11,9 +11,9 @@ const default_insects = { preload("res://Tile/Prefabs/Beetle.tres"): 2, preload("res://Tile/Prefabs/Grasshopper.tres"): 3, preload("res://Tile/Prefabs/Spider.tres"): 2, - #preload("res://Tile/Prefabs/Ladybug.tres"): 1, - #preload("res://Tile/Prefabs/Mosquito.tres"): 1, - #preload("res://Tile/Prefabs/Pillbug.tres"): 1 + preload("res://Tile/Prefabs/Ladybug.tres"): 1, + preload("res://Tile/Prefabs/Mosquito.tres"): 1, + preload("res://Tile/Prefabs/Pillbug.tres"): 1 } var local_bee_button: InsectButton diff --git a/UI/main_menu.tscn b/UI/main_menu.tscn index 9e5f4fb..98e3174 100644 --- a/UI/main_menu.tscn +++ b/UI/main_menu.tscn @@ -58,7 +58,7 @@ text = "Join Game" [node name="SingleplayerButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"] layout_mode = 2 disabled = true -text = "Singleplayer" +text = "Singleplayer (vs AI)" [node name="HSeparator2" type="HSeparator" parent="PanelContainer/MarginContainer/VBoxContainer"] layout_mode = 2