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

Ship Battle: Draw the rest of the freaking owl

This commit is contained in:
John 2021-11-24 12:17:07 -06:00
parent 3f4b42821b
commit af9b18243e
14 changed files with 304 additions and 211 deletions

View File

@ -1,7 +1,7 @@
[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_dark.png" type="Texture" id=2]
[ext_resource path="res://assets/game/board_blue.png" type="Texture" id=2]
[node name="Board" type="Node2D"]
position = Vector2( 36, 36 )

View File

@ -29,7 +29,7 @@ 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
@ -54,6 +54,13 @@ 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

@ -10,25 +10,12 @@ 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="exit_to_main" type="Button" parent="."]
margin_left = 541.0
margin_top = 327.85
@ -47,6 +34,20 @@ margin_right = 63.2202
margin_bottom = 357.41
text = "Restart"
[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

@ -93,9 +93,19 @@ text = "Connect to Game"
[node name="Connected Options" type="VBoxContainer" parent="Lobby Options"]
visible = false
margin_top = 84.0
margin_top = 36.0
margin_right = 123.0
margin_bottom = 104.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
@ -162,6 +172,7 @@ 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"]

View File

@ -60,7 +60,7 @@ func _on_scene_start(scene):
var instance
#print ("_on_scene_start(",scene,")")
match scene:
"Singleplayer":
"Gameplay":
instance = Game.instance()
add_child (instance)
return true

View File

@ -10,6 +10,7 @@ enum {MISS = -1, READY = 0, HIT = 1, SUNK = 2, LOST = 3}
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
@ -33,50 +34,55 @@ func hit(pos):
var res = MISS
# Get the ship-metadata for that location
var ship = bottom_board[pos.x][pos.y]
# If there's a ship there, which exists, and hasn't been hit,
if ship and ship[0] > NO_SHIP and ship[1] == READY:
# Hit the ship, and store whether HIT or SUNK
# 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)
# TODO: display KABOOM
# Update the ship
ships[ship[0]].update()
# Mark the ship as hit
ship[1] = HIT
else:
# Mark that position as a miss, with no ship
bottom_board[pos.x][pos.y] = [NO_SHIP, MISS]
# If ship sunk,
if res == SUNK:
# remove it from the count
ship_count -= 1
# If no ships left,
# If we have no more ships left, we LOST
if ship_count == 0:
# Game has been lost
res = LOST;
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] == null:
if top_board[pos.x][pos.y] == READY:
top_board[pos.x][pos.y] = res
return true
return false
return res
else:
return top_board[pos.x][pos.y]
# Place a ship on the board at board-space coordinates
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)
# Not sure why this is necessary yet
func get_bottom_board():
return bottom_board
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():
@ -84,16 +90,16 @@ func get_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):

View File

@ -1,19 +1,20 @@
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 = []
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 _init(topBoard):
hits = topBoard
func _on_Fire_pressed():
var crosshair = get_node("Crosshair")
# Check if the crosshair is in a valid position
@ -21,10 +22,7 @@ func _on_Fire_pressed():
var crosshair_pos = crosshair.world_to_board_space(crosshair.position)
if(hits[crosshair_pos.x][crosshair_pos.y] == 0):
# fires at position
print("Fire at position: ", crosshair_pos)
emit_signal("fire_at", crosshair_pos)
# Close the Firing menu
queue_free()
return
#if invalid position popup appears
var dialog = get_node("FireDialog")
@ -32,7 +30,7 @@ func _on_Fire_pressed():
func _on_FireDialog_confirmed():
get_node("Crosshair").visible = true
const OFFSET = Vector2(18, 18)
func texture(index):
@ -52,7 +50,4 @@ func texture(index):
var sprite = Sprite.new()
sprite.texture = t
sprite.position = Vector2(index.x, index.y) * textureSize + OFFSET
printt(t.get_height(), t.get_width())
$board_blue.add_child(sprite)

View File

