networking demos were notworking, not areworking,

This commit is contained in:
Juan Linietsky
2017-07-01 14:59:37 -03:00
parent 13eab7d1aa
commit da56d77d42
40 changed files with 2484 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
extends Area2D
const DEFAULT_SPEED=80
var direction = Vector2(1,0)
var ball_speed = DEFAULT_SPEED
var stopped=false
onready var screen_size = get_viewport_rect().size
sync func _reset_ball(for_left):
position = screen_size /2
if (for_left):
direction = Vector2(-1,0)
else:
direction = Vector2( 1,0)
ball_speed = DEFAULT_SPEED
sync func stop():
stopped=true
func _process(delta):
# ball will move normally for both players
# even if it's sightly out of sync between them
# so each player sees the motion as smooth and not jerky
if (not stopped):
translate( direction * ball_speed * delta )
# check screen bounds to make ball bounce
var ball_pos = position
if ((ball_pos.y < 0 and direction.y < 0) or (ball_pos.y > screen_size.y and direction.y > 0)):
direction.y = -direction.y
if (is_network_master()):
# only master will decide when the ball is out in the left side (it's own side)
# this makes the game playable even if latency is high and ball is going fast
# otherwise ball might be out in the other player's screen but not this one
if (ball_pos.x < 0 ):
get_parent().rpc("update_score",false)
rpc("_reset_ball",false)
else:
# only the slave will decide when the ball is out in the right side (it's own side)
# this makes the game playable even if latency is high and ball is going fast
# otherwise ball might be out in the other player's screen but not this one
if (ball_pos.x > screen_size.x):
get_parent().rpc("update_score",true)
rpc("_reset_ball",true)
sync func bounce(left,random):
#using sync because both players can make it bounce
if (left):
direction.x = abs(direction.x)
else:
direction.x = -abs(direction.x)
ball_speed *= 1.1
direction.y = random*2.0 - 1
direction = direction.normalized()

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

View File

@@ -0,0 +1,23 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/ball.png-9a4ca347acb7532f6ae347744a6b04f7.stex"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=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
stream=false
size_limit=0
detect_3d=true

View File

@@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://ball.gd" type="Script" id=1]
[ext_resource path="res://ball.png" type="Texture" id=2]
[sub_resource type="CircleShape2D" id=1]
custom_solver_bias = 0.0
radius = 5.11969
[node name="ball" type="Area2D"]
input_pickable = true
shapes/0/shape = SubResource( 1 )
shapes/0/transform = Transform2D( 1, 0, 0, 1, 0, 0 )
shapes/0/trigger = false
gravity_vec = Vector2( 0, 1 )
gravity = 98.0
linear_damp = 0.1
angular_damp = 1.0
script = ExtResource( 1 )
[node name="sprite" type="Sprite" parent="."]
texture = ExtResource( 2 )
[node name="shape" type="CollisionShape2D" parent="."]
shape = SubResource( 1 )
trigger = false
_update_shape_index = 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

View File

@@ -0,0 +1,23 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=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
stream=false
size_limit=0
detect_3d=true

View File

