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:
parent
3f4b42821b
commit
af9b18243e
@ -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 )
|
||||
|
@ -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"]
|
||||
|
@ -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"]
|
||||
|
@ -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"]
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
@ -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" )
|
||||
|
@ -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():
|
||||
|
Loading…
x
Reference in New Issue
Block a user