@ -1,11 +1,18 @@
extends Control
# warning-ignore-all:unused_signal
# warning-ignore-all:return_value_discarded
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 win # win (): sent when opponent player lost
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
var Player = preload("res://scenes/Game/Player.tscn")
@ -16,10 +23,6 @@ var Victory = preload("res://scenes/Game/Victory.tscn")
# Array of instances of the Player class; stores the Players
var player
var players_ready = []
# turn counter
var turn = 0
# winner
var winner = 0
# Every game is a multiplayer game, even the ones that aren't.
# We're taking the Minecraft approach, baby
@ -28,129 +31,159 @@ var network_id
# Called when the node enters the scene tree for the first time.
func _ready():
get_node("ConfirmationDialog").get_ok().text = "Yes"
get_node("ConfirmationDialog").get_cancel().text = "No"
get_node("ConfirmationDialog").get_ok().rect_min_size.x = 100
get_node("ConfirmationDialog").get_cancel().rect_min_size.x = 100
if multiplayer:
# TODO: Spawn a lobby where people can either connect to a peer or create a server
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
# TODO: Change this to keep track of ready states only
func player_ready():
players_ready.append(Net.get_network_id())
pass
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
# 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
# game_start: Runs on host. Controls the game.
func game_start():
var state = "P1_fire"
# Make sure we're the server
while true:
match state:
"P1_fire":
# Tell local player to fire
# Wait for result
# Send fire REQUEST to P2
pass
"P2_check":
# Wait for hit
var ret = yield(self, "hit")
# Record the hit
#
pass
"P2_fire":
pass
"P1_check":
# Check if
pass
"P1_win":
pass
"P2_win":
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
func fire_on(id, pos:Vector2):
# REQUEST fire on opponent
Net.send(id, ["fire", pos], Net.REQUEST)
# Wait for REPLY
# 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")
func return_hit(id, ship_status):
# 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
Net.send(id, ["hit", ship_status], Net.REPLY)
func _on_win():
pass
# 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:
var sender = mail[0]
print ("mail: ", mail, mail.size())
var sender = int(mail[0])
var message = mail[1]
var mailtype = mail[2]
var mailtype = int(mail[2])
printt(sender, message, mailtype)
match mailtype:
# if message is a REQUEST (to perform an action)
Net.REQUEST:
match message[0]:
# Opponent asks for player.fire()
"fire":
emit_signal("fire", message[1])
# Opponent asks for hit(pos)
"hit":
pass
_:
pass
Net.REPLY:
print ("got REPLY")
# message is a REPLY (return value)
match message[0]:
# on "fire": fire(result)
"fire":
emit_signal("hit", message[1])
# Return value of
hit(message[1])
# on "hit": mark(state)
"hit":
mark(message[1])
"forfeit":
pass
pass
Net.READY:
print ("got READY")
# Add player to the ready array
players_ready.append(sender)
pass
player_ready(sender)
_:
print ("got ", mailtype)
# _on_player_ready: Player Ready signal handler
func _on_player_ready():
print ("_on_player_ready")
Net.send(1, [], Net.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()
# end: end the Game
func end():
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():
@ -159,6 +192,13 @@ func _on_Button_button_down():
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

@ -12,15 +12,13 @@ var Setup = preload("res://scenes/Game/Setup.tscn")
var Fire = preload("res://scenes/Game/Fire.tscn")
# Members
var pid # Player ID
var board # Board
var fire_at_position # Position to fire at
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():
# Set the player ID according to which network peer ID we are
pid = int(name)
pass
func set_up_begin():
var setup = Setup.instance()
@ -32,22 +30,23 @@ func set_up_begin():
# hit: Called when opponent fires on us.
# 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(pos, value):
func mark(value):
# Mark the position on the top board
board.fire(pos, value)
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, variant}
func place_ship(pos, size, orientation, variant):
board.place_ship(pos, size, orientation, variant)
return board.place_ship(pos, size, orientation, variant)
# setup: set up the board given the placed ship locations
# 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):
@ -62,17 +61,22 @@ func set_up(ships):
# Initiates the player's turn, and blocks until the player selects a location to fire upon
# returns: fire = [player id, target coordinates]
func turn_start():
print("turn_start")
var fire = Fire.instance()
fire.hits = board.top_board
add_child(fire)
var pos = yield(fire, "fire_at")
return pos
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
@ -86,7 +90,3 @@ func forfeit():
# getShipCount: get the number of ships the player has left alive
func getShipCount():
return board.get_ship_count()
func _on_fire_at(pos):
fire_at_position = pos

