Merge branch 'game-logic'
@ -1,3 +1,3 @@
|
||||
source_md5="a88d669f1f058a347cc4de2244bac64b"
|
||||
dest_md5="1073062c6e594eff250036d7489d44a7"
|
||||
dest_md5="1ed8fab74f35d40e257776b2eab84c5f"
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="e860aab5fa3b6ce9c5831b3624861eb0"
|
||||
dest_md5="a265f8881bf649748bb86076a1059462"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="f1043053126af1a739ae9a6d20541705"
|
||||
dest_md5="33d90f901d38e94006bc94b2bafbcc7f"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="e5510033f1a1421d95771be4d1f17c06"
|
||||
dest_md5="acfea8b7761d165a201dbc0a0af2c167"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="236f053c1af2cb6dc8fb21dd8c49fee6"
|
||||
dest_md5="e8811c15e8ebcd4a71c62994dc9c6d5a"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="dc5c89239ead115c7989cdbee213c307"
|
||||
dest_md5="d26cc3c5d8c5165d3f5afb242806bdb4"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="d743da5448801d5a71eb2caff679e6ff"
|
||||
dest_md5="5d974b679ce52f358bf54f29b7a68669"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="136899ff4c68986c4cc62e296277b8ab"
|
||||
dest_md5="3d16ccd1874686296ee01de7097a3a6f"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="8a6c98eec519fd0b594b073b527e6e96"
|
||||
dest_md5="c9201153f0494a1eb4f9e353a0aafe9f"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="4608512057ad7b079766b3ddf107024a"
|
||||
dest_md5="8f5996bd2322644767582317aefaf44d"
|
||||
|
@ -1,3 +1,3 @@
|
||||
source_md5="47313fa4c47a9963fddd764e1ec6e4a8"
|
||||
dest_md5="2ded9e7f9060e2b530aab678b135fc5b"
|
||||
source_md5="236f053c1af2cb6dc8fb21dd8c49fee6"
|
||||
dest_md5="e8811c15e8ebcd4a71c62994dc9c6d5a"
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="005f64fb1ff8de71218d3545cc20441c"
|
||||
dest_md5="dcee8e0391b5bffbc76299f1b93a1100"
|
||||
|
@ -0,0 +1,3 @@
|
||||
source_md5="a177b00b79bd7412a6b0c6aa07f5020b"
|
||||
dest_md5="2bf8d94b2316e0d5b19647de6827b854"
|
||||
|
@ -20,7 +20,7 @@ compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
@ -30,5 +30,5 @@ process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
detect_3d=false
|
||||
svg/scale=1.0
|
||||
|
BIN
godot_ship/assets/backgrounds/PanelBG_Dark.png
Normal file
After Width: | Height: | Size: 152 B |
34
godot_ship/assets/backgrounds/PanelBG_Dark.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/PanelBG_Dark.png-664d38fd54271fbacb81205517c40701.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/backgrounds/PanelBG_Dark.png"
|
||||
dest_files=[ "res://.import/PanelBG_Dark.png-664d38fd54271fbacb81205517c40701.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
12
godot_ship/assets/backgrounds/PanelBG_Dark.tres
Normal file
@ -0,0 +1,12 @@
|
||||
[gd_resource type="StyleBoxTexture" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/backgrounds/PanelBG_Dark.png" type="Texture" id=1]
|
||||
|
||||
[resource]
|
||||
texture = ExtResource( 1 )
|
||||
region_rect = Rect2( 0, 0, 32, 32 )
|
||||
margin_left = 6.0
|
||||
margin_right = 6.0
|
||||
margin_top = 6.0
|
||||
margin_bottom = 6.0
|
||||
axis_stretch_horizontal = 1
|
BIN
godot_ship/assets/backgrounds/PanelBG_Light.png
Normal file
After Width: | Height: | Size: 152 B |
34
godot_ship/assets/backgrounds/PanelBG_Light.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/PanelBG_Light.png-25b7c30a8a8b20ed722b3b35c8a79d7b.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/backgrounds/PanelBG_Light.png"
|
||||
dest_files=[ "res://.import/PanelBG_Light.png-25b7c30a8a8b20ed722b3b35c8a79d7b.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
11
godot_ship/assets/backgrounds/PanelBG_Light.tres
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_resource type="StyleBoxTexture" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/backgrounds/PanelBG_Light.png" type="Texture" id=1]
|
||||
|
||||
[resource]
|
||||
texture = ExtResource( 1 )
|
||||
region_rect = Rect2( 0, 0, 32, 32 )
|
||||
margin_left = 6.0
|
||||
margin_right = 6.0
|
||||
margin_top = 6.0
|
||||
margin_bottom = 7.0
|
BIN
godot_ship/assets/backgrounds/splash_image.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
34
godot_ship/assets/backgrounds/splash_image.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/splash_image.png-6121c2cee560834f4965fe53dd93125b.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/backgrounds/splash_image.png"
|
||||
dest_files=[ "res://.import/splash_image.png-6121c2cee560834f4965fe53dd93125b.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/game/HitMissAtlas.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
43
godot_ship/assets/game/HitMissAtlas.png.import
Normal file
@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
<<<<<<< HEAD:godot_ship/assets/backgrounds/Background_Dark.png.import
|
||||
path="res://.import/Background_Dark.png-f04f9416ce96aca35dfd0f16063b0d5b.stex"
|
||||
=======
|
||||
path="res://.import/HitMissAtlas.png-47e352b9aa0deb2bd08f554355b13c14.stex"
|
||||
>>>>>>> game-logic:godot_ship/assets/game/HitMissAtlas.png.import
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
<<<<<<< HEAD:godot_ship/assets/backgrounds/Background_Dark.png.import
|
||||
source_file="res://assets/backgrounds/Background_Dark.png"
|
||||
dest_files=[ "res://.import/Background_Dark.png-f04f9416ce96aca35dfd0f16063b0d5b.stex" ]
|
||||
=======
|
||||
source_file="res://assets/game/HitMissAtlas.png"
|
||||
dest_files=[ "res://.import/HitMissAtlas.png-47e352b9aa0deb2bd08f554355b13c14.stex" ]
|
||||
>>>>>>> game-logic:godot_ship/assets/game/HitMissAtlas.png.import
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/game/TextureAtlas.png
Normal file
After Width: | Height: | Size: 19 KiB |
34
godot_ship/assets/game/TextureAtlas.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/TextureAtlas.png-f8378824db0f2b64b8339984d33f1a41.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/game/TextureAtlas.png"
|
||||
dest_files=[ "res://.import/TextureAtlas.png-f8378824db0f2b64b8339984d33f1a41.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/icons/Icon128.png
Normal file
After Width: | Height: | Size: 653 B |
43
godot_ship/assets/icons/Icon128.png.import
Normal file
@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
<<<<<<< HEAD:godot_ship/assets/game/2Ship.png.import
|
||||
path="res://.import/2Ship.png-f56f600f71c287a0900c4554ec6e9837.stex"
|
||||
=======
|
||||
path="res://.import/Icon128.png-8fa6a445b29adcafaf69c45a7d758b76.stex"
|
||||
>>>>>>> game-logic:godot_ship/assets/icons/Icon128.png.import
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
<<<<<<< HEAD:godot_ship/assets/game/2Ship.png.import
|
||||
source_file="res://assets/game/2Ship.png"
|
||||
dest_files=[ "res://.import/2Ship.png-f56f600f71c287a0900c4554ec6e9837.stex" ]
|
||||
=======
|
||||
source_file="res://assets/icons/Icon128.png"
|
||||
dest_files=[ "res://.import/Icon128.png-8fa6a445b29adcafaf69c45a7d758b76.stex" ]
|
||||
>>>>>>> game-logic:godot_ship/assets/icons/Icon128.png.import
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=false
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/icons/Icon16.png
Normal file
After Width: | Height: | Size: 256 B |
43
godot_ship/assets/icons/Icon16.png.import
Normal file
@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
<<<<<<< HEAD:godot_ship/assets/game/3ShipA.png.import
|
||||
path="res://.import/3ShipA.png-1fe0003af4adcd83b8c94b2b9d6e5b6d.stex"
|
||||
=======
|
||||
path="res://.import/Icon16.png-e916d7bb27530c71f994d2d2cacbe08b.stex"
|
||||
>>>>>>> game-logic:godot_ship/assets/icons/Icon16.png.import
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
<<<<<<< HEAD:godot_ship/assets/game/3ShipA.png.import
|
||||
source_file="res://assets/game/3ShipA.png"
|
||||
dest_files=[ "res://.import/3ShipA.png-1fe0003af4adcd83b8c94b2b9d6e5b6d.stex" ]
|
||||
=======
|
||||
source_file="res://assets/icons/Icon16.png"
|
||||
dest_files=[ "res://.import/Icon16.png-e916d7bb27530c71f994d2d2cacbe08b.stex" ]
|
||||
>>>>>>> game-logic:godot_ship/assets/icons/Icon16.png.import
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=false
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/icons/Icon256.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
43
godot_ship/assets/icons/Icon256.png.import
Normal file
@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
<<<<<<< HEAD:godot_ship/assets/game/3ShipB.png.import
|
||||
path="res://.import/3ShipB.png-28ed039caa6839d715648812af8f65e4.stex"
|
||||
=======
|
||||
path="res://.import/Icon256.png-5fcf1bd6fb6791cb3c432c7c88dff8da.stex"
|
||||
>>>>>>> game-logic:godot_ship/assets/icons/Icon256.png.import
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
<<<<<<< HEAD:godot_ship/assets/game/3ShipB.png.import
|
||||
source_file="res://assets/game/3ShipB.png"
|
||||
dest_files=[ "res://.import/3ShipB.png-28ed039caa6839d715648812af8f65e4.stex" ]
|
||||
=======
|
||||
source_file="res://assets/icons/Icon256.png"
|
||||
dest_files=[ "res://.import/Icon256.png-5fcf1bd6fb6791cb3c432c7c88dff8da.stex" ]
|
||||
>>>>>>> game-logic:godot_ship/assets/icons/Icon256.png.import
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=false
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=false
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/icons/Icon32.png
Normal file
After Width: | Height: | Size: 402 B |
34
godot_ship/assets/icons/Icon32.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/Icon32.png-ba330b5438b784e541f4d4c7ff1165f1.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/icons/Icon32.png"
|
||||
dest_files=[ "res://.import/Icon32.png-ba330b5438b784e541f4d4c7ff1165f1.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
BIN
godot_ship/assets/icons/Icon64.png
Normal file
After Width: | Height: | Size: 474 B |
34
godot_ship/assets/icons/Icon64.png.import
Normal file
@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/Icon64.png-688550eb2085ba14f76a5ffeb3504d87.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/icons/Icon64.png"
|
||||
dest_files=[ "res://.import/Icon64.png-688550eb2085ba14f76a5ffeb3504d87.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
64
godot_ship/dark_theme.tres
Normal file
@ -0,0 +1,64 @@
|
||||
[gd_resource type="Theme" load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://assets/font/Minecraft.ttf" type="DynamicFontData" id=1]
|
||||
[ext_resource path="res://assets/backgrounds/PanelBG_Dark.tres" type="StyleBox" id=2]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=1]
|
||||
bg_color = Color( 0.239216, 0.211765, 0.317647, 1 )
|
||||
corner_radius_top_left = 3
|
||||
corner_radius_top_right = 3
|
||||
corner_radius_bottom_right = 3
|
||||
corner_radius_bottom_left = 3
|
||||
shadow_size = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=2]
|
||||
bg_color = Color( 0.109804, 0.0862745, 0.172549, 1 )
|
||||
corner_radius_top_left = 3
|
||||
corner_radius_top_right = 3
|
||||
corner_radius_bottom_right = 3
|
||||
corner_radius_bottom_left = 3
|
||||
shadow_size = 3
|
||||
|
||||
[sub_resource type="DynamicFont" id=3]
|
||||
outline_size = 1
|
||||
outline_color = Color( 0, 0, 0, 1 )
|
||||
extra_spacing_top = 5
|
||||
extra_spacing_bottom = 3
|
||||
extra_spacing_char = 1
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[resource]
|
||||
default_font = SubResource( 3 )
|
||||
Button/colors/font_color = Color( 1, 1, 1, 1 )
|
||||
Button/colors/font_color_disabled = Color( 0.901961, 0.901961, 0.901961, 0.2 )
|
||||
Button/colors/font_color_hover = Color( 1, 1, 1, 1 )
|
||||
Button/colors/font_color_pressed = Color( 1, 1, 1, 1 )
|
||||
Button/constants/hseparation = 2
|
||||
Button/fonts/font = null
|
||||
Button/styles/disabled = null
|
||||
Button/styles/focus = null
|
||||
Button/styles/hover = SubResource( 1 )
|
||||
Button/styles/normal = SubResource( 2 )
|
||||
Button/styles/pressed = null
|
||||
Dialogs/constants/button_margin = 100
|
||||
Dialogs/constants/margin = 8
|
||||
Label/colors/font_color = Color( 1, 1, 1, 1 )
|
||||
Label/colors/font_color_shadow = Color( 0, 0, 0, 0.25098 )
|
||||
Label/colors/font_outline_modulate = Color( 0, 0, 0, 1 )
|
||||
Label/constants/line_spacing = 3
|
||||
Label/constants/shadow_as_outline = 0
|
||||
Label/constants/shadow_offset_x = 0
|
||||
Label/constants/shadow_offset_y = 2
|
||||
Label/fonts/font = null
|
||||
Label/styles/normal = null
|
||||
Panel/styles/panel = ExtResource( 2 )
|
||||
PanelContainer/styles/panel = ExtResource( 2 )
|
||||
WindowDialog/colors/title_color = Color( 0.152941, 0.152941, 0.152941, 1 )
|
||||
WindowDialog/constants/close_h_ofs = 18
|
||||
WindowDialog/constants/close_v_ofs = 18
|
||||
WindowDialog/constants/scaleborder_size = 4
|
||||
WindowDialog/constants/title_height = 20
|
||||
WindowDialog/fonts/title_font = null
|
||||
WindowDialog/icons/close = null
|
||||
WindowDialog/icons/close_highlight = null
|
||||
WindowDialog/styles/panel = null
|
@ -31,7 +31,7 @@ codesign/timestamp_server_url=""
|
||||
codesign/digest_algorithm=1
|
||||
codesign/description=""
|
||||
codesign/custom_options=PoolStringArray( )
|
||||
application/icon=""
|
||||
application/icon="res://icon.ico"
|
||||
application/file_version=""
|
||||
application/product_version=""
|
||||
application/company_name=""
|
||||
|
BIN
godot_ship/icon.icns
Normal file
BIN
godot_ship/icon.ico
Normal file
After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.0 KiB |
63
godot_ship/light_theme.tres
Normal file
@ -0,0 +1,63 @@
|
||||
[gd_resource type="Theme" load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://assets/font/Minecraft.ttf" type="DynamicFontData" id=1]
|
||||
[ext_resource path="res://assets/backgrounds/PanelBG_Light.tres" type="StyleBox" id=2]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=1]
|
||||
bg_color = Color( 1, 1, 1, 1 )
|
||||
corner_radius_top_left = 3
|
||||
corner_radius_top_right = 3
|
||||
corner_radius_bottom_right = 3
|
||||
corner_radius_bottom_left = 3
|
||||
shadow_size = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=2]
|
||||
bg_color = Color( 0.847059, 0.921569, 0.964706, 1 )
|
||||
corner_radius_top_left = 3
|
||||
corner_radius_top_right = 3
|
||||
corner_radius_bottom_right = 3
|
||||
corner_radius_bottom_left = 3
|
||||
shadow_size = 3
|
||||
|
||||
[sub_resource type="DynamicFont" id=3]
|
||||
outline_size = 1
|
||||
extra_spacing_top = 5
|
||||
extra_spacing_bottom = 3
|
||||
extra_spacing_char = 1
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[resource]
|
||||
default_font = SubResource( 3 )
|
||||
Button/colors/font_color = Color( 0.0784314, 0.0784314, 0.0784314, 1 )
|
||||
Button/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 )
|
||||
Button/colors/font_color_hover = Color( 0, 0, 0, 1 )
|
||||
Button/colors/font_color_pressed = Color( 0, 0, 0, 1 )
|
||||
Button/constants/hseparation = 2
|
||||
Button/fonts/font = null
|
||||
Button/styles/disabled = null
|
||||
Button/styles/focus = null
|
||||
Button/styles/hover = SubResource( 1 )
|
||||
Button/styles/normal = SubResource( 2 )
|
||||
Button/styles/pressed = null
|
||||
Dialogs/constants/button_margin = 100
|
||||
Dialogs/constants/margin = 8
|
||||
Label/colors/font_color = Color( 1, 1, 1, 1 )
|
||||
Label/colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
Label/colors/font_outline_modulate = Color( 0, 0, 0, 1 )
|
||||
Label/constants/line_spacing = 3
|
||||
Label/constants/shadow_as_outline = 0
|
||||
Label/constants/shadow_offset_x = 0
|
||||
Label/constants/shadow_offset_y = 2
|
||||
Label/fonts/font = null
|
||||
Label/styles/normal = null
|
||||
Panel/styles/panel = ExtResource( 2 )
|
||||
PanelContainer/styles/panel = ExtResource( 2 )
|
||||
WindowDialog/colors/title_color = Color( 0.152941, 0.152941, 0.152941, 1 )
|
||||
WindowDialog/constants/close_h_ofs = 18
|
||||
WindowDialog/constants/close_v_ofs = 18
|
||||
WindowDialog/constants/scaleborder_size = 4
|
||||
WindowDialog/constants/title_height = 20
|
||||
WindowDialog/fonts/title_font = null
|
||||
WindowDialog/icons/close = null
|
||||
WindowDialog/icons/close_highlight = null
|
||||
WindowDialog/styles/panel = null
|
@ -12,7 +12,10 @@ config_version=4
|
||||
|
||||
config/name="godot_ship"
|
||||
run/main_scene="res://scenes/Main.tscn"
|
||||
boot_splash/image="res://assets/backgrounds/splash_image.png"
|
||||
config/icon="res://icon.png"
|
||||
config/macos_native_icon="res://icon.icns"
|
||||
config/windows_native_icon="res://icon.ico"
|
||||
|
||||
[autoload]
|
||||
|
||||
@ -20,6 +23,7 @@ MessageBus="*res://script/Message Bus.gd"
|
||||
AudioBus="*res://script/audio controller/Audio Bus.gd"
|
||||
OptionsController="*res://script/options/OptionsController.gd"
|
||||
AudioController="*res://scenes/AudioController.tscn"
|
||||
Net="*res://script/network/Net.gd"
|
||||
|
||||
[display]
|
||||
|
||||
@ -30,6 +34,10 @@ window/per_pixel_transparency/allowed=true
|
||||
window/stretch/mode="viewport"
|
||||
window/stretch/aspect="keep"
|
||||
|
||||
[global]
|
||||
|
||||
verbose=false
|
||||
|
||||
[input]
|
||||
|
||||
ui_left={
|
||||
|
276
godot_ship/scenes/Credits.tscn
Normal file
@ -0,0 +1,276 @@
|
||||
[gd_scene load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://assets/font/Minecraft.ttf" type="DynamicFontData" id=1]
|
||||
[ext_resource path="res://script/credits/Credits.gd" type="Script" id=2]
|
||||
[ext_resource path="res://light_theme.tres" type="Theme" id=3]
|
||||
|
||||
[sub_resource type="DynamicFont" id=1]
|
||||
size = 44
|
||||
outline_size = 2
|
||||
outline_color = Color( 0, 0, 0, 1 )
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[sub_resource type="DynamicFont" id=2]
|
||||
outline_size = 1
|
||||
outline_color = Color( 0, 0, 0, 1 )
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[node name="Credits" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
theme = ExtResource( 3 )
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Back" type="Button" parent="."]
|
||||
margin_left = 16.0
|
||||
margin_top = 16.0
|
||||
margin_right = 83.0
|
||||
margin_bottom = 40.0
|
||||
focus_neighbour_left = NodePath(".")
|
||||
focus_neighbour_top = NodePath(".")
|
||||
focus_neighbour_right = NodePath("../Sliders/SFX Setting/SFX Slider")
|
||||
focus_neighbour_bottom = NodePath("../Buttons/Light")
|
||||
focus_next = NodePath("../Sliders/SFX Setting/SFX Slider")
|
||||
focus_previous = NodePath(".")
|
||||
text = "Back"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Credits Label" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
margin_left = -82.0
|
||||
margin_top = 49.0
|
||||
margin_right = 82.0
|
||||
margin_bottom = 93.0
|
||||
custom_fonts/font = SubResource( 1 )
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_offset_y = 8
|
||||
text = "Credits"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Developmental Team" type="Label" parent="."]
|
||||
margin_left = 64.0
|
||||
margin_top = 99.0
|
||||
margin_right = 576.0
|
||||
margin_bottom = 115.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_offset_y = 4
|
||||
text = "Developmental Team"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Programmer Titles" type="VBoxContainer" parent="."]
|
||||
margin_left = 64.0
|
||||
margin_top = 120.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 196.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Programmer" type="Label" parent="Programmer Titles"]
|
||||
margin_right = 248.0
|
||||
margin_bottom = 16.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Lead Programmer:"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Design" type="Label" parent="Programmer Titles"]
|
||||
margin_top = 20.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 36.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Project Design:"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Art" type="Label" parent="Programmer Titles"]
|
||||
margin_top = 40.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 56.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Artist:"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Sound" type="Label" parent="Programmer Titles"]
|
||||
margin_top = 60.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 76.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Sound Engineer:"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Programmer Name" type="VBoxContainer" parent="."]
|
||||
margin_left = 328.0
|
||||
margin_top = 120.0
|
||||
margin_right = 576.0
|
||||
margin_bottom = 196.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Programmer" type="Label" parent="Programmer Name"]
|
||||
margin_right = 248.0
|
||||
margin_bottom = 16.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "John Breaux"
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Design" type="Label" parent="Programmer Name"]
|
||||
margin_top = 20.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 36.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Chance Atkinson"
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Art" type="Label" parent="Programmer Name"]
|
||||
margin_top = 40.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 56.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Tommy Ngo"
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Sound" type="Label" parent="Programmer Name"]
|
||||
margin_top = 60.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 76.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Hien Pham"
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Assets" type="Label" parent="."]
|
||||
margin_left = 64.0
|
||||
margin_top = 203.0
|
||||
margin_right = 576.0
|
||||
margin_bottom = 219.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_offset_y = 4
|
||||
text = "Assets"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Assets Titles" type="VBoxContainer" parent="."]
|
||||
margin_left = 64.0
|
||||
margin_top = 224.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 288.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="BGM" type="Label" parent="Assets Titles"]
|
||||
margin_right = 248.0
|
||||
margin_bottom = 35.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Background Music:
|
||||
"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="SFX" type="Label" parent="Assets Titles"]
|
||||
margin_top = 39.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 55.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "SFX Sounds:"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Assets Credits" type="VBoxContainer" parent="."]
|
||||
margin_left = 328.0
|
||||
margin_top = 225.0
|
||||
margin_right = 576.0
|
||||
margin_bottom = 299.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Composer" type="Label" parent="Assets Credits"]
|
||||
margin_right = 248.0
|
||||
margin_bottom = 35.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "\"Captain Scurvy\" Kevin
|
||||
MacLeod (incompetech.com)"
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="SFX creators" type="Label" parent="Assets Credits"]
|
||||
margin_top = 39.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 74.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Creator Assets
|
||||
Free Sounds Library"
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Engine" type="Label" parent="."]
|
||||
margin_left = 64.0
|
||||
margin_top = 312.0
|
||||
margin_right = 576.0
|
||||
margin_bottom = 328.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Created Using Godot Engine"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[connection signal="pressed" from="Back" to="." method="_on_Back_pressed"]
|
13
godot_ship/scenes/Game/Board.tscn
Normal file
@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://script/game/Gameplay/Board.gd" type="Script" id=1]
|
||||
[ext_resource path="res://assets/game/board_blue.png" type="Texture" id=2]
|
||||
|
||||
[node name="Board" type="Node2D"]
|
||||
position = Vector2( 36, 36 )
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="TempBoardSprite" type="Sprite" parent="."]
|
||||
texture = ExtResource( 2 )
|
||||
centered = false
|
||||
offset = Vector2( -18, -18 )
|
@ -40,7 +40,7 @@ __meta__ = {
|
||||
pause_mode = 2
|
||||
margin_right = 83.0
|
||||
margin_bottom = 58.0
|
||||
dialog_text = "You can't fire outside the board"
|
||||
dialog_text = "You must select a valid position"
|
||||
|
||||
[connection signal="pressed" from="Fire" to="." method="_on_Fire_pressed"]
|
||||
[connection signal="confirmed" from="FireDialog" to="." method="_on_FireDialog_confirmed"]
|
||||
|
@ -16,20 +16,20 @@ anchor_left = 0.912
|
||||
anchor_top = 0.932
|
||||
anchor_right = 0.912
|
||||
anchor_bottom = 0.932
|
||||
margin_left = -3.68005
|
||||
margin_top = -4.52002
|
||||
margin_right = 49.3199
|
||||
margin_bottom = 15.48
|
||||
margin_left = -37.68
|
||||
margin_top = -329.52
|
||||
margin_right = 50.32
|
||||
margin_bottom = -305.52
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Forfeit" type="Button" parent="Buttons"]
|
||||
margin_right = 53.0
|
||||
margin_right = 88.0
|
||||
margin_bottom = 20.0
|
||||
text = "Forfeit"
|
||||
|
||||
[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."]
|
||||
[node name="Forfeit Confirmation" type="ConfirmationDialog" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
@ -46,5 +46,21 @@ __meta__ = {
|
||||
"_editor_description_": ""
|
||||
}
|
||||
|
||||
[node name="Button" type="Button" parent="."]
|
||||
visible = false
|
||||
margin_left = 6.4668
|
||||
margin_top = 6.14783
|
||||
margin_right = 43.4668
|
||||
margin_bottom = 26.1478
|
||||
text = "Win"
|
||||
|
||||
[node name="Connection Error" type="AcceptDialog" parent="."]
|
||||
margin_right = 230.0
|
||||
margin_bottom = 58.0
|
||||
window_title = "Connection Error"
|
||||
dialog_text = "Host disconnected unexpectedly."
|
||||
|
||||
[connection signal="pressed" from="Buttons/Forfeit" to="." method="_on_Forfeit_pressed"]
|
||||
[connection signal="confirmed" from="ConfirmationDialog" to="." method="_on_ConfirmationDialog_confirmed"]
|
||||
[connection signal="confirmed" from="Forfeit Confirmation" to="." method="_on_Forfeit_Confirmation_confirmed"]
|
||||
[connection signal="button_down" from="Button" to="." method="_on_Button_button_down"]
|
||||
[connection signal="confirmed" from="Connection Error" to="." method="_on_Connection_Error_confirmed"]
|
||||
|
@ -1,8 +1,12 @@
|
||||
[gd_scene format=2]
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://script/game/Gameplay/Player.gd" type="Script" id=1]
|
||||
|
||||
[node name="Player" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
[gd_scene load_steps=9 format=2]
|
||||
|
||||
[ext_resource path="res://assets/game/board_blue.png" type="Texture" id=1]
|
||||
[ext_resource path="res://dark_theme.tres" type="Theme" id=2]
|
||||
[ext_resource path="res://scenes/ships/3ShipB.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://scenes/ships/3shipA.tscn" type="PackedScene" id=5]
|
||||
[ext_resource path="res://scenes/ships/4Ship.tscn" type="PackedScene" id=6]
|
||||
@ -15,6 +16,7 @@ anchor_bottom = 0.890237
|
||||
margin_top = -0.445435
|
||||
margin_bottom = 39.5145
|
||||
mouse_filter = 2
|
||||
theme = ExtResource( 2 )
|
||||
script = ExtResource( 10 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
@ -70,20 +72,20 @@ contacts_reported = 1
|
||||
contact_monitor = true
|
||||
|
||||
[node name="Confirm Placement" type="Button" parent="."]
|
||||
margin_left = 409.0
|
||||
margin_top = 331.0
|
||||
margin_right = 543.0
|
||||
margin_bottom = 351.0
|
||||
margin_left = 417.0
|
||||
margin_top = 316.0
|
||||
margin_right = 608.0
|
||||
margin_bottom = 340.0
|
||||
text = "Confirm Placement"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Clear" type="Button" parent="."]
|
||||
margin_left = 353.0
|
||||
margin_top = 331.0
|
||||
margin_right = 406.0
|
||||
margin_bottom = 351.0
|
||||
margin_left = 348.0
|
||||
margin_top = 316.0
|
||||
margin_right = 408.0
|
||||
margin_bottom = 340.0
|
||||
text = "Clear"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
|
6
godot_ship/scenes/Game/Ship.tscn
Normal file
@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://script/game/Gameplay/Ship.gd" type="Script" id=1]
|
||||
|
||||
[node name="Ship" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
@ -10,26 +10,13 @@ font_data = ExtResource( 2 )
|
||||
[node name="Victory" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
margin_left = 118.32
|
||||
margin_top = 44.5109
|
||||
margin_right = 260.32
|
||||
margin_bottom = 84.5109
|
||||
size_flags_vertical = 0
|
||||
custom_fonts/font = SubResource( 1 )
|
||||
text = "Victory"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Button" type="Button" parent="."]
|
||||
[node name="exit_to_main" type="Button" parent="."]
|
||||
margin_left = 541.0
|
||||
margin_top = 327.85
|
||||
margin_right = 636.0
|
||||
@ -47,5 +34,20 @@ margin_right = 63.2202
|
||||
margin_bottom = 357.41
|
||||
text = "Restart"
|
||||
|
||||
[connection signal="pressed" from="Button" to="." method="_on_Button_pressed"]
|
||||
[node name="Victory" type="Label" parent="."]
|
||||
margin_left = 380.0
|
||||
margin_top = 44.5109
|
||||
margin_right = 260.32
|
||||
margin_bottom = 84.5109
|
||||
size_flags_vertical = 0
|
||||
custom_fonts/font = SubResource( 1 )
|
||||
text = "Victory"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[connection signal="button_down" from="exit_to_main" to="." method="_on_exit_to_main_button_down"]
|
||||
[connection signal="pressed" from="exit_to_main" to="." method="_on_Button_pressed"]
|
||||
[connection signal="button_down" from="Button2" to="." method="_on_restart_button_down"]
|
||||
|
180
godot_ship/scenes/Lobby.tscn
Normal file
@ -0,0 +1,180 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://script/network/Lobby.gd" type="Script" id=1]
|
||||
|
||||
[node name="Lobby" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Player List Container" type="PanelContainer" parent="."]
|
||||
anchor_left = 0.6
|
||||
anchor_top = 0.2
|
||||
anchor_right = 0.9
|
||||
anchor_bottom = 0.8
|
||||
size_flags_vertical = 4
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Align Vertically" type="VBoxContainer" parent="Player List Container"]
|
||||
margin_left = 7.0
|
||||
margin_top = 7.0
|
||||
margin_right = 185.0
|
||||
margin_bottom = 209.0
|
||||
grow_horizontal = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Players" type="Label" parent="Player List Container/Align Vertically"]
|
||||
margin_right = 178.0
|
||||
margin_bottom = 14.0
|
||||
text = "Players"
|
||||
align = 1
|
||||
|
||||
[node name="Player List" type="Label" parent="Player List Container/Align Vertically"]
|
||||
margin_top = 18.0
|
||||
margin_right = 178.0
|
||||
margin_bottom = 32.0
|
||||
align = 1
|
||||
|
||||
[node name="Lobby Options" type="VBoxContainer" parent="."]
|
||||
anchor_left = 0.2
|
||||
anchor_top = 0.2
|
||||
anchor_right = 0.2
|
||||
anchor_bottom = 0.2
|
||||
margin_right = 123.0
|
||||
margin_bottom = 84.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Lobby Text" type="Label" parent="Lobby Options"]
|
||||
margin_right = 123.0
|
||||
margin_bottom = 14.0
|
||||
text = "Multiplayer Lobby"
|
||||
align = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="IP Address" type="Label" parent="Lobby Options"]
|
||||
margin_top = 18.0
|
||||
margin_right = 123.0
|
||||
margin_bottom = 32.0
|
||||
align = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Host or Connect" type="VBoxContainer" parent="Lobby Options"]
|
||||
margin_top = 36.0
|
||||
margin_right = 123.0
|
||||
margin_bottom = 80.0
|
||||
|
||||
[node name="Host Button" type="Button" parent="Lobby Options/Host or Connect"]
|
||||
margin_right = 123.0
|
||||
margin_bottom = 20.0
|
||||
text = "Host Game"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Connect Button" type="Button" parent="Lobby Options/Host or Connect"]
|
||||
margin_top = 24.0
|
||||
margin_right = 123.0
|
||||
margin_bottom = 44.0
|
||||
text = "Connect to Game"
|
||||
|
||||
[node name="Connected Options" type="VBoxContainer" parent="Lobby Options"]
|
||||
visible = false
|
||||
margin_top = 36.0
|
||||
margin_right = 123.0
|
||||
margin_bottom = 56.0
|
||||
|
||||
[node name="Host Options" type="VBoxContainer" parent="Lobby Options/Connected Options"]
|
||||
visible = false
|
||||
margin_right = 123.0
|
||||
margin_bottom = 20.0
|
||||
|
||||
[node name="Start Game" type="Button" parent="Lobby Options/Connected Options/Host Options"]
|
||||
margin_right = 123.0
|
||||
margin_bottom = 20.0
|
||||
text = "Start Game"
|
||||
|
||||
[node name="Disconnect Button" type="Button" parent="Lobby Options/Connected Options"]
|
||||
margin_right = 123.0
|
||||
margin_bottom = 20.0
|
||||
text = "Disconnect"
|
||||
|
||||
[node name="Change Name Button" type="Button" parent="Lobby Options"]
|
||||
margin_top = 84.0
|
||||
margin_right = 123.0
|
||||
margin_bottom = 104.0
|
||||
text = "Change Name"
|
||||
|
||||
[node name="Exit Lobby Button" type="Button" parent="Lobby Options"]
|
||||
margin_top = 108.0
|
||||
margin_right = 123.0
|
||||
margin_bottom = 128.0
|
||||
text = "Exit Lobby"
|
||||
|
||||
[node name="Change Name" type="WindowDialog" parent="."]
|
||||
visible = true
|
||||
margin_left = 201.002
|
||||
margin_top = 516.255
|
||||
margin_right = 441.002
|
||||
margin_bottom = 562.255
|
||||
rect_min_size = Vector2( 240, 46 )
|
||||
window_title = "Change Name"
|
||||
|
||||
[node name="Name Entry" type="LineEdit" parent="Change Name"]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
margin_left = -112.0
|
||||
margin_top = 8.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 38.0
|
||||
grow_horizontal = 2
|
||||
rect_min_size = Vector2( 224, 30 )
|
||||
text = "127.0.0.1"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Connect to Game" type="WindowDialog" parent="."]
|
||||
visible = true
|
||||
margin_left = 201.136
|
||||
margin_top = 404.977
|
||||
margin_right = 441.136
|
||||
margin_bottom = 450.977
|
||||
rect_min_size = Vector2( 240, 46 )
|
||||
window_title = "Connect to Game"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="IP and Port Entry" type="LineEdit" parent="Connect to Game"]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
margin_left = -112.0
|
||||
margin_top = 8.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 38.0
|
||||
grow_horizontal = 2
|
||||
rect_min_size = Vector2( 224, 30 )
|
||||
text = "127.0.0.1"
|
||||
|
||||
[connection signal="pressed" from="Lobby Options/Host or Connect/Host Button" to="." method="_on_Host_Button_pressed"]
|
||||
[connection signal="pressed" from="Lobby Options/Host or Connect/Connect Button" to="." method="_on_Connect_Button_pressed"]
|
||||
[connection signal="pressed" from="Lobby Options/Connected Options/Host Options/Start Game" to="." method="_on_Start_Game_pressed"]
|
||||
[connection signal="pressed" from="Lobby Options/Connected Options/Disconnect Button" to="." method="_on_Disconnect_Button_pressed"]
|
||||
[connection signal="pressed" from="Lobby Options/Change Name Button" to="." method="_on_Change_Name_Button_pressed"]
|
||||
[connection signal="pressed" from="Lobby Options/Exit Lobby Button" to="." method="_on_Exit_Lobby_pressed"]
|
||||
[connection signal="text_entered" from="Change Name/Name Entry" to="." method="_on_Name_Entry_text_entered"]
|
||||
[connection signal="text_entered" from="Connect to Game/IP and Port Entry" to="." method="_on_IP_and_Port_Entry_text_entered"]
|
@ -1,24 +1,52 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://assets/font/Minecraft.ttf" type="DynamicFontData" id=1]
|
||||
[ext_resource path="res://script/options/Options.gd" type="Script" id=2]
|
||||
[ext_resource path="res://light_theme.tres" type="Theme" id=3]
|
||||
|
||||
[sub_resource type="DynamicFont" id=1]
|
||||
size = 44
|
||||
outline_size = 2
|
||||
outline_color = Color( 0, 0, 0, 1 )
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[sub_resource type="DynamicFont" id=2]
|
||||
outline_size = 1
|
||||
outline_color = Color( 0, 0, 0, 1 )
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[sub_resource type="DynamicFont" id=3]
|
||||
outline_size = 1
|
||||
outline_color = Color( 0, 0, 0, 1 )
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[sub_resource type="DynamicFont" id=4]
|
||||
outline_size = 1
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[node name="Options" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
theme = ExtResource( 3 )
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="MenuLabel" type="RichTextLabel" parent="."]
|
||||
margin_left = 294.0
|
||||
margin_top = 68.0
|
||||
margin_right = 346.0
|
||||
margin_bottom = 83.0
|
||||
custom_colors/default_color = Color( 0, 0, 0, 1 )
|
||||
[node name="Options Label" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
margin_left = -82.0
|
||||
margin_top = 49.0
|
||||
margin_right = 82.0
|
||||
margin_bottom = 93.0
|
||||
custom_fonts/font = SubResource( 1 )
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_offset_y = 8
|
||||
text = "Options"
|
||||
align = 2
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_lock_": true,
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
@ -36,11 +64,11 @@ __meta__ = {
|
||||
position = Vector2( 0, 8 )
|
||||
|
||||
[node name="Master Label" type="Label" parent="Sliders/Master Volume Setting"]
|
||||
margin_left = -0.140289
|
||||
margin_top = -8.0
|
||||
margin_right = 63.8597
|
||||
margin_bottom = 8.0
|
||||
custom_colors/font_color = Color( 0, 0, 0, 1 )
|
||||
margin_left = -8.14029
|
||||
margin_top = -14.0
|
||||
margin_right = 57.8597
|
||||
margin_bottom = 10.0
|
||||
custom_fonts/font = SubResource( 2 )
|
||||
text = "Volume:"
|
||||
align = 2
|
||||
valign = 1
|
||||
@ -50,9 +78,9 @@ __meta__ = {
|
||||
|
||||
[node name="Master Slider" type="HSlider" parent="Sliders/Master Volume Setting"]
|
||||
margin_left = 64.0
|
||||
margin_top = -8.0
|
||||
margin_top = -10.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 8.0
|
||||
margin_bottom = 6.0
|
||||
focus_neighbour_left = NodePath("../../../Back")
|
||||
focus_neighbour_top = NodePath("../../../Back")
|
||||
focus_neighbour_bottom = NodePath("../../Volume Setting/Volume Slider")
|
||||
@ -61,6 +89,7 @@ focus_previous = NodePath("../../../Back")
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
tick_count = 10
|
||||
ticks_on_borders = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
@ -69,10 +98,11 @@ __meta__ = {
|
||||
position = Vector2( 0, 33 )
|
||||
|
||||
[node name="Music Label" type="Label" parent="Sliders/Music Volume Setting"]
|
||||
margin_top = -8.0
|
||||
margin_right = 64.0
|
||||
margin_bottom = 8.0
|
||||
custom_colors/font_color = Color( 0, 0, 0, 1 )
|
||||
margin_left = -6.0
|
||||
margin_top = -13.0
|
||||
margin_right = 58.0
|
||||
margin_bottom = 11.0
|
||||
custom_fonts/font = SubResource( 3 )
|
||||
text = "Music:"
|
||||
align = 2
|
||||
valign = 1
|
||||
@ -81,10 +111,10 @@ __meta__ = {
|
||||
}
|
||||
|
||||
[node name="Music Slider" type="HSlider" parent="Sliders/Music Volume Setting"]
|
||||
margin_left = 64.0
|
||||
margin_top = -8.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 8.0
|
||||
margin_left = 64.25
|
||||
margin_top = -9.0
|
||||
margin_right = 208.25
|
||||
margin_bottom = 7.0
|
||||
focus_neighbour_top = NodePath("../../SFX Setting/SFX Slider")
|
||||
focus_neighbour_bottom = NodePath("../../../Buttons/Dark")
|
||||
focus_next = NodePath("../../../Buttons/Dark")
|
||||
@ -92,6 +122,7 @@ focus_previous = NodePath("../../SFX Setting/SFX Slider")
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
tick_count = 10
|
||||
ticks_on_borders = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
@ -99,10 +130,11 @@ __meta__ = {
|
||||
[node name="SFX Volume Setting" type="Node2D" parent="Sliders"]
|
||||
|
||||
[node name="SFX Label" type="Label" parent="Sliders/SFX Volume Setting"]
|
||||
margin_top = 48.0
|
||||
margin_right = 64.0
|
||||
margin_bottom = 64.0
|
||||
custom_colors/font_color = Color( 0, 0, 0, 1 )
|
||||
margin_left = -6.0
|
||||
margin_top = 46.0
|
||||
margin_right = 58.0
|
||||
margin_bottom = 70.0
|
||||
custom_fonts/font = SubResource( 4 )
|
||||
text = "SFX:"
|
||||
align = 2
|
||||
valign = 1
|
||||
@ -112,23 +144,27 @@ __meta__ = {
|
||||
|
||||
[node name="SFX Slider" type="HSlider" parent="Sliders/SFX Volume Setting"]
|
||||
margin_left = 64.0
|
||||
margin_top = 48.0
|
||||
margin_top = 50.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 64.0
|
||||
margin_bottom = 66.0
|
||||
max_value = 1.0
|
||||
step = 0.05
|
||||
tick_count = 10
|
||||
ticks_on_borders = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Buttons" type="HBoxContainer" parent="."]
|
||||
margin_left = 216.0
|
||||
margin_top = 200.0
|
||||
margin_right = 424.0
|
||||
margin_bottom = 224.0
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.498036
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.498036
|
||||
margin_left = -102.0
|
||||
margin_top = 30.7071
|
||||
margin_right = 106.0
|
||||
margin_bottom = 54.7071
|
||||
__meta__ = {
|
||||
"_edit_lock_": true,
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
@ -157,8 +193,8 @@ text = "Dark Mode"
|
||||
[node name="Back" type="Button" parent="."]
|
||||
margin_left = 16.0
|
||||
margin_top = 16.0
|
||||
margin_right = 28.0
|
||||
margin_bottom = 36.0
|
||||
margin_right = 83.0
|
||||
margin_bottom = 40.0
|
||||
focus_neighbour_left = NodePath(".")
|
||||
focus_neighbour_top = NodePath(".")
|
||||
focus_neighbour_right = NodePath("../Sliders/SFX Setting/SFX Slider")
|
||||
@ -167,7 +203,6 @@ focus_next = NodePath("../Sliders/SFX Setting/SFX Slider")
|
||||
focus_previous = NodePath(".")
|
||||
text = "Back"
|
||||
__meta__ = {
|
||||
"_edit_lock_": true,
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://light_theme.tres" type="Theme" id=1]
|
||||
[ext_resource path="res://script/title screen/Title Screen.gd" type="Script" id=2]
|
||||
[ext_resource path="res://assets/font/Minecraft.ttf" type="DynamicFontData" id=3]
|
||||
|
||||
@ -12,6 +13,7 @@ font_data = ExtResource( 3 )
|
||||
[node name="Title Node" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
theme = ExtResource( 1 )
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
@ -22,36 +24,42 @@ anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -68.077
|
||||
margin_top = 10.0
|
||||
margin_right = 68.077
|
||||
margin_bottom = 102.0
|
||||
margin_left = -80.0
|
||||
margin_top = 11.0
|
||||
margin_right = 80.0
|
||||
margin_bottom = 119.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Singleplayer" type="Button" parent="VBoxContainer"]
|
||||
margin_right = 136.0
|
||||
margin_bottom = 20.0
|
||||
visible = false
|
||||
margin_right = 160.0
|
||||
margin_bottom = 24.0
|
||||
focus_neighbour_top = NodePath("../Quit")
|
||||
text = "Single Player"
|
||||
|
||||
[node name="Multiplayer" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 24.0
|
||||
margin_right = 136.0
|
||||
margin_bottom = 44.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 24.0
|
||||
text = "Multiplayer"
|
||||
|
||||
[node name="Options" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 48.0
|
||||
margin_right = 136.0
|
||||
margin_bottom = 68.0
|
||||
margin_top = 28.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 52.0
|
||||
text = "Options"
|
||||
|
||||
[node name="Credits" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 56.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 80.0
|
||||
text = "Credits"
|
||||
|
||||
[node name="Quit" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 72.0
|
||||
margin_right = 136.0
|
||||
margin_bottom = 92.0
|
||||
margin_top = 84.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 108.0
|
||||
focus_neighbour_bottom = NodePath("../Singleplayer")
|
||||
text = "Quit"
|
||||
|
||||
@ -61,11 +69,12 @@ anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -157.0
|
||||
margin_top = -50.0
|
||||
margin_top = -59.0
|
||||
margin_right = 157.0
|
||||
margin_bottom = -6.0
|
||||
margin_bottom = -15.0
|
||||
size_flags_stretch_ratio = 0.0
|
||||
custom_fonts/font = SubResource( 1 )
|
||||
custom_colors/font_color = Color( 1, 1, 1, 1 )
|
||||
custom_colors/font_outline_modulate = Color( 0, 0, 0, 1 )
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
custom_constants/shadow_offset_x = 0
|
||||
@ -80,4 +89,5 @@ __meta__ = {
|
||||
[connection signal="pressed" from="VBoxContainer/Singleplayer" to="." method="_on_Singleplayer_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/Multiplayer" to="." method="_on_Multiplayer_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/Options" to="." method="_on_Options_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/Credits" to="." method="_on_Credits_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/Quit" to="." method="_on_Quit_pressed"]
|
||||
|
@ -3,12 +3,16 @@ extends Control
|
||||
# Scenes
|
||||
onready var Title_Screen = preload("res://scenes/Title Screen.tscn")
|
||||
onready var Game = preload("res://scenes/Game/Game.tscn" )
|
||||
onready var Lobby = preload("res://scenes/Lobby.tscn" )
|
||||
onready var Options = preload("res://scenes/Options.tscn" )
|
||||
onready var Credits = preload("res://scenes/Credits.tscn" )
|
||||
onready var Debug_Menu = preload("res://scenes/Debug Menu.tscn" )
|
||||
|
||||
# Themes
|
||||
var lightmode = preload("res://assets/backgrounds/Background_Light.png");
|
||||
var darkmode = preload("res://assets/backgrounds/Background_Dark.png");
|
||||
var lightmode = preload("res://assets/backgrounds/Background_Light.png")
|
||||
var darkmode = preload("res://assets/backgrounds/Background_Dark.png")
|
||||
var light_theme = load("res://light_theme.tres")
|
||||
var dark_theme = load("res://dark_theme.tres")
|
||||
|
||||
#flags
|
||||
var power_saving = true
|
||||
@ -56,19 +60,22 @@ func _on_scene_start(scene):
|
||||
var instance
|
||||
#print ("_on_scene_start(",scene,")")
|
||||
match scene:
|
||||
"Singleplayer":
|
||||
"Gameplay":
|
||||
instance = Game.instance()
|
||||
add_child (instance)
|
||||
return true
|
||||
"Multiplayer":
|
||||
instance = Game.instance()
|
||||
instance.is_multiplayer = true
|
||||
instance = Lobby.instance()
|
||||
add_child (instance)
|
||||
return true
|
||||
"Options":
|
||||
instance = Options.instance()
|
||||
add_child (instance)
|
||||
return true
|
||||
"Credits":
|
||||
instance = Credits.instance()
|
||||
add_child (instance)
|
||||
return true
|
||||
"Title":
|
||||
instance = Title_Screen.instance()
|
||||
add_child (instance)
|
||||
@ -104,5 +111,7 @@ func _on_title_request():
|
||||
func _on_change_theme(theme):
|
||||
if theme == "light":
|
||||
get_node("Background").set_texture(lightmode)
|
||||
self.set_theme(light_theme)
|
||||
elif theme == "dark":
|
||||
get_node("Background").set_texture(darkmode)
|
||||
self.set_theme(dark_theme)
|
||||
|
21
godot_ship/script/credits/Credits.gd
Normal file
@ -0,0 +1,21 @@
|
||||
extends Control
|
||||
|
||||
var light_theme = load("res://light_theme.tres")
|
||||
var dark_theme = load("res://dark_theme.tres")
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
var _errno = 0;
|
||||
_errno += OptionsController.connect("change_theme", self, "_on_change_theme")
|
||||
_on_change_theme(OptionsController.get_theme())
|
||||
|
||||
func _on_Back_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
queue_free()
|
||||
pass # Replace with function body.
|
||||
|
||||
func _on_change_theme(theme):
|
||||
if theme == "light":
|
||||
self.set_theme(light_theme)
|
||||
elif theme == "dark":
|
||||
self.set_theme(dark_theme)
|
@ -11,6 +11,9 @@ var menu_velocity = 4
|
||||
var history : Array = []
|
||||
var history_pos = 0
|
||||
|
||||
# Controls whether to print to the screen
|
||||
var echo = true
|
||||
|
||||
onready var expression = Expression.new()
|
||||
|
||||
# helptext: args list and help blurb accessed by function name
|
||||
@ -38,6 +41,8 @@ var helptext = {
|
||||
"command_getprop": [" prop", "Get the value of property prop\n" ],
|
||||
"command_setprop": [" prop value", "Set the property prop to value.\n" ],
|
||||
|
||||
"command_script": [" path", "Load and execute a script at user://scripts/<name>\n" ],
|
||||
"command_echo": [" on/off", "Controls whether lines should be printed to the screen\n" ],
|
||||
"command_restart": ["", "Kill the current scene tree and plant a new Root.\n" ],
|
||||
"command_exit": ["", "Quits the program.\n" ],
|
||||
|
||||
@ -70,10 +75,12 @@ var commands = {
|
||||
["getprop","get", "g"]: "command_getprop",
|
||||
["setprop","set", "s"]: "command_setprop",
|
||||
|
||||
["script", "sh"]: "command_script",
|
||||
["@echo"]: "command_echo",
|
||||
["restart", "killall"]: "command_restart",
|
||||
["exit", "quit"]: "command_exit",
|
||||
|
||||
[""]: "command_empty"
|
||||
["", "#"]: "command_empty"
|
||||
}
|
||||
|
||||
#List of all of Godot's builtin types
|
||||
@ -151,23 +158,29 @@ func _input(event):
|
||||
#traverse history down
|
||||
history_move(+1)
|
||||
|
||||
# Signal-processing functions:
|
||||
# Command-processing functions:
|
||||
# _on_LineEdit_text_entered: process incoming text line
|
||||
# params: line: Line of text entered by user
|
||||
# returns: void
|
||||
func _on_LineEdit_text_entered(line):
|
||||
if line != "":
|
||||
history_append(line)
|
||||
emit_signal("clear_in")
|
||||
debug_print_line(line + "\n")
|
||||
var command = line.split(' ', true, 1)
|
||||
var command_func = parse(command[0])
|
||||
if command_func:
|
||||
call(command_func, command)
|
||||
if execute_command(command):
|
||||
history_append(line)
|
||||
else:
|
||||
debug_print_line("dbg: command not found: " + command[0] + "\n")
|
||||
debug_print_line("> ")
|
||||
|
||||
# execute_command: execute a line of text as a command
|
||||
# params: command: partially tokenized PoolStringArray ["command_alias", "parameters ..."]
|
||||
# returns: name of executed function, or null if nothing executed
|
||||
func execute_command(command):
|
||||
var command_func = parse(command[0])
|
||||
if command_func:
|
||||
call(command_func, command)
|
||||
return command_func
|
||||
|
||||
# History_related helper functions:
|
||||
# history_append: add a line of text to the history
|
||||
# params: text: line of text (unparsed command) to add to history
|
||||
@ -195,7 +208,8 @@ func history_move(rel_pos):
|
||||
# params: string: Text string to print
|
||||
# returns: void
|
||||
func debug_print_line(string):
|
||||
emit_signal("print_text", string.c_unescape())
|
||||
if echo:
|
||||
emit_signal("print_text", string.c_unescape())
|
||||
|
||||
# get_pwn: get the present working node if valid, otherwise cd to root
|
||||
func get_pwn():
|
||||
@ -280,7 +294,7 @@ func string_to_variant(string, type):
|
||||
res = null
|
||||
TYPE_BOOL:
|
||||
match string.to_lower():
|
||||
"true", "1", "ok":
|
||||
"true", "1", "ok", "on":
|
||||
res = true
|
||||
_:
|
||||
res = false
|
||||
@ -369,7 +383,7 @@ func command_restart (_command):
|
||||
# print: prints a message to the in-game debug console
|
||||
func command_print(command):
|
||||
if command.size() > 1:
|
||||
debug_print_line(command[1] + "\n")
|
||||
debug_print_line(command[1])
|
||||
else:
|
||||
debug_print_line("\n")
|
||||
|
||||
@ -519,6 +533,46 @@ func command_perf(command):
|
||||
else:
|
||||
debug_print_line(get_usage(command[0]))
|
||||
|
||||
# script: run a script from user://scripts/
|
||||
func command_script(command):
|
||||
var script = []
|
||||
if (command.size() > 1):
|
||||
var path = "user://scripts/" + command[1]
|
||||
var f = File.new()
|
||||
var err = f.open(path, File.READ)
|
||||
if err == OK:
|
||||
# Read the file
|
||||
while not f.eof_reached():
|
||||
script.push_back(f.get_line())
|
||||
f.close()
|
||||
# Save state and turn off echo
|
||||
var state = {"echo": echo,
|
||||
"pwn": present_working_node,
|
||||
"history_pos": history_pos,
|
||||
"history": history,
|
||||
"expression": expression}
|
||||
echo = false
|
||||
# Execute the script
|
||||
for cmd in script:
|
||||
cmd = cmd.split(' ', true, 1)
|
||||
execute_command(cmd)
|
||||
# Restore state
|
||||
echo = state["echo"]
|
||||
present_working_node = state["pwn"]
|
||||
history_pos = state["history_pos"]
|
||||
history = state["history"]
|
||||
expression = state["expression"]
|
||||
else:
|
||||
debug_print_line("File not found: " + command[1] + "\n")
|
||||
else:
|
||||
debug_print_line(get_usage(command[0]))
|
||||
|
||||
func command_echo(command):
|
||||
if command.size() > 1:
|
||||
echo = string_to_variant(command[1], TYPE_BOOL)
|
||||
else:
|
||||
debug_print_line(get_usage(command[0]))
|
||||
|
||||
func perf(attribute):
|
||||
if attribute.is_valid_integer():
|
||||
return Performance.get_monitor(int(attribute))
|
||||
|
@ -1,54 +1,107 @@
|
||||
extends Node
|
||||
extends Node2D
|
||||
|
||||
# Path to Ship class, for instantiating new Ships in code
|
||||
onready var Ship = load("res://script/game/Gameplay/Ship.gd")
|
||||
var Ship = preload("res://scenes/Game/Ship.tscn")
|
||||
|
||||
var bottom_board # Player board
|
||||
var top_board # Opponent board
|
||||
var ships # list of Ships
|
||||
var ship_count # number of 'active' (un-sunk) ships
|
||||
# Consts and enums
|
||||
const NO_SHIP = -1
|
||||
enum {MISS = -1, READY = 0, HIT = 1, SUNK = 2, LOST = 3}
|
||||
|
||||
# a board is square. This is its side lengths
|
||||
var bottom_board:Array # Player board
|
||||
var top_board:Array # Opponent board
|
||||
var ships = [] # list of Ships
|
||||
var ship_data = [] # Data used to generate ships
|
||||
var ship_count = 0 # number of 'active' (un-sunk) ships
|
||||
|
||||
# a board is square. This is its side length
|
||||
var board_len = 10
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
ships = []
|
||||
ship_count = 0
|
||||
# The top board must be marked by textures. This is where they are stored:
|
||||
var sprites = []
|
||||
|
||||
# Here are where the hit/miss textures are loaded, so that they may be used:
|
||||
var hit_texture = preload("res://assets/game/Hit.png")
|
||||
var miss_texture = preload("res://assets/game/Miss.png")
|
||||
|
||||
|
||||
# TODO: What state?
|
||||
func getState():
|
||||
func get_state():
|
||||
pass
|
||||
|
||||
# Evaluate being hit by an opponent
|
||||
# pos: board position opponent fired at
|
||||
func hit(pos):
|
||||
var res = MISS
|
||||
# Get the ship-metadata for that location
|
||||
var ship = bottom_board[pos.x][pos.y]
|
||||
# If the ship's already been hit here, don't bother beating it again
|
||||
if ship[1] != READY:
|
||||
return ship[1]
|
||||
if ship[0] > NO_SHIP:
|
||||
# Decide whether HIT or SUNK
|
||||
res = ships[ship[0]].hit(pos)
|
||||
# If ship sunk,
|
||||
if res == SUNK:
|
||||
# remove it from the count
|
||||
ship_count -= 1
|
||||
# If we have no more ships left, we LOST
|
||||
if ship_count == 0:
|
||||
res = LOST
|
||||
# Record the result on the board, and return it
|
||||
ship[1] = res
|
||||
return res
|
||||
|
||||
# fire: Store the results of firing on an opponent
|
||||
# pos: board position fired on
|
||||
# res: result of firing on the opponent
|
||||
func fire(pos, res):
|
||||
if top_board[pos.x][pos.y] == READY:
|
||||
top_board[pos.x][pos.y] = res
|
||||
return res
|
||||
else:
|
||||
return top_board[pos.x][pos.y]
|
||||
|
||||
# Place a ship on the board at board-space coordinates
|
||||
func placeShip(in_position, in_size, in_orientation):
|
||||
ships.append(Ship.new(in_position, in_size, in_orientation))
|
||||
pass
|
||||
func place_ship(in_position, in_size, in_orientation, in_variant = 0):
|
||||
# Save the ship data
|
||||
ship_data.append([in_position, in_size, in_orientation])
|
||||
# Create a new Ship, and give it some data
|
||||
var ship = Ship.instance()
|
||||
ship._init(in_position, in_size, in_orientation, in_variant)
|
||||
# Mark the ship on the board
|
||||
for pos in ship.get_extent():
|
||||
bottom_board[pos.x][pos.y] = [ships.size(), READY]
|
||||
# Add the ship to the ships array, and keep count
|
||||
ships.append(ship)
|
||||
ship_count += 1
|
||||
# Add the ship to the scene tree
|
||||
add_child(ship)
|
||||
|
||||
func getBottomBoard():
|
||||
pass
|
||||
|
||||
func getShipCount():
|
||||
func query_bottom(pos):
|
||||
return bottom_board[pos.x][pos.y]
|
||||
|
||||
func query_top(pos):
|
||||
return top_board[pos.x][pos.y]
|
||||
|
||||
# Get the number of live ships
|
||||
func get_ship_count():
|
||||
return ship_count
|
||||
|
||||
# _init: Constructor
|
||||
func _init():
|
||||
# Initialize the bottom_board to a 10x10 array
|
||||
for _row in range(board_len):
|
||||
# Initialize the bottom_board to a len*len array
|
||||
for x in board_len:
|
||||
bottom_board.append([])
|
||||
for column in bottom_board:
|
||||
column.resize(10)
|
||||
# Initialize the top_board to a 10x10 array
|
||||
for _row in range(board_len):
|
||||
for y in board_len:
|
||||
bottom_board[x].append([NO_SHIP, READY])
|
||||
# Initialize the top_board to a len*len array
|
||||
for x in board_len:
|
||||
top_board.append([])
|
||||
for column in top_board:
|
||||
column.resize(board_len)
|
||||
for y in board_len:
|
||||
top_board[x].append(READY)
|
||||
|
||||
# worldspace_to_boardspace: convert a Vector2 in world-space to board-space
|
||||
func worldspace_to_boardspace(coordinate:Vector2):
|
||||
# subtract 36 to get the position relative to (0,0) on the board, and integer divide by 32
|
||||
return Vector2(int(coordinate.x - 36) >> 5, int(coordinate.y-36) >> 5)
|
||||
|
||||
# Coordinates of ship's center. Ship extends [-(size-1 >> 1), (size/2 >> 1)]
|
||||
func shiptoboard(ship:Ship):
|
||||
for i in range (ship.)
|
||||
pass
|
||||
|
@ -1,30 +1,53 @@
|
||||
extends Control
|
||||
|
||||
# Signal to pass the fire location back to parent
|
||||
signal fire_at
|
||||
|
||||
var atlas = preload("res://assets/game/HitMissAtlas.png")
|
||||
var sprites = []
|
||||
var hits
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
print("Fire: _ready()")
|
||||
for x in 10:
|
||||
for y in 10:
|
||||
texture(Vector2(x,y))
|
||||
pass # Replace with function body.
|
||||
|
||||
# Signal to pass the fire location back to yet-unknown nodes
|
||||
signal fire_at
|
||||
|
||||
|
||||
func _on_Fire_pressed():
|
||||
var crosshair = get_node("Crosshair")
|
||||
# hides crosshair
|
||||
crosshair.visible = false
|
||||
if crosshair.validate_position(crosshair.position) == true:
|
||||
# Check if the crosshair is in a valid position
|
||||
if crosshair.validate_position(crosshair.position):
|
||||
var crosshair_pos = crosshair.world_to_board_space(crosshair.position)
|
||||
# fires at position
|
||||
print("Fire at position: ", crosshair_pos)
|
||||
emit_signal("fire_at", crosshair_pos)
|
||||
# Close the Firing menu
|
||||
queue_free()
|
||||
else:
|
||||
#if invalid position popup appears
|
||||
var dialog = get_node("FireDialog")
|
||||
dialog.popup_centered()
|
||||
pass # Replace with function body.
|
||||
if(hits[crosshair_pos.x][crosshair_pos.y] == 0):
|
||||
# fires at position
|
||||
emit_signal("fire_at", crosshair_pos)
|
||||
return
|
||||
#if invalid position popup appears
|
||||
var dialog = get_node("FireDialog")
|
||||
dialog.popup_centered()
|
||||
|
||||
func _on_FireDialog_confirmed():
|
||||
get_node("Crosshair").visible = true
|
||||
pass # Replace with function body.
|
||||
|
||||
const OFFSET = Vector2(18, 18)
|
||||
|
||||
func texture(index):
|
||||
if(hits[index.x][index.y] != 0):
|
||||
var textureSize = 32
|
||||
# It's okay to create a new texture every time, as resources are refcounted
|
||||
var t = AtlasTexture.new()
|
||||
t.set_atlas(atlas)
|
||||
t.margin = Rect2(0, 0, 0, 0)
|
||||
t.region = Rect2(
|
||||
0 if(hits[index.x][index.y] < 0) else textureSize,
|
||||
0,
|
||||
textureSize,
|
||||
textureSize
|
||||
)
|
||||
# Create a new Sprite to house the texture, or use the existing sprite
|
||||
var sprite = Sprite.new()
|
||||
sprite.texture = t
|
||||
sprite.position = Vector2(index.x, index.y) * textureSize + OFFSET
|
||||
$board_blue.add_child(sprite)
|
||||
|
@ -1,75 +1,204 @@
|
||||
extends Node
|
||||
extends Control
|
||||
|
||||
class ShipData:
|
||||
var Coor: Vector2
|
||||
var Length: int
|
||||
var Orientation: bool #vertical is true, (Trueship = vertical) (Falseship = horizontal)
|
||||
# warning-ignore-all:unused_signal
|
||||
# warning-ignore-all:return_value_discarded
|
||||
|
||||
# Preloaded assets, to be used later
|
||||
# TODO: Move Setup into the Player. It's just here, for now, so that it can be tested and the game doesn't appear broken
|
||||
onready var Setup = preload("res://scenes/Game/Setup.tscn")
|
||||
# TODO: Move Fire into the Player. See above.
|
||||
onready var Fire = preload("res://scenes/Game/Fire.tscn")
|
||||
enum {MISS = -1, READY = 0, HIT = 1, SUNK = 2, LOST = 3}
|
||||
|
||||
# Signals
|
||||
signal fire # fire(position)
|
||||
signal hit # hit (state): see Miss/Ready/Hit/Sunk enum in Board.gd)
|
||||
signal miss
|
||||
signal loss
|
||||
signal forfeit
|
||||
|
||||
signal game_ready
|
||||
|
||||
# Path to Player class, for instantiating new Players in code
|
||||
onready var Player = preload("res://scenes/Game/Player.tscn")
|
||||
var Player = preload("res://scenes/Game/Player.tscn")
|
||||
|
||||
onready var Victory = preload("res://scenes/Game/Victory.tscn")
|
||||
var Victory = preload("res://scenes/Game/Victory.tscn")
|
||||
|
||||
|
||||
# Array of instances of the Player class; stores the Players
|
||||
var players # = player1, player2, ...
|
||||
# turn counter
|
||||
var turn = 0
|
||||
# Variable transporting hit state between players
|
||||
var hit = false
|
||||
# Variable tracking whether a game is multiplayer (so that the correct Player type can be spawned)
|
||||
# TODO: Multiplayer
|
||||
var is_multiplayer = false
|
||||
var player
|
||||
var players_ready = []
|
||||
|
||||
# Every game is a multiplayer game, even the ones that aren't.
|
||||
# We're taking the Minecraft approach, baby
|
||||
var network_id
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
# TODO: Move Setup into the Player.
|
||||
var setup = Setup.instance()
|
||||
setup.connect("game_ready", self, "game_setup")
|
||||
add_child(setup)
|
||||
|
||||
get_node("ConfirmationDialog").get_ok().text = "Yes"
|
||||
get_node("ConfirmationDialog").get_cancel().text = "No"
|
||||
|
||||
# TODO: Move Setup into the Player.
|
||||
func game_setup(_ships):
|
||||
print_debug("Congrats! Setup complete.")
|
||||
# TODO: Move Fire into the Player.
|
||||
add_child(Fire.instance())
|
||||
get_node("Forfeit Confirmation").get_ok().text = "Yes"
|
||||
get_node("Forfeit Confirmation").get_cancel().text = "No"
|
||||
get_node("Forfeit Confirmation").get_ok().rect_min_size.x = 100
|
||||
get_node("Forfeit Confirmation").get_cancel().rect_min_size.x = 100
|
||||
|
||||
if Net.connected:
|
||||
Net.connect("disconnected", self, "connection_error")
|
||||
Net.connect("incoming", self, "_on_Net_incoming")
|
||||
pass
|
||||
game_setup()
|
||||
|
||||
# Function used to keep track of which players are ready
|
||||
func player_ready(sender):
|
||||
print("player_ready(%s), %d" % [sender, players_ready.size()])
|
||||
players_ready.append(sender)
|
||||
if (players_ready.size() >= Net.peer_info.size()):
|
||||
emit_signal("game_ready")
|
||||
|
||||
# Member functions:
|
||||
# game_start: starts the game
|
||||
func game_start():
|
||||
# game_setup: starts the game
|
||||
sync func game_setup():
|
||||
# If there's no server connected, create one
|
||||
if not Net.connected:
|
||||
# TODO: Create a fake peer who we can automate, for single-player mode
|
||||
Net.start_host()
|
||||
network_id = Net.get_network_id()
|
||||
player = Player.instance()
|
||||
player.connect("player_ready", self, "_on_player_ready")
|
||||
add_child(player)
|
||||
player.set_up_begin()
|
||||
yield(self, "game_ready")
|
||||
if Net.hosting:
|
||||
state_fire()
|
||||
|
||||
# state_fire: The firing state. Displays fire menu, then notifies opponent.
|
||||
remote func state_fire():
|
||||
var pos = player.turn_start()
|
||||
if pos is GDScriptFunctionState:
|
||||
pos = yield(pos, "completed")
|
||||
rpc("state_check", pos)
|
||||
|
||||
# state_check: The checking state. Branches out to the other states.
|
||||
# pos: Position which the opponent is trying to fire upon
|
||||
remote func state_check(pos):
|
||||
var res = player.hit(pos)
|
||||
# Tell the opponent
|
||||
Net.send(0, ["hit", res], Net.REPLY)
|
||||
rpc("play_hit_sound", res)
|
||||
match res:
|
||||
LOST:
|
||||
# the other player wins
|
||||
rpc("state_win", player.board.ship_data)
|
||||
victory_screen(null, false)
|
||||
SUNK, HIT:
|
||||
# Hit
|
||||
rpc("state_fire")
|
||||
MISS:
|
||||
# Our turn to fire
|
||||
state_fire()
|
||||
pass
|
||||
|
||||
# state_win: The winning state. If you reach here, someone's won.
|
||||
# ships: The opponent's ship data, so that their board can be shown
|
||||
remote func state_win(ships):
|
||||
victory_screen(ships)
|
||||
pass
|
||||
|
||||
# play_hit_sound: Play a hit sound depending on the severity of the hit
|
||||
# value: Lost/Sunk/Hit/Miss
|
||||
sync func play_hit_sound(value):
|
||||
match value:
|
||||
LOST, SUNK:
|
||||
AudioBus.emit_signal("ship_sunk")
|
||||
HIT:
|
||||
AudioBus.emit_signal("ship_hit")
|
||||
MISS:
|
||||
AudioBus.emit_signal("ship_missed")
|
||||
|
||||
# hit: Update the local player's board when the opponent fires
|
||||
# pos: Opponent's target
|
||||
func hit(pos):
|
||||
pos = Vector2(pos[0], pos[1])
|
||||
var res = player.hit(pos)
|
||||
return res
|
||||
|
||||
# mark: Update the local player's hit/miss board when opponent replies
|
||||
func mark(res):
|
||||
return player.mark(res)
|
||||
|
||||
# _on_Net_incoming: Handle mail.
|
||||
func _on_Net_incoming(mail):
|
||||
print ("mail: ", mail, mail.size())
|
||||
if mail.size() == 3:
|
||||
print ("mail: ", mail, mail.size())
|
||||
var sender = int(mail[0])
|
||||
var message = mail[1]
|
||||
var mailtype = int(mail[2])
|
||||
printt(sender, message, mailtype)
|
||||
match mailtype:
|
||||
Net.REPLY:
|
||||
print ("got REPLY")
|
||||
# message is a REPLY (return value)
|
||||
match message[0]:
|
||||
# on "fire": fire(result)
|
||||
"fire":
|
||||
hit(message[1])
|
||||
# on "hit": mark(state)
|
||||
"hit":
|
||||
mark(message[1])
|
||||
"forfeit":
|
||||
pass
|
||||
Net.READY:
|
||||
print ("got READY")
|
||||
# Add player to the ready array
|
||||
player_ready(sender)
|
||||
_:
|
||||
print ("got ", mailtype)
|
||||
|
||||
# _on_player_ready: Player Ready signal handler
|
||||
func _on_player_ready():
|
||||
print ("_on_player_ready")
|
||||
Net.send(0, [], Net.READY)
|
||||
player_ready(Net.get_network_id())
|
||||
|
||||
# victory_screen: display the victory screen
|
||||
func victory_screen():
|
||||
# TODO: Create the victory screen, fill it with knowledge
|
||||
pass
|
||||
|
||||
# display_turn(): display which turn it is on the screen
|
||||
func display_turn():
|
||||
# TODO: Update the turn display, if there is one?
|
||||
pass
|
||||
func victory_screen(ships, winner = true):
|
||||
if winner:
|
||||
# Hide the buttons
|
||||
get_node("Bittons").hide()
|
||||
# Create a new Victory screen
|
||||
var victory = Victory.instance()
|
||||
# Give it the ships received from the opponent
|
||||
victory.reveal_ships(ships)
|
||||
# Print a nice message to stdout
|
||||
print("You won!")
|
||||
# Add victory to the scene tree
|
||||
add_child(victory)
|
||||
else:
|
||||
end()
|
||||
|
||||
# _on_Forfeit_pressed: Handle forfeit button press
|
||||
func _on_Forfeit_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
get_node("ConfirmationDialog").popup()
|
||||
get_node("Forfeit Confirmation").popup_centered()
|
||||
|
||||
func end():
|
||||
# end: end the Game
|
||||
sync func end():
|
||||
queue_free()
|
||||
|
||||
|
||||
func connection_error():
|
||||
get_node("Connection Error").popup_centered()
|
||||
|
||||
# _on_Button_button_down: Handle win button press
|
||||
# TODO: This isn't a thing any more
|
||||
func _on_Button_button_down():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
var victory = Victory.instance()
|
||||
add_child(victory)
|
||||
victory.connect("exit_main", self, "end")
|
||||
|
||||
func _on_ConfirmationDialog_confirmed():
|
||||
func _on_Forfeit_Confirmation_confirmed():
|
||||
if Net.connected:
|
||||
# Send forfeit request to all users
|
||||
rpc("end")
|
||||
end()
|
||||
|
||||
func _on_Connection_Error_confirmed():
|
||||
# End the game
|
||||
queue_free()
|
||||
|
||||
|
@ -1,55 +1,92 @@
|
||||
extends Node
|
||||
|
||||
# Path to Board class, for instantiating new Boards in code
|
||||
var Board = "res://script/game/Gameplay/Board.gd"
|
||||
# Emitted when the player is ready
|
||||
signal player_ready
|
||||
|
||||
# Player ID of this player
|
||||
var pid
|
||||
# board (an instance of the Board class)
|
||||
onready var board = Board.new()
|
||||
# Preloaded assets, to be used later
|
||||
# Path to Board class, for instantiating new Boards in code
|
||||
var Board = preload("res://scenes/Game/Board.tscn")
|
||||
# Path to Setup menu, so the player may set up their Board
|
||||
var Setup = preload("res://scenes/Game/Setup.tscn")
|
||||
# Path to Fire menu, so the player may fire on the opponent
|
||||
var Fire = preload("res://scenes/Game/Fire.tscn")
|
||||
|
||||
# Members
|
||||
var board # Board
|
||||
var fire_pos = Vector2(-1,-1)
|
||||
var target = Vector2(-1,-1)
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
pass
|
||||
|
||||
func set_up_begin():
|
||||
var setup = Setup.instance()
|
||||
setup.connect("board_ready", self, "set_up")
|
||||
add_child(setup)
|
||||
board = Board.instance()
|
||||
|
||||
# Member functions:
|
||||
# hit: Called when opponent fires on us.
|
||||
# Update internal state, and return bool hit/miss
|
||||
func hit():
|
||||
pass
|
||||
# Update internal state, and return hit/miss/sunk
|
||||
func hit(pos):
|
||||
target = pos
|
||||
var res = board.hit(pos)
|
||||
return res
|
||||
|
||||
# mark: Called when the opponent returns hit/miss/sunk
|
||||
# Update internal state, return ack/nak
|
||||
func mark(value):
|
||||
# Mark the position on the top board
|
||||
return board.fire(fire_pos, value)
|
||||
|
||||
# place_ship: called when ships are placed.
|
||||
# forwards Ship locations to the Board, so that it may construct a ship
|
||||
# ship: a list of ship properties {position, orientation, size}
|
||||
func place_ship(_ship):
|
||||
pass
|
||||
# ship: a list of ship properties {position, orientation, size, variant}
|
||||
func place_ship(pos, size, orientation, variant):
|
||||
return board.place_ship(pos, size, orientation, variant)
|
||||
|
||||
# setUp: set up the board given the placed ship locations
|
||||
# translates the ship positions in the Setup UI to board-space, then places each ship
|
||||
# ships: a list of lists of ship properties {{position, orientation, size}, ...}
|
||||
func set_up(_ships):
|
||||
pass
|
||||
# set_up: set up the board given the placed ship locations
|
||||
# Places each ship onto the board
|
||||
# ships: a list of lists of ship properties [[position, orientation, size, variant], ...]
|
||||
func set_up(ships):
|
||||
# Place all the ships
|
||||
for i in ships:
|
||||
place_ship(i[0], i[1], i[2], i[3])
|
||||
# Add the board to the tree
|
||||
add_child(board)
|
||||
emit_signal("player_ready")
|
||||
|
||||
# turnStart: start player's turn
|
||||
# turn_start: start player's turn
|
||||
# Initiates the player's turn, and blocks until the player selects a location to fire upon
|
||||
# returns: fire = [player id, target coordinates]
|
||||
func turnStart():
|
||||
var player_id = 0
|
||||
var target = Vector2(0,0)
|
||||
return [player_id, target]
|
||||
pass
|
||||
func turn_start():
|
||||
var fire = Fire.instance()
|
||||
fire.hits = board.top_board
|
||||
add_child(fire)
|
||||
fire_pos = yield(fire, "fire_at")
|
||||
fire.queue_free()
|
||||
return fire_pos
|
||||
|
||||
|
||||
# getBoard: returns the player's board
|
||||
# returns: board
|
||||
func getBoard():
|
||||
return board
|
||||
func board_query(boardname):
|
||||
match boardname:
|
||||
"top":
|
||||
return board.query_top (fire_pos)
|
||||
"bottom":
|
||||
return board.quert_bottom (target)
|
||||
|
||||
# forfeit: ends game for player
|
||||
# Sinks all ships
|
||||
# Ensures there are no ships left behind
|
||||
func forfeit():
|
||||
pass
|
||||
for i in 10:
|
||||
for j in 10:
|
||||
# Hit the board
|
||||
hit(Vector2(i, j))
|
||||
|
||||
# getShipCount: get the number of ships the player has left alive
|
||||
func getShipCount():
|
||||
pass
|
||||
|
||||
return board.get_ship_count()
|
||||
|
@ -1,55 +1,148 @@
|
||||
extends Node
|
||||
extends Node2D
|
||||
|
||||
# This is the rendered element of a "ship", generated when the game transitions from the placing state to the gameplay state
|
||||
|
||||
# Enum denoting the orientation (X is 1, Y is 0)
|
||||
enum Orientation {X = 1, Y = 0}
|
||||
# Enum denoting the orientation (X is 0, Y is 1)
|
||||
enum Orientation {X = 0, Y = 1}
|
||||
enum {MISS = -1, READY = 0, HIT = 1, SUNK = 2}
|
||||
|
||||
# Size of ship in board units
|
||||
var size
|
||||
var health
|
||||
# Coordinates of ship's center. Ship extends [-(size-1 >> 1), (size/2 >> 1)]
|
||||
var position
|
||||
var boardposition = Vector2(-1,-1)
|
||||
# Variable storing whether the ship is sunk, for rendering purposes
|
||||
var sunk = false
|
||||
# Orientation of the ship (see enum Orientation)
|
||||
var orientation = Orientation.Y
|
||||
# array of spots thats been hit
|
||||
var hits = []
|
||||
# Variable storing the positions of each piece of the ship
|
||||
var extents = []
|
||||
|
||||
# Ship sprite metadata
|
||||
# sprite: the texture atlas containing all ship parts
|
||||
var atlas # = TODO: figure out how to use one sprite for multiple textures
|
||||
# texture: the offset into the texture atlas of the first part of the ship.
|
||||
var texture = 0
|
||||
# atlas: the texture atlas containing all ship parts
|
||||
var atlas = preload("res://assets/game/TextureAtlas.png")
|
||||
# sprites: the individual sprite nodes which make up the ship
|
||||
var sprites = []
|
||||
# variant: Ships of the same length can have different textures
|
||||
# variant A is 0, variant B is 1, ...
|
||||
var variant = 0
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
# member functions:
|
||||
# getSize: get the size of the ship, in board-units (2 for 2-ship, 3 for 3-ship, ...)
|
||||
func getSize():
|
||||
return size
|
||||
|
||||
# getPosition: get the position of the ship's center, in board units
|
||||
func getPosition():
|
||||
return position
|
||||
|
||||
# getOrientation: get the orientation of the ship (see enum Orientation)
|
||||
func getOrientation():
|
||||
return orientation
|
||||
# getShip():
|
||||
func get_ship():
|
||||
return [boardposition, size, orientation, variant]
|
||||
|
||||
# getSunk: get whether the ship is sunk
|
||||
func getSunk():
|
||||
func get_sunk():
|
||||
return sunk
|
||||
|
||||
func hit(pos):
|
||||
# Assume the opponent missed
|
||||
var res = MISS
|
||||
# Find the position in the extents
|
||||
var index = extents.find(pos)
|
||||
# If that position exists:
|
||||
if (index > -1):
|
||||
# Hit the ship piece at that location
|
||||
hits[index] = true
|
||||
res = HIT
|
||||
# Decrement its health
|
||||
health -= 1
|
||||
# If there's no more health,
|
||||
if health == 0:
|
||||
# Sink the ship.
|
||||
set_sunk()
|
||||
res = SUNK
|
||||
# Update graphics
|
||||
update()
|
||||
return res
|
||||
|
||||
# update: (re)calculates extents and textures
|
||||
func update():
|
||||
# Calculate the extents (shouldn't change)
|
||||
extents = get_extent()
|
||||
# Update the textures
|
||||
for i in size:
|
||||
texture(i)
|
||||
|
||||
# returns an array of the positions that the ship occupies
|
||||
func get_extent():
|
||||
var extent = []
|
||||
# Find each tile of the ship
|
||||
for i in size:
|
||||
# Calculate the x axis position
|
||||
var x = boardposition.x - (1 - orientation) * ( (size - 1) / 2 - i )
|
||||
# Calculate the y axis position
|
||||
var y = boardposition.y - orientation * ( (size - 1) / 2 - i )
|
||||
# Append the point onto the array
|
||||
extent.push_back(Vector2(x,y))
|
||||
return extent
|
||||
|
||||
# Update textures
|
||||
func texture(index):
|
||||
var state = 0 # ready
|
||||
if(hits[index]):
|
||||
state = 1 # hit
|
||||
var textureSize = 32
|
||||
# It's okay to create a new texture every time, as resources are refcounted
|
||||
var t = AtlasTexture.new()
|
||||
t.set_atlas(atlas)
|
||||
t.margin = Rect2(0, 0, 32, 32)
|
||||
t.region = Rect2(
|
||||
(size * variant + index) * textureSize,
|
||||
#(size * textureSize) * variant + (32 * index),
|
||||
(size - 2) * textureSize * 2 + (32 * state),
|
||||
textureSize,
|
||||
textureSize
|
||||
)
|
||||
# Create a new Sprite to house the texture, or use the existing sprite
|
||||
var sprite = sprites[index]
|
||||
if sprite == null:
|
||||
sprite = Sprite.new()
|
||||
sprite.texture = t
|
||||
# This is relative to the ship
|
||||
# (index + 1) => Index, but 1-based
|
||||
# (floor((size-1)/2) => Offset from edge to 'center' of ship
|
||||
# Vector2(0.5,0.5) => Center the texture on the axis of rotation
|
||||
# 32 => Converts from board-units to pixels
|
||||
sprite.position = Vector2((index + 1) - (floor((size-1)/2) + 0.5), 0.5) * textureSize
|
||||
sprite.rotation = 0
|
||||
# Add the sprite to the "sprites" group, persistently
|
||||
sprite.add_to_group("Ship Sprites", true)
|
||||
# Add the sprite node to an array so it can be modified later, unless it's already there
|
||||
if not sprites[index]:
|
||||
sprites[index] = sprite
|
||||
add_child(sprite)
|
||||
|
||||
# setSunk: sink the ship
|
||||
func setSunk():
|
||||
func set_sunk():
|
||||
sunk = true
|
||||
|
||||
# _init: called on object initialization. Accepts args if called via <Ship>.new(...)
|
||||
# in_position: position of the ship, in board-coordinates; (0,0) by default
|
||||
# in_size: size of the ship, in board-units; 2 by default
|
||||
# in_orientation: orientation of the ship (see enum Orientation); vertical by default
|
||||
func _init(in_position = Vector2(0,0), in_size = 2, in_orientation = Orientation.Y):
|
||||
position = in_position
|
||||
# in_variant: Which ship is this?
|
||||
func _init(in_position = Vector2(0,0), in_size = 0, in_orientation = Orientation.Y, in_variant = 0):
|
||||
# Set the ship's positions
|
||||
boardposition = in_position
|
||||
position = boardposition * 32
|
||||
# Set the ship's size and health
|
||||
size = in_size
|
||||
health = size
|
||||
# Set the ship's orientation/rotation
|
||||
orientation = in_orientation
|
||||
rotation = orientation * PI/2
|
||||
# Set the ship's variant(A, B, ... )
|
||||
variant = in_variant
|
||||
# Resize the size-based arrays
|
||||
hits.resize(in_size)
|
||||
sprites.resize(in_size)
|
||||
# Update the extents and draw the textures
|
||||
update()
|
||||
|
@ -1,21 +1,28 @@
|
||||
extends Control
|
||||
|
||||
signal game_ready
|
||||
signal board_ready
|
||||
|
||||
onready var Ships = ["2Ship", "3ShipA", "3ShipB", "4Ship", "5Ship"]
|
||||
|
||||
onready var Victory = preload("res://scenes/Game/Player.tscn")
|
||||
var light_theme = load("res://light_theme.tres")
|
||||
var dark_theme = load("res://dark_theme.tres")
|
||||
|
||||
class ShipData:
|
||||
var Position: Vector2
|
||||
var Length: int
|
||||
var Orientation: bool # (True = vertical) (False = horizontal)
|
||||
var Variant: int = 0
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
# Moves the focus to this menu
|
||||
if find_next_valid_focus(): find_next_valid_focus().grab_focus()
|
||||
|
||||
|
||||
get_node("PlaceShipDialog").get_ok().rect_min_size.x = 50
|
||||
|
||||
var _errno = 0;
|
||||
_errno += OptionsController.connect("change_theme", self, "_on_change_theme")
|
||||
_on_change_theme(OptionsController.get_theme())
|
||||
|
||||
func _on_Confirm_Placement_pressed():
|
||||
# Make the button noise
|
||||
@ -26,25 +33,17 @@ func _on_Confirm_Placement_pressed():
|
||||
# if this is more than zero, the ship is invalid
|
||||
if get_node(ship).validate_placement():
|
||||
valid = false
|
||||
print ("Placement: ", valid)
|
||||
if valid == false:
|
||||
get_node("PlaceShipDialog").popup()
|
||||
else:
|
||||
#Saves the location of ships and length of ship into an array
|
||||
var shipLocation = []
|
||||
var ship_data = []
|
||||
for ship in Ships:
|
||||
var location = ShipData.new()
|
||||
location.Position = get_node(ship).position
|
||||
location.Length = get_node(ship).get("ship_length")
|
||||
location.Orientation = get_node(ship).get("vertical")
|
||||
shipLocation.append(location)
|
||||
|
||||
#print out the array for testing
|
||||
for x in shipLocation:
|
||||
print("Ship Length: ", x.Length, ", Ship Orientation: ", x.Orientation, ", Ship Position: ", x.Position)
|
||||
|
||||
ship = get_node(ship)
|
||||
var data = ship.get_shipdata()
|
||||
ship_data.append(data)
|
||||
# Return the shipLocation array to those listening on game_ready
|
||||
emit_signal("game_ready", shipLocation)
|
||||
emit_signal("board_ready", ship_data)
|
||||
queue_free()
|
||||
return valid # Replace with function body.
|
||||
|
||||
@ -53,3 +52,9 @@ func _on_Clear_pressed():
|
||||
for ship in Ships:
|
||||
get_node(ship).clear()
|
||||
pass # Replace with function body.
|
||||
|
||||
func _on_change_theme(theme):
|
||||
if theme == "light":
|
||||
self.set_theme(light_theme)
|
||||
elif theme == "dark":
|
||||
self.set_theme(dark_theme)
|
||||
|
@ -146,6 +146,12 @@ func ship_stacked(_body):
|
||||
func ship_unstacked(_body):
|
||||
collision = false
|
||||
|
||||
func get_shipdata():
|
||||
var shipdata = [world_to_board_space(position), ship_length, int(vertical)]
|
||||
var variant = int(name.match("*B"))
|
||||
shipdata.push_back(variant)
|
||||
return shipdata
|
||||
|
||||
# Calculate the extents (front to back) of the ship and check whether they're on the board
|
||||
# Returns how many squares to move the ship along its orientation axis (positive or negative)
|
||||
func check_extents(center, orientation, length):
|
||||
|
@ -1,30 +1,30 @@
|
||||
extends Control
|
||||
|
||||
signal exit_main
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
# Path to Board class, for instantiating new Boards in code
|
||||
var Board = preload("res://scenes/Game/Board.tscn")
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
# Reveal a list of ships
|
||||
func reveal_ships(ships:Array):
|
||||
var board = Board.instance()
|
||||
add_child(board);
|
||||
for ship in ships:
|
||||
board.callv("place_ship", ship)
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
||||
|
||||
|
||||
# returns player(s) back to main menu
|
||||
func _on_Button_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
#MessageBus.emit_signal("change_scene", "Title")
|
||||
emit_signal("exit_main")
|
||||
|
||||
|
||||
func _on_restart_button_down():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
#MessageBus.emit_signal("change_scene", "Multiplayer")
|
||||
pass # Replace with function body.
|
||||
|
||||
MessageBus.emit_signal("change_scene", "Multiplayer")
|
||||
MessageBus.emit_signal("kill_scene", "Game")
|
||||
|
||||
|
||||
# returns player(s) back to main menu
|
||||
func _on_exit_to_main_button_down():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
MessageBus.emit_signal("return_to_title")
|
||||
|
132
godot_ship/script/network/Lobby.gd
Normal file
@ -0,0 +1,132 @@
|
||||
extends Control
|
||||
# Ignore discarded return values
|
||||
# warning-ignore-all:return_value_discarded
|
||||
onready var player_list = find_node("Player List")
|
||||
onready var ip_address = find_node("IP Address")
|
||||
onready var name_popup = find_node("Change Name")
|
||||
onready var game_popup = find_node("Connect to Game")
|
||||
|
||||
# TODO: Write a function to update Player List with the list of attached players
|
||||
|
||||
func _on_peers_updated():
|
||||
var connected_peers = ""
|
||||
for peer in Net.peer_info:
|
||||
connected_peers += ("%s\n" % Net.peer_info[peer]["name"])
|
||||
pass
|
||||
player_list.text = connected_peers.rsplit("\n", true, 1)[0].c_unescape()
|
||||
pass
|
||||
|
||||
func set_IP_Address_text(show):
|
||||
# Print the IP address and port
|
||||
if show:
|
||||
ip_address.text = "IP: %s\nPort: %s" % [Net.get_ip(), Net.DEFAULT_PORT]
|
||||
else:
|
||||
ip_address.text = ""
|
||||
|
||||
func _ready():
|
||||
Net.connect("peers_updated", self, "_on_peers_updated")
|
||||
Net.connect("disconnected", self, "_on_Net_disconnected")
|
||||
name_popup.get_node("Name Entry").text = Net.get_hostname()
|
||||
_on_peers_updated()
|
||||
pass
|
||||
|
||||
func show_Connected_Options(show, host = false):
|
||||
# [Hide]/Show the host options
|
||||
get_node("Lobby Options/Connected Options/Host Options").visible = host
|
||||
# [Hide]/Show the host and connect buttons
|
||||
get_node("Lobby Options/Host or Connect").visible = !show
|
||||
# [Show]/Hide the host options
|
||||
get_node("Lobby Options/Connected Options").visible = show
|
||||
|
||||
# Buttons
|
||||
# Host Button: Host a game
|
||||
# Hides the connect button
|
||||
func _on_Host_Button_pressed():
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Show "Connected Options"
|
||||
show_Connected_Options(true, true)
|
||||
# Show the host IP address
|
||||
set_IP_Address_text(true)
|
||||
# Begin hosting
|
||||
Net.start_host()
|
||||
|
||||
# Disconnect
|
||||
# Disconnect from (or stop hosting) a game
|
||||
# Shows the host/connect buttons
|
||||
func _on_Disconnect_Button_pressed():
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Disconnect
|
||||
Net.disconnect_host()
|
||||
# Hide "Connected Options"
|
||||
show_Connected_Options(false)
|
||||
# Hide the host IP address
|
||||
set_IP_Address_text(false)
|
||||
|
||||
func _on_Start_Game_pressed():
|
||||
# If there are enough players for a game
|
||||
if Net.peer_info.size() >= 2:
|
||||
# Start the game for all players
|
||||
rpc("start_game")
|
||||
pass # Replace with function body.
|
||||
|
||||
func _on_Net_disconnected():
|
||||
# Hide "Connected Options"
|
||||
show_Connected_Options(false)
|
||||
# Hide the host IP address
|
||||
set_IP_Address_text(false)
|
||||
|
||||
func _on_Change_Name_Button_pressed():
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Show the Change Name dialogue
|
||||
get_node("Change Name").popup_centered()
|
||||
|
||||
func _on_Connect_Button_pressed():
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Show the Connect to Game dialogue
|
||||
get_node("Connect to Game").popup_centered()
|
||||
|
||||
func _on_Exit_Lobby_pressed():
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Disconnect
|
||||
if Net.connected:
|
||||
Net.disconnect_host()
|
||||
# Close Lobby menu
|
||||
queue_free()
|
||||
|
||||
|
||||
func _on_IP_and_Port_Entry_text_entered(text):
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Split it into IP and Port segments
|
||||
var ip_port = text.split(":")
|
||||
# If text exists and contains valid IP address
|
||||
if ip_port.size() > 0 and ip_port[0].is_valid_ip_address():
|
||||
# Connect to host
|
||||
var connected = Net.callv("connect_host", ip_port)
|
||||
if connected == OK:
|
||||
# Show "Connected Options"
|
||||
show_Connected_Options(true)
|
||||
# Hide the popup
|
||||
game_popup.hide()
|
||||
|
||||
|
||||
func _on_Name_Entry_text_entered(text):
|
||||
# Make noise
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
# Check the length of the name
|
||||
if text.length() < 18:
|
||||
# Change the name
|
||||
Net.change_name(text)
|
||||
# Hide the popup
|
||||
name_popup.hide()
|
||||
|
||||
sync func start_game():
|
||||
MessageBus.emit_signal("change_scene", "Gameplay")
|
||||
queue_free()
|
||||
|
||||
|
188
godot_ship/script/network/Net.gd
Normal file
@ -0,0 +1,188 @@
|
||||
extends Node
|
||||
|
||||
# Constants
|
||||
# DEFAULT_PORT: The port GodotShip will listen on/connect to by default
|
||||
const DEFAULT_PORT = 35879
|
||||
# LOCALHOST: loopback address
|
||||
const LOCALHOST = "127.0.0.1"
|
||||
|
||||
# Enums, used for mail types
|
||||
# Mail types:
|
||||
# 0: REQUEST: Message is a request for information
|
||||
# 1: REPLY: Message is a reply
|
||||
# 2: READY: Message is "ready"
|
||||
# 3: ACK: Message is an acknowledgement
|
||||
enum {REQUEST, REPLY, READY, ACK}
|
||||
|
||||
# Signals
|
||||
# incoming(mail): Sent when there's an incoming message
|
||||
signal incoming
|
||||
# peers_updated(): Sent when the peer list is updated
|
||||
signal peers_updated
|
||||
# disconnected(): Sent when unexpectedly disconnected
|
||||
signal disconnected
|
||||
# Variables
|
||||
# inbox: Array: Message history
|
||||
var inbox = []
|
||||
# connected: Boolean: True when in the Connected state
|
||||
var connected = false
|
||||
# hosting: Boolean: True when in the Hosting state
|
||||
var hosting = false
|
||||
# peer_info: Dictionary: Store peer info in a dictionary, by player ID
|
||||
var peer_info = {}
|
||||
# local_info: Dictionary: Store this player's info
|
||||
var local_info = {"name": ""}
|
||||
|
||||
# Network -- handles server and client setup, and facilitates communication between the two
|
||||
# receive: Receive a message (called by sender's `send` function)
|
||||
# mail: The message received from the sender (implicitly JSON-decoded by JSONRPC)
|
||||
# mail_type: Type of mail (see "Mail Types" enum above)
|
||||
remote func receive(mail):
|
||||
print_debug("recv: %s" % mail)
|
||||
# Unpack the mail
|
||||
# Uses json parser of unknown stability, how fun
|
||||
mail = parse_json(mail)
|
||||
# Get the sender's ID and force letter to be properly addressed
|
||||
mail[0] = get_tree().get_rpc_sender_id()
|
||||
# Add the mail to the inbox (so it can be read back later if necessary
|
||||
inbox.append(mail)
|
||||
# Sent it off to anything that expects mail
|
||||
emit_signal("incoming", mail)
|
||||
|
||||
# send: Send a message
|
||||
# id: Peer ID of the recipient
|
||||
# mail: Variant of a json-encodable type (non-Object) to send
|
||||
# mail_type: Type of mail (see "Mail Types" enum above)
|
||||
func send(id, mail, mail_type = REPLY):
|
||||
print_debug("send: %d, %s, %d" % [id, mail, mail_type])
|
||||
# Make the recipient receive the mail
|
||||
rpc_id(id, "receive", to_json([-1, mail, mail_type]))
|
||||
|
||||
# Host
|
||||
# start_host: Host the game
|
||||
# port: TCP port
|
||||
# max_players: Largest number of players allowed to connect at a time
|
||||
func start_host(port = DEFAULT_PORT, max_players = 2):
|
||||
get_hostname()
|
||||
peer_info[1] = local_info
|
||||
# Notify that peer list has updated
|
||||
emit_signal("peers_updated")
|
||||
# Create a new NetworkedMultiplayerENet (handles multiplayer communication through ENet)
|
||||
var peer = NetworkedMultiplayerENet.new()
|
||||
# Create a server
|
||||
peer.create_server(port, max_players)
|
||||
# Add the server to the scene tree
|
||||
get_tree().network_peer = peer
|
||||
# Update state
|
||||
connected = true
|
||||
hosting = true
|
||||
|
||||
# accept_guests:
|
||||
# Select whether to accept new guests
|
||||
func accept_guests(accept:bool):
|
||||
if hosting:
|
||||
multiplayer.refuse_new_network_connections = not accept
|
||||
|
||||
# Guest
|
||||
# connect_host: Connect to a host
|
||||
func connect_host(ip = LOCALHOST, port = DEFAULT_PORT):
|
||||
get_hostname()
|
||||
var peer = NetworkedMultiplayerENet.new()
|
||||
var ret = peer.create_client(ip, int(port))
|
||||
get_tree().network_peer = peer
|
||||
return ret
|
||||
|
||||
# disconnect_host
|
||||
func disconnect_host():
|
||||
# Send intent to disconnect
|
||||
rpc("unregister_peer", get_network_id())
|
||||
# Set state to disconnected
|
||||
connected = false
|
||||
hosting = false
|
||||
# Attempt disconnection
|
||||
if get_tree().network_peer:
|
||||
get_tree().network_peer.close_connection()
|
||||
# Disconnect
|
||||
get_tree().network_peer = null
|
||||
# Clear peer info
|
||||
peer_info = {}
|
||||
# Notify that peer list has updated
|
||||
emit_signal("peers_updated")
|
||||
|
||||
# change_name: Change the local name, and re-register with all peers (including self)
|
||||
func change_name(name):
|
||||
# Change name locally
|
||||
local_info["name"] = name
|
||||
# If connected, update peers
|
||||
if connected:
|
||||
# Send updated info info to all peers
|
||||
rpc("register_peer", local_info)
|
||||
|
||||
# Helper Functions
|
||||
# get_hostname: Asks the host machine to provide its hostname,
|
||||
# and if the peer name isn't set, set it to the hostname
|
||||
func get_hostname():
|
||||
var hostname = []
|
||||
# Execute the `hostname` command
|
||||
var _ret = OS.execute("hostname", [], true, hostname)
|
||||
# If there's no name set, set it to the hostname
|
||||
if local_info["name"] == "":
|
||||
local_info["name"] = hostname[0].split("\n")[0]
|
||||
return hostname[0].split("\n")[0]
|
||||
|
||||
func get_network_id():
|
||||
return get_tree().get_network_unique_id()
|
||||
|
||||
func get_ip():
|
||||
return IP.resolve_hostname(get_hostname(), IP.TYPE_IPV4)
|
||||
pass
|
||||
|
||||
func _ready():
|
||||
var _trash
|
||||
_trash = get_tree().connect("network_peer_connected", self, "_peer_connected" )
|
||||
_trash = get_tree().connect("network_peer_disconnected", self, "_peer_disconnected")
|
||||
_trash = get_tree().connect("connected_to_server", self, "_host_connected" )
|
||||
_trash = get_tree().connect("server_disconnected", self, "_host_disconnected")
|
||||
_trash = get_tree().connect("connection_failed", self, "_connection_fail" )
|
||||
|
||||
# Signal Handlers
|
||||
func _peer_connected(id):
|
||||
# Send peer info to remote peer
|
||||
rpc_id(id, "register_peer", local_info)
|
||||
if hosting and peer_info.size() >= 2:
|
||||
pass
|
||||
pass
|
||||
|
||||
func _peer_disconnected(id):
|
||||
# Unregister the peer locally
|
||||
unregister_peer(id)
|
||||
if hosting and peer_info.size() < 2:
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
func _host_connected():
|
||||
# On connection to the server, you get a global network id
|
||||
# Save your info at this id
|
||||
peer_info[get_network_id()] = local_info
|
||||
# Set state to connected
|
||||
connected = true
|
||||
|
||||
func _host_disconnected():
|
||||
# Ensure host is disconnected
|
||||
disconnect_host()
|
||||
# Send disconnection message to listeners
|
||||
emit_signal("disconnected")
|
||||
|
||||
func _connection_fail():
|
||||
# Ensure Net state is clear
|
||||
disconnect_host()
|
||||
|
||||
sync func register_peer(info):
|
||||
# Save player information under the sender id's peer info
|
||||
peer_info[get_tree().get_rpc_sender_id()] = info
|
||||
emit_signal("peers_updated")
|
||||
|
||||
sync func unregister_peer(id):
|
||||
peer_info.erase(id)
|
||||
emit_signal("peers_updated")
|
5
godot_ship/script/options/Network.gd
Normal file
@ -0,0 +1,5 @@
|
||||
extends Node
|
||||
|
||||
|
||||
func _ready():
|
||||
pass
|
@ -5,6 +5,8 @@ onready var music_slider = find_node("Music Slider", true, true)
|
||||
onready var sound_slider = find_node("SFX Slider", true, true)
|
||||
onready var theme_buttons = find_node("Buttons", true, true).get_children()
|
||||
|
||||
var light_theme = load("res://light_theme.tres")
|
||||
var dark_theme = load("res://dark_theme.tres")
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
@ -13,6 +15,10 @@ func _ready():
|
||||
master_slider.value = db2linear(OptionsController.get_mas_volume())
|
||||
music_slider.value = db2linear(OptionsController.get_mus_volume())
|
||||
sound_slider.value = db2linear(OptionsController.get_sfx_volume())
|
||||
|
||||
var _errno = 0;
|
||||
_errno += OptionsController.connect("change_theme", self, "_on_change_theme")
|
||||
_on_change_theme(OptionsController.get_theme())
|
||||
|
||||
func _on_Button_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
@ -41,3 +47,9 @@ func _on_Light_pressed():
|
||||
func _on_Dark_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
OptionsController.set_theme("dark")
|
||||
|
||||
func _on_change_theme(theme):
|
||||
if theme == "light":
|
||||
self.set_theme(light_theme)
|
||||
elif theme == "dark":
|
||||
self.set_theme(dark_theme)
|
||||
|
@ -1,12 +1,18 @@
|
||||
extends Control
|
||||
|
||||
var light_theme = load("res://light_theme.tres")
|
||||
var dark_theme = load("res://dark_theme.tres")
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
$VBoxContainer/Singleplayer.grab_focus()
|
||||
var _errno = 0;
|
||||
_errno += OptionsController.connect("change_theme", self, "_on_change_theme")
|
||||
_on_change_theme(OptionsController.get_theme())
|
||||
|
||||
func _on_Singleplayer_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
MessageBus.emit_signal("change_scene", "Singleplayer")
|
||||
MessageBus.emit_signal("change_scene", "Gameplay")
|
||||
queue_free()
|
||||
|
||||
func _on_Multiplayer_pressed():
|
||||
@ -19,7 +25,18 @@ func _on_Options_pressed():
|
||||
MessageBus.emit_signal("change_scene", "Options")
|
||||
queue_free()
|
||||
|
||||
func _on_Credits_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
MessageBus.emit_signal("change_scene", "Credits")
|
||||
queue_free()
|
||||
|
||||
func _on_Quit_pressed():
|
||||
AudioBus.emit_signal("button_clicked")
|
||||
MessageBus.emit_signal("quit")
|
||||
queue_free()
|
||||
|
||||
func _on_change_theme(theme):
|
||||
if theme == "light":
|
||||
self.set_theme(light_theme)
|
||||
elif theme == "dark":
|
||||
self.set_theme(dark_theme)
|
||||
|