diff --git a/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd b/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd index 4da47a4..47cc193 100644 --- a/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd +++ b/ActionBehaviour/Prefabs/ActionBehaviourMosquito.gd @@ -10,7 +10,8 @@ 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... - if not tile.resource.movement_behaviour is MovementBehaviourMosquito: - possible_action_targets.push_back(tile) + pass + #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/Game.tscn b/Game.tscn index 8a13d20..d7e70cc 100644 --- a/Game.tscn +++ b/Game.tscn @@ -1,37 +1,21 @@ -[gd_scene load_steps=23 format=3 uid="uid://bx0bbrwdr0h40"] +[gd_scene load_steps=22 format=3 uid="uid://bx0bbrwdr0h40"] [ext_resource type="Script" path="res://Game.gd" id="1_dgt1j"] [ext_resource type="Script" path="res://Misc/RTSCamera3D.gd" id="1_dtmfo"] [ext_resource type="Script" path="res://HexGrid3D/HexGrid3D.gd" id="2_suxca"] [ext_resource type="Script" path="res://GameEndChecker.gd" id="2_ufkw3"] -[ext_resource type="Texture2D" uid="uid://cilgpyanfb3a8" path="res://Testbed/textures/wood_table_001_diff_4k.jpg" id="3_w3jge"] -[ext_resource type="Texture2D" uid="uid://diamo44e2x4if" path="res://Testbed/textures/wood_table_001_disp_4k.png" id="4_b7cy7"] -[ext_resource type="Texture2D" uid="uid://b6ejmikbfrprs" path="res://Testbed/textures/wood_table_001_rough_4k.jpg" id="5_lck42"] +[ext_resource type="Material" uid="uid://dv2oo7hlc5nyy" path="res://Testbed/Table.tres" id="5_u4p4p"] [ext_resource type="Script" path="res://WebLightChecker.gd" id="6_41m5i"] [ext_resource type="Script" path="res://UI/BuildMenu.gd" id="7_1oc55"] -[ext_resource type="PackedScene" uid="uid://bo8hgq66dbbb6" path="res://UI/insect_button.tscn" id="8_lfn34"] +[ext_resource type="Script" path="res://Table.gd" id="8_ys5y3"] [ext_resource type="Texture2D" uid="uid://d2i5vboeyq8qx" path="res://UI/hex_white.svg" id="11_cl0he"] [ext_resource type="Script" path="res://GameOverMenu.gd" id="11_ffmss"] +[ext_resource type="Script" path="res://MenuButtons.gd" id="11_urihv"] [ext_resource type="Script" path="res://TurnTexture.gd" id="12_kjwp8"] - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_u8oxs"] -albedo_texture = ExtResource("3_w3jge") -roughness_texture = ExtResource("5_lck42") -roughness_texture_channel = 4 -normal_enabled = true -normal_scale = 0.1 -normal_texture = ExtResource("4_b7cy7") -heightmap_scale = 1.0 -heightmap_deep_parallax = true -heightmap_min_layers = 1 -heightmap_max_layers = 1 -heightmap_texture = ExtResource("4_b7cy7") -refraction_scale = 0.28 -refraction_texture = ExtResource("4_b7cy7") -texture_filter = 5 +[ext_resource type="PackedScene" uid="uid://8ffmln680deh" path="res://Testbed/Rules.tscn" id="12_xhim1"] [sub_resource type="PlaneMesh" id="PlaneMesh_cu5ir"] -material = SubResource("StandardMaterial3D_u8oxs") +material = ExtResource("5_u4p4p") size = Vector2(50, 50) [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_dv0dt"] @@ -40,12 +24,22 @@ size = Vector2(50, 50) sky_material = SubResource("ProceduralSkyMaterial_dv0dt") [sub_resource type="Environment" id="Environment_xoohw"] -background_mode = 2 +background_mode = 1 +background_energy_multiplier = 0.0 sky = SubResource("Sky_v4pi7") +ambient_light_source = 2 +ambient_light_color = Color(1, 1, 1, 1) +ambient_light_energy = 0.3 tonemap_mode = 1 ssao_enabled = true +fog_light_color = Color(0, 0, 0, 1) +fog_density = 0.3 [sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_41x5h"] +dof_blur_far_enabled = true +dof_blur_far_distance = 15.0 +dof_blur_far_transition = 10.0 +dof_blur_near_enabled = true [sub_resource type="Gradient" id="Gradient_pctcs"] interpolation_mode = 2 @@ -84,6 +78,7 @@ script = ExtResource("2_suxca") [node name="MeshInstance3D" type="MeshInstance3D" parent="."] mesh = SubResource("PlaneMesh_cu5ir") +script = ExtResource("8_ys5y3") [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_xoohw") @@ -92,6 +87,8 @@ camera_attributes = SubResource("CameraAttributesPractical_41x5h") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(0.843961, -0.46784, 0.262404, -0.0775016, 0.377705, 0.922677, -0.530777, -0.79904, 0.28251, 0.262159, 3.27869, -0.104568) light_color = Color(1, 0.941176, 0.823529, 1) +light_energy = 0.8 +light_indirect_energy = 0.8 shadow_enabled = true directional_shadow_blend_splits = true script = ExtResource("6_41m5i") @@ -162,12 +159,6 @@ alignment = 1 layout_mode = 2 mouse_filter = 0 -[node name="BeeButton" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects" instance=ExtResource("8_lfn34")] -layout_mode = 2 - -[node name="VSeparator" type="VSeparator" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects"] -layout_mode = 2 - [node name="PanelContainer2" type="PanelContainer" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"] modulate = Color(1, 1, 1, 0) layout_mode = 2 @@ -230,13 +221,6 @@ mouse_filter = 2 layout_mode = 2 mouse_filter = 0 -[node name="VSeparator" type="VSeparator" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects"] -layout_mode = 2 - -[node name="BeeButton" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects" instance=ExtResource("8_lfn34")] -layout_mode = 2 -is_black = true - [node name="CurrentTurnDisplay" type="Control" parent="."] layout_mode = 3 anchors_preset = 5 @@ -249,6 +233,29 @@ size_flags_horizontal = 4 size_flags_vertical = 0 mouse_filter = 2 +[node name="MenuButtons" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("11_urihv") + +[node name="VBoxContainer" type="VBoxContainer" parent="MenuButtons"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="MenuButton" type="Button" parent="MenuButtons/VBoxContainer"] +layout_mode = 2 +text = "Menu" + +[node name="RulesButton" type="Button" parent="MenuButtons/VBoxContainer"] +layout_mode = 2 +text = "Rules" + +[node name="Rules" parent="." instance=ExtResource("12_xhim1")] +visible = false + [node name="GameOverMenu" type="CanvasLayer" parent="."] script = ExtResource("11_ffmss") @@ -284,4 +291,5 @@ text = "Back to menu" [node name="PauseMenu" type="CanvasLayer" parent="."] +[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"] diff --git a/GameEndChecker.gd b/GameEndChecker.gd index 3106301..6170ab7 100644 --- a/GameEndChecker.gd +++ b/GameEndChecker.gd @@ -13,8 +13,10 @@ func _on_insect_tile_created(tile: InsectTile, pos: Vector4i) -> void: if is_same(BEE, tile.resource): bees.push_back(tile) - if tile.is_black == GameData.is_player_black: - GameData.has_bee_been_placed = true + GameData.bees_placed[tile.is_black] = tile + + #if tile.is_black == GameData.is_player_black: + # GameData.has_bee_been_placed = true func _on_turn_ended(turn_num: int, map: HexGrid) -> void: var black_lost: bool = false diff --git a/GameOverMenu.gd b/GameOverMenu.gd index 5a04d76..a4edd2f 100644 --- a/GameOverMenu.gd +++ b/GameOverMenu.gd @@ -21,5 +21,5 @@ func _on_game_over(black_lost: bool, white_lost: bool) -> void: print("should never happen...") func _on_button_pressed(): - WSClient.close() + #WSClient.close() get_tree().change_scene_to_file("res://main_menu.tscn") diff --git a/Globals/GameData.gd b/Globals/GameData.gd index 6a7d5da..753ac92 100644 --- a/Globals/GameData.gd +++ b/Globals/GameData.gd @@ -2,7 +2,11 @@ extends Node const WEBSOCKET_ENDPOINT: String = "wss://dev.bytesandpieces.xyz:9088" -var is_hot_seat: bool = false +# By default, peer_id is 1. This should make everything work flawless for local hotseat +var peer_id: int = 1 + + +var is_hot_seat: bool = true var is_player_black: bool = false var debug: bool = false @@ -10,13 +14,17 @@ var allow_selecting_in_stack: bool = false var lobby_code: String = "" -var has_bee_been_placed: bool = false -var bees_placed: Dictionary = {} +# false as key = white +# true as key = black + +# bees_placed.has(is_player_black) false/true -> white/black +var bees_placed: Dictionary = {} + var disconnect_reason: String = "" func reset() -> void: is_hot_seat = false - has_bee_been_placed = false disconnect_reason = "" bees_placed = {} + peer_id = 1 diff --git a/HexGrid3D/HexGrid3D.gd b/HexGrid3D/HexGrid3D.gd index 61a9499..52b02a4 100644 --- a/HexGrid3D/HexGrid3D.gd +++ b/HexGrid3D/HexGrid3D.gd @@ -339,12 +339,16 @@ func place_insect_tile(resource_path: String, is_black: bool, pos: Vector4i) -> tile_copy.resource = resource tile_copy.is_black = is_black tile_copy.coordinates = pos - #print(pos) + #print(pos) tile_copy.map_reference = self var target_pos = Vector3(hex_pos.x, 0.0, hex_pos.y) used_cells[pos] = tile_copy + var sender_id = multiplayer.get_remote_sender_id() + + tile_copy.set_multiplayer_authority(sender_id) + add_child(tile_copy) GameEvents.insect_tile_created.emit(tile_copy, pos) diff --git a/InsectButton.gd b/InsectButton.gd index ede11b2..dd3cffc 100644 --- a/InsectButton.gd +++ b/InsectButton.gd @@ -24,8 +24,32 @@ var is_blacks_turn: bool = false var should_disable: bool = false -func is_players_turn() -> bool: - return is_blacks_turn == is_black or GameData.debug +@rpc("call_local", "authority") +func set_authority(peer_id: int) -> void: + set_multiplayer_authority(peer_id, true) + pass + + +func is_players_turn() -> bool: + return is_blacks_turn == is_black + +# Have a functions that checks if we're the "owner" +func is_owner() -> bool: + # TODO: Only use multiplayer authority + # According to https://docs.godotengine.org/en/stable/classes/class_offlinemultiplayerpeer.html + # Even without active multiplayer, the normal calls just work as expected + #if GameData.is_hot_seat: + # return true + #elif GameData.is_player_black == is_black: # we could use multiplayer authority here + # return true + + #return false + return is_multiplayer_authority() + +@rpc("call_remote", "any_peer") +func update_amount(amount: int) -> void: + tile_count = amount + update_tile_count_display() func update_color(_is_black: bool) -> void: is_black = _is_black @@ -37,10 +61,7 @@ func update_color(_is_black: bool) -> void: update_tile_count_display() insect_icon.texture = insect_resource.ui_texture - if GameData.is_hot_seat: - return - - if is_black != is_blacks_turn and not GameData.debug: + if is_black != GameData.is_player_black: disabled = true return @@ -55,6 +76,7 @@ func update_tile_count_display() -> void: func decrement_tile_count() -> void: tile_count -= 1 update_tile_count_display() + update_amount.rpc(tile_count) func disable() -> void: disabled = true @@ -110,10 +132,12 @@ func _ready() -> void: GameEvents.turn_started.connect(_on_turn_started) + name = insect_resource.tile_name + func _on_turn_started(turn_num: int, map: HexGrid, _is_blacks_turn: bool) -> void: is_blacks_turn = _is_blacks_turn should_disable = false - if turn_num >= 7 and not GameData.bees_placed.has(is_black): #has_bee_been_placed: + if turn_num >= 7 and not GameData.bees_placed.has(is_black): if is_black == is_blacks_turn: # if not bee has been placed for this player # lock all buttons except the bee @@ -123,7 +147,8 @@ func _on_turn_started(turn_num: int, map: HexGrid, _is_blacks_turn: bool) -> voi else: #lock should_disable = true - + + refresh_state() func _on_insect_tile_deselected(tile: InsectTile) -> void: @@ -140,16 +165,18 @@ func _on_insect_selected(button: InsectButton, _is_black: bool) -> void: disable() func hover() -> void: - - #if is_blacks_turn != is_black and not GameData.debug: - # return + if is_blacks_turn != is_black: + return + + if not is_owner(): + return var 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) func unhover() -> void: - #if is_blacks_turn != is_black and not GameData.debug: - # return + #if GameData.is_player_black != is_black: + #return var tween = get_tree().create_tween() tween.tween_property(hex, "position", Vector2(0, 0), 0.25).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_SPRING) @@ -167,17 +194,10 @@ func _on_mouse_exited(): unhover() func _on_pressed(): - # We can only press under these conditions - # Check if its the currents player turn (is black) - # If hotseat: we're done - # If multiplayer: Check if GameData.is_player_black is correct, this prevents - # the other player from using this button on their game instance - - #GameData.is_hot_seat if is_empty(): return - if not is_blacks_turn == is_black and not GameData.debug: + if not is_owner(): return if not is_players_turn(): diff --git a/InsectTiles/InsectTile.tscn b/InsectTiles/InsectTile.tscn index 5f35884..3e38482 100644 --- a/InsectTiles/InsectTile.tscn +++ b/InsectTiles/InsectTile.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=7 format=3 uid="uid://dxwngv0xmk3vy"] +[gd_scene load_steps=8 format=3 uid="uid://dxwngv0xmk3vy"] [ext_resource type="Script" path="res://Tile/Tile.gd" id="1_b68ym"] [ext_resource type="ArrayMesh" uid="uid://dsbshu53k588h" path="res://hexagon_small.res" id="2_vm00h"] +[ext_resource type="Resource" uid="uid://b70uxn2ofij8y" path="res://Tile/Prefabs/Bee.tres" id="2_xu8wf"] [ext_resource type="Texture2D" uid="uid://bp5lbofkicsqq" path="res://InsectTiles/Assets/Textures/ant_black.png" id="3_r51ol"] [ext_resource type="Texture2D" uid="uid://dr36631neiknu" path="res://InsectTiles/Assets/Textures/ant_white.png" id="4_f75dl"] @@ -15,6 +16,7 @@ data = PackedVector3Array(-0.25, 0.4004, 0.433014, 0.25, 0.000399577, 0.433014, [node name="InsectTile" type="Area3D"] monitoring = false script = ExtResource("1_b68ym") +resource = ExtResource("2_xu8wf") [node name="HexagonSmall" type="MeshInstance3D" parent="."] mesh = ExtResource("2_vm00h") diff --git a/MenuButtons.gd b/MenuButtons.gd new file mode 100644 index 0000000..48667a0 --- /dev/null +++ b/MenuButtons.gd @@ -0,0 +1,17 @@ +extends Control + +@onready var rules = $"../Rules" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_rules_button_pressed(): + rules.show_panel() diff --git a/Multiplayer/LobbyInfo.gd b/Multiplayer/LobbyInfo.gd index 8a15bf2..ab0fbc8 100644 --- a/Multiplayer/LobbyInfo.gd +++ b/Multiplayer/LobbyInfo.gd @@ -1,33 +1,6 @@ extends CanvasLayer -@onready var insect_icons: HBoxContainer = $PanelContainer/VBoxContainer/InsectIcons - @onready var lobby_code: Label = $PanelContainer/VBoxContainer/LobbyCode -const INSECT_BUTTON = preload("res://UI/insect_button.tscn") - -const insect_resources = [ - preload("res://Tile/Prefabs/Ant.tres"), - preload("res://Tile/Prefabs/Bee.tres"), - preload("res://Tile/Prefabs/Beetle.tres"), - preload("res://Tile/Prefabs/Grasshopper.tres"), - preload("res://Tile/Prefabs/Ladybug.tres"), - preload("res://Tile/Prefabs/Mosquito.tres"), - preload("res://Tile/Prefabs/Pillbug.tres"), - preload("res://Tile/Prefabs/Spider.tres") -] - -var insect_data = { - -} - -func prepare_insect_data() -> void: - var c: int = 65 - - for i in insect_resources: - for k in 2: - insect_data[String.chr(c)] = {"resource": i, "is_black": k%2 != 0} - c = c + 1 - @onready var start_game_button = $PanelContainer/VBoxContainer/StartGameButton @@ -41,23 +14,9 @@ func _ready(): if not multiplayer.is_server(): return - insect_icons.visible = true start_game_button.visible = true - lobby_code.text = GameData.lobby_code - - prepare_insect_data() - - for c in GameData.lobby_code: - var b = INSECT_BUTTON.instantiate() - b.deactivated = true - b.disabled = true - b.disable_amount_display = true - var data = insect_data[c] - b.is_black = data.is_black - b.insect_resource = data.resource - insect_icons.add_child(b) - + lobby_code.text = GameData.lobby_code # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta): diff --git a/Multiplayer/Multiplayer.gd b/Multiplayer/Multiplayer.gd index ad012bb..f5df305 100644 --- a/Multiplayer/Multiplayer.gd +++ b/Multiplayer/Multiplayer.gd @@ -15,6 +15,7 @@ func _ready(): func _mp_peer_disconnected(id: int) -> void: has_opponent = false + GameData.peer_id = 1 start_game_button.disabled = true if game_in_progress or id == 1: @@ -41,6 +42,7 @@ func _mp_server_disconnect(): func _mp_peer_connected(id: int): _log("[Multiplayer] Peer %d connected" % id) has_opponent = true + GameData.peer_id = id start_game_button.disabled = false @onready var lobby_info = $LobbyInfo @@ -62,4 +64,3 @@ func load_game() -> void: func _on_start_game_button_pressed(): # tell other peer to now load the world via rpc load_game.rpc() - pass # Replace with function body. diff --git a/Multiplayer/Multiplayer.tscn b/Multiplayer/Multiplayer.tscn index 6667470..17329d9 100644 --- a/Multiplayer/Multiplayer.tscn +++ b/Multiplayer/Multiplayer.tscn @@ -27,10 +27,6 @@ alignment = 1 layout_mode = 2 horizontal_alignment = 1 -[node name="InsectIcons" type="HBoxContainer" parent="LobbyInfo/PanelContainer/VBoxContainer"] -visible = false -layout_mode = 2 - [node name="StartGameButton" type="Button" parent="LobbyInfo/PanelContainer/VBoxContainer"] visible = false layout_mode = 2 diff --git a/Networking/Networking.tscn b/Networking/Networking.tscn new file mode 100644 index 0000000..5fdbee8 --- /dev/null +++ b/Networking/Networking.tscn @@ -0,0 +1,3 @@ +[gd_scene format=3 uid="uid://cigm5ol2f8b4b"] + +[node name="Networking" type="Node"] diff --git a/Table.gd b/Table.gd new file mode 100644 index 0000000..1715b20 --- /dev/null +++ b/Table.gd @@ -0,0 +1,24 @@ +extends MeshInstance3D + +var mat: ShaderMaterial +# Called when the node enters the scene tree for the first time. +func _ready(): + mat = get_active_material(0) + + var tween = get_tree().create_tween() + tween.set_parallel(true) + tween.tween_method(tween_inner, -1.0, 10.0, 3.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO) + tween.tween_method(tween_outer, 0.0, 25.0, 3.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CIRC) + + pass # Replace with function body. + + +func tween_inner(value: float) -> void: + mat.set_shader_parameter("distance_fade_max", value) + +func tween_outer(value: float) -> void: + mat.set_shader_parameter("distance_fade_min", value) + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/Testbed/DistanceFaceWorld.gdshader b/Testbed/DistanceFaceWorld.gdshader new file mode 100644 index 0000000..331cf31 --- /dev/null +++ b/Testbed/DistanceFaceWorld.gdshader @@ -0,0 +1,41 @@ +// NOTE: Shader automatically converted from Godot Engine 4.2.1.stable's StandardMaterial3D. + +shader_type spatial; +render_mode blend_add,depth_draw_always,cull_back,diffuse_burley,specular_schlick_ggx; +uniform vec4 albedo : source_color; +uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable; +uniform float distance_fade_min; +uniform float distance_fade_max; +uniform float roughness : hint_range(0,1); +uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable; +uniform vec4 metallic_texture_channel; +uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable; +uniform float specular; +uniform float metallic; +uniform vec3 uv1_scale; +uniform vec3 uv1_offset; + + +void vertex() { + UV=UV*uv1_scale.xy+uv1_offset.xy; +} + + + + + + +void fragment() { + vec2 base_uv = UV; + vec4 albedo_tex = texture(texture_albedo,base_uv); + ALBEDO = albedo.rgb * albedo_tex.rgb; + float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel); + METALLIC = metallic_tex * metallic; + vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0); + float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel); + ROUGHNESS = roughness_tex * roughness; + SPECULAR = specular; + ALPHA *= albedo.a * albedo_tex.a; + vec4 wrld_vertex = INV_VIEW_MATRIX * vec4(VERTEX, 1.0); + ALPHA *= clamp(smoothstep(distance_fade_min, distance_fade_max, length(wrld_vertex)), 0.0, 1.0); +} diff --git a/Testbed/GridTest.gdshader b/Testbed/GridTest.gdshader new file mode 100644 index 0000000..cfdd2c6 --- /dev/null +++ b/Testbed/GridTest.gdshader @@ -0,0 +1,57 @@ +shader_type spatial; + +uniform int scale_0 : hint_range(1, 1024, 1); +uniform int scale_1 : hint_range(1, 1024, 1); + +uniform float line_scale_0 : hint_range(0.001, 1, 0.001); +uniform float line_scale_1 : hint_range(0.001, 1, 0.001); + +uniform vec4 color_0 : source_color; +uniform vec4 color_1 : source_color; + +render_mode blend_add; + +float pristineGrid( vec2 uv, vec2 lineWidth) +{ + vec2 ddx = dFdx(uv); + vec2 ddy = dFdy(uv); + + vec2 uvDeriv = vec2(length(vec2(ddx.x, ddy.x)), length(vec2(ddx.y, ddy.y))); + bvec2 invertLine = bvec2(lineWidth.x > 0.5, lineWidth.y > 0.5); + + vec2 targetWidth = vec2( + invertLine.x ? 1.0 - lineWidth.x : lineWidth.x, + invertLine.y ? 1.0 - lineWidth.y : lineWidth.y + ); + + vec2 drawWidth = clamp(targetWidth, uvDeriv, vec2(0.5)); + vec2 lineAA = uvDeriv * 1.5; + vec2 gridUV = abs(fract(uv) * 2.0 - 1.0); + + gridUV.x = invertLine.x ? gridUV.x : 1.0 - gridUV.x; + gridUV.y = invertLine.y ? gridUV.y : 1.0 - gridUV.y; + + vec2 grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV); + + grid2 *= clamp(targetWidth / drawWidth, 0.0, 1.0); + grid2 = mix(grid2, targetWidth, clamp(uvDeriv * 2.0 - 1.0, 0.0, 1.0)); + grid2.x = invertLine.x ? 1.0 - grid2.x : grid2.x; + grid2.y = invertLine.y ? 1.0 - grid2.y : grid2.y; + return mix(grid2.x, 1.0, grid2.y); +} + +void vertex() +{ + //UV = VERTEX.xz; +} + +void fragment() +{ + vec3 grid_0 = vec3(pristineGrid(UV * float(scale_0), vec2(line_scale_0))); + vec3 grid_1 = vec3(pristineGrid(UV * float(scale_1), vec2(line_scale_1))); + + vec3 grid_3 = mix(grid_1 * color_1.rgb, grid_0 * color_0.rgb, grid_0); + + ALBEDO = grid_3; + ALPHA = 1.5; +} \ No newline at end of file diff --git a/Testbed/Rules.gd b/Testbed/Rules.gd new file mode 100644 index 0000000..196eca5 --- /dev/null +++ b/Testbed/Rules.gd @@ -0,0 +1,53 @@ +extends Control + +@onready var category_label = $Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/CategoryLabel +@onready var margin_container = $Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer +@onready var panel_container = $PanelContainer + +@onready var general = $Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/General + +@onready var margin_container2 = $Pivot/MarginContainer + +var mat: ShaderMaterial + +func show_panel() -> void: + margin_container2.position.y = 700 + mat.set_shader_parameter("lod", 0) + + visible = true + + var tween = get_tree().create_tween() + tween.set_parallel(true) + tween.tween_method(tween_blur, 0.0, 1.0, 0.5).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT) + tween.tween_property(margin_container2, "position:y", 0.0, 0.5).set_trans(Tween.TRANS_SPRING).set_ease(Tween.EASE_OUT) + +# Called when the node enters the scene tree for the first time. +func _ready(): + mat = panel_container.material + pass # Replace with function body. + +func tween_blur(val: float) -> void: + mat.set_shader_parameter("lod", val) + pass + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_button_pressed(label: NodePath, category: String = ""): + for child in margin_container.get_children(): + child.visible = false + + category_label.text = category + + # hacky + general.get_node(label).visible = true + + +func _on_ant_pressed(extra_arg_0, extra_arg_1): + pass # Replace with function body. + + +func _on_close_button_pressed(): + visible = false diff --git a/Testbed/Rules.tscn b/Testbed/Rules.tscn new file mode 100644 index 0000000..426574e --- /dev/null +++ b/Testbed/Rules.tscn @@ -0,0 +1,249 @@ +[gd_scene load_steps=4 format=3 uid="uid://8ffmln680deh"] + +[ext_resource type="Script" path="res://Testbed/Rules.gd" id="1_qbtgw"] +[ext_resource type="Shader" path="res://Testbed/UIBlur.gdshader" id="2_ux84o"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_h3smw"] +shader = ExtResource("2_ux84o") +shader_parameter/lod = 1.0 + +[node name="Rules" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +script = ExtResource("1_qbtgw") + +[node name="PanelContainer" type="PanelContainer" parent="."] +self_modulate = Color(1, 1, 1, 0.392157) +material = SubResource("ShaderMaterial_h3smw") +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Pivot" type="Control" parent="."] +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="Pivot"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 50 +theme_override_constants/margin_top = 50 +theme_override_constants/margin_right = 50 +theme_override_constants/margin_bottom = 50 + +[node name="PanelContainer" type="PanelContainer" parent="Pivot/MarginContainer"] +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="Pivot/MarginContainer/PanelContainer"] +layout_mode = 2 +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="Pivot/MarginContainer/PanelContainer/MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/separation = 15 + +[node name="VBoxContainer" type="VBoxContainer" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"] +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 + +[node name="General" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "General" + +[node name="Placing" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Placing" + +[node name="Moving" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Moving" + +[node name="HSeparator" type="HSeparator" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Bee" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Bee" + +[node name="Beetle" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Beetle" + +[node name="Grasshopper" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Grasshopper" + +[node name="Spider" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Spider" + +[node name="Ant" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "Ant" + +[node name="Ladybug" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +disabled = true +text = "Ladybug" + +[node name="Mosquito" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +disabled = true +text = "Mosquito" + +[node name="Pillbug" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"] +layout_mode = 2 +disabled = true +text = "Pillbug" + +[node name="VBoxContainer2" type="VBoxContainer" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="CategoryLabel" type="Label" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +text = "General" + +[node name="ScrollContainer" type="ScrollContainer" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="PanelContainer" type="PanelContainer" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="MarginContainer" type="MarginContainer" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="GeneralLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +layout_mode = 2 +text = "The pieces in play define the playing surface, known as the Hive. + +Play begings with one player placing a piece from their hand in the center of the table and the next player joining one of their own pieces to it edge to edge. + +Players then take turns to either place or move any one of their pieces." +fit_content = true + +[node name="PlacingLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "A new piece can be introduced into the game at any time. However, with the exception of the first piece placed by each player, pieces may not be placed next to a piece of the opponent's color. + +It is possible to win the game without placing all your pieces but once a piece has been placed it can't be removed. + +Your Queen Bee can be placed at any time from your first to your fourth turn. You must place your Queen Bee on your fourth turn if you have not placed it before." +fit_content = true + +[node name="MovingLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "Once your Queen Bee has been placed (but not before), you can decide whether to use each turn after that to place another tile or to move one of the pieces that have already been placed. + +Each creature has its own way of moving about the Hive and it's possible to move pieces to a position where they touch one or more of your opponent's tiles. + +Note: All pieces must always touch at least one other piece. If a piece the only connection between two parts of the Hive, it may not be moved." +fit_content = true + +[node name="BeeLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +bbcode_enabled = true +text = "The Queen Bee can move only one space per turn. Even though it is restricted in this way, if moved at the right time it can severely disrupt your opponent's plans. + +[img]res://Testbed/queenbeemove.png[/img] + + +From this position, the black Queen Bee is able to move into one of four spaces." +fit_content = true + +[node name="BeetleLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "The Beetle, like the Queen Bee, moves only one space per turn. + +Unlike any other creature though, it can also move on top of the Hive. + +A piece with a beetle on top of it is unable to move and for the purposes of the placing rules, the stack takes on the color of the Beetle. + +From its position on top of the Hive, the Beetle can move from tile to tile across the top of the Hive. It can also drop into spaces that are surrounded and therefore not accessible to most other creatures. + +From its position, the white Beetle is able to move into one of four positions. + +The only way to block a Beetle that is on top of the Hive is to move another Beetle on top of it. All four Beetles can be stacked on top of each other. + +Note: When it is first placed, the Beetle is placed in the same way as all other pieces. It can't be placed directly on top of the Hive, even though it can be moved there later." +fit_content = true + +[node name="GrasshopperLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "The Grasshopper does not move around the outside of the Hive like the other creatures. Instead, it jumps from its space over any number of pieces (but at least one) to the next unoccupied space along a straight row of joined pieces. + +This gives it the advantage of being able to fill in a space which is surrounded by other tiles. + +From its position, the white Grasshopper can jump to one of three spaces. Note: It can't jump across the gap to the space marked x." +fit_content = true + +[node name="SpiderLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "The Spider moves three spaces per turn - no more, no less. + +It must move in a direct path and can't backtrack on itself. It may only move around pieces that it is in direct contact with on each step of its move and it may not move across to a piece that it's not in direct contact with. + +From its position, the black Spider can move into one of four spaces but is unable to move to the position on its left marked 2 on its first step. +" +fit_content = true + +[node name="AntLabel" type="RichTextLabel" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "The Soldier Ant can move from its position to any other position around the Hive provided the restrictions are adhered to. This freedom of movement makes the Ant one of the most valuable pieces. + +In this case, the Ant can be moved into one of eleven positions but is unable to move into the position in the center of the Hive. +" +fit_content = true + +[node name="CloseButton" type="Button" parent="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Close" + +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/General" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/GeneralLabel"), "General"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Placing" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/PlacingLabel"), "Placing"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Moving" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/MovingLabel")]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Bee" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/BeeLabel"), "Bee"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Beetle" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/BeetleLabel"), "Beetle"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Grasshopper" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/GrasshopperLabel"), "Grasshopper"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Spider" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/SpiderLabel"), "Spider"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer/Ant" to="." method="_on_button_pressed" binds= [NodePath("../../VBoxContainer2/ScrollContainer/PanelContainer/MarginContainer/AntLabel"), "Ant"]] +[connection signal="pressed" from="Pivot/MarginContainer/PanelContainer/MarginContainer/VBoxContainer/CloseButton" to="." method="_on_close_button_pressed"] diff --git a/Testbed/Table.tres b/Testbed/Table.tres new file mode 100644 index 0000000..e5c4778 --- /dev/null +++ b/Testbed/Table.tres @@ -0,0 +1,22 @@ +[gd_resource type="ShaderMaterial" load_steps=5 format=3 uid="uid://dv2oo7hlc5nyy"] + +[ext_resource type="Shader" path="res://Testbed/DistanceFaceWorld.gdshader" id="1_edhah"] +[ext_resource type="Texture2D" uid="uid://cilgpyanfb3a8" path="res://Testbed/textures/wood_table_001_diff_4k.jpg" id="2_hb1x7"] +[ext_resource type="Texture2D" uid="uid://diamo44e2x4if" path="res://Testbed/textures/wood_table_001_disp_4k.png" id="3_eyslc"] +[ext_resource type="Texture2D" uid="uid://b6ejmikbfrprs" path="res://Testbed/textures/wood_table_001_rough_4k.jpg" id="4_r705j"] + +[resource] +render_priority = 0 +shader = ExtResource("1_edhah") +shader_parameter/albedo = Color(1, 1, 1, 1) +shader_parameter/distance_fade_min = 0.0 +shader_parameter/distance_fade_max = 0.0 +shader_parameter/roughness = 0.5 +shader_parameter/metallic_texture_channel = null +shader_parameter/specular = 0.5 +shader_parameter/metallic = 0.5 +shader_parameter/uv1_scale = Vector3(1, 1, 1) +shader_parameter/uv1_offset = Vector3(0, 0, 0) +shader_parameter/texture_albedo = ExtResource("2_hb1x7") +shader_parameter/texture_metallic = ExtResource("3_eyslc") +shader_parameter/texture_roughness = ExtResource("4_r705j") diff --git a/Testbed/UIBlur.gdshader b/Testbed/UIBlur.gdshader new file mode 100644 index 0000000..692b2b7 --- /dev/null +++ b/Testbed/UIBlur.gdshader @@ -0,0 +1,9 @@ +shader_type canvas_item; + +uniform float lod: hint_range(0.0, 5.0) = 0.0; +uniform sampler2D SCREEN_TEXTURE: hint_screen_texture, filter_linear_mipmap; + +void fragment() { + vec4 color = texture(SCREEN_TEXTURE, SCREEN_UV, lod); + COLOR = vec4(color.rgb, 1.0); +} \ No newline at end of file diff --git a/Testbed/queenbeemove.png b/Testbed/queenbeemove.png new file mode 100644 index 0000000..894ce02 Binary files /dev/null and b/Testbed/queenbeemove.png differ diff --git a/Testbed/queenbeemove.png.import b/Testbed/queenbeemove.png.import new file mode 100644 index 0000000..33b286b --- /dev/null +++ b/Testbed/queenbeemove.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ce3vdaa8y4pmc" +path="res://.godot/imported/queenbeemove.png-5c1df16cbe3c407ebc595b848eeffac1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Testbed/queenbeemove.png" +dest_files=["res://.godot/imported/queenbeemove.png-5c1df16cbe3c407ebc595b848eeffac1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Tile/Tile.gd b/Tile/Tile.gd index 5717e2f..a351398 100644 --- a/Tile/Tile.gd +++ b/Tile/Tile.gd @@ -40,7 +40,20 @@ var selected_for_action: bool = false var can_be_selected: bool = false func is_players_turn() -> bool: - return is_blacks_turn == GameData.is_player_black or GameData.debug + return is_blacks_turn == is_black + +# Have a functions that checks if we're the "owner" +func is_owner() -> bool: + # TODO: Only use multiplayer authority + # According to https://docs.godotengine.org/en/stable/classes/class_offlinemultiplayerpeer.html + # Even without active multiplayer, the normal calls just work as expected + #if GameData.is_hot_seat: + # return true + #elif GameData.is_player_black == is_black: # we could use multiplayer authority here + # return true + + #return false + return is_multiplayer_authority() func _ready() -> void: if is_black: @@ -65,9 +78,9 @@ func _ready() -> void: func _on_turn_started(turn_num: int, map: HexGrid, _is_blacks_turn: bool) -> void: is_blacks_turn = _is_blacks_turn - can_be_selected = GameData.has_bee_been_placed - print(GameData.has_bee_been_placed) - if turn_num >= 7 and not GameData.has_bee_been_placed: + 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): can_be_selected = true func _on_tiles_selected_for_action(source_pos: Vector4i, targets: Array[InsectTile]) -> void: @@ -116,9 +129,9 @@ func _process(delta): if not hovered: return - if not GameData.is_player_black == is_black: + if not is_owner(): return - + if not is_players_turn(): return @@ -138,7 +151,7 @@ func _process(delta): GameEvents.insect_tile_selected.emit(self) func hover() -> void: - if GameData.is_player_black != is_black: + if is_blacks_turn != is_black: return if tween != null: @@ -155,7 +168,7 @@ func tween_hover_shader(color: Color) -> void: mat.next_pass.set_shader_parameter("emission_color", color) func unhover() -> void: - if GameData.is_player_black != is_black: + if is_blacks_turn != is_black: return if tween != null: diff --git a/UI/BuildMenu.gd b/UI/BuildMenu.gd index 0afa162..1466935 100644 --- a/UI/BuildMenu.gd +++ b/UI/BuildMenu.gd @@ -11,20 +11,127 @@ 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 } -@onready var local_bee_button: InsectButton = $PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects/BeeButton -@onready var remote_bee_button: InsectButton = $PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects/BeeButton +var local_bee_button: InsectButton +var remote_bee_button: InsectButton +@rpc("call_local", "authority", "reliable") +func reverse_enemy_list() -> void: + for child in remote_player_insects.get_children(): + remote_player_insects.move_child(child, 0) + pass + +@rpc("call_local", "authority", "reliable") +func add_spacer(is_black: bool, peer_id: int = 1) -> void: + var seperator = VSeparator.new() + + if GameData.is_hot_seat: + # left = white, right = black + if not is_black: + local_player_insects.add_child(seperator) + else: + remote_player_insects.add_child(seperator) + else: + if peer_id == multiplayer.get_unique_id(): + local_player_insects.add_child(seperator) + else: + remote_player_insects.add_child(seperator) + + #local_player_insects.add_spacer(false) + +@rpc("call_local", "authority", "reliable") +func add_insect(resource_path: String, count: int, is_black: bool, peer_id: int = 1) -> void: + var resource = load(resource_path) + + var btn = INSECT_BUTTON.instantiate() + btn.insect_resource = resource + btn.tile_count = count + btn.is_black = is_black + + btn.set_multiplayer_authority(peer_id, true) + + # TODO: if authority, put local, else put remote + # We can use authority, in hotseat authority will always be true + # if hotseat -> white left, black right + # else -> local left, remote right + if GameData.is_hot_seat: + if not is_black: + local_player_insects.add_child(btn) + else: + remote_player_insects.add_child(btn) + + else: + print("@") + print(peer_id) + print(multiplayer.get_unique_id()) + if peer_id == multiplayer.get_unique_id(): + local_player_insects.add_child(btn) + else: + remote_player_insects.add_child(btn) + + +@rpc("call_local", "authority", "reliable") +func setup_colors(is_host_black: bool) -> void: + if GameData.is_hot_seat: + local_player_insects.name = "White" + remote_player_insects.name = "Black" + return + + + if multiplayer.is_server(): + GameData.is_player_black = is_host_black + else: + GameData.is_player_black = !is_host_black + + if not GameData.is_player_black: + local_player_insects.name = "White" + remote_player_insects.name = "Black" + else: + local_player_insects.name = "Black" + remote_player_insects.name = "White" + # Called when the node enters the scene tree for the first time. func _ready(): + if multiplayer.is_server(): + setup_colors.rpc(false) + + add_insect.rpc("res://Tile/Prefabs/Bee.tres", 1, false, 1) + add_spacer.rpc(false, 1) + + add_insect.rpc("res://Tile/Prefabs/Bee.tres", 1, true, GameData.peer_id) + add_spacer.rpc(true, GameData.peer_id) + + #remote_bee_button.set_authority.rpc(GameData.peer_id) + for key in default_insects.keys(): + add_insect.rpc(key.get_path(), default_insects[key], false, 1) + add_insect.rpc(key.get_path(), default_insects[key], true, GameData.peer_id) + + #add_insect.rpc("res://Tile/Prefabs/Ant.tres", 1, false, GameData.peer_id) + reverse_enemy_list.rpc() + return + + if GameData.is_player_black: + # Rename LocalPlayerInsects and RemotePlayerInsects + local_player_insects.name = "Black" + remote_player_insects.name = "White" + else: + local_player_insects.name = "White" + remote_player_insects.name = "Black" + + local_bee_button = local_player_insects.get_node("Bee") + remote_bee_button = remote_player_insects.get_node("Bee") + #var unique_array = default_insects.duplicate().map() local_bee_button.update_color(GameData.is_player_black) remote_bee_button.update_color(!GameData.is_player_black) + if multiplayer.is_server(): + remote_bee_button.set_authority.rpc(GameData.peer_id) + for key in default_insects.keys(): #print(default_insects[key]) var btn = INSECT_BUTTON.instantiate() @@ -40,6 +147,8 @@ func _ready(): btn.is_black = !GameData.is_player_black remote_player_insects.add_child(btn) remote_player_insects.move_child(btn, 0) + if multiplayer.is_server(): + btn.set_authority.rpc(GameData.peer_id) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta): diff --git a/main_menu.gd b/main_menu.gd index 8c09806..9b179b8 100644 --- a/main_menu.gd +++ b/main_menu.gd @@ -1,13 +1,17 @@ extends Control @onready var exit_button = $PanelContainer/MarginContainer/VBoxContainer/ExitButton +@onready var lan_button = $PanelContainer/MarginContainer/VBoxContainer/LANButton + +@onready var rules = $Rules # Called when the node enters the scene tree for the first time. func _ready() -> void: if OS.has_feature("web"): exit_button.visible = false + lan_button.visible = false - WSClient.lobby_joined.connect(_on_lobby_joined) + #WSClient.lobby_joined.connect(_on_lobby_joined) GameData.reset() func _on_lobby_joined(lobby: String) -> void: @@ -21,7 +25,7 @@ func _process(delta: float) -> void: func _on_host_button_pressed(): GameData.is_player_black = false - WSClient.start(GameData.WEBSOCKET_ENDPOINT, "", false) + #WSClient.start(GameData.WEBSOCKET_ENDPOINT, "", false) func _on_join_button_pressed(): @@ -34,5 +38,22 @@ func _on_exit_button_pressed(): func _on_rules_button_pressed(): # https://bacon.bytesandpieces.xyz/swarm/ - OS.shell_open("https://www.ultraboardgames.com/hive/game-rules.php") + #OS.shell_open("https://www.ultraboardgames.com/hive/game-rules.php") + rules.show_panel() pass # Replace with function body. + + +func _on_online_button_pressed(): + #GameData.is_player_black = false + #WSClient.start(GameData.WEBSOCKET_ENDPOINT, "", false) + pass # Replace with function body. + + +func _on_online_button_2_pressed(): + get_tree().change_scene_to_file("res://UI/join_menu.tscn") + pass # Replace with function body. + + +func _on_local_button_pressed(): + GameData.is_hot_seat = true + get_tree().change_scene_to_file("res://Game.tscn") diff --git a/main_menu.tscn b/main_menu.tscn index 1ab5621..78dc4d6 100644 --- a/main_menu.tscn +++ b/main_menu.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=4 format=3 uid="uid://dogu37xma5vsp"] +[gd_scene load_steps=5 format=3 uid="uid://dogu37xma5vsp"] [ext_resource type="Script" path="res://main_menu.gd" id="1_q3q3u"] [ext_resource type="Script" path="res://DisconnectInfo.gd" id="2_2fkdc"] +[ext_resource type="PackedScene" uid="uid://8ffmln680deh" path="res://Testbed/Rules.tscn" id="2_7qmw6"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_47fa1"] bg_color = Color(0, 0, 0, 1) @@ -74,6 +75,10 @@ text = "Local (Hotseat)" layout_mode = 2 text = "Online" +[node name="OnlineButton2" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Online (Join)" + [node name="LANButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"] layout_mode = 2 disabled = true @@ -98,6 +103,10 @@ text = "Rules" layout_mode = 2 text = "Exit" +[node name="Rules" parent="." instance=ExtResource("2_7qmw6")] +visible = false +layout_mode = 1 + [node name="DisconnectInfo" type="Control" parent="."] visible = false layout_mode = 1 @@ -140,8 +149,9 @@ text = "Ok" [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/HostButton" to="." method="_on_host_button_pressed"] [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/JoinButton" to="." method="_on_join_button_pressed"] [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/SingleplayerButton" to="." method="_on_rules_button_pressed"] -[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/LocalButton" to="." method="_on_rules_button_pressed"] -[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/OnlineButton" to="." method="_on_rules_button_pressed"] +[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/LocalButton" to="." method="_on_local_button_pressed"] +[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/OnlineButton" to="." method="_on_online_button_pressed"] +[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/OnlineButton2" to="." method="_on_online_button_2_pressed"] [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/LANButton" to="." method="_on_rules_button_pressed"] [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/SettingsButton" to="." method="_on_rules_button_pressed"] [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/RulesButton" to="." method="_on_rules_button_pressed"] diff --git a/project.godot b/project.godot index 74c82de..9d9e4e8 100644 --- a/project.godot +++ b/project.godot @@ -20,7 +20,7 @@ config/icon="res://icon.svg" GameEvents="*res://Globals/GameEvents.gd" GameData="*res://Globals/GameData.gd" DebugMenu="*res://addons/debug_menu/debug_menu.tscn" -WSClient="*res://Networking/ws_client.tscn" +Networking="*res://Networking/Networking.tscn" [editor_plugins]