@@ -0,0 +1,106 @@
extends Control
const DEFAULT_PORT = 8910 # some random number, pick your port properly
#### Network callbacks from SceneTree ####
# callback from SceneTree
func _player_connected(id):
#someone connected, start the game!
var pong = load("res://pong.tscn").instance()
pong.connect("game_finished",self,"_end_game",[],CONNECT_DEFERRED) # connect deferred so we can safely erase it from the callback
get_tree().get_root().add_child(pong)
hide()
func _player_disconnected(id):
if (get_tree().is_network_server()):
_end_game("Client disconnected")
else:
_end_game("Server disconnected")
# callback from SceneTree, only for clients (not server)
func _connected_ok():
# will not use this one
pass
# callback from SceneTree, only for clients (not server)
func _connected_fail():
_set_status("Couldn't connect",false)
get_tree().set_network_peer(null) #remove peer
get_node("panel/join").set_disabled(false)
get_node("panel/host").set_disabled(false)
func _server_disconnected():
_end_game("Server disconnected")
##### Game creation functions ######
func _end_game(with_error=""):
if (has_node("/root/pong")):
#erase pong scene
get_node("/root/pong").free() # erase immediately, otherwise network might show errors (this is why we connected deferred above)
show()
get_tree().set_network_peer(null) #remove peer
get_node("panel/join").set_disabled(false)
get_node("panel/host").set_disabled(false)
_set_status(with_error,false)
func _set_status(text,isok):
#simple way to show status
if (isok):
get_node("panel/status_ok").set_text(text)
get_node("panel/status_fail").set_text("")
else:
get_node("panel/status_ok").set_text("")
get_node("panel/status_fail").set_text(text)
func _on_host_pressed():
var host = NetworkedMultiplayerENet.new()
host.set_compression_mode(NetworkedMultiplayerENet.COMPRESS_RANGE_CODER)
var err = host.create_server(DEFAULT_PORT,1) # max: 1 peer, since it's a 2 players game
if (err!=OK):
#is another server running?
_set_status("Can't host, address in use.",false)
return
get_tree().set_network_peer(host)
get_node("panel/join").set_disabled(true)
get_node("panel/host").set_disabled(true)
_set_status("Waiting for player..",true)
func _on_join_pressed():
var ip = get_node("panel/address").get_text()
if (not ip.is_valid_ip_address()):
_set_status("IP address is invalid",false)
return
var host = NetworkedMultiplayerENet.new()
host.set_compression_mode(NetworkedMultiplayerENet.COMPRESS_RANGE_CODER)
host.create_client(ip,DEFAULT_PORT)
get_tree().set_network_peer(host)
_set_status("Connecting..",true)
### INITIALIZER ####
func _ready():
# connect all the callbacks related to networking
get_tree().connect("network_peer_connected",self,"_player_connected")
get_tree().connect("network_peer_disconnected",self,"_player_disconnected")
get_tree().connect("connected_to_server",self,"_connected_ok")
get_tree().connect("connection_failed",self,"_connected_fail")
get_tree().connect("server_disconnected",self,"_server_disconnected")

View File

@@ -0,0 +1,145 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://lobby.gd" type="Script" id=1]
[node name="lobby" type="Control"]
margin_right = 40.0
margin_bottom = 40.0
rect_clip_content = false
mouse_filter = 0
size_flags_horizontal = 2
size_flags_vertical = 2
script = ExtResource( 1 )
[node name="title" type="Label" parent="."]
margin_left = 210.0
margin_top = 40.0
margin_right = 430.0
margin_bottom = 80.0
rect_clip_content = false
mouse_filter = 2
size_flags_horizontal = 2
size_flags_vertical = 0
text = "Multiplayer Pong"
align = 1
valign = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="panel" type="Panel" parent="."]
margin_left = 210.0
margin_top = 160.0
margin_right = 430.0
margin_bottom = 270.0
rect_clip_content = false
mouse_filter = 0
size_flags_horizontal = 2
size_flags_vertical = 2
[node name="address_label" type="Label" parent="panel"]
margin_left = 10.0
margin_top = 10.0
margin_right = 62.0
margin_bottom = 24.0
rect_clip_content = false
mouse_filter = 2
size_flags_horizontal = 2
size_flags_vertical = 0
text = "Address"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="address" type="LineEdit" parent="panel"]
margin_left = 10.0
margin_top = 30.0
margin_right = 210.0
margin_bottom = 54.0
rect_clip_content = false
mouse_filter = 0
size_flags_horizontal = 2
size_flags_vertical = 2
text = "127.0.0.1"
expand_to_len = false
focus_mode = 2
placeholder_alpha = 0.6
caret_blink = false
caret_blink_speed = 0.65
[node name="host" type="Button" parent="panel"]
margin_left = 10.0
margin_top = 60.0
margin_right = 90.0
margin_bottom = 80.0
rect_clip_content = false
mouse_filter = 0
size_flags_horizontal = 2
size_flags_vertical = 2
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Host"
flat = false
[node name="join" type="Button" parent="panel"]
margin_left = 130.0
margin_top = 60.0
margin_right = 210.0
margin_bottom = 80.0
rect_clip_content = false
mouse_filter = 0
size_flags_horizontal = 2
size_flags_vertical = 2
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Join"
flat = false
[node name="status_ok" type="Label" parent="panel"]
margin_left = 10.0
margin_top = 90.0
margin_right = 210.0
margin_bottom = 104.0
rect_clip_content = false
mouse_filter = 2
size_flags_horizontal = 2
size_flags_vertical = 0
custom_colors/font_color = Color( 0, 1, 0.015625, 1 )
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="status_fail" type="Label" parent="panel"]
margin_left = 10.0
margin_top = 90.0
margin_right = 210.0
margin_bottom = 104.0
rect_clip_content = false
mouse_filter = 2
size_flags_horizontal = 2
size_flags_vertical = 0
custom_colors/font_color = Color( 1, 0, 0, 1 )
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[connection signal="pressed" from="panel/host" to="." method="_on_host_pressed"]
[connection signal="pressed" from="panel/join" to="." method="_on_join_pressed"]

