Working prototype

This commit is contained in:
Sch1nken 2024-03-16 19:56:22 +01:00
parent 3de181134d
commit 1ed0ec226d
24 changed files with 682 additions and 31 deletions

14
DisconnectInfo.gd Normal file
View file

@ -0,0 +1,14 @@
extends Control
@onready var label = $PanelContainer/MarginContainer/VBoxContainer/Label
# Called when the node enters the scene tree for the first time.
func _ready():
visible = false
if not GameData.disconnect_reason.is_empty():
label.text = GameData.disconnect_reason
visible = true
func _on_button_pressed():
visible = false

34
Game.gd Normal file
View file

@ -0,0 +1,34 @@
extends Node3D
var is_blacks_turn: bool = false
var current_turn: int = 1
@onready var map: HexGrid = $HexGrid
# Called when the node enters the scene tree for the first time.
func _ready():
GameEvents.insect_tile_finished_moving.connect(_on_insect_tile_finished_moving)
GameEvents.insect_tile_created.connect(_on_insect_tile_created)
GameEvents.game_started.emit()
func advance_turn():
GameEvents.turn_ended.emit(current_turn, map)
is_blacks_turn = !is_blacks_turn
current_turn = current_turn + 1
print(current_turn)
GameEvents.turn_started.emit(current_turn, map, is_blacks_turn)
func _on_insect_tile_finished_moving(tile: InsectTile, target: Vector4i) -> void:
print("moved")
print(multiplayer.is_server())
advance_turn()
func _on_insect_tile_created(tile: InsectTile, pos: Vector4i) -> void:
print("created")
advance_turn()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

110
Game.tscn
View file

