From 26fec25a6e3593cc607c16ecbaa353adc6c7dfc1 Mon Sep 17 00:00:00 2001 From: Sch1nken Date: Fri, 15 Mar 2024 03:24:32 +0100 Subject: [PATCH] Fixed more movement bugs, disabled expansions for now. Added turnendbehaviour (for bee, should add trigger by turn end signal) --- ActionBehaviour/ActionBehaviourResource.gd | 3 + .../Prefabs/ActionBehaviourMosquito.gd | 14 +++++ .../Prefabs/ActionBehaviourPillbug.gd | 10 +++ BuildMenu.gd | 6 +- Globals/GameData.gd | 1 + Globals/GameEvents.gd | 6 ++ HexGrid3D/HexGrid3D.gd | 61 ++++++++++++++++--- InsectTiles/ActionShader.tres | 11 ++++ Misc/RTSCamera3D.gd | 2 +- .../Prefabs/MovementBehaviourBeetle.gd | 12 +++- Tile/Tile.gd | 50 ++++++++------- Tile/TileResource.gd | 2 + .../Prefabs/TurnEndBehaviourBee.gd | 8 +++ TurnEndBehaviour/TurnEndBehaviour.gd | 5 ++ 14 files changed, 154 insertions(+), 37 deletions(-) create mode 100644 InsectTiles/ActionShader.tres create mode 100644 TurnEndBehaviour/Prefabs/TurnEndBehaviourBee.gd create mode 100644 TurnEndBehaviour/TurnEndBehaviour.gd diff --git a/ActionBehaviour/ActionBehaviourResource.gd b/ActionBehaviour/ActionBehaviourResource.gd index fe0e848..49fe783 100644 --- a/ActionBehaviour/ActionBehaviourResource.gd +++ b/ActionBehaviour/ActionBehaviourResource.gd @@ -4,6 +4,9 @@ class_name ActionBehaviour func do_action() -> void: pass +func select_targets(source_pos: Vector4i, map: HexGrid) -> void: + pass + # 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) # also show action options (usually clicking other nearby tiles) diff --git a/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd b/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd index 3345b37..4da47a4 100644 --- a/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd +++ b/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd @@ -1,2 +1,16 @@ extends ActionBehaviour class_name ActionBehaviourMosquito + +# GameEvents.insect_tiles_selected_for_action +func select_targets(source_pos: Vector4i, map: HexGrid): # -> Array[InsectTile]: + var neighbours = map.get_neighbours(source_pos) + # Filter out other mosquitos + var possible_action_targets: Array[InsectTile] = [] + for neighbour in neighbours: + var tile = map.get_tile(neighbour) + if tile != null: + # TODO: Find better way to see what tile we have... + 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) diff --git a/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd b/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd index faa91d9..5f051f1 100644 --- a/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd +++ b/ActionBehaviour/Prefabs/ActionBehaviourPillbug.gd @@ -1,2 +1,12 @@ extends ActionBehaviour class_name ActionBehaviourPillbug + +func select_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) + + GameEvents.insect_tiles_selected_for_action.emit(source_pos, possible_action_targets) diff --git a/BuildMenu.gd b/BuildMenu.gd index 1952388..799386b 100644 --- a/BuildMenu.gd +++ b/BuildMenu.gd @@ -12,9 +12,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 } # Called when the node enters the scene tree for the first time. diff --git a/Globals/GameData.gd b/Globals/GameData.gd index 0f2c495..8559c99 100644 --- a/Globals/GameData.gd +++ b/Globals/GameData.gd @@ -2,3 +2,4 @@ extends Node var is_player_black: bool = false var debug: bool = true +var allow_selecting_in_stack: bool = false diff --git a/Globals/GameEvents.gd b/Globals/GameEvents.gd index 5e6ed0a..0e6a47d 100644 --- a/Globals/GameEvents.gd +++ b/Globals/GameEvents.gd @@ -8,5 +8,11 @@ signal insect_tile_selected(tile) signal insect_tile_deselected(tile) signal insect_tile_moved(tile, to) +signal insect_tiles_selected_for_action(source_tile, target_tiles, action) +signal insect_action_cancelled() +signal insect_action_done() # ??? Maybe? + signal turn_started(turn_num) signal turn_ended(turn_num) + +signal game_over(is_winner_black) diff --git a/HexGrid3D/HexGrid3D.gd b/HexGrid3D/HexGrid3D.gd index 4736e53..ba4c215 100644 --- a/HexGrid3D/HexGrid3D.gd +++ b/HexGrid3D/HexGrid3D.gd @@ -113,6 +113,19 @@ func is_cell_not_empty(coords: Vector4i) -> bool: func get_empty_neighbours(coords: Vector4i) -> Array[Vector4i]: return get_neighbours(coords).filter(is_cell_empty) +func get_highest_in_stack(coords: Vector4i) -> Vector4i: + if not used_cells.has(coords): + print("ground") + return coords + + var top: InsectTile = used_cells[coords] + while top.hat != null: + top = top.hat + + print("found top") + print(top.coordinates) + return top.coordinates + func get_neighbours(coords: Vector4i, ground_layer: bool = false) -> Array[Vector4i]: var layer: int = coords.w if ground_layer: @@ -147,7 +160,13 @@ func get_placeable_positions(button: InsectButton) -> Array[Vector4i]: var possible_placements: Dictionary = {} var positions: Array[Vector4i] = [] - for hex in used_cells.keys(): + for hex in used_cells.keys().filter(func(coords): return coords.w == 0): + # We filter here because we only want neighbours of ground level tiles + # Otherwise we spawn an oultine on ground level but with an internal + # Coordinate of somewhere higher up + # Visually everything will be correct but internally the resulting hex + # Will count as higher layer tile leading to nasty bugs + for neighbour in get_empty_neighbours(hex): if not used_cells.has(neighbour): possible_placements[neighbour] = true @@ -218,7 +237,7 @@ func can_reach(start: Vector4i, target: Vector4i, exclude: Array[Vector4i] = []) func _on_insect_selected(button: InsectButton, is_black: bool) -> void: var positions = get_placeable_positions(button) - for p in positions: + for p in positions: var outline = HEX_OUTLINE.instantiate() var hex_pos = cube_to_world_pos(p) outline.position = Vector3(hex_pos.x, 0.0, hex_pos.y) @@ -317,6 +336,7 @@ func _on_insect_placed(resource: TileResource, is_black: bool, pos: Vector4i) -> tile_copy.resource = resource tile_copy.is_black = is_black tile_copy.coordinates = pos + print(pos) tile_copy.map_reference = self var target_pos = Vector3(hex_pos.x, 0.0, hex_pos.y) @@ -339,6 +359,9 @@ func _on_insect_tile_selected(tile: InsectTile) -> void: 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(): @@ -353,9 +376,14 @@ func _on_insect_tile_selected(tile: InsectTile) -> void: if non_empty_neighbours.size() == 1: # NOTE: This is correct! But seemed wrong when testing the beetle movement # If there are only two tiles (beetle + some other) the beetle can't climb ontop of the other - # tile. This fixes itself automatically when there are more than two tiles present + # tile. (would not necessarily split the hive, but the simple logic I use thinks so). + # This fixes itself automatically when there are more than two tiles present # And since you can't move unless you place the bee, there will always be at least 3 tiles # before you can move your beetle + + # NOTE: This MIGHT result in a bug when you stack beetles... but no I don't think so + # You'd need to have a bee to be able to move, so yeah + var occupied_neighbour = non_empty_neighbours.front() if occupied_neighbour == tile.coordinates: continue @@ -365,9 +393,10 @@ func _on_insect_tile_selected(tile: InsectTile) -> void: if is_cell_not_empty(space): temp_tile = used_cells.get(space) layer = 1 - while tile.hat != null: + while temp_tile.hat != null: layer += 1 - tile = tile.hat + temp_tile = temp_tile.hat + print(layer) space.w = layer @@ -387,15 +416,20 @@ func get_tile(pos: Vector4i) -> InsectTile: return used_cells.get(pos) func _on_insect_tile_moved(tile: InsectTile, target: Vector4i) -> void: + # Remove from old stack + if tile.coordinates.w > 0: + var below: Vector4i = tile.coordinates + Vector4i(0, 0, 0, -1) + used_cells[below].hat = null + used_cells.erase(tile.coordinates) var new_hex_pos = cube_to_world_pos(target) var sky_new_hex_pos = Vector3(new_hex_pos.x, 20.0, new_hex_pos.y) var ground_new_hex_pos = Vector3(new_hex_pos.x, target.w * layer_height, new_hex_pos.y) - # + var current_hex_pos = tile.position var sky_current_hex_pos = tile.position + Vector3(0.0, 20.0, 0.0) -# + var tween = get_tree().create_tween() tween.tween_property(tile, "position", sky_current_hex_pos, 0.5).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_EXPO) tween.tween_property(tile, "position", sky_new_hex_pos, 0.0) @@ -404,6 +438,12 @@ func _on_insect_tile_moved(tile: InsectTile, target: Vector4i) -> void: tile.coordinates = target used_cells[tile.coordinates] = tile + + if tile.coordinates.w > 0: + var below: Vector4i = tile.coordinates + Vector4i(0, 0, 0, -1) + used_cells[below].hat = tile + + # Add to new stack func get_same_neighbours(cell1: Vector4i, cell2: Vector4i) -> Array[Vector4i]: var neighbours1 = get_neighbours(cell1).filter(is_cell_not_empty) @@ -423,14 +463,17 @@ func is_position_on_hive(pos: Vector4i) -> bool: return get_empty_neighbours(pos).size() < 6 func can_hive_exist_without_tile(tile: InsectTile) -> bool: - # TODO: BFS-Search from random cell to see if all other cells could still be reached when this + if tile.coordinates.w != 0: + return true + + # TODO: BFS-Search from random cell to see if all other cells could still be reached when this # tile would be empty space if get_empty_neighbours(tile.coordinates).size() == 5: # we only have one real neighbour, so can't break anything return true # DO BFS var tiles_reached: Array = [] - var tiles_available: Array = used_cells.keys().filter(func(coords): return coords != tile.coordinates).filter(func(coords): coords.w != tile.coordinates.w) + var tiles_available: Array = used_cells.keys().filter(func(coords): return coords != tile.coordinates).filter(func(coords): return coords.w == 0) if tiles_available.size() <= 1: # If we only have 1 or 2 total tiles, we can always move diff --git a/InsectTiles/ActionShader.tres b/InsectTiles/ActionShader.tres new file mode 100644 index 0000000..ae3642c --- /dev/null +++ b/InsectTiles/ActionShader.tres @@ -0,0 +1,11 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://cjoq705fsnga5"] + +[ext_resource type="Shader" path="res://InsectTiles/HoverShader.gdshader" id="1_rk2jr"] + +[resource] +render_priority = 0 +shader = ExtResource("1_rk2jr") +shader_parameter/albedo = Color(0, 0.392157, 0, 1) +shader_parameter/emission_color = Color(0, 0.552941, 0, 0.886275) +shader_parameter/emission_amount = 5.0 +shader_parameter/rim_steepness = 0.214 diff --git a/Misc/RTSCamera3D.gd b/Misc/RTSCamera3D.gd index 793311d..79d09ca 100644 --- a/Misc/RTSCamera3D.gd +++ b/Misc/RTSCamera3D.gd @@ -72,7 +72,7 @@ func _set_zoom_level(value: float) -> void: self, "camera_distance", _camera_distance, - 0.3 + 0.15 ) func _unhandled_input(event: InputEvent) -> void: diff --git a/MovementBehaviour/Prefabs/MovementBehaviourBeetle.gd b/MovementBehaviour/Prefabs/MovementBehaviourBeetle.gd index 70c73fa..2fdb4d8 100644 --- a/MovementBehaviour/Prefabs/MovementBehaviourBeetle.gd +++ b/MovementBehaviour/Prefabs/MovementBehaviourBeetle.gd @@ -17,9 +17,9 @@ func simulate_move_recursive(start: Vector4i, max_num: int, map: HexGrid, visite continue # can reach... can_reach should only apply to our current level - if not map.can_reach(start, neighbour): - continue - + #if not map.can_reach(start, neighbour): + # continue + visited.append(neighbour) possible.append_array(simulate_move_recursive(neighbour, max_num - 1, map, visited)) @@ -29,5 +29,11 @@ func get_available_spaces(pos: Vector4i, map: HexGrid) -> Array[Vector4i]: var possible_places: Array[Vector4i] = [] possible_places = simulate_move_recursive(pos, max_movement_reach, map) + + var possible_with_hats: Array[Vector4i] = [] + + for p in possible_places: + possible_with_hats.push_back(map.get_highest_in_stack(p)) + return possible_places diff --git a/Tile/Tile.gd b/Tile/Tile.gd index 5591022..7ad9d91 100644 --- a/Tile/Tile.gd +++ b/Tile/Tile.gd @@ -27,6 +27,7 @@ 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 mat: StandardMaterial3D @@ -34,6 +35,8 @@ var tween: Tween var tweening: bool = false +var selected_for_action: bool = false + func _ready() -> void: if is_black: hexagon_small.set_surface_override_material(0, resource.material_black.duplicate()) @@ -50,7 +53,17 @@ func _ready() -> void: 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) +func _on_tiles_selected_for_action(source_pos: Vector4i, targets: Array[InsectTile]) -> void: + if self in targets: + selected_for_action = true + print("meme") + mat.next_pass = ACTION_SHADER + return + + deactivated = true + func _on_insect_tile_moved(tile: InsectTile, to: Vector4i) -> void: move_in_progress = false @@ -66,7 +79,6 @@ func _on_insect_tile_deselected(tile: InsectTile) -> void: selected = false func _on_insect_tile_selected(tile: InsectTile) -> void: - move_in_progress = true if tile == self: selected = true @@ -86,25 +98,21 @@ func _process(delta): if not hovered: return + + # Move up the insect stack.... or just do not react while we have something on top of us? - ## Check with map if we can be placed - #if not map_reference.can_move(self): - #return - # - # - #if resource.movement_behaviour == null: - ## TODO: Play fail animation/tween - #return - # - #var spaces = resource.movement_behaviour.get_available_spaces(coordinates, map_reference) - # - #if spaces.is_empty(): - ##GameEvents.insect_tile_selection_request_failed.emit(tile) - #return - - print(resource) - - GameEvents.insect_tile_selected.emit(self) + if GameData.allow_selecting_in_stack: + var top: InsectTile = self + while top.hat != null: + top = top.hat + + if top.is_black == GameData.is_player_black or GameData.debug: + GameEvents.insect_tile_selected.emit(top) + else: + if hat != null: + return + else: + GameEvents.insect_tile_selected.emit(self) func hover() -> void: #if GameData.is_player_black != is_black: @@ -138,11 +146,11 @@ func unhover() -> void: func _on_mouse_entered(): hovered = true - if not deactivated: + if not deactivated and not selected_for_action: hover() func _on_mouse_exited(): hovered = false - if not selected: + if not selected and not selected_for_action: unhover() diff --git a/Tile/TileResource.gd b/Tile/TileResource.gd index dee7797..f4a1868 100644 --- a/Tile/TileResource.gd +++ b/Tile/TileResource.gd @@ -5,6 +5,8 @@ class_name TileResource @export var movement_behaviour: MovementBehaviour @export var action_behaviour: ActionBehaviour +@export var turn_end_behaviour: TurnEndBehaviour + @export var material_black: StandardMaterial3D @export var material_white: StandardMaterial3D diff --git a/TurnEndBehaviour/Prefabs/TurnEndBehaviourBee.gd b/TurnEndBehaviour/Prefabs/TurnEndBehaviourBee.gd new file mode 100644 index 0000000..40f313c --- /dev/null +++ b/TurnEndBehaviour/Prefabs/TurnEndBehaviourBee.gd @@ -0,0 +1,8 @@ +extends TurnEndBehaviour +class_name TurnEndBehaviourBee + +func trigger(tile: InsectTile, map: HexGrid, was_turn_black: bool = false) -> void: + if map.get_empty_neighbours(tile.coordinates).size() == 0: + # Game Over for this player + GameEvents.game_over.emit(!tile.is_black) + pass diff --git a/TurnEndBehaviour/TurnEndBehaviour.gd b/TurnEndBehaviour/TurnEndBehaviour.gd new file mode 100644 index 0000000..96050f0 --- /dev/null +++ b/TurnEndBehaviour/TurnEndBehaviour.gd @@ -0,0 +1,5 @@ +extends Resource +class_name TurnEndBehaviour + +func trigger(tile: InsectTile, map: HexGrid, was_turn_black: bool = false) -> void: + pass