View File

@@ -0,0 +1,66 @@
extends Area2D
export var left=false
const MOTION_SPEED=150
var motion = 0
var you_hidden=false
onready var screen_size = get_viewport_rect().size
#synchronize position and speed to the other peers
slave func set_pos_and_motion(p_pos,p_motion):
position=p_pos
motion=p_motion
func _hide_you_label():
you_hidden=true
get_node("you").hide()
func _process(delta):
#is the master of the paddle
if (is_network_master()):
motion = 0
if (Input.is_action_pressed("move_up")):
motion -= 1
elif (Input.is_action_pressed("move_down")):
motion += 1
if (not you_hidden and motion!=0):
_hide_you_label()
motion*=MOTION_SPEED
#using unreliable to make sure position is updated as fast as possible, even if one of the calls is dropped
rpc_unreliable("set_pos_and_motion",position,motion)
else:
if (not you_hidden):
_hide_you_label()
translate( Vector2(0,motion*delta) )
# set screen limits
var pos = position
if (pos.y < 0 ):
position = Vector2( pos.x, 0)
elif (pos.y > screen_size.y):
position = Vector2( pos.x, screen_size.y)
func _on_paddle_area_enter( area ):
if (is_network_master()):
area.rpc("bounce",left,randf()) #random for new direction generated on each peer

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

View File

@@ -0,0 +1,23 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/paddle.png-0e798fb0912613386507c9904d5cc01a.stex"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=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
stream=false
size_limit=0
detect_3d=true

View File

@@ -0,0 +1,51 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://paddle.gd" type="Script" id=1]
[ext_resource path="res://paddle.png" type="Texture" id=2]
[sub_resource type="CapsuleShape2D" id=1]
custom_solver_bias = 0.0
radius = 4.78568
height = 23.6064
[node name="paddle" type="Area2D"]
input_pickable = true
shapes/0/shape = SubResource( 1 )
shapes/0/transform = Transform2D( 1, 0, 0, 1, 0, 0 )
shapes/0/trigger = false
gravity_vec = Vector2( 0, 1 )
gravity = 98.0
linear_damp = 0.1
angular_damp = 1.0
script = ExtResource( 1 )
left = false
[node name="sprite" type="Sprite" parent="."]
texture = ExtResource( 2 )
[node name="shape" type="CollisionShape2D" parent="."]
shape = SubResource( 1 )
trigger = false
_update_shape_index = 0
[node name="you" type="Label" parent="."]
focus_ignore_mouse = true
focus_stop_mouse = true
size_flags_horizontal = 2
size_flags_vertical = 0
margin_left = -26.0
margin_top = -33.0
margin_right = 27.0
margin_bottom = -19.0
text = "You"
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[connection signal="area_entered" from="." to="." method="_on_paddle_area_enter" binds=[ ]]

View File