View File

@ -59,6 +59,8 @@ func hit(pos):
# Sink the ship.
set_sunk()
res = SUNK
# Update graphics
update()
return res
# update: (re)calculates extents and textures

View File

@ -1,15 +1,18 @@
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):
@ -17,11 +20,11 @@ func _ready():
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("change_scene", "Title")
emit_signal("exit_main")
MessageBus.emit_signal("return_to_title")

View File

@ -1,8 +1,10 @@
extends Control
# Ignore discarded return values
# warning-ignore:return_value_discarded
# warning-ignore-all:return_value_discarded
onready var player_list = find_node("Player List")
onready var ip = find_node("IP Address")
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
@ -17,28 +19,33 @@ func _on_peers_updated():
func set_IP_Address_text(show):
# Print the IP address and port
if show:
ip.text = "IP: %s\nPort: %s" % [Net.get_ip(), Net.DEFAULT_PORT]
ip_address.text = "IP: %s\nPort: %s" % [Net.get_ip(), Net.DEFAULT_PORT]
else:
ip.text = ""
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):
# Hide the host and connect buttons
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 the host options
# [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)
show_Connected_Options(true, true)
# Show the host IP address
set_IP_Address_text(true)
# Begin hosting
@ -48,6 +55,8 @@ func _on_Host_Button_pressed():
# 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"
@ -55,6 +64,13 @@ func _on_Disconnect_Button_pressed():
# 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)
@ -62,28 +78,20 @@ func _on_Net_disconnected():
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()
pass
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()
pass
func _on_Connect_to_Game_confirmed():
# Get the IP and port specified by the player
var ipbox = find_node("IP and Port Entry")
# Split it into IP and Port segments
var ip_port = ipbox.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
Net.callv("connect_host", ip_port)
# Show "Connected Options"
show_Connected_Options(true)
func _on_Exit_Lobby_pressed():
# Make noise
AudioBus.emit_signal("button_clicked")
# Disconnect
if Net.connected:
Net.disconnect_host()
@ -92,6 +100,8 @@ func _on_Exit_Lobby_pressed():
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
@ -102,11 +112,21 @@ func _on_IP_and_Port_Entry_text_entered(text):
# Show "Connected Options"
show_Connected_Options(true)
# Hide the popup
find_node("Connect to Game").hide()
game_popup.hide()
func _on_Name_Entry_text_entered(text):
# Change the name
Net.change_name(text)
# Hide the popup
find_node("Change Name").hide()
# 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

@ -8,9 +8,11 @@ const LOCALHOST = "127.0.0.1"
# Enums, used for mail types
# Mail types:
# 1: REQUEST: Message is a request for information
# 0: REPLY: Message is a reply
enum {REPLY, REQUEST, READY, ACK}
# 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
@ -36,6 +38,10 @@ var local_info = {"name": ""}
# 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
@ -48,6 +54,7 @@ remote func receive(mail):
# 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]))
@ -81,7 +88,7 @@ func accept_guests(accept:bool):
func connect_host(ip = LOCALHOST, port = DEFAULT_PORT):
get_hostname()
var peer = NetworkedMultiplayerENet.new()
var ret = peer.create_client(ip, port)
var ret = peer.create_client(ip, int(port))
get_tree().network_peer = peer
return ret
@ -106,9 +113,10 @@ func disconnect_host():
func change_name(name):
# Change name locally
local_info["name"] = name
# Send updated info info to all peers
rpc("register_peer", local_info)
pass
# 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,
@ -130,7 +138,7 @@ func get_ip():
pass
func _ready():
var _trash
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" )

View File

@ -12,7 +12,7 @@ func _ready():
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():