@ -1,13 +1,18 @@
[gd_scene load_steps=18 format=3 uid="uid://bx0bbrwdr0h40"] [gd_scene load_steps=23 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://Misc/RTSCamera3D.gd" id="1_dtmfo"]
[ext_resource type="Script" path="res://HexGrid3D/HexGrid3D.gd" id="2_suxca"] [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://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://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="Texture2D" uid="uid://b6ejmikbfrprs" path="res://Testbed/textures/wood_table_001_rough_4k.jpg" id="5_lck42"]
[ext_resource type="Script" path="res://WebLightChecker.gd" id="6_41m5i"] [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="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="PackedScene" uid="uid://bo8hgq66dbbb6" path="res://UI/insect_button.tscn" id="8_lfn34"]
[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://TurnTexture.gd" id="12_kjwp8"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_u8oxs"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_u8oxs"]
albedo_texture = ExtResource("3_w3jge") albedo_texture = ExtResource("3_w3jge")
@ -60,12 +65,16 @@ axis_stretch_vertical = 2
modulate_color = Color(1, 1, 1, 0.639216) modulate_color = Color(1, 1, 1, 0.639216)
[node name="Game" type="Node3D"] [node name="Game" type="Node3D"]
script = ExtResource("1_dgt1j")
[node name="Camera3D" type="Camera3D" parent="."] [node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.5, 0.866025, 0, -0.866025, 0.5, 0, 6, 5) transform = Transform3D(1, 0, 0, 0, 0.5, 0.866025, 0, -0.866025, 0.5, 0, 6, 5)
script = ExtResource("1_dtmfo") script = ExtResource("1_dtmfo")
edge_panning_enabled = false edge_panning_enabled = false
[node name="GameEndChecker" type="Node" parent="."]
script = ExtResource("2_ufkw3")
[node name="HexGrid" type="Node3D" parent="."] [node name="HexGrid" type="Node3D" parent="."]
script = ExtResource("2_suxca") script = ExtResource("2_suxca")
@ -159,6 +168,58 @@ layout_mode = 2
[node name="VSeparator" type="VSeparator" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects"] [node name="VSeparator" type="VSeparator" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects"]
layout_mode = 2 layout_mode = 2
[node name="PanelContainer2" type="PanelContainer" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
modulate = Color(1, 1, 1, 0)
layout_mode = 2
size_flags_horizontal = 3
mouse_filter = 2
[node name="Control" type="Control" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
mouse_filter = 2
[node name="Control" type="Control" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -64.0
offset_bottom = -64.0
grow_horizontal = 2
grow_vertical = 2
[node name="Control2" type="Control" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/Control/Control"]
layout_mode = 1
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
scale = Vector2(0.1, 0.1)
mouse_filter = 2
script = ExtResource("12_kjwp8")
[node name="TextureRect" type="TextureRect" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/Control/Control/Control2"]
texture_filter = 6
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -256.0
offset_top = -256.0
offset_right = 256.0
offset_bottom = 256.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
texture = ExtResource("11_cl0he")
[node name="PanelContainer" type="PanelContainer" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"] [node name="PanelContainer" type="PanelContainer" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
modulate = Color(1, 1, 1, 0) modulate = Color(1, 1, 1, 0)
layout_mode = 2 layout_mode = 2
@ -175,3 +236,50 @@ layout_mode = 2
[node name="BeeButton" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects" instance=ExtResource("8_lfn34")] [node name="BeeButton" parent="BuildMenu/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects" instance=ExtResource("8_lfn34")]
layout_mode = 2 layout_mode = 2
is_black = true is_black = true
[node name="CurrentTurnDisplay" type="Control" parent="."]
layout_mode = 3
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_top = 50.0
offset_bottom = 50.0
grow_horizontal = 2
size_flags_horizontal = 4
size_flags_vertical = 0
mouse_filter = 2
[node name="GameOverMenu" type="CanvasLayer" parent="."]
script = ExtResource("11_ffmss")
[node name="Control" type="Control" parent="GameOverMenu"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="PanelContainer" type="PanelContainer" parent="GameOverMenu/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="GameOverMenu/Control/PanelContainer"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="Label" type="Label" parent="GameOverMenu/Control/PanelContainer/VBoxContainer"]
layout_mode = 2
text = "#WINNER#"
horizontal_alignment = 1
[node name="Button" type="Button" parent="GameOverMenu/Control/PanelContainer/VBoxContainer"]
layout_mode = 2
text = "Back to menu"
[connection signal="pressed" from="GameOverMenu/Control/PanelContainer/VBoxContainer/Button" to="GameOverMenu" method="_on_button_pressed"]

31
GameEndChecker.gd Normal file
View file

@ -0,0 +1,31 @@
extends Node
const BEE = preload("res://Tile/Prefabs/Bee.tres")
var bees: Array[InsectTile] = []
# Called when the node enters the scene tree for the first time.
func _ready():
GameEvents.insect_tile_created.connect(_on_insect_tile_created)
GameEvents.turn_ended.connect(_on_turn_ended)
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
func _on_turn_ended(turn_num: int, map: HexGrid) -> void:
var black_lost: bool = false
var white_lost: bool = false
for b in bees:
if map.get_empty_neighbours(b.coordinates).size() == 0:
if b.is_black:
black_lost = true
else:
white_lost = true
if black_lost or white_lost:
GameEvents.game_over.emit(black_lost, white_lost)

25
GameOverMenu.gd Normal file
View file

@ -0,0 +1,25 @@
extends CanvasLayer
@onready var label = $Control/PanelContainer/VBoxContainer/Label
# Called when the node enters the scene tree for the first time.
func _ready():
visible = false
GameEvents.game_over.connect(_on_game_over)
func _on_game_over(black_lost: bool, white_lost: bool) -> void:
visible = true
if black_lost and white_lost:
# draw
label.text = "Draw!"
elif black_lost:
label.text = "White won!"
elif white_lost:
label.text = "Black won!"
else:
print("should never happen...")
func _on_button_pressed():
WSClient.close()
get_tree().change_scene_to_file("res://main_menu.tscn")

View file

@ -7,3 +7,11 @@ var debug: bool = false
var allow_selecting_in_stack: bool = false var allow_selecting_in_stack: bool = false
var lobby_code: String = "" var lobby_code: String = ""
var has_bee_been_placed: bool = false
var disconnect_reason: String = ""
func reset() -> void:
has_bee_been_placed = false
disconnect_reason = ""

View file

@ -4,15 +4,19 @@ signal insect_selected(button, is_black)
signal insect_placed(insect_resource, is_black, position) signal insect_placed(insect_resource, is_black, position)
signal insect_placement_cancelled signal insect_placement_cancelled
signal insect_tile_created(tile, pos)
signal insect_tile_selected(tile) signal insect_tile_selected(tile)
signal insect_tile_deselected(tile) signal insect_tile_deselected(tile)
signal insect_tile_moved(tile, to) 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_tiles_selected_for_action(source_tile, target_tiles, action)
signal insect_action_cancelled() signal insect_action_cancelled()
signal insect_action_done() # ??? Maybe? signal insect_action_done() # ??? Maybe? Right no we have a gameendchecker...
signal turn_started(turn_num) # Turn started could work implicitly? We'll see...
signal turn_ended(turn_num) signal turn_started(turn_num, map, is_blacks_turn)
signal turn_ended(turn_num, map)
signal game_over(is_winner_black) signal game_started
signal game_over(black_lost, white_lost)

View file

@ -347,6 +347,8 @@ func place_insect_tile(resource_path: String, is_black: bool, pos: Vector4i) ->
add_child(tile_copy) add_child(tile_copy)
GameEvents.insect_tile_created.emit(tile_copy, pos)
var tween = get_tree().create_tween() var tween = get_tree().create_tween()
tween.tween_property(tile_copy, "position", target_pos, 1.0).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_EXPO) tween.tween_property(tile_copy, "position", target_pos, 1.0).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_EXPO)
@ -455,7 +457,7 @@ func move_insect_tile(tile_coords: Vector4i, target: Vector4i) -> void:
var below: Vector4i = tile.coordinates + Vector4i(0, 0, 0, -1) var below: Vector4i = tile.coordinates + Vector4i(0, 0, 0, -1)
used_cells[below].hat = tile used_cells[below].hat = tile
# Add to new stack GameEvents.insect_tile_finished_moving.emit(tile, target)
func _on_insect_tile_moved(tile: InsectTile, target: Vector4i) -> void: func _on_insect_tile_moved(tile: InsectTile, target: Vector4i) -> void:
move_insect_tile.rpc(tile.coordinates, target) move_insect_tile.rpc(tile.coordinates, target)

View file

@ -20,6 +20,13 @@ var selected: bool = false
var hovered: bool = false var hovered: bool = false
var deactivated: bool = false var deactivated: bool = false
var is_blacks_turn: bool = false
var should_disable: bool = false
func is_players_turn() -> bool:
return is_blacks_turn == GameData.is_player_black or GameData.debug
func update_color(_is_black: bool) -> void: func update_color(_is_black: bool) -> void:
is_black = _is_black is_black = _is_black
if is_black: if is_black:
@ -73,7 +80,10 @@ func _on_insect_placed(resource: TileResource, _is_black: bool, pos: Vector4i) -
func refresh_state() -> void: func refresh_state() -> void:
selected = false selected = false
if not is_empty(): if should_disable:
disable()
if not is_empty() and not should_disable:
enable() enable()
if hovered and not is_empty(): if hovered and not is_empty():
@ -95,6 +105,25 @@ func _ready() -> void:
GameEvents.insect_tile_moved.connect(_on_insect_tile_moved) GameEvents.insect_tile_moved.connect(_on_insect_tile_moved)
GameEvents.insect_tile_deselected.connect(_on_insect_tile_deselected) GameEvents.insect_tile_deselected.connect(_on_insect_tile_deselected)
GameEvents.turn_started.connect(_on_turn_started)
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.has_bee_been_placed:
if GameData.is_player_black == is_blacks_turn:
# if not bee has been placed for this player
# lock all buttons except the bee
if is_same(BEE, insect_resource):
# don't lock
should_disable = false
else:
#lock
should_disable = true
refresh_state()
func _on_insect_tile_deselected(tile: InsectTile) -> void: func _on_insect_tile_deselected(tile: InsectTile) -> void:
refresh_state() refresh_state()
@ -141,6 +170,9 @@ func _on_pressed():
if GameData.is_player_black != is_black and not GameData.debug: if GameData.is_player_black != is_black and not GameData.debug:
return return
if not is_players_turn():
return
selected = true selected = true
GameEvents.insect_selected.emit(self, is_black) GameEvents.insect_selected.emit(self, is_black)

View file

@ -4,6 +4,8 @@ var has_opponent: bool = false
@onready var start_game_button = $LobbyInfo/PanelContainer/VBoxContainer/StartGameButton @onready var start_game_button = $LobbyInfo/PanelContainer/VBoxContainer/StartGameButton
@onready var game = $Game @onready var game = $Game
var game_in_progress: bool = false
func _ready(): func _ready():
multiplayer.connected_to_server.connect(_mp_server_connected) multiplayer.connected_to_server.connect(_mp_server_connected)
multiplayer.connection_failed.connect(_mp_server_disconnect) multiplayer.connection_failed.connect(_mp_server_disconnect)
@ -15,7 +17,9 @@ func _mp_peer_disconnected(id: int) -> void:
has_opponent = false has_opponent = false
start_game_button.disabled = true start_game_button.disabled = true
if id == 1: if game_in_progress or id == 1:
GameData.disconnect_reason = "Other peer terminated the connection"
# Display message that other end terminated the connection
# 1 is always the server # 1 is always the server
# So we better get going back to the main menu? # So we better get going back to the main menu?
WSClient.close() WSClient.close()
@ -32,7 +36,7 @@ func _mp_server_connected():
func _mp_server_disconnect(): func _mp_server_disconnect():
_log("[Multiplayer] Server disconnected (I am %d)" % WSClient.rtc_mp.get_unique_id()) _log("[Multiplayer] Server disconnected (I am %d)" % WSClient.rtc_mp.get_unique_id())
get_tree().change_scene_to_file("res://main_menu.tscn") #get_tree().change_scene_to_file("res://main_menu.tscn")
func _mp_peer_connected(id: int): func _mp_peer_connected(id: int):
_log("[Multiplayer] Peer %d connected" % id) _log("[Multiplayer] Peer %d connected" % id)
@ -50,6 +54,7 @@ func _process(delta):
func load_game() -> void: func load_game() -> void:
# Hide menu # Hide menu
# load game scene # load game scene
game_in_progress = true
lobby_info.visible = false lobby_info.visible = false
var game_scene = preload("res://Game.tscn").instantiate() var game_scene = preload("res://Game.tscn").instantiate()
game.add_child(game_scene) game.add_child(game_scene)

View file

@ -16,7 +16,6 @@ func _init():
peer_connected.connect(self._peer_connected) peer_connected.connect(self._peer_connected)
peer_disconnected.connect(self._peer_disconnected) peer_disconnected.connect(self._peer_disconnected)
func start(url, _lobby = "", _mesh:=true): func start(url, _lobby = "", _mesh:=true):
stop() stop()
sealed = false sealed = false

View file

@ -9,6 +9,7 @@ enum Message {JOIN, ID, PEER_CONNECT, PEER_DISCONNECT, OFFER, ANSWER, CANDIDATE,
var ws: WebSocketPeer = WebSocketPeer.new() var ws: WebSocketPeer = WebSocketPeer.new()
var code = 1000 var code = 1000
var reason = "Unknown" var reason = "Unknown"
var old_state = WebSocketPeer.STATE_CLOSED
signal lobby_joined(lobby) signal lobby_joined(lobby)
signal connected(id, use_mesh) signal connected(id, use_mesh)
@ -33,9 +34,6 @@ func close():
func _process(delta): func _process(delta):
var old_state: int = ws.get_ready_state()
if old_state == WebSocketPeer.STATE_CLOSED:
return
ws.poll() ws.poll()
var state = ws.get_ready_state() var state = ws.get_ready_state()
if state != old_state and state == WebSocketPeer.STATE_OPEN and autojoin: if state != old_state and state == WebSocketPeer.STATE_OPEN and autojoin:
@ -43,10 +41,11 @@ func _process(delta):
while state == WebSocketPeer.STATE_OPEN and ws.get_available_packet_count(): while state == WebSocketPeer.STATE_OPEN and ws.get_available_packet_count():
if not _parse_msg(): if not _parse_msg():
print("Error parsing message from server.") print("Error parsing message from server.")
if state == WebSocketPeer.STATE_CLOSED: if state != old_state and state == WebSocketPeer.STATE_CLOSED:
code = ws.get_close_code() code = ws.get_close_code()
reason = ws.get_close_reason() reason = ws.get_close_reason()
disconnected.emit() disconnected.emit()
old_state = state
func _parse_msg(): func _parse_msg():
@ -93,7 +92,7 @@ func _parse_msg():
return true # Parsed return true # Parsed
func join_lobby(_lobby: String): func join_lobby(lobby: String):
return _send_msg(Message.JOIN, 0 if mesh else 1, lobby) return _send_msg(Message.JOIN, 0 if mesh else 1, lobby)

View file

@ -3,6 +3,7 @@ class_name InsectTile
var map_reference: HexGrid var map_reference: HexGrid
var is_blacks_turn: bool = false
var coordinates: Vector4i var coordinates: Vector4i
var layer: int = 0 var layer: int = 0
@ -36,6 +37,10 @@ var tween: Tween
var tweening: bool = false var tweening: bool = false
var selected_for_action: bool = false 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
func _ready() -> void: func _ready() -> void:
if is_black: if is_black:
@ -54,7 +59,17 @@ func _ready() -> void:
GameEvents.insect_tile_deselected.connect(_on_insect_tile_deselected) GameEvents.insect_tile_deselected.connect(_on_insect_tile_deselected)
GameEvents.insect_tile_moved.connect(_on_insect_tile_moved) GameEvents.insect_tile_moved.connect(_on_insect_tile_moved)
GameEvents.insect_tiles_selected_for_action.connect(_on_tiles_selected_for_action) GameEvents.insect_tiles_selected_for_action.connect(_on_tiles_selected_for_action)
GameEvents.turn_started.connect(_on_turn_started)
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 = true
func _on_tiles_selected_for_action(source_pos: Vector4i, targets: Array[InsectTile]) -> void: func _on_tiles_selected_for_action(source_pos: Vector4i, targets: Array[InsectTile]) -> void:
if self in targets: if self in targets:
selected_for_action = true selected_for_action = true
@ -92,12 +107,21 @@ func _on_insect_selected(button: InsectButton, is_black: bool) -> void:
func _process(delta): func _process(delta):
if Input.is_action_just_pressed("place_tile"): if Input.is_action_just_pressed("place_tile"):
if not can_be_selected:
return
if deactivated: if deactivated:
return return
if not hovered: if not hovered:
return return
if not GameData.is_player_black == is_black:
return
if not is_players_turn():
return
# Move up the insect stack.... or just do not react while we have something on top of us? # Move up the insect stack.... or just do not react while we have something on top of us?
if GameData.allow_selecting_in_stack: if GameData.allow_selecting_in_stack:
@ -114,8 +138,8 @@ func _process(delta):
GameEvents.insect_tile_selected.emit(self) GameEvents.insect_tile_selected.emit(self)
func hover() -> void: func hover() -> void:
#if GameData.is_player_black != is_black: if GameData.is_player_black != is_black:
#return return
if tween != null: if tween != null:
tween.kill() tween.kill()
@ -131,8 +155,8 @@ func tween_hover_shader(color: Color) -> void:
mat.next_pass.set_shader_parameter("emission_color", color) mat.next_pass.set_shader_parameter("emission_color", color)
func unhover() -> void: func unhover() -> void:
#if GameData.is_player_black != is_black: if GameData.is_player_black != is_black:
#return return
if tween != null: if tween != null:
tween.kill() tween.kill()

29
TurnTexture.gd Normal file
View file

@ -0,0 +1,29 @@
extends Control
const HEX_BLACK = preload("res://UI/hex_black.svg")
const HEX_WHITE = preload("res://UI/hex_white.svg")
@onready var texture_rect: TextureRect = $TextureRect
# Called when the node enters the scene tree for the first time.
func _ready():
GameEvents.turn_started.connect(_on_turn_started)
pass # Replace with function body.
func _on_turn_started(turn_num: int, map: HexGrid, is_blacks_turn: bool) -> void:
print("turn started")
print(multiplayer.is_server())
var new_texture = HEX_WHITE
if is_blacks_turn:
new_texture = HEX_BLACK
var tween = get_tree().create_tween()
tween.tween_property(self, "scale", Vector2(0.0, 0.0), 0.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_ELASTIC)
tween.tween_property(texture_rect, "texture", new_texture, 0.0)
tween.tween_property(self, "scale", Vector2(0.1, 0.1), 0.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_ELASTIC)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
rotation += delta * PI / 12.0
pass

View file

@ -11,15 +11,14 @@ const default_insects = {
preload("res://Tile/Prefabs/Beetle.tres"): 2, preload("res://Tile/Prefabs/Beetle.tres"): 2,
preload("res://Tile/Prefabs/Grasshopper.tres"): 3, preload("res://Tile/Prefabs/Grasshopper.tres"): 3,
preload("res://Tile/Prefabs/Spider.tres"): 2, preload("res://Tile/Prefabs/Spider.tres"): 2,
#preload("res://Tile/Prefabs/Ladybug.tres"): 1, preload("res://Tile/Prefabs/Ladybug.tres"): 1,
#preload("res://Tile/Prefabs/Mosquito.tres"): 1, preload("res://Tile/Prefabs/Mosquito.tres"): 1,
#preload("res://Tile/Prefabs/Pillbug.tres"): 1 preload("res://Tile/Prefabs/Pillbug.tres"): 1
} }
@onready var local_bee_button: InsectButton = $PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects/BeeButton @onready var local_bee_button: InsectButton = $PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/LocalPlayerInsects/BeeButton
@onready var remote_bee_button: InsectButton = $PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects/BeeButton @onready var remote_bee_button: InsectButton = $PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2/RemotePlayerInsects/BeeButton
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
#var unique_array = default_insects.duplicate().map() #var unique_array = default_insects.duplicate().map()

84
UI/hex_black.svg Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="512"
viewBox="0 0 135.46667 135.46667"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hex.svg"
inkscape:export-filename="hex_black.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showguides="true"
inkscape:zoom="1.3089908"
inkscape:cx="292.97379"
inkscape:cy="347.59603"
inkscape:window-width="2560"
inkscape:window-height="1368"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<sodipodi:guide
position="67.733335,67.733335"
orientation="0,1"
id="guide1"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
</sodipodi:namedview>
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="display:none;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.001"
id="path1"
inkscape:flatsided="true"
sodipodi:sides="6"
sodipodi:cx="67.733337"
sodipodi:cy="67.733337"
sodipodi:r1="64.409515"
sodipodi:r2="55.780277"
sodipodi:arg1="1.0471976"
sodipodi:arg2="1.5707963"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 99.938092,123.51362 -64.409515,-1e-5 -32.204755,-55.780276 32.20476,-55.780275 64.409516,3e-6 32.204752,55.780279 z" />
<path
sodipodi:type="star"
style="fill:#050505;fill-opacity:1;stroke:#ffffff;stroke-width:1.001;stroke-opacity:1"
id="path2"
inkscape:flatsided="true"
sodipodi:sides="6"
sodipodi:cx="67.733337"
sodipodi:cy="67.733337"
sodipodi:r1="64.409515"
sodipodi:r2="55.780277"
sodipodi:arg1="1.0471976"
sodipodi:arg2="1.5707963"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 99.938092,123.51362 -64.409515,-1e-5 -32.204755,-55.780276 32.20476,-55.780275 64.409516,3e-6 32.204752,55.780279 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

37
UI/hex_black.svg.import Normal file
View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ctc46cqy0srip"
path="res://.godot/imported/hex_black.svg-9d962341f549264abaeb5efcd8e99b18.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://UI/hex_black.svg"
dest_files=["res://.godot/imported/hex_black.svg-9d962341f549264abaeb5efcd8e99b18.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=true
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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

84
UI/hex_white.svg Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="512"
viewBox="0 0 135.46667 135.46667"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hex.svg"
inkscape:export-filename="hex_black.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showguides="true"
inkscape:zoom="1.3089908"
inkscape:cx="461.80615"
inkscape:cy="103.13289"
inkscape:window-width="2560"
inkscape:window-height="1368"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<sodipodi:guide
position="67.733335,67.733335"
orientation="0,1"
id="guide1"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
</sodipodi:namedview>
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.001"
id="path1"
inkscape:flatsided="true"
sodipodi:sides="6"
sodipodi:cx="67.733337"
sodipodi:cy="67.733337"
sodipodi:r1="64.409515"
sodipodi:r2="55.780277"
sodipodi:arg1="1.0471976"
sodipodi:arg2="1.5707963"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 99.938092,123.51362 -64.409515,-1e-5 -32.204755,-55.780276 32.20476,-55.780275 64.409516,3e-6 32.204752,55.780279 z" />
<path
sodipodi:type="star"
style="display:none;fill:#050505;fill-opacity:1;stroke:#ffffff;stroke-width:1.001;stroke-opacity:1"
id="path2"
inkscape:flatsided="true"
sodipodi:sides="6"
sodipodi:cx="67.733337"
sodipodi:cy="67.733337"
sodipodi:r1="64.409515"
sodipodi:r2="55.780277"
sodipodi:arg1="1.0471976"
sodipodi:arg2="1.5707963"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 99.938092,123.51362 -64.409515,-1e-5 -32.204755,-55.780276 32.20476,-55.780275 64.409516,3e-6 32.204752,55.780279 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

37
UI/hex_white.svg.import Normal file
View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d2i5vboeyq8qx"
path="res://.godot/imported/hex_white.svg-aa2a6c3f24a602d4d345875405e4ff56.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://UI/hex_white.svg"
dest_files=["res://.godot/imported/hex_white.svg-aa2a6c3f24a602d4d345875405e4ff56.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=true
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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -18,4 +18,4 @@ func _on_back_button_pressed():
func _on_connect_button_pressed(): func _on_connect_button_pressed():
GameData.is_player_black = true GameData.is_player_black = true
WSClient.start(GameData.WEBSOCKET_ENDPOINT, lobby_code_input.text) WSClient.start(GameData.WEBSOCKET_ENDPOINT, lobby_code_input.text, false)

View file

@ -8,7 +8,7 @@ custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="" export_path="../SwarmWeb/index.html"
encryption_include_filters="" encryption_include_filters=""
encryption_exclude_filters="" encryption_exclude_filters=""
encrypt_pck=false encrypt_pck=false
@ -20,7 +20,7 @@ custom_template/debug=""
custom_template/release="" custom_template/release=""
variant/extensions_support=false variant/extensions_support=false
vram_texture_compression/for_desktop=true vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false vram_texture_compression/for_mobile=true
html/export_icon=true html/export_icon=true
html/custom_html_shell="" html/custom_html_shell=""
html/head_include="" html/head_include=""
@ -46,7 +46,7 @@ custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="" export_path="../SwarmWindows/Swarm.exe"
encryption_include_filters="" encryption_include_filters=""
encryption_exclude_filters="" encryption_exclude_filters=""
encrypt_pck=false encrypt_pck=false
@ -98,3 +98,43 @@ Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorActi
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'" Remove-Item -Recurse -Force '{temp_dir}'"
[preset.2]
name="Linux/X11"
platform="Linux/X11"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../SwarmLinux/Swarm.x86_64"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.2.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""

View file

@ -2,7 +2,8 @@ extends Control
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
WSClient.lobby_joined.connect(_on_lobby_joined) WSClient.lobby_joined.connect(_on_lobby_joined)
GameData.reset()
func _on_lobby_joined(lobby: String) -> void: func _on_lobby_joined(lobby: String) -> void:
GameData.lobby_code = lobby GameData.lobby_code = lobby
@ -15,7 +16,7 @@ func _process(delta: float) -> void:
func _on_host_button_pressed(): func _on_host_button_pressed():
GameData.is_player_black = false GameData.is_player_black = false
WSClient.start(GameData.WEBSOCKET_ENDPOINT, "") WSClient.start(GameData.WEBSOCKET_ENDPOINT, "", false)
func _on_join_button_pressed(): func _on_join_button_pressed():
@ -24,3 +25,9 @@ func _on_join_button_pressed():
func _on_exit_button_pressed(): func _on_exit_button_pressed():
get_tree().quit() get_tree().quit()
func _on_rules_button_pressed():
# https://bacon.bytesandpieces.xyz/swarm/
OS.shell_open("https://www.ultraboardgames.com/hive/game-rules.php")
pass # Replace with function body.

View file

@ -1,6 +1,10 @@
[gd_scene load_steps=2 format=3 uid="uid://dogu37xma5vsp"] [gd_scene load_steps=4 format=3 uid="uid://dogu37xma5vsp"]
[ext_resource type="Script" path="res://main_menu.gd" id="1_q3q3u"] [ext_resource type="Script" path="res://main_menu.gd" id="1_q3q3u"]
[ext_resource type="Script" path="res://DisconnectInfo.gd" id="2_2fkdc"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_47fa1"]
bg_color = Color(0, 0, 0, 1)
[node name="MainMenu" type="Control"] [node name="MainMenu" type="Control"]
layout_mode = 3 layout_mode = 3
@ -44,10 +48,54 @@ text = "Host Game"
layout_mode = 2 layout_mode = 2
text = "Join Game" text = "Join Game"
[node name="RulesButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Rules (Opens Web Browser)"
[node name="ExitButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"] [node name="ExitButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
text = "Exit" text = "Exit"
[node name="DisconnectInfo" type="Control" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_2fkdc")
[node name="PanelContainer" type="PanelContainer" parent="DisconnectInfo"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_47fa1")
[node name="MarginContainer" type="MarginContainer" parent="DisconnectInfo/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="DisconnectInfo/PanelContainer/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="DisconnectInfo/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "#REASON#"
[node name="Button" type="Button" parent="DisconnectInfo/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Ok"
[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/HostButton" to="." method="_on_host_button_pressed"] [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/JoinButton" to="." method="_on_join_button_pressed"]
[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/RulesButton" to="." method="_on_rules_button_pressed"]
[connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/ExitButton" to="." method="_on_exit_button_pressed"] [connection signal="pressed" from="PanelContainer/MarginContainer/VBoxContainer/ExitButton" to="." method="_on_exit_button_pressed"]
[connection signal="pressed" from="DisconnectInfo/PanelContainer/MarginContainer/VBoxContainer/Button" to="DisconnectInfo" method="_on_button_pressed"]

View file

@ -86,4 +86,5 @@ select_tile={
[rendering] [rendering]
textures/vram_compression/import_etc2_astc=true
mesh_lod/lod_change/threshold_pixels=0.0 mesh_lod/lod_change/threshold_pixels=0.0