@@ -0,0 +1,52 @@
extends Node2D
const SCORE_TO_WIN=10
var score_left = 0
var score_right = 0
signal game_finished()
sync func update_score(add_to_left):
if (add_to_left):
score_left+=1
get_node("score_left").set_text( str(score_left) )
else:
score_right+=1
get_node("score_right").set_text( str(score_right) )
var game_ended = false
if (score_left==SCORE_TO_WIN):
get_node("winner_left").show()
game_ended=true
elif (score_right==SCORE_TO_WIN):
get_node("winner_right").show()
game_ended=true
if (game_ended):
get_node("exit_game").show()
get_node("ball").rpc("stop")
func _on_exit_game_pressed():
emit_signal("game_finished")
func _ready():
# by default, all nodes in server inherit from master
# while all nodes in clients inherit from slave
if (get_tree().is_network_server()):
#if in the server, get control of player 2 to the other peeer, this function is tree recursive by default
get_node("player2").set_network_master(get_tree().get_network_connected_peers()[0])
else:
#if in the client, give control of player 2 to itself, this function is tree recursive by default
get_node("player2").set_network_master(get_tree().get_network_unique_id())
#let each paddle know which one is left, too
get_node("player1").left=true
get_node("player2").left=false
print("unique id: ",get_tree().get_network_unique_id())

View File

@@ -0,0 +1,120 @@
[gd_scene load_steps=12 format=2]
[ext_resource path="res://pong.gd" type="Script" id=1]
[ext_resource path="res://separator.png" type="Texture" id=2]
[ext_resource path="res://paddle.tscn" type="PackedScene" id=3]
[ext_resource path="res://ball.tscn" type="PackedScene" id=4]
[node name="pong" type="Node2D"]
script = ExtResource( 1 )
[node name="separator" type="Sprite" parent="."]
position = Vector2( 320, 200 )
texture = ExtResource( 2 )
[node name="player1" parent="." instance=ExtResource( 3 )]
position = Vector2( 32.49, 188.622 )
[node name="sprite" parent="player1"]
self_modulate = Color( 1, 0, 0.960938, 1 )
[node name="player2" parent="." instance=ExtResource( 3 )]
position = Vector2( 608.88, 188.622 )
[node name="sprite" parent="player2"]
self_modulate = Color( 0, 0.929688, 1, 1 )
[node name="ball" parent="." instance=ExtResource( 4 )]
position = Vector2( 320.387, 189.525 )
[node name="score_left" type="Label" parent="."]
focus_ignore_mouse = true
focus_stop_mouse = true
size_flags_horizontal = 2
size_flags_vertical = 0
margin_left = 240.0
margin_top = 10.0
margin_right = 280.0
margin_bottom = 30.0
text = "0"
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="score_right" type="Label" parent="."]
focus_ignore_mouse = true
focus_stop_mouse = true
size_flags_horizontal = 2
size_flags_vertical = 0
margin_left = 360.0
margin_top = 10.0
margin_right = 400.0
margin_bottom = 30.0
text = "0"
align = 1
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="winner_left" type="Label" parent="."]
visible = false
focus_ignore_mouse = true
focus_stop_mouse = true
size_flags_horizontal = 2
size_flags_vertical = 0
margin_left = 190.0
margin_top = 170.0
margin_right = 267.0
margin_bottom = 184.0
text = "The Winner!"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="winner_right" type="Label" parent="."]
visible = false
focus_ignore_mouse = true
focus_stop_mouse = true
size_flags_horizontal = 2
size_flags_vertical = 0
margin_left = 380.0
margin_top = 170.0
margin_right = 457.0
margin_bottom = 184.0
text = "The Winner!"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="exit_game" type="Button" parent="."]
visible = false
focus_ignore_mouse = false
focus_stop_mouse = true
size_flags_horizontal = 2
size_flags_vertical = 2
margin_left = 280.0
margin_top = 340.0
margin_right = 360.0
margin_bottom = 360.0
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
text = "Exit Game"
flat = false
[connection signal="pressed" from="exit_game" to="." method="_on_exit_game_pressed" binds=[ ]]
[editable path="player1"]
[editable path="player2"]

View File

@@ -0,0 +1,21 @@
[application]
icon = "res://icon.png"
main_scene = "res://lobby.tscn"
name = "Pong Multiplayer"
[display]
stretch_2d = true
window/height = 400
window/width = 640
[input]
move_down = [ InputEvent(KEY,16777234) ]
move_up = [ InputEvent(KEY,16777232) ]
[rendering]
viewport/default_clear_color = Color( 0, 0, 0, 1 )

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

View File

@@ -0,0 +1,23 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/separator.png-f981c8489b9148e2e1dc63398273da74.stex"
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=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
stream=false
size_limit=0
detect_3d=true