Compare commits
13 Commits
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,7 +3,11 @@
|
|||||||
/android/
|
/android/
|
||||||
.idea/
|
.idea/
|
||||||
*.csproj
|
*.csproj
|
||||||
|
*.csproj*
|
||||||
*.csproj.old
|
*.csproj.old
|
||||||
|
*.csproj.old*
|
||||||
*.sln
|
*.sln
|
||||||
*.sln.*
|
*.sln.*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
**/.DS_Store
|
||||||
|
Folder.DotSettings.user
|
||||||
|
|||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Joshua Higgins
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1 +1,9 @@
|
|||||||
# Connect4 Moderator - Observer
|
# Connect4 Moderator - Observer
|
||||||
|
|
||||||
|
The front end for the [server](https://github.com/joshuafhiggins/connect4-moderator-server) made in [Godot](https://godotengine.org/), an open-soruce game engine.
|
||||||
|
|
||||||
|
# Downloads
|
||||||
|
See [releases](https://github.com/joshuafhiggins/connect4-moderator-observer/releases)
|
||||||
|
|
||||||
|
# For Future Maintainers
|
||||||
|
This was made in Godot 4.5. Due to the use of C# for a lot of the scripting, we are unable to export for the web but [progress is being made](https://github.com/godotengine/godot/pull/106125). An icon in Icon Composer was made for macOS builds but can't be used till Godot 4.6. Currently, there is also a bug in Godot's Websocket implementation that causes random disconnects, options are submitting upstream fixes and debugging or wrapping a third party library to use. It would also be nice to rework the bracket screen to show the bracket and be more thematic with the other pixel art pieces. Some scripts are leftovers/incomplete implementations of having this program act as a client, which would be helpful to finish.
|
||||||
BIN
assets/.DS_Store
vendored
BIN
assets/.DS_Store
vendored
Binary file not shown.
1
assets/music/.gitattributes
vendored
Normal file
1
assets/music/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
jazz_music.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||||
BIN
assets/music/jazz_music.mp3
LFS
Normal file
BIN
assets/music/jazz_music.mp3
LFS
Normal file
Binary file not shown.
19
assets/music/jazz_music.mp3.import
Normal file
19
assets/music/jazz_music.mp3.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="mp3"
|
||||||
|
type="AudioStreamMP3"
|
||||||
|
uid="uid://csy7ltflvsjq5"
|
||||||
|
path="res://.godot/imported/jazz_music.mp3-51c0488dbe42064eda25eafa56d387ed.mp3str"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/music/jazz_music.mp3"
|
||||||
|
dest_files=["res://.godot/imported/jazz_music.mp3-51c0488dbe42064eda25eafa56d387ed.mp3str"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_1.ogg
Normal file
BIN
assets/sfx/chip_collide_1.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_1.ogg.import
Normal file
19
assets/sfx/chip_collide_1.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://dauf0pi1pkd3x"
|
||||||
|
path="res://.godot/imported/chip_collide_1.ogg-406dd38ea9c3d5652eebd8457cb16d54.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_1.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_1.ogg-406dd38ea9c3d5652eebd8457cb16d54.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_2.ogg
Normal file
BIN
assets/sfx/chip_collide_2.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_2.ogg.import
Normal file
19
assets/sfx/chip_collide_2.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://b6b7b7sc038n7"
|
||||||
|
path="res://.godot/imported/chip_collide_2.ogg-f3e4af1639a40a7e5696a0d76240e083.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_2.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_2.ogg-f3e4af1639a40a7e5696a0d76240e083.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_3.ogg
Normal file
BIN
assets/sfx/chip_collide_3.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_3.ogg.import
Normal file
19
assets/sfx/chip_collide_3.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://c6a4wqoopu53j"
|
||||||
|
path="res://.godot/imported/chip_collide_3.ogg-8dacdc0da1447d7f98373dc814c23342.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_3.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_3.ogg-8dacdc0da1447d7f98373dc814c23342.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_4.ogg
Normal file
BIN
assets/sfx/chip_collide_4.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_4.ogg.import
Normal file
19
assets/sfx/chip_collide_4.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://5liedrachob2"
|
||||||
|
path="res://.godot/imported/chip_collide_4.ogg-a636adca2293a212ad4dd420b3445fd5.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_4.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_4.ogg-a636adca2293a212ad4dd420b3445fd5.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_5.ogg
Normal file
BIN
assets/sfx/chip_collide_5.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_5.ogg.import
Normal file
19
assets/sfx/chip_collide_5.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://dsyovynhhbmw8"
|
||||||
|
path="res://.godot/imported/chip_collide_5.ogg-43d68269cdbbab204cb581d3f2f55acc.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_5.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_5.ogg-43d68269cdbbab204cb581d3f2f55acc.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_6.ogg
Normal file
BIN
assets/sfx/chip_collide_6.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_6.ogg.import
Normal file
19
assets/sfx/chip_collide_6.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://c0a5rl5q04noq"
|
||||||
|
path="res://.godot/imported/chip_collide_6.ogg-277685742efbfc8894a8af489e0a5d40.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_6.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_6.ogg-277685742efbfc8894a8af489e0a5d40.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/chip_collide_7.ogg
Normal file
BIN
assets/sfx/chip_collide_7.ogg
Normal file
Binary file not shown.
19
assets/sfx/chip_collide_7.ogg.import
Normal file
19
assets/sfx/chip_collide_7.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://b6d73wiiqxles"
|
||||||
|
path="res://.godot/imported/chip_collide_7.ogg-7f61ae7f863bd72768f0889e7ed11946.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/chip_collide_7.ogg"
|
||||||
|
dest_files=["res://.godot/imported/chip_collide_7.ogg-7f61ae7f863bd72768f0889e7ed11946.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sfx/game_end.ogg
Normal file
BIN
assets/sfx/game_end.ogg
Normal file
Binary file not shown.
19
assets/sfx/game_end.ogg.import
Normal file
19
assets/sfx/game_end.ogg.import
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="oggvorbisstr"
|
||||||
|
type="AudioStreamOggVorbis"
|
||||||
|
uid="uid://crxjuk1vyq331"
|
||||||
|
path="res://.godot/imported/game_end.ogg-8ceab2b7181c15a955c6f20334947ba7.oggvorbisstr"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sfx/game_end.ogg"
|
||||||
|
dest_files=["res://.godot/imported/game_end.ogg-8ceab2b7181c15a955c6f20334947ba7.oggvorbisstr"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
loop=false
|
||||||
|
loop_offset=0
|
||||||
|
bpm=0
|
||||||
|
beat_count=0
|
||||||
|
bar_beats=4
|
||||||
BIN
assets/sprites/rpi.png
Normal file
BIN
assets/sprites/rpi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
40
assets/sprites/rpi.png.import
Normal file
40
assets/sprites/rpi.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://uritd4ygetrk"
|
||||||
|
path="res://.godot/imported/rpi.png-0f0faa9ccfa1d0b656d9c381bb4a7a6d.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/sprites/rpi.png"
|
||||||
|
dest_files=["res://.godot/imported/rpi.png-0f0faa9ccfa1d0b656d9c381bb4a7a6d.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
|
||||||
6
assets/theme.tres
Normal file
6
assets/theme.tres
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://bbgxacei1vwba"]
|
||||||
|
|
||||||
|
[ext_resource type="FontFile" uid="uid://c3jmev24lo6ci" path="res://assets/fonts/PixelOperator8.ttf" id="1_5x3i2"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
default_font = ExtResource("1_5x3i2")
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 2012
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "connect4-moderator-observer", "connect4-moderator-observer.csproj", "{88C189D2-5C9A-411D-8713-291AC0841D8C}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
ExportDebug|Any CPU = ExportDebug|Any CPU
|
|
||||||
ExportRelease|Any CPU = ExportRelease|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{88C189D2-5C9A-411D-8713-291AC0841D8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{88C189D2-5C9A-411D-8713-291AC0841D8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{88C189D2-5C9A-411D-8713-291AC0841D8C}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
|
|
||||||
{88C189D2-5C9A-411D-8713-291AC0841D8C}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
|
|
||||||
{88C189D2-5C9A-411D-8713-291AC0841D8C}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
|
|
||||||
{88C189D2-5C9A-411D-8713-291AC0841D8C}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
name="macOS"
|
name="macOS"
|
||||||
platform="macOS"
|
platform="macOS"
|
||||||
runnable=true
|
runnable=true
|
||||||
advanced_options=false
|
advanced_options=true
|
||||||
dedicated_server=false
|
dedicated_server=false
|
||||||
custom_features=""
|
custom_features=""
|
||||||
export_filter="all_resources"
|
export_filter="all_resources"
|
||||||
@@ -26,13 +26,13 @@ custom_template/debug=""
|
|||||||
custom_template/release=""
|
custom_template/release=""
|
||||||
debug/export_console_wrapper=0
|
debug/export_console_wrapper=0
|
||||||
application/icon="uid://dd7lvnidxr5ss"
|
application/icon="uid://dd7lvnidxr5ss"
|
||||||
application/icon_interpolation=4
|
application/icon_interpolation=0
|
||||||
application/bundle_identifier="com.abunchofknowitalls.connect4"
|
application/bundle_identifier="com.abunchofknowitalls.connect4"
|
||||||
application/signature=""
|
application/signature=""
|
||||||
application/app_category="Games"
|
application/app_category="Games"
|
||||||
application/short_version=""
|
application/short_version=""
|
||||||
application/version=""
|
application/version=""
|
||||||
application/copyright="RPI Minds & Machines"
|
application/copyright="RPI Minds and Machines"
|
||||||
application/copyright_localized={}
|
application/copyright_localized={}
|
||||||
application/min_macos_version_x86_64="10.12"
|
application/min_macos_version_x86_64="10.12"
|
||||||
application/min_macos_version_arm64="11.00"
|
application/min_macos_version_arm64="11.00"
|
||||||
@@ -49,7 +49,7 @@ xcode/xcode_build="14C18"
|
|||||||
codesign/codesign=3
|
codesign/codesign=3
|
||||||
codesign/installer_identity=""
|
codesign/installer_identity=""
|
||||||
codesign/apple_team_id="8S7C654DQ4"
|
codesign/apple_team_id="8S7C654DQ4"
|
||||||
codesign/identity="Developer ID Application: Joshua Higgins (8S7C654DQ4)"
|
codesign/identity="73BA692FE950ABC209210ACAA8AD412BD9C6C4A3"
|
||||||
codesign/entitlements/custom_file=""
|
codesign/entitlements/custom_file=""
|
||||||
codesign/entitlements/allow_jit_code_execution=false
|
codesign/entitlements/allow_jit_code_execution=false
|
||||||
codesign/entitlements/allow_unsigned_executable_memory=false
|
codesign/entitlements/allow_unsigned_executable_memory=false
|
||||||
|
|||||||
BIN
icon.icon/Assets/icon.png
Normal file
BIN
icon.icon/Assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
40
icon.icon/Assets/icon.png.import
Normal file
40
icon.icon/Assets/icon.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dbn4ae2a7ao0t"
|
||||||
|
path="res://.godot/imported/icon.png-d1b269abce4c61d818c5589654ffbcc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://icon.icon/Assets/icon.png"
|
||||||
|
dest_files=["res://.godot/imported/icon.png-d1b269abce4c61d818c5589654ffbcc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
|
||||||
37
icon.icon/icon.json
Normal file
37
icon.icon/icon.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"fill" : {
|
||||||
|
"automatic-gradient" : "extended-srgb:0.00000,0.53333,1.00000,1.00000"
|
||||||
|
},
|
||||||
|
"groups" : [
|
||||||
|
{
|
||||||
|
"layers" : [
|
||||||
|
{
|
||||||
|
"glass" : true,
|
||||||
|
"image-name" : "icon.png",
|
||||||
|
"name" : "icon",
|
||||||
|
"position" : {
|
||||||
|
"scale" : 0.2,
|
||||||
|
"translation-in-points" : [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shadow" : {
|
||||||
|
"kind" : "neutral",
|
||||||
|
"opacity" : 0.5
|
||||||
|
},
|
||||||
|
"translucency" : {
|
||||||
|
"enabled" : true,
|
||||||
|
"value" : 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"supported-platforms" : {
|
||||||
|
"circles" : [
|
||||||
|
"watchOS"
|
||||||
|
],
|
||||||
|
"squares" : "shared"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,8 @@ config_version=5
|
|||||||
|
|
||||||
[application]
|
[application]
|
||||||
|
|
||||||
config/name="Connect4 Moderator - Observer"
|
config/name="Connect4 Observer"
|
||||||
config/version="0.1.2"
|
config/version="1.0.0"
|
||||||
run/main_scene="uid://dcx5nvs0pa7me"
|
run/main_scene="uid://dcx5nvs0pa7me"
|
||||||
config/features=PackedStringArray("4.5", "C#", "Forward Plus")
|
config/features=PackedStringArray("4.5", "C#", "Forward Plus")
|
||||||
boot_splash/image="uid://dd7lvnidxr5ss"
|
boot_splash/image="uid://dd7lvnidxr5ss"
|
||||||
@@ -20,6 +20,7 @@ config/icon="uid://dd7lvnidxr5ss"
|
|||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
Connection="*res://scripts/Connection.cs"
|
Connection="*res://scripts/Connection.cs"
|
||||||
|
BackgroundMusic="*res://scripts/background_music.gd"
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ window/size/viewport_width=1280
|
|||||||
window/size/viewport_height=720
|
window/size/viewport_height=720
|
||||||
window/stretch/mode="canvas_items"
|
window/stretch/mode="canvas_items"
|
||||||
window/stretch/aspect="expand"
|
window/stretch/aspect="expand"
|
||||||
|
window/vsync/vsync_mode=2
|
||||||
|
|
||||||
[dotnet]
|
[dotnet]
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
[gd_scene load_steps=14 format=3 uid="uid://m542qwlp7hl7"]
|
[gd_scene load_steps=17 format=3 uid="uid://m542qwlp7hl7"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://dg5jt0o0r0v3r" path="res://scripts/BoardScreen.cs" id="1_b3w8x"]
|
[ext_resource type="Script" uid="uid://dg5jt0o0r0v3r" path="res://scripts/BoardScreen.cs" id="1_b3w8x"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://crxjuk1vyq331" path="res://assets/sfx/game_end.ogg" id="2_kseed"]
|
||||||
[ext_resource type="Texture2D" uid="uid://dlx02qat7j6lf" path="res://assets/sprites/AssetTileset.png" id="3_1tlhv"]
|
[ext_resource type="Texture2D" uid="uid://dlx02qat7j6lf" path="res://assets/sprites/AssetTileset.png" id="3_1tlhv"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bbgxacei1vwba" path="res://assets/theme.tres" id="3_3louw"]
|
||||||
[ext_resource type="FontFile" uid="uid://c3jmev24lo6ci" path="res://assets/fonts/PixelOperator8.ttf" id="3_rjcmr"]
|
[ext_resource type="FontFile" uid="uid://c3jmev24lo6ci" path="res://assets/fonts/PixelOperator8.ttf" id="3_rjcmr"]
|
||||||
[ext_resource type="Texture2D" uid="uid://ckmfi0cjgxgyk" path="res://assets/sprites/RedChip.png" id="4_1hrcj"]
|
[ext_resource type="Texture2D" uid="uid://ckmfi0cjgxgyk" path="res://assets/sprites/RedChip.png" id="4_1hrcj"]
|
||||||
[ext_resource type="Texture2D" uid="uid://qy30emdgrk7o" path="res://assets/sprites/YellowChip.png" id="5_i2o8i"]
|
[ext_resource type="Texture2D" uid="uid://qy30emdgrk7o" path="res://assets/sprites/YellowChip.png" id="5_i2o8i"]
|
||||||
|
[ext_resource type="Script" uid="uid://cwfg17tdbk44b" path="res://scripts/thinking.gd" id="5_wjs8a"]
|
||||||
[ext_resource type="Texture2D" uid="uid://8un28mol7qow" path="res://assets/sprites/BoardTileMap.png" id="6_i2o8i"]
|
[ext_resource type="Texture2D" uid="uid://8un28mol7qow" path="res://assets/sprites/BoardTileMap.png" id="6_i2o8i"]
|
||||||
[ext_resource type="PackedScene" uid="uid://pdean68jjg80" path="res://scenes/button_small.tscn" id="7_glh1q"]
|
[ext_resource type="PackedScene" uid="uid://pdean68jjg80" path="res://scenes/button_small.tscn" id="7_glh1q"]
|
||||||
[ext_resource type="Script" uid="uid://b3q4gq63qmx23" path="res://scripts/BackButton.cs" id="8_u1oi2"]
|
[ext_resource type="Script" uid="uid://b3q4gq63qmx23" path="res://scripts/BackButton.cs" id="8_u1oi2"]
|
||||||
@@ -33,6 +36,8 @@ region = Rect2(112, 32, 16, 16)
|
|||||||
|
|
||||||
[node name="BoardScreen" type="Node2D"]
|
[node name="BoardScreen" type="Node2D"]
|
||||||
script = ExtResource("1_b3w8x")
|
script = ExtResource("1_b3w8x")
|
||||||
|
endingSfx = ExtResource("2_kseed")
|
||||||
|
theme = ExtResource("3_3louw")
|
||||||
|
|
||||||
[node name="Floor Collider" type="StaticBody2D" parent="."]
|
[node name="Floor Collider" type="StaticBody2D" parent="."]
|
||||||
position = Vector2(0, 200)
|
position = Vector2(0, 200)
|
||||||
@@ -116,10 +121,10 @@ offset_left = -529.0
|
|||||||
offset_top = -292.0
|
offset_top = -292.0
|
||||||
offset_right = -427.0
|
offset_right = -427.0
|
||||||
offset_bottom = -284.0
|
offset_bottom = -284.0
|
||||||
theme_override_colors/font_color = Color(1, 0, 0, 1)
|
|
||||||
theme_override_fonts/font = ExtResource("3_rjcmr")
|
theme_override_fonts/font = ExtResource("3_rjcmr")
|
||||||
theme_override_font_sizes/font_size = 8
|
theme_override_font_sizes/font_size = 8
|
||||||
text = "NOT READY"
|
text = "THINKING"
|
||||||
|
script = ExtResource("5_wjs8a")
|
||||||
|
|
||||||
[node name="Player2Card" type="Node2D" parent="."]
|
[node name="Player2Card" type="Node2D" parent="."]
|
||||||
position = Vector2(989, -64)
|
position = Vector2(989, -64)
|
||||||
@@ -163,10 +168,10 @@ offset_left = -530.0
|
|||||||
offset_top = -220.0
|
offset_top = -220.0
|
||||||
offset_right = -428.0
|
offset_right = -428.0
|
||||||
offset_bottom = -212.0
|
offset_bottom = -212.0
|
||||||
theme_override_colors/font_color = Color(1, 0, 0, 1)
|
|
||||||
theme_override_fonts/font = ExtResource("3_rjcmr")
|
theme_override_fonts/font = ExtResource("3_rjcmr")
|
||||||
theme_override_font_sizes/font_size = 8
|
theme_override_font_sizes/font_size = 8
|
||||||
text = "NOT READY"
|
text = "THINKING"
|
||||||
|
script = ExtResource("5_wjs8a")
|
||||||
|
|
||||||
[node name="TileMap" type="TileMap" parent="."]
|
[node name="TileMap" type="TileMap" parent="."]
|
||||||
position = Vector2(39, 200)
|
position = Vector2(39, 200)
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
[gd_scene load_steps=5 format=3 uid="uid://rl33x81cxlh0"]
|
[gd_scene load_steps=8 format=3 uid="uid://rl33x81cxlh0"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://bbgxacei1vwba" path="res://assets/theme.tres" id="1_as653"]
|
||||||
[ext_resource type="Script" uid="uid://dm25u0a2lqk2x" path="res://scripts/BracketScene.cs" id="1_dvj3m"]
|
[ext_resource type="Script" uid="uid://dm25u0a2lqk2x" path="res://scripts/BracketScene.cs" id="1_dvj3m"]
|
||||||
[ext_resource type="Texture2D" uid="uid://da13ksuf4vkqe" path="res://assets/sprites/observe.png" id="2_mbqc8"]
|
[ext_resource type="Texture2D" uid="uid://da13ksuf4vkqe" path="res://assets/sprites/observe.png" id="2_mbqc8"]
|
||||||
[ext_resource type="Texture2D" uid="uid://stk7umv2ppss" path="res://assets/sprites/cancel.png" id="3_as653"]
|
[ext_resource type="Texture2D" uid="uid://stk7umv2ppss" path="res://assets/sprites/cancel.png" id="3_as653"]
|
||||||
[ext_resource type="Script" uid="uid://1y72woiynf31" path="res://scripts/AdminControls.cs" id="4_mbqc8"]
|
[ext_resource type="Script" uid="uid://1y72woiynf31" path="res://scripts/AdminControls.cs" id="4_mbqc8"]
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_wu84c"]
|
||||||
|
colors = PackedColorArray(0, 0.07058824, 0.101960786, 1, 0.39215687, 0.39215687, 0.39215687, 1)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_as653"]
|
||||||
|
gradient = SubResource("Gradient_wu84c")
|
||||||
|
width = 1024
|
||||||
|
height = 1024
|
||||||
|
fill_from = Vector2(0.5, 1)
|
||||||
|
fill_to = Vector2(0.5, 0)
|
||||||
|
metadata/_snap_enabled = true
|
||||||
|
|
||||||
[node name="BracketView" type="Control" node_paths=PackedStringArray("Players", "Matches")]
|
[node name="BracketView" type="Control" node_paths=PackedStringArray("Players", "Matches")]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
@@ -12,12 +24,24 @@ anchor_right = 1.0
|
|||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_as653")
|
||||||
script = ExtResource("1_dvj3m")
|
script = ExtResource("1_dvj3m")
|
||||||
Players = NodePath("HBoxContainer/PlayerList")
|
Players = NodePath("HBoxContainer/PlayerList")
|
||||||
Matches = NodePath("HBoxContainer/MatchList")
|
Matches = NodePath("HBoxContainer/MatchList")
|
||||||
WatchButton = ExtResource("2_mbqc8")
|
WatchButton = ExtResource("2_mbqc8")
|
||||||
TerminateKickButton = ExtResource("3_as653")
|
TerminateKickButton = ExtResource("3_as653")
|
||||||
|
|
||||||
|
[node name="Background" type="TextureRect" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -152.0
|
||||||
|
offset_bottom = 152.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = SubResource("GradientTexture2D_as653")
|
||||||
|
|
||||||
[node name="ColorRect" type="ColorRect" parent="."]
|
[node name="ColorRect" type="ColorRect" parent="."]
|
||||||
custom_minimum_size = Vector2(0, 36)
|
custom_minimum_size = Vector2(0, 36)
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
@@ -26,7 +50,7 @@ anchor_right = 1.0
|
|||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
color = Color(0.13319641, 0.13319641, 0.13319638, 1)
|
color = Color(0.13319641, 0.13319641, 0.13319638, 1)
|
||||||
|
|
||||||
[node name="AdminControls" type="HBoxContainer" parent="ColorRect" node_paths=PackedStringArray("BecomeAdmin", "StartTournament", "Label", "Timeout")]
|
[node name="AdminControls" type="HBoxContainer" parent="ColorRect" node_paths=PackedStringArray("BecomeAdmin", "StartTournament", "CancelTournament", "Label", "Timeout")]
|
||||||
custom_minimum_size = Vector2(0, 36)
|
custom_minimum_size = Vector2(0, 36)
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 10
|
anchors_preset = 10
|
||||||
@@ -36,6 +60,7 @@ grow_horizontal = 2
|
|||||||
script = ExtResource("4_mbqc8")
|
script = ExtResource("4_mbqc8")
|
||||||
BecomeAdmin = NodePath("BecomeAdmin")
|
BecomeAdmin = NodePath("BecomeAdmin")
|
||||||
StartTournament = NodePath("StartTournament")
|
StartTournament = NodePath("StartTournament")
|
||||||
|
CancelTournament = NodePath("CancelTournament")
|
||||||
Label = NodePath("Label")
|
Label = NodePath("Label")
|
||||||
Timeout = NodePath("HSlider")
|
Timeout = NodePath("HSlider")
|
||||||
|
|
||||||
@@ -47,6 +72,10 @@ text = "Become Admin"
|
|||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Start Tournament"
|
text = "Start Tournament"
|
||||||
|
|
||||||
|
[node name="CancelTournament" type="Button" parent="ColorRect/AdminControls"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Cancel Tournament"
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="ColorRect/AdminControls"]
|
[node name="Label" type="Label" parent="ColorRect/AdminControls"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Wait To Move: 5.0s "
|
text = "Wait To Move: 5.0s "
|
||||||
|
|||||||
@@ -1,10 +1,33 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cr8fi0e4r88s8"]
|
[gd_scene load_steps=5 format=3 uid="uid://cr8fi0e4r88s8"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://cct663hb47yka" path="res://scenes/create_join_room.tscn" id="1_yqjtg"]
|
[ext_resource type="PackedScene" uid="uid://cct663hb47yka" path="res://scenes/create_join_room.tscn" id="1_yqjtg"]
|
||||||
[ext_resource type="PackedScene" uid="uid://m542qwlp7hl7" path="res://scenes/board_screen.tscn" id="2_lnu2h"]
|
[ext_resource type="PackedScene" uid="uid://m542qwlp7hl7" path="res://scenes/board_screen.tscn" id="2_lnu2h"]
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_wu84c"]
|
||||||
|
colors = PackedColorArray(0, 0.07058824, 0.101960786, 1, 0.39215687, 0.39215687, 0.39215687, 1)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_yqjtg"]
|
||||||
|
gradient = SubResource("Gradient_wu84c")
|
||||||
|
width = 1024
|
||||||
|
height = 1024
|
||||||
|
fill_from = Vector2(0.5, 1)
|
||||||
|
fill_to = Vector2(0.5, 0)
|
||||||
|
metadata/_snap_enabled = true
|
||||||
|
|
||||||
[node name="Game" type="Node2D"]
|
[node name="Game" type="Node2D"]
|
||||||
|
|
||||||
|
[node name="Background" type="TextureRect" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -658.0
|
||||||
|
offset_top = -547.0
|
||||||
|
offset_right = 668.0
|
||||||
|
offset_bottom = 657.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = SubResource("GradientTexture2D_yqjtg")
|
||||||
|
|
||||||
[node name="GameManager" type="Node" parent="."]
|
[node name="GameManager" type="Node" parent="."]
|
||||||
|
|
||||||
[node name="Camera2D" type="Camera2D" parent="."]
|
[node name="Camera2D" type="Camera2D" parent="."]
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://dcx5nvs0pa7me"]
|
[gd_scene load_steps=7 format=3 uid="uid://dcx5nvs0pa7me"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bk22f71oximjk" path="res://scripts/AddressUI.cs" id="1_l6cm7"]
|
[ext_resource type="Script" uid="uid://bk22f71oximjk" path="res://scripts/AddressUI.cs" id="1_l6cm7"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bbgxacei1vwba" path="res://assets/theme.tres" id="1_wu84c"]
|
||||||
[ext_resource type="Script" uid="uid://cpjbiqn26khck" path="res://scripts/ConnectButtonUI.cs" id="2_ekxnf"]
|
[ext_resource type="Script" uid="uid://cpjbiqn26khck" path="res://scripts/ConnectButtonUI.cs" id="2_ekxnf"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://uritd4ygetrk" path="res://assets/sprites/rpi.png" id="3_bqqt6"]
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_wu84c"]
|
||||||
|
colors = PackedColorArray(0, 0.07058824, 0.101960786, 1, 0.39215687, 0.39215687, 0.39215687, 1)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_yqjtg"]
|
||||||
|
gradient = SubResource("Gradient_wu84c")
|
||||||
|
width = 1024
|
||||||
|
height = 1024
|
||||||
|
fill_from = Vector2(0.5, 1)
|
||||||
|
fill_to = Vector2(0.5, 0)
|
||||||
|
metadata/_snap_enabled = true
|
||||||
|
|
||||||
[node name="Control" type="Control"]
|
[node name="Control" type="Control"]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
@@ -11,6 +24,63 @@ anchor_bottom = 1.0
|
|||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="Background" type="TextureRect" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = SubResource("GradientTexture2D_yqjtg")
|
||||||
|
|
||||||
|
[node name="RPI Minds and Machines" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 5
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
offset_left = -193.5
|
||||||
|
offset_top = 128.0
|
||||||
|
offset_right = 193.5
|
||||||
|
offset_bottom = 152.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
theme = ExtResource("1_wu84c")
|
||||||
|
theme_type_variation = &"HeaderMedium"
|
||||||
|
text = "RPI Minds & Machines"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="Connect" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 5
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
offset_left = -100.0
|
||||||
|
offset_top = 200.0
|
||||||
|
offset_right = 68.00122
|
||||||
|
offset_bottom = 229.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
theme = ExtResource("1_wu84c")
|
||||||
|
theme_type_variation = &"HeaderLarge"
|
||||||
|
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_constants/outline_size = 16
|
||||||
|
text = "Connect"
|
||||||
|
|
||||||
|
[node name="4" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 5
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
offset_left = 78.0
|
||||||
|
offset_top = 200.0
|
||||||
|
offset_right = 118.00116
|
||||||
|
offset_bottom = 229.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
theme = ExtResource("1_wu84c")
|
||||||
|
theme_type_variation = &"HeaderLarge"
|
||||||
|
theme_override_colors/font_color = Color(1, 0, 0, 1)
|
||||||
|
theme_override_constants/outline_size = 16
|
||||||
|
text = "4"
|
||||||
|
|
||||||
[node name="Address" type="TextEdit" parent="."]
|
[node name="Address" type="TextEdit" parent="."]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 8
|
anchors_preset = 8
|
||||||
@@ -24,10 +94,13 @@ offset_right = 250.0
|
|||||||
offset_bottom = 20.0
|
offset_bottom = 20.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_wu84c")
|
||||||
placeholder_text = "Server Address"
|
placeholder_text = "Server Address"
|
||||||
|
emoji_menu_enabled = false
|
||||||
|
scroll_smooth = true
|
||||||
script = ExtResource("1_l6cm7")
|
script = ExtResource("1_l6cm7")
|
||||||
|
|
||||||
[node name="Button" type="Button" parent="." node_paths=PackedStringArray("AddressUi", "ErrorLabel")]
|
[node name="Button" type="Button" parent="." node_paths=PackedStringArray("AddressField", "ErrorLabel")]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 8
|
anchors_preset = 8
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
@@ -40,9 +113,10 @@ offset_right = 250.0
|
|||||||
offset_bottom = 67.25
|
offset_bottom = 67.25
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_wu84c")
|
||||||
text = "Connect"
|
text = "Connect"
|
||||||
script = ExtResource("2_ekxnf")
|
script = ExtResource("2_ekxnf")
|
||||||
AddressUi = NodePath("../Address")
|
AddressField = NodePath("../Address")
|
||||||
ErrorLabel = NodePath("../Label")
|
ErrorLabel = NodePath("../Label")
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="."]
|
[node name="Label" type="Label" parent="."]
|
||||||
@@ -58,4 +132,17 @@ offset_right = 68.5
|
|||||||
offset_bottom = 98.149994
|
offset_bottom = 98.149994
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_wu84c")
|
||||||
theme_override_colors/font_color = Color(1, 0, 0, 1)
|
theme_override_colors/font_color = Color(1, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 2
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 5.0
|
||||||
|
offset_top = -69.0
|
||||||
|
offset_right = 69.0
|
||||||
|
offset_bottom = -5.0
|
||||||
|
grow_vertical = 0
|
||||||
|
texture = ExtResource("3_bqqt6")
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
[gd_scene load_steps=4 format=3 uid="uid://b4tujjdhmk4h"]
|
[gd_scene load_steps=11 format=3 uid="uid://b4tujjdhmk4h"]
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://ckmfi0cjgxgyk" path="res://assets/sprites/RedChip.png" id="1_qsflu"]
|
[ext_resource type="Texture2D" uid="uid://ckmfi0cjgxgyk" path="res://assets/sprites/RedChip.png" id="1_qsflu"]
|
||||||
[ext_resource type="Script" uid="uid://dd5nu6037qsr0" path="res://scripts/red_chip.gd" id="1_tfypd"]
|
[ext_resource type="Script" uid="uid://dd5nu6037qsr0" path="res://scripts/chip_sfx.gd" id="1_tfypd"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://dauf0pi1pkd3x" path="res://assets/sfx/chip_collide_1.ogg" id="2_g7r6w"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://b6b7b7sc038n7" path="res://assets/sfx/chip_collide_2.ogg" id="3_l66m7"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://c6a4wqoopu53j" path="res://assets/sfx/chip_collide_3.ogg" id="4_5isma"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://5liedrachob2" path="res://assets/sfx/chip_collide_4.ogg" id="5_sa1hx"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://dsyovynhhbmw8" path="res://assets/sfx/chip_collide_5.ogg" id="6_752ap"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://c0a5rl5q04noq" path="res://assets/sfx/chip_collide_6.ogg" id="7_ky42j"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://b6d73wiiqxles" path="res://assets/sfx/chip_collide_7.ogg" id="8_lgcne"]
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_tfypd"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_tfypd"]
|
||||||
radius = 13.017083
|
radius = 12.8
|
||||||
|
|
||||||
[node name="RedChip" type="RigidBody2D"]
|
[node name="RedChip" type="RigidBody2D" node_paths=PackedStringArray("audio_stream_player_2d")]
|
||||||
|
lock_rotation = true
|
||||||
|
contact_monitor = true
|
||||||
|
max_contacts_reported = 3
|
||||||
script = ExtResource("1_tfypd")
|
script = ExtResource("1_tfypd")
|
||||||
|
audio_stream_player_2d = NodePath("AudioStreamPlayer2D")
|
||||||
|
sounds = Array[AudioStream]([ExtResource("2_g7r6w"), ExtResource("3_l66m7"), ExtResource("4_5isma"), ExtResource("5_sa1hx"), ExtResource("6_752ap"), ExtResource("7_ky42j"), ExtResource("8_lgcne")])
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
scale = Vector2(3, 3)
|
scale = Vector2(3, 3)
|
||||||
@@ -16,3 +28,8 @@ texture = ExtResource("1_qsflu")
|
|||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||||
scale = Vector2(3, 3)
|
scale = Vector2(3, 3)
|
||||||
shape = SubResource("CircleShape2D_tfypd")
|
shape = SubResource("CircleShape2D_tfypd")
|
||||||
|
|
||||||
|
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||||
|
volume_db = -5.0
|
||||||
|
|
||||||
|
[connection signal="body_entered" from="." to="." method="_on_body_entered"]
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
[gd_scene load_steps=4 format=3 uid="uid://lruk652t0xe5"]
|
[gd_scene load_steps=11 format=3 uid="uid://lruk652t0xe5"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://ddg7dv686sbrb" path="res://scripts/yellow_chip.gd" id="1_epi6l"]
|
[ext_resource type="Script" uid="uid://dd5nu6037qsr0" path="res://scripts/chip_sfx.gd" id="1_epi6l"]
|
||||||
[ext_resource type="Texture2D" uid="uid://qy30emdgrk7o" path="res://assets/sprites/YellowChip.png" id="1_eu0sq"]
|
[ext_resource type="Texture2D" uid="uid://qy30emdgrk7o" path="res://assets/sprites/YellowChip.png" id="1_eu0sq"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://dauf0pi1pkd3x" path="res://assets/sfx/chip_collide_1.ogg" id="2_ki13g"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://b6b7b7sc038n7" path="res://assets/sfx/chip_collide_2.ogg" id="3_kic5w"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://c6a4wqoopu53j" path="res://assets/sfx/chip_collide_3.ogg" id="4_nbcpr"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://5liedrachob2" path="res://assets/sfx/chip_collide_4.ogg" id="5_wq2sm"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://dsyovynhhbmw8" path="res://assets/sfx/chip_collide_5.ogg" id="6_ik045"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://c0a5rl5q04noq" path="res://assets/sfx/chip_collide_6.ogg" id="7_evobg"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://b6d73wiiqxles" path="res://assets/sfx/chip_collide_7.ogg" id="8_b44ux"]
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_epi6l"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_epi6l"]
|
||||||
radius = 13.004272
|
radius = 12.8
|
||||||
|
|
||||||
[node name="YellowChip" type="RigidBody2D"]
|
[node name="YellowChip" type="RigidBody2D" node_paths=PackedStringArray("audio_stream_player_2d")]
|
||||||
|
lock_rotation = true
|
||||||
|
contact_monitor = true
|
||||||
|
max_contacts_reported = 3
|
||||||
script = ExtResource("1_epi6l")
|
script = ExtResource("1_epi6l")
|
||||||
|
audio_stream_player_2d = NodePath("AudioStreamPlayer2D")
|
||||||
|
sounds = Array[AudioStream]([ExtResource("2_ki13g"), ExtResource("3_kic5w"), ExtResource("4_nbcpr"), ExtResource("5_wq2sm"), ExtResource("6_ik045"), ExtResource("7_evobg"), ExtResource("8_b44ux")])
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
scale = Vector2(3, 3)
|
scale = Vector2(3, 3)
|
||||||
@@ -16,3 +28,8 @@ texture = ExtResource("1_eu0sq")
|
|||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||||
scale = Vector2(3, 3)
|
scale = Vector2(3, 3)
|
||||||
shape = SubResource("CircleShape2D_epi6l")
|
shape = SubResource("CircleShape2D_epi6l")
|
||||||
|
|
||||||
|
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
|
||||||
|
volume_db = -5.0
|
||||||
|
|
||||||
|
[connection signal="body_entered" from="." to="." method="_on_body_entered"]
|
||||||
|
|||||||
@@ -1,39 +1,26 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
public partial class AdminControls : HBoxContainer
|
public partial class AdminControls : HBoxContainer
|
||||||
{
|
{
|
||||||
[Export] public Button BecomeAdmin;
|
[Export] public Button BecomeAdmin;
|
||||||
[Export] public Button StartTournament;
|
[Export] public Button StartTournament;
|
||||||
|
[Export] public Button CancelTournament;
|
||||||
[Export] public Label Label;
|
[Export] public Label Label;
|
||||||
[Export] public Slider Timeout;
|
[Export] public Slider Timeout;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
Connection.Instance.OnBecomeAdmin += OnBecomeAdmin;
|
Connection.Instance.OnBecomeAdmin += UpdateUI;
|
||||||
Connection.Instance.OnTournamentEnd += OnEndTournament;
|
Connection.Instance.OnTournamentEnd += UpdateUI;
|
||||||
|
Connection.Instance.OnStartTournamentAck += UpdateUI;
|
||||||
|
Connection.Instance.OnCancelTournamentAck += UpdateUI;
|
||||||
|
Connection.Instance.OnGetDataAcks += UpdateUI;
|
||||||
|
|
||||||
StartTournament.Pressed += StartTournamentCommand;
|
StartTournament.Pressed += () => Connection.Instance.StartTournament();
|
||||||
if (!Connection.Instance.IsAdmin || Connection.Instance.ActiveTournament)
|
CancelTournament.Pressed += () => Connection.Instance.CancelTournament();
|
||||||
{
|
|
||||||
StartTournament.Hide();
|
UpdateUI();
|
||||||
}
|
|
||||||
|
|
||||||
if (!Connection.Instance.IsAdmin)
|
|
||||||
{
|
|
||||||
Label.Hide();
|
|
||||||
Timeout.Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
Timeout.Value = Connection.Instance.CurrentWaitTimeout;
|
|
||||||
var time = Connection.Instance.CurrentWaitTimeout.ToString();
|
|
||||||
if (time.Length > 3)
|
|
||||||
{
|
|
||||||
time = time.Substring(0, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
Label.Text = "Wait To Move: " + time + "s ";
|
|
||||||
Timeout.ValueChanged += value =>
|
Timeout.ValueChanged += value =>
|
||||||
{
|
{
|
||||||
Connection.Instance.SetTournamentWait((float)value);
|
Connection.Instance.SetTournamentWait((float)value);
|
||||||
@@ -50,24 +37,60 @@ public partial class AdminControls : HBoxContainer
|
|||||||
|
|
||||||
public override void _ExitTree()
|
public override void _ExitTree()
|
||||||
{
|
{
|
||||||
Connection.Instance.OnBecomeAdmin -= OnBecomeAdmin;
|
Connection.Instance.OnBecomeAdmin -= UpdateUI;
|
||||||
Connection.Instance.OnTournamentEnd -= OnEndTournament;
|
Connection.Instance.OnTournamentEnd -= UpdateUI;
|
||||||
|
Connection.Instance.OnStartTournamentAck -= UpdateUI;
|
||||||
|
Connection.Instance.OnCancelTournamentAck -= UpdateUI;
|
||||||
|
Connection.Instance.OnGetDataAcks -= UpdateUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartTournamentCommand()
|
private void UpdateUI()
|
||||||
{
|
{
|
||||||
Connection.Instance.StartTournament();
|
if (!Connection.Instance.IsAdmin)
|
||||||
}
|
{
|
||||||
|
BecomeAdmin.Show();
|
||||||
|
StartTournament.Hide();
|
||||||
|
CancelTournament.Hide();
|
||||||
|
Label.Hide();
|
||||||
|
Timeout.Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BecomeAdmin.Hide();
|
||||||
|
Label.Show();
|
||||||
|
Timeout.Show();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnEndTournament(List<(string, int)> playerScoreboard)
|
if (Connection.Instance.IsAdmin && Connection.Instance.DemoMode)
|
||||||
{
|
{
|
||||||
StartTournament.Show();
|
StartTournament.Hide();
|
||||||
ShowTournamentScoreboard(playerScoreboard);
|
CancelTournament.Hide();
|
||||||
|
}
|
||||||
|
else if (Connection.Instance.IsAdmin && Connection.Instance.ActiveTournament)
|
||||||
|
{
|
||||||
|
StartTournament.Hide();
|
||||||
|
CancelTournament.Show();
|
||||||
|
}
|
||||||
|
else if (Connection.Instance.IsAdmin)
|
||||||
|
{
|
||||||
|
StartTournament.Show();
|
||||||
|
CancelTournament.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
Timeout.Value = Connection.Instance.CurrentWaitTimeout;
|
||||||
|
var time = Connection.Instance.CurrentWaitTimeout.ToString();
|
||||||
|
if (time.Length > 3)
|
||||||
|
{
|
||||||
|
time = time.Substring(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label.Text = "Wait To Move: " + time + "s ";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowAuthPopup()
|
private void ShowAuthPopup()
|
||||||
{
|
{
|
||||||
var authWindow = new Window();
|
var authWindow = new Window();
|
||||||
|
authWindow.Theme = GD.Load<Theme>("res://assets/theme.tres");
|
||||||
authWindow.AlwaysOnTop = true;
|
authWindow.AlwaysOnTop = true;
|
||||||
authWindow.MaximizeDisabled = true;
|
authWindow.MaximizeDisabled = true;
|
||||||
authWindow.Unresizable = true;
|
authWindow.Unresizable = true;
|
||||||
@@ -75,7 +98,7 @@ public partial class AdminControls : HBoxContainer
|
|||||||
authWindow.Size = new Vector2I(256, 128);
|
authWindow.Size = new Vector2I(256, 128);
|
||||||
authWindow.CloseRequested += () =>
|
authWindow.CloseRequested += () =>
|
||||||
{
|
{
|
||||||
GetTree().Root.RemoveChild(authWindow);
|
GetTree().Root.CallDeferred(Node.MethodName.RemoveChild, authWindow);
|
||||||
};
|
};
|
||||||
|
|
||||||
var vbox = new VBoxContainer();
|
var vbox = new VBoxContainer();
|
||||||
@@ -90,12 +113,30 @@ public partial class AdminControls : HBoxContainer
|
|||||||
passwordBox.PlaceholderText = "Password";
|
passwordBox.PlaceholderText = "Password";
|
||||||
passwordBox.SetCustomMinimumSize(new Vector2(32, 32));
|
passwordBox.SetCustomMinimumSize(new Vector2(32, 32));
|
||||||
|
|
||||||
|
passwordBox.GuiInput += e =>
|
||||||
|
{
|
||||||
|
if (passwordBox.HasFocus() && e is InputEventKey inputEventKey && inputEventKey.IsPressed())
|
||||||
|
{
|
||||||
|
if (inputEventKey.KeyLabel == Key.Enter)
|
||||||
|
{
|
||||||
|
Connection.Instance.AdminAuth(passwordBox.Text);
|
||||||
|
GetTree().Root.CallDeferred(Node.MethodName.RemoveChild, authWindow);
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputEventKey.KeyLabel == Key.Space)
|
||||||
|
{
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var button = new Button();
|
var button = new Button();
|
||||||
button.Text = "Login";
|
button.Text = "Login";
|
||||||
button.Pressed += () =>
|
button.Pressed += () =>
|
||||||
{
|
{
|
||||||
Connection.Instance.AdminAuth(passwordBox.Text);
|
Connection.Instance.AdminAuth(passwordBox.Text);
|
||||||
GetTree().Root.RemoveChild(authWindow);
|
GetTree().Root.CallDeferred(Node.MethodName.RemoveChild, authWindow);
|
||||||
};
|
};
|
||||||
|
|
||||||
vbox.AddChild(passwordBox);
|
vbox.AddChild(passwordBox);
|
||||||
@@ -105,48 +146,4 @@ public partial class AdminControls : HBoxContainer
|
|||||||
|
|
||||||
GetTree().Root.AddChild(authWindow);
|
GetTree().Root.AddChild(authWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowTournamentScoreboard(List<(string, int)> playerScoreboard)
|
|
||||||
{
|
|
||||||
var scoreboardWindow = new Window();
|
|
||||||
scoreboardWindow.AlwaysOnTop = true;
|
|
||||||
scoreboardWindow.MaximizeDisabled = true;
|
|
||||||
scoreboardWindow.Unresizable = true;
|
|
||||||
scoreboardWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
|
|
||||||
scoreboardWindow.Size = new Vector2I(256, 512);
|
|
||||||
scoreboardWindow.CloseRequested += () =>
|
|
||||||
{
|
|
||||||
GetTree().Root.RemoveChild(scoreboardWindow);
|
|
||||||
};
|
|
||||||
|
|
||||||
var tree = new Tree();
|
|
||||||
tree.HideRoot = true;
|
|
||||||
tree.Columns = 2;
|
|
||||||
tree.ColumnTitlesVisible = true;
|
|
||||||
tree.SetColumnTitle(0, "Player");
|
|
||||||
tree.SetColumnTitle(1, "Score");
|
|
||||||
var root = tree.CreateItem();
|
|
||||||
|
|
||||||
foreach ((string, int) entry in playerScoreboard)
|
|
||||||
{
|
|
||||||
var item = tree.CreateItem(root);
|
|
||||||
item.SetText(0, entry.Item1);
|
|
||||||
item.SetText(1, entry.Item2.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
scoreboardWindow.AddChild(tree);
|
|
||||||
|
|
||||||
GetTree().Root.AddChild(scoreboardWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBecomeAdmin()
|
|
||||||
{
|
|
||||||
BecomeAdmin.Hide();
|
|
||||||
if (!Connection.Instance.ActiveTournament)
|
|
||||||
{
|
|
||||||
StartTournament.Show();
|
|
||||||
}
|
|
||||||
Label.Show();
|
|
||||||
Timeout.Show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
public partial class BoardScreen : Node2D {
|
public partial class BoardScreen : Node2D
|
||||||
|
{
|
||||||
|
[Export] private AudioStream endingSfx;
|
||||||
|
[Export] private Theme theme;
|
||||||
|
|
||||||
private const string RED_CHIP_PATH = "res://scenes/red_chip.tscn";
|
private const string RED_CHIP_PATH = "res://scenes/red_chip.tscn";
|
||||||
private const string YELLOW_CHIP_PATH = "res://scenes/yellow_chip.tscn";
|
private const string YELLOW_CHIP_PATH = "res://scenes/yellow_chip.tscn";
|
||||||
@@ -23,11 +25,13 @@ public partial class BoardScreen : Node2D {
|
|||||||
private Node2D player1Card;
|
private Node2D player1Card;
|
||||||
private Node2D player2Card;
|
private Node2D player2Card;
|
||||||
private MatchData matchData;
|
private MatchData matchData;
|
||||||
|
|
||||||
private List<(string, int)> moves;
|
|
||||||
|
|
||||||
private RigidBody2D[,] chips = new RigidBody2D[6, 7]; // 6 rows 7 cols | 0, 0 is top left
|
private RigidBody2D[,] chips = new RigidBody2D[6, 7]; // 6 rows 7 cols | 0, 0 is top left
|
||||||
|
|
||||||
|
private bool _lastMove = false;
|
||||||
|
private float _lastMoveTimer = 2.5f;
|
||||||
|
private string _winner = "";
|
||||||
|
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready() {
|
public override void _Ready() {
|
||||||
// Node initialization
|
// Node initialization
|
||||||
@@ -43,12 +47,27 @@ public partial class BoardScreen : Node2D {
|
|||||||
matchData = Connection.Instance.CurrentObservingMatch;
|
matchData = Connection.Instance.CurrentObservingMatch;
|
||||||
player1Card.GetNode<Label>("Name").Text = matchData.player1;
|
player1Card.GetNode<Label>("Name").Text = matchData.player1;
|
||||||
player2Card.GetNode<Label>("Name").Text = matchData.player2;
|
player2Card.GetNode<Label>("Name").Text = matchData.player2;
|
||||||
|
|
||||||
|
if (Connection.Instance.PreviousMoves.Count == 0)
|
||||||
|
{
|
||||||
|
player1Card.GetNode<Label>("Status").Show();
|
||||||
|
player2Card.GetNode<Label>("Status").Hide();
|
||||||
|
}
|
||||||
|
else if (Connection.Instance.PreviousMoves.Last().Item1 == matchData.player1)
|
||||||
|
{
|
||||||
|
player1Card.GetNode<Label>("Status").Hide();
|
||||||
|
player2Card.GetNode<Label>("Status").Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player1Card.GetNode<Label>("Status").Show();
|
||||||
|
player2Card.GetNode<Label>("Status").Hide();
|
||||||
|
}
|
||||||
|
|
||||||
Connection.Instance.OnObserveWin += ObserveWin;
|
Connection.Instance.OnObserveWin += OnObserveWin;
|
||||||
Connection.Instance.OnObserveDraw += ObserveDraw;
|
Connection.Instance.OnObserveDraw += OnObserveDraw;
|
||||||
Connection.Instance.OnObserveTerminated += ObserveTerminated;
|
Connection.Instance.OnObserveTerminated += OnObserveTerminated;
|
||||||
Connection.Instance.OnObserveMove += ObserveMove;
|
Connection.Instance.OnObserveMove += ObserveMove;
|
||||||
Connection.Instance.OnTournamentEnd += ShowTournamentScoreboard;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
@@ -72,45 +91,84 @@ public partial class BoardScreen : Node2D {
|
|||||||
{
|
{
|
||||||
currentTimeout -= delta;
|
currentTimeout -= delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_lastMove)
|
||||||
|
{
|
||||||
|
_lastMoveTimer -= (float) delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastMoveTimer <= 0.0f)
|
||||||
|
{
|
||||||
|
if (_winner == "")
|
||||||
|
{
|
||||||
|
PopupMessage("Draw!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PopupMessage(_winner + " wins!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public override void _ExitTree()
|
||||||
{
|
{
|
||||||
Connection.Instance.OnObserveWin -= ObserveWin;
|
Connection.Instance.OnObserveWin -= OnObserveWin;
|
||||||
Connection.Instance.OnObserveDraw -= ObserveDraw;
|
Connection.Instance.OnObserveDraw -= OnObserveDraw;
|
||||||
Connection.Instance.OnObserveTerminated -= ObserveTerminated;
|
Connection.Instance.OnObserveTerminated -= OnObserveTerminated;
|
||||||
Connection.Instance.OnObserveMove -= ObserveMove;
|
Connection.Instance.OnObserveMove -= ObserveMove;
|
||||||
Connection.Instance.OnTournamentEnd -= ShowTournamentScoreboard;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ObserveMove(string username, int column)
|
private void OnObserveWin(string winner)
|
||||||
{
|
{
|
||||||
Connection.Instance.PreviousMoves.Add((username, column));
|
_lastMove = true;
|
||||||
|
_winner = winner;
|
||||||
|
player1Card.GetNode<Label>("Status").Hide();
|
||||||
|
player2Card.GetNode<Label>("Status").Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ObserveWin(string winner)
|
private void OnObserveDraw()
|
||||||
{
|
{
|
||||||
PopupMessage(winner + " wins!");
|
_lastMove = true;
|
||||||
|
player1Card.GetNode<Label>("Status").Hide();
|
||||||
|
player2Card.GetNode<Label>("Status").Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ObserveDraw()
|
private void OnObserveTerminated()
|
||||||
{
|
|
||||||
PopupMessage("Draw!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ObserveTerminated()
|
|
||||||
{
|
{
|
||||||
PopupMessage("Match Terminated");
|
PopupMessage("Match Terminated");
|
||||||
|
player1Card.GetNode<Label>("Status").Hide();
|
||||||
|
player2Card.GetNode<Label>("Status").Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ObserveMove(string username, int column)
|
||||||
|
{
|
||||||
|
if (username == matchData.player1)
|
||||||
|
{
|
||||||
|
if (!_lastMove)
|
||||||
|
player2Card.GetNode<Label>("Status").Show();
|
||||||
|
player1Card.GetNode<Label>("Status").Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_lastMove)
|
||||||
|
player1Card.GetNode<Label>("Status").Show();
|
||||||
|
player2Card.GetNode<Label>("Status").Hide();
|
||||||
|
}
|
||||||
|
Connection.Instance.PreviousMoves.Add((username, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopupMessage(string message)
|
private void PopupMessage(string message)
|
||||||
{
|
{
|
||||||
var popup = new Popup();
|
var popup = new Popup();
|
||||||
popup.AlwaysOnTop = true;
|
popup.AlwaysOnTop = true;
|
||||||
popup.PopupCentered();
|
|
||||||
popup.Size = new Vector2I(200, 100);
|
popup.Size = new Vector2I(200, 100);
|
||||||
|
popup.Theme = GD.Load<Theme>("res://assets/theme.tres");
|
||||||
var text = new Label();
|
var text = new Label();
|
||||||
text.Text = message;
|
text.Text = message;
|
||||||
|
var sfx = new AudioStreamPlayer();
|
||||||
|
sfx.Stream = endingSfx;
|
||||||
|
sfx.VolumeDb = -2;
|
||||||
|
popup.AddChild(sfx);
|
||||||
popup.AddChild(text);
|
popup.AddChild(text);
|
||||||
text.GrowHorizontal = Control.GrowDirection.Both;
|
text.GrowHorizontal = Control.GrowDirection.Both;
|
||||||
text.GrowVertical = Control.GrowDirection.Both;
|
text.GrowVertical = Control.GrowDirection.Both;
|
||||||
@@ -118,44 +176,14 @@ public partial class BoardScreen : Node2D {
|
|||||||
text.VerticalAlignment = VerticalAlignment.Center;
|
text.VerticalAlignment = VerticalAlignment.Center;
|
||||||
text.AnchorsPreset = (int) Control.LayoutPreset.FullRect;
|
text.AnchorsPreset = (int) Control.LayoutPreset.FullRect;
|
||||||
popup.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
|
popup.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
|
||||||
|
popup.PopupHide += () => popup.QueueFree();
|
||||||
GetTree().Root.AddChild(popup);
|
GetTree().Root.AddChild(popup);
|
||||||
|
popup.PopupCentered();
|
||||||
|
sfx.Play();
|
||||||
popup.Show();
|
popup.Show();
|
||||||
TransitionToBracket();
|
TransitionToBracket();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowTournamentScoreboard(List<(string, int)> playerScoreboard)
|
|
||||||
{
|
|
||||||
var scoreboardWindow = new Window();
|
|
||||||
scoreboardWindow.AlwaysOnTop = true;
|
|
||||||
scoreboardWindow.MaximizeDisabled = true;
|
|
||||||
scoreboardWindow.Unresizable = true;
|
|
||||||
scoreboardWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
|
|
||||||
scoreboardWindow.Size = new Vector2I(256, 512);
|
|
||||||
scoreboardWindow.CloseRequested += () =>
|
|
||||||
{
|
|
||||||
GetTree().Root.RemoveChild(scoreboardWindow);
|
|
||||||
};
|
|
||||||
|
|
||||||
var tree = new Tree();
|
|
||||||
tree.HideRoot = true;
|
|
||||||
tree.Columns = 2;
|
|
||||||
tree.ColumnTitlesVisible = true;
|
|
||||||
tree.SetColumnTitle(0, "Player");
|
|
||||||
tree.SetColumnTitle(1, "Score");
|
|
||||||
var root = tree.CreateItem();
|
|
||||||
|
|
||||||
foreach ((string, int) entry in playerScoreboard)
|
|
||||||
{
|
|
||||||
var item = tree.CreateItem(root);
|
|
||||||
item.SetText(0, entry.Item1);
|
|
||||||
item.SetText(1, entry.Item2.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
scoreboardWindow.AddChild(tree);
|
|
||||||
|
|
||||||
GetTree().Root.AddChild(scoreboardWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TransitionToBracket()
|
private void TransitionToBracket()
|
||||||
{
|
{
|
||||||
GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH);
|
GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public partial class BracketScene : Control
|
public partial class BracketScene : Control
|
||||||
@@ -45,6 +44,7 @@ public partial class BracketScene : Control
|
|||||||
{
|
{
|
||||||
Players.Clear();
|
Players.Clear();
|
||||||
_playerList = playerList;
|
_playerList = playerList;
|
||||||
|
_playerList.Sort((a, b) => a.username.CompareTo(b.username));
|
||||||
var root = Players.CreateItem();
|
var root = Players.CreateItem();
|
||||||
for (int i = 0; i < _playerList.Count; i++)
|
for (int i = 0; i < _playerList.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ public partial class BracketScene : Control
|
|||||||
item.SetText(2, playerList[i].isPlaying ? "Yes" : "No");
|
item.SetText(2, playerList[i].isPlaying ? "Yes" : "No");
|
||||||
if (Connection.Instance.IsAdmin)
|
if (Connection.Instance.IsAdmin)
|
||||||
{
|
{
|
||||||
item.AddButton(0, TerminateKickButton, i, false, "Kick"); // TODO
|
item.AddButton(0, TerminateKickButton, i, false, "Kick");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,22 +70,30 @@ public partial class BracketScene : Control
|
|||||||
item.SetText(0, matchList[i].matchId.ToString());
|
item.SetText(0, matchList[i].matchId.ToString());
|
||||||
item.SetText(1, matchList[i].player1);
|
item.SetText(1, matchList[i].player1);
|
||||||
item.SetText(2, matchList[i].player2);
|
item.SetText(2, matchList[i].player2);
|
||||||
item.AddButton(0, WatchButton, item.GetButtonCount(0), false, "Watch");
|
item.AddButton(0, WatchButton, i, false, "Watch");
|
||||||
if (Connection.Instance.IsAdmin)
|
if (Connection.Instance.IsAdmin)
|
||||||
{
|
{
|
||||||
item.AddButton(0, TerminateKickButton, item.GetButtonCount(0), false, "Terminate");
|
item.AddButton(0, TerminateKickButton, 128 + i, false, "Terminate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WatchGame(TreeItem item, long column, long id, long mouseButtonIndex)
|
private void WatchGame(TreeItem item, long column, long id, long mouseButtonIndex)
|
||||||
{
|
{
|
||||||
if (mouseButtonIndex == 1 && column == 0)
|
if (mouseButtonIndex == 1 && column == 0 && id < 128)
|
||||||
{
|
{
|
||||||
Connection.Instance.SendWatchGame(_matchList[(int) id].matchId);
|
Connection.Instance.SendWatchGame(_matchList[(int) id].matchId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TerminateGame(TreeItem item, long column, long id, long mouseButtonIndex)
|
||||||
|
{
|
||||||
|
if (mouseButtonIndex == 1 && column == 0 && id - 128 >= 0 && _matchList[(int) id - 128] != null)
|
||||||
|
{
|
||||||
|
Connection.Instance.TerminateGame(_matchList[(int) id - 128].matchId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void KickPlayer(TreeItem item, long column, long id, long mouseButtonIndex)
|
private void KickPlayer(TreeItem item, long column, long id, long mouseButtonIndex)
|
||||||
{
|
{
|
||||||
if (mouseButtonIndex == 1 && column == 0)
|
if (mouseButtonIndex == 1 && column == 0)
|
||||||
@@ -94,14 +102,6 @@ public partial class BracketScene : Control
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TerminateGame(TreeItem item, long column, long id, long mouseButtonIndex)
|
|
||||||
{
|
|
||||||
if (mouseButtonIndex == 1 && column == 0 && id - 1 > 0 && _matchList[(int) id - 1] != null)
|
|
||||||
{
|
|
||||||
Connection.Instance.TerminateGame(_matchList[(int) id - 1].matchId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TransitionToBoard()
|
private void TransitionToBoard()
|
||||||
{
|
{
|
||||||
GetTree().ChangeSceneToFile(BOARD_SCENE_PATH);
|
GetTree().ChangeSceneToFile(BOARD_SCENE_PATH);
|
||||||
|
|||||||
@@ -1,23 +1,62 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
|
|
||||||
public partial class ConnectButtonUI : Button
|
public partial class ConnectButtonUI : Button
|
||||||
{
|
{
|
||||||
[Export] public TextEdit AddressUi;
|
[Export] public TextEdit AddressField;
|
||||||
[Export] public Label ErrorLabel;
|
[Export] public Label ErrorLabel;
|
||||||
private const string BRACKET_SCENE_PATH = "res://scenes/bracket_view.tscn";
|
private const string BRACKET_SCENE_PATH = "res://scenes/bracket_view.tscn";
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
Connection.Instance.OnWsConnectionSuccess += OnConnectionSuccess;
|
||||||
|
Connection.Instance.OnWsConnectionFailed += OnConnectionFailed;
|
||||||
|
|
||||||
|
if (Connection.Instance.LastUsedConnectionAddress.Length > 0)
|
||||||
|
{
|
||||||
|
AddressField.Text = Connection.Instance.LastUsedConnectionAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Connection.Instance.LastError.Length > 0)
|
||||||
|
{
|
||||||
|
ErrorLabel.Text = Connection.Instance.LastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressField.GuiInput += e =>
|
||||||
|
{
|
||||||
|
if (AddressField.HasFocus() && e is InputEventKey inputEventKey && inputEventKey.IsPressed())
|
||||||
|
{
|
||||||
|
if (inputEventKey.KeyLabel == Key.Enter)
|
||||||
|
{
|
||||||
|
Connection.Instance.Connect(AddressField.Text);
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputEventKey.KeyLabel == Key.Space)
|
||||||
|
{
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
Connection.Instance.OnWsConnectionSuccess -= OnConnectionSuccess;
|
||||||
|
Connection.Instance.OnWsConnectionFailed -= OnConnectionFailed;
|
||||||
|
}
|
||||||
|
|
||||||
public override void _Pressed()
|
public override void _Pressed()
|
||||||
{
|
{
|
||||||
if (Connection.Instance.Connect(AddressUi.Text))
|
Connection.Instance.Connect(AddressField.Text);
|
||||||
{
|
}
|
||||||
GD.Print("Success!");
|
|
||||||
GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH);
|
private void OnConnectionSuccess()
|
||||||
}
|
{
|
||||||
else
|
GetTree().ChangeSceneToFile(BRACKET_SCENE_PATH);
|
||||||
{
|
}
|
||||||
ErrorLabel.Text = "Couldn't connect to server!";
|
|
||||||
}
|
private void OnConnectionFailed()
|
||||||
base._Pressed();
|
{
|
||||||
|
ErrorLabel.Text = "Couldn't connect to server! " + Connection.Instance.LastError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ public partial class Connection : Node
|
|||||||
|
|
||||||
public static Connection Instance { get; private set; }
|
public static Connection Instance { get; private set; }
|
||||||
|
|
||||||
private WebSocketPeer _webSocket = new WebSocketPeer();
|
private WebSocketPeer _webSocket = new ();
|
||||||
private bool _firstConnect = true;
|
|
||||||
private Thread _gameListThread;
|
private Thread _gameListThread;
|
||||||
private bool _gameListThreadRunning;
|
private bool _gameListThreadRunning;
|
||||||
|
|
||||||
@@ -31,87 +30,134 @@ public partial class Connection : Node
|
|||||||
public event Action<List<MatchData>> OnUpdatedMatches;
|
public event Action<List<MatchData>> OnUpdatedMatches;
|
||||||
public event Action<List<PlayerData>> OnUpdatedPlayers;
|
public event Action<List<PlayerData>> OnUpdatedPlayers;
|
||||||
public event Action OnStartTournamentAck;
|
public event Action OnStartTournamentAck;
|
||||||
public event Action<List<(string, int)>> OnTournamentEnd;
|
public event Action OnTournamentEnd;
|
||||||
|
public event Action OnCancelTournamentAck;
|
||||||
public event Action OnBecomeAdmin;
|
public event Action OnBecomeAdmin;
|
||||||
|
public event Action OnGetDataAcks;
|
||||||
|
|
||||||
|
public event Action OnWsConnectionSuccess;
|
||||||
|
public event Action OnWsConnectionFailed;
|
||||||
|
public event Action OnWsDisconnect;
|
||||||
|
|
||||||
// Already prints to console
|
// Already prints to console
|
||||||
public event Action<string, string> OnError;
|
public event Action<string> OnError;
|
||||||
|
|
||||||
public bool IsAdmin { get; private set; }
|
public bool IsAdmin { get; private set; }
|
||||||
public bool IsPlayer { get; private set; }
|
public bool IsPlayer { get; private set; }
|
||||||
public bool ActiveTournament { get; private set; }
|
public bool ActiveTournament { get; private set; }
|
||||||
public List<(string, int)> PreviousMoves { get; private set; } = new List<(string, int)>();
|
public bool DemoMode { get; private set; }
|
||||||
|
public List<(string, int)> PreviousMoves { get; private set; } = [];
|
||||||
public double CurrentWaitTimeout { get; private set; } = 5.0;
|
public double CurrentWaitTimeout { get; private set; } = 5.0;
|
||||||
|
|
||||||
|
|
||||||
public MatchData CurrentObservingMatch { get; private set; }
|
public MatchData CurrentObservingMatch { get; private set; }
|
||||||
|
public string LastUsedConnectionAddress { get; private set; } = "";
|
||||||
|
public string LastError { get; private set; } = "";
|
||||||
|
|
||||||
private bool IsSocketOpen => _webSocket.GetReadyState() == WebSocketPeer.State.Open;
|
private bool IsSocketOpen => _webSocket.GetReadyState() == WebSocketPeer.State.Open;
|
||||||
|
|
||||||
|
private bool _connecting = false;
|
||||||
|
private bool _connected = false;
|
||||||
|
private List<(string, int)> _lastScoreboard = [];
|
||||||
|
private bool _shouldShowTournamentResults = false;
|
||||||
|
private float _refreshGamePlayerListTimer = 5.0f;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
_webSocket.SetHeartbeatInterval(5.0);
|
_webSocket.SetHeartbeatInterval(5.0);
|
||||||
_webSocket.HeartbeatInterval = 5.0;
|
_webSocket.HeartbeatInterval = 5.0;
|
||||||
|
Instance.OnWsDisconnect += () => GetTree().ChangeSceneToFile("res://scenes/main_menu.tscn");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Connect(string address)
|
public void Connect(string address)
|
||||||
{
|
{
|
||||||
if (_webSocket.GetReadyState() == WebSocketPeer.State.Open)
|
_connecting = true;
|
||||||
|
LastUsedConnectionAddress = address;
|
||||||
|
if (_connected)
|
||||||
{
|
{
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error = _webSocket.ConnectToUrl(address);
|
Error error = _webSocket.ConnectToUrl(address);
|
||||||
if (error != Error.Ok)
|
if (error != Error.Ok)
|
||||||
{
|
{
|
||||||
return false;
|
LastError = error.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
_webSocket.Poll();
|
|
||||||
|
|
||||||
while (_webSocket.GetReadyState() == WebSocketPeer.State.Connecting)
|
|
||||||
{
|
|
||||||
_webSocket.Poll();
|
|
||||||
Thread.Sleep(TimeSpan.FromMilliseconds(5));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_webSocket.GetReadyState() != WebSocketPeer.State.Open)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_webSocket.SetHeartbeatInterval(5.0);
|
|
||||||
_webSocket.HeartbeatInterval = 5.0;
|
|
||||||
_firstConnect = false;
|
|
||||||
StartGameListRefreshLoop();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public override void _Process(double delta)
|
||||||
{
|
|
||||||
StopGameListRefreshLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _PhysicsProcess(double delta)
|
|
||||||
{
|
{
|
||||||
_webSocket.Poll();
|
_webSocket.Poll();
|
||||||
WebSocketPeer.State state = _webSocket.GetReadyState();
|
WebSocketPeer.State state = _webSocket.GetReadyState();
|
||||||
if ((state == WebSocketPeer.State.Closed || state == WebSocketPeer.State.Closing) && !_firstConnect)
|
if (state == WebSocketPeer.State.Open)
|
||||||
{
|
|
||||||
StopGameListRefreshLoop();
|
|
||||||
GD.PrintErr("Connection lost.");
|
|
||||||
//GetTree().Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsSocketOpen)
|
|
||||||
{
|
{
|
||||||
|
if (_connecting)
|
||||||
|
{
|
||||||
|
_connecting = false;
|
||||||
|
_connected = true;
|
||||||
|
LastError = "";
|
||||||
|
OnWsConnectionSuccess?.Invoke();
|
||||||
|
UpdateGameList();
|
||||||
|
UpdatePlayerList();
|
||||||
|
_refreshGamePlayerListTimer = 5.0f;
|
||||||
|
} else if (_refreshGamePlayerListTimer <= 0.0f)
|
||||||
|
{
|
||||||
|
UpdateGameList();
|
||||||
|
UpdatePlayerList();
|
||||||
|
_refreshGamePlayerListTimer = 5.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_refreshGamePlayerListTimer -= (float) delta;
|
||||||
|
}
|
||||||
|
|
||||||
while (_webSocket.GetAvailablePacketCount() > 0)
|
while (_webSocket.GetAvailablePacketCount() > 0)
|
||||||
{
|
{
|
||||||
string message = _webSocket.GetPacket().GetStringFromUtf8();
|
string message = _webSocket.GetPacket().GetStringFromUtf8();
|
||||||
HandleServerMessage(message);
|
HandleServerMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_shouldShowTournamentResults)
|
||||||
|
{
|
||||||
|
var children = GetTree().Root.GetChildren();
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
if (child.Name.ToString() == "BracketView")
|
||||||
|
{
|
||||||
|
_shouldShowTournamentResults = false;
|
||||||
|
ShowTournamentScoreboard(_lastScoreboard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == WebSocketPeer.State.Connecting)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
else if (state == WebSocketPeer.State.Closing)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
else if (state == WebSocketPeer.State.Closed)
|
||||||
|
{
|
||||||
|
if (_connecting)
|
||||||
|
{
|
||||||
|
_connecting = false;
|
||||||
|
OnWsConnectionFailed?.Invoke();
|
||||||
|
}
|
||||||
|
else if (_connected)
|
||||||
|
{
|
||||||
|
_connected = false;
|
||||||
|
IsAdmin = false;
|
||||||
|
CurrentWaitTimeout = 5.0;
|
||||||
|
ActiveTournament = false;
|
||||||
|
DemoMode = false;
|
||||||
|
_refreshGamePlayerListTimer = 5.0f;
|
||||||
|
var code = _webSocket.GetCloseCode();
|
||||||
|
var reason = _webSocket.GetCloseReason();
|
||||||
|
LastError = "Unexpected Disconnect. Reason: " + reason + ", Code: " + code;
|
||||||
|
GD.PrintErr("WebSocket closed with code: " + code + ", reason " + reason + ". Clean: " + (code != -1));
|
||||||
|
OnWsDisconnect?.Invoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,45 +197,6 @@ public partial class Connection : Node
|
|||||||
SendCommand("GAME", "LIST");
|
SendCommand("GAME", "LIST");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartGameListRefreshLoop()
|
|
||||||
{
|
|
||||||
if (_gameListThreadRunning)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_gameListThreadRunning = true;
|
|
||||||
_gameListThread = new Thread(() =>
|
|
||||||
{
|
|
||||||
while (_gameListThreadRunning)
|
|
||||||
{
|
|
||||||
if (IsSocketOpen)
|
|
||||||
{
|
|
||||||
UpdateGameList();
|
|
||||||
UpdatePlayerList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(5));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
IsBackground = true
|
|
||||||
};
|
|
||||||
_gameListThread.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopGameListRefreshLoop()
|
|
||||||
{
|
|
||||||
if (!_gameListThreadRunning)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_gameListThreadRunning = false;
|
|
||||||
_gameListThread?.Join();
|
|
||||||
_gameListThread = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdatePlayerList()
|
public void UpdatePlayerList()
|
||||||
{
|
{
|
||||||
SendCommand("PLAYER", "LIST");
|
SendCommand("PLAYER", "LIST");
|
||||||
@@ -206,6 +213,16 @@ public partial class Connection : Node
|
|||||||
SendCommand("ADMIN", "AUTH:" + password);
|
SendCommand("ADMIN", "AUTH:" + password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetMoveWait()
|
||||||
|
{
|
||||||
|
SendCommand("GET", "MOVE_WAIT");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetTournamentStatus()
|
||||||
|
{
|
||||||
|
SendCommand("GET", "TOURNAMENT_STATUS");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Admin commands
|
// Admin commands
|
||||||
public void KickPlayer(string playerId)
|
public void KickPlayer(string playerId)
|
||||||
@@ -220,6 +237,12 @@ public partial class Connection : Node
|
|||||||
SendCommand("TOURNAMENT", "START");
|
SendCommand("TOURNAMENT", "START");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CancelTournament()
|
||||||
|
{
|
||||||
|
if (!IsAdmin) return;
|
||||||
|
SendCommand("TOURNAMENT", "CANCEL");
|
||||||
|
}
|
||||||
|
|
||||||
public void TerminateGame(int matchID)
|
public void TerminateGame(int matchID)
|
||||||
{
|
{
|
||||||
if (!IsAdmin) return;
|
if (!IsAdmin) return;
|
||||||
@@ -308,7 +331,8 @@ public partial class Connection : Node
|
|||||||
if (body == "AUTH:ACK")
|
if (body == "AUTH:ACK")
|
||||||
{
|
{
|
||||||
IsAdmin = true;
|
IsAdmin = true;
|
||||||
SetTournamentWait(5.0f);
|
GetMoveWait();
|
||||||
|
GetTournamentStatus();
|
||||||
OnBecomeAdmin?.Invoke();
|
OnBecomeAdmin?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,9 +340,29 @@ public partial class Connection : Node
|
|||||||
case "TOURNAMENT":
|
case "TOURNAMENT":
|
||||||
HandleTournamentMessage(body);
|
HandleTournamentMessage(body);
|
||||||
break;
|
break;
|
||||||
|
case "GET":
|
||||||
|
if (body.StartsWith("MOVE_WAIT"))
|
||||||
|
{
|
||||||
|
CurrentWaitTimeout = double.Parse(body.Split(":")[1]);
|
||||||
|
}
|
||||||
|
else if (body.StartsWith("TOURNAMENT_STATUS"))
|
||||||
|
{
|
||||||
|
string status = body.Split(":")[1];
|
||||||
|
if (status != "DEMO")
|
||||||
|
{
|
||||||
|
ActiveTournament = bool.Parse(status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ActiveTournament = false;
|
||||||
|
DemoMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OnGetDataAcks?.Invoke();
|
||||||
|
break;
|
||||||
case "ERROR":
|
case "ERROR":
|
||||||
HandleErrorMessage(body);
|
GD.PrintErr(message);
|
||||||
GD.PrintErr($"Error: {body}");
|
OnError?.Invoke(message);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GD.Print($"Unhandled server message: {message}");
|
GD.Print($"Unhandled server message: {message}");
|
||||||
@@ -350,13 +394,21 @@ public partial class Connection : Node
|
|||||||
playerScoreboard.Add((data[0], int.Parse(data[1])));
|
playerScoreboard.Add((data[0], int.Parse(data[1])));
|
||||||
}
|
}
|
||||||
|
|
||||||
OnTournamentEnd?.Invoke(playerScoreboard);
|
_lastScoreboard = playerScoreboard;
|
||||||
|
_shouldShowTournamentResults = true;
|
||||||
|
OnTournamentEnd?.Invoke();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "START":
|
case "START":
|
||||||
{
|
{
|
||||||
OnStartTournamentAck?.Invoke();
|
|
||||||
ActiveTournament = true;
|
ActiveTournament = true;
|
||||||
|
OnStartTournamentAck?.Invoke();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "CANCEL":
|
||||||
|
{
|
||||||
|
ActiveTournament = false;
|
||||||
|
OnCancelTournamentAck?.Invoke();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,19 +547,42 @@ public partial class Connection : Node
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleErrorMessage(string body)
|
public void ShowTournamentScoreboard(List<(string, int)> playerScoreboard)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(body))
|
var scoreboardWindow = new Window();
|
||||||
|
scoreboardWindow.Theme = GD.Load<Theme>("res://assets/theme.tres");
|
||||||
|
scoreboardWindow.AlwaysOnTop = true;
|
||||||
|
scoreboardWindow.MaximizeDisabled = true;
|
||||||
|
scoreboardWindow.Unresizable = true;
|
||||||
|
scoreboardWindow.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
|
||||||
|
scoreboardWindow.Size = new Vector2I(256, 512);
|
||||||
|
scoreboardWindow.CloseRequested += () =>
|
||||||
{
|
{
|
||||||
OnError?.Invoke("UNKNOWN", string.Empty);
|
GetTree().Root.RemoveChild(scoreboardWindow);
|
||||||
return;
|
};
|
||||||
|
|
||||||
|
var tree = new Tree();
|
||||||
|
tree.HideRoot = true;
|
||||||
|
tree.Columns = 2;
|
||||||
|
tree.ColumnTitlesVisible = true;
|
||||||
|
tree.Theme = GD.Load<Theme>("res://assets/theme.tres");
|
||||||
|
tree.GrowHorizontal = Control.GrowDirection.Both;
|
||||||
|
tree.GrowVertical = Control.GrowDirection.Both;
|
||||||
|
tree.SetColumnTitle(0, "Player");
|
||||||
|
tree.SetColumnTitle(1, "Score");
|
||||||
|
var root = tree.CreateItem();
|
||||||
|
|
||||||
|
foreach ((string, int) entry in playerScoreboard)
|
||||||
|
{
|
||||||
|
var item = tree.CreateItem(root);
|
||||||
|
item.SetText(0, entry.Item1);
|
||||||
|
item.SetText(1, entry.Item2.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] segments = body.Split(':');
|
scoreboardWindow.AddChild(tree);
|
||||||
string code = segments.Length > 0 ? segments[0].Trim().ToUpperInvariant() : "UNKNOWN";
|
tree.SetAnchorsPreset(Control.LayoutPreset.FullRect);
|
||||||
string detail = segments.Length > 1 ? string.Join(":", segments, 1, segments.Length - 1).Trim() : string.Empty;
|
|
||||||
|
GetTree().Root.AddChild(scoreboardWindow);
|
||||||
OnError?.Invoke(code, detail);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
scripts/background_music.gd
Normal file
8
scripts/background_music.gd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
var music = AudioStreamPlayer.new()
|
||||||
|
add_child(music)
|
||||||
|
music.stream = load("res://assets/music/jazz_music.mp3")
|
||||||
|
music.volume_db = -10
|
||||||
|
music.play()
|
||||||
1
scripts/background_music.gd.uid
Normal file
1
scripts/background_music.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://hh10ct26xx1b
|
||||||
13
scripts/chip_sfx.gd
Normal file
13
scripts/chip_sfx.gd
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
extends RigidBody2D
|
||||||
|
|
||||||
|
@export var audio_stream_player_2d: AudioStreamPlayer2D
|
||||||
|
@export var velocity_for_sfx: float = 2.0
|
||||||
|
@export var sounds: Array[AudioStream]
|
||||||
|
|
||||||
|
func _on_body_entered(body: Node) -> void:
|
||||||
|
if body.name.begins_with("@RigidBody2D@") || body.name.begins_with("Floor"):
|
||||||
|
var rng = RandomNumberGenerator.new()
|
||||||
|
rng.randomize()
|
||||||
|
var index = rng.randi_range(0, sounds.size() - 1)
|
||||||
|
audio_stream_player_2d.stream = sounds[index]
|
||||||
|
audio_stream_player_2d.play();
|
||||||
@@ -10,5 +10,5 @@ func _ready() -> void:
|
|||||||
|
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
func _process(delta: float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
extends RigidBody2D
|
|
||||||
|
|
||||||
var color_ = "red";
|
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
|
||||||
func _ready() -> void:
|
|
||||||
pass # Replace with function body.
|
|
||||||
|
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
||||||
func _process(_delta: float) -> void:
|
|
||||||
pass
|
|
||||||
10
scripts/thinking.gd
Normal file
10
scripts/thinking.gd
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
extends Label
|
||||||
|
|
||||||
|
@export var hue = 0.0
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
modulate = Color.from_hsv(hue, 1.0, 1.0, 1.0)
|
||||||
|
if hue < 1.0:
|
||||||
|
hue += 0.1 * delta
|
||||||
|
else:
|
||||||
|
hue = 0.0
|
||||||
1
scripts/thinking.gd.uid
Normal file
1
scripts/thinking.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cwfg17tdbk44b
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
extends RigidBody2D
|
|
||||||
|
|
||||||
var color_ = "yellow";
|
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
|
||||||
func _ready() -> void:
|
|
||||||
pass # Replace with function body.
|
|
||||||
|
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
||||||
func _process(_delta: float) -> void:
|
|
||||||
pass
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://ddg7dv686sbrb
|
|
||||||
Reference in New Issue
Block a user