1
0
mirror of https://github.com/JohnBreaux/Boat-Battle.git synced 2025-02-04 12:28:35 +00:00

Merge branch 'game-logic'

This commit is contained in:
John 2021-11-24 22:32:17 -06:00
commit 21a5de5701
83 changed files with 2184 additions and 289 deletions

View File

@ -1,3 +1,3 @@
source_md5="a88d669f1f058a347cc4de2244bac64b"
dest_md5="1073062c6e594eff250036d7489d44a7"
dest_md5="1ed8fab74f35d40e257776b2eab84c5f"

View File

@ -0,0 +1,3 @@
source_md5="e860aab5fa3b6ce9c5831b3624861eb0"
dest_md5="a265f8881bf649748bb86076a1059462"

View File

@ -0,0 +1,3 @@
source_md5="f1043053126af1a739ae9a6d20541705"
dest_md5="33d90f901d38e94006bc94b2bafbcc7f"

View File

@ -0,0 +1,3 @@
source_md5="e5510033f1a1421d95771be4d1f17c06"
dest_md5="acfea8b7761d165a201dbc0a0af2c167"

View File

@ -0,0 +1,3 @@
source_md5="236f053c1af2cb6dc8fb21dd8c49fee6"
dest_md5="e8811c15e8ebcd4a71c62994dc9c6d5a"

View File

@ -0,0 +1,3 @@
source_md5="dc5c89239ead115c7989cdbee213c307"
dest_md5="d26cc3c5d8c5165d3f5afb242806bdb4"

View File

@ -0,0 +1,3 @@
source_md5="d743da5448801d5a71eb2caff679e6ff"
dest_md5="5d974b679ce52f358bf54f29b7a68669"

View File

@ -0,0 +1,3 @@
source_md5="136899ff4c68986c4cc62e296277b8ab"
dest_md5="3d16ccd1874686296ee01de7097a3a6f"

View File

@ -0,0 +1,3 @@
source_md5="8a6c98eec519fd0b594b073b527e6e96"
dest_md5="c9201153f0494a1eb4f9e353a0aafe9f"

View File

@ -0,0 +1,3 @@
source_md5="4608512057ad7b079766b3ddf107024a"
dest_md5="8f5996bd2322644767582317aefaf44d"

View File

@ -1,3 +1,3 @@
source_md5="47313fa4c47a9963fddd764e1ec6e4a8"
dest_md5="2ded9e7f9060e2b530aab678b135fc5b"
source_md5="236f053c1af2cb6dc8fb21dd8c49fee6"
dest_md5="e8811c15e8ebcd4a71c62994dc9c6d5a"

View File

@ -0,0 +1,3 @@
source_md5="005f64fb1ff8de71218d3545cc20441c"
dest_md5="dcee8e0391b5bffbc76299f1b93a1100"

View File

@ -0,0 +1,3 @@
source_md5="a177b00b79bd7412a6b0c6aa07f5020b"
dest_md5="2bf8d94b2316e0d5b19647de6827b854"

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

View 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

View 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

View File

@ -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

Binary file not shown.

BIN
godot_ship/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View 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

View File

@ -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={

View 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"]

View 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 )

View File

@ -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"]

View File

@ -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"]

View File

@ -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
}

View File

@ -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

View 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 )

View File

@ -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"]

View 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"]

View File

@ -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
}

View File

@ -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"]

View File

@ -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)

View 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)

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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):

View File

@ -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")

View 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()

View 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")

View File

@ -0,0 +1,5 @@
extends Node
func _ready():
pass

View File

@ -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)

View File

@ -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)