diff --git a/2d/pong/left_pallete.png b/2d/pong/left_pallete.png
deleted file mode 100644
index a44c5bba..00000000
Binary files a/2d/pong/left_pallete.png and /dev/null differ
diff --git a/2d/pong/paddle.png b/2d/pong/paddle.png
new file mode 100644
index 00000000..1860b074
Binary files /dev/null and b/2d/pong/paddle.png differ
diff --git a/mono/pong/left_pallete.png.import b/2d/pong/paddle.png.import
similarity index 70%
rename from mono/pong/left_pallete.png.import
rename to 2d/pong/paddle.png.import
index c546b14c..8abc1c7c 100644
--- a/mono/pong/left_pallete.png.import
+++ b/2d/pong/paddle.png.import
@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
-path="res://.import/left_pallete.png-bc33611074a0f886142e37c77bd2545a.stex"
+path="res://.import/paddle.png-0e798fb0912613386507c9904d5cc01a.stex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://left_pallete.png"
-dest_files=[ "res://.import/left_pallete.png-bc33611074a0f886142e37c77bd2545a.stex" ]
+source_file="res://paddle.png"
+dest_files=[ "res://.import/paddle.png-0e798fb0912613386507c9904d5cc01a.stex" ]
[params]
diff --git a/2d/pong/pong.tscn b/2d/pong/pong.tscn
index ee2f72e0..7490b280 100644
--- a/2d/pong/pong.tscn
+++ b/2d/pong/pong.tscn
@@ -1,8 +1,7 @@
-[gd_scene load_steps=13 format=2]
+[gd_scene load_steps=12 format=2]
[ext_resource path="res://logic/paddle.gd" type="Script" id=1]
-[ext_resource path="res://left_pallete.png" type="Texture" id=2]
-[ext_resource path="res://right_pallete.png" type="Texture" id=3]
+[ext_resource path="res://paddle.png" type="Texture" id=2]
[ext_resource path="res://logic/ball.gd" type="Script" id=4]
[ext_resource path="res://ball.png" type="Texture" id=5]
[ext_resource path="res://separator.png" type="Texture" id=6]
@@ -32,6 +31,7 @@ __meta__ = {
}
[node name="Left" type="Area2D" parent="."]
+modulate = Color( 0, 1, 1, 1 )
position = Vector2( 67.6285, 192.594 )
script = ExtResource( 1 )
@@ -42,11 +42,12 @@ texture = ExtResource( 2 )
shape = SubResource( 1 )
[node name="Right" type="Area2D" parent="."]
+modulate = Color( 1, 0, 1, 1 )
position = Vector2( 563.815, 188.919 )
script = ExtResource( 1 )
[node name="Sprite" type="Sprite" parent="Right"]
-texture = ExtResource( 3 )
+texture = ExtResource( 2 )
[node name="Collision" type="CollisionShape2D" parent="Right"]
shape = SubResource( 1 )
diff --git a/2d/pong/right_pallete.png b/2d/pong/right_pallete.png
deleted file mode 100644
index 4a583eac..00000000
Binary files a/2d/pong/right_pallete.png and /dev/null differ
diff --git a/2d/pong/right_pallete.png.import b/2d/pong/right_pallete.png.import
deleted file mode 100644
index 4b442ffb..00000000
--- a/2d/pong/right_pallete.png.import
+++ /dev/null
@@ -1,34 +0,0 @@
-[remap]
-
-importer="texture"
-type="StreamTexture"
-path="res://.import/right_pallete.png-fc6e4a6a7c8197834656482b94708e47.stex"
-metadata={
-"vram_texture": false
-}
-
-[deps]
-
-source_file="res://right_pallete.png"
-dest_files=[ "res://.import/right_pallete.png-fc6e4a6a7c8197834656482b94708e47.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
diff --git a/mono/multiplayer_pong/Pong Multiplayer with C#.csproj b/mono/multiplayer_pong/Pong Multiplayer with C#.csproj
new file mode 100644
index 00000000..ffaa5571
--- /dev/null
+++ b/mono/multiplayer_pong/Pong Multiplayer with C#.csproj
@@ -0,0 +1,6 @@
+
+
+ net472
+ PongMultiplayer
+
+
\ No newline at end of file
diff --git a/mono/multiplayer_pong/Pong Multiplayer with C#.sln b/mono/multiplayer_pong/Pong Multiplayer with C#.sln
new file mode 100644
index 00000000..158b1317
--- /dev/null
+++ b/mono/multiplayer_pong/Pong Multiplayer with C#.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pong Multiplayer with C#", "Pong Multiplayer with C#.csproj", "{4BB6C2D0-FC11-466E-8C73-8DAD689F135A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ ExportDebug|Any CPU = ExportDebug|Any CPU
+ ExportRelease|Any CPU = ExportRelease|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
+ {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
+ {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
+ {4BB6C2D0-FC11-466E-8C73-8DAD689F135A}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/mono/multiplayer_pong/README.md b/mono/multiplayer_pong/README.md
new file mode 100644
index 00000000..38f21dab
--- /dev/null
+++ b/mono/multiplayer_pong/README.md
@@ -0,0 +1,13 @@
+# Pong Multiplayer with C#
+
+A multiplayer demo of Pong. One player presses "host". The other presses "join". This only works locally.
+
+Language: [C#](https://docs.godotengine.org/en/latest/getting_started/scripting/c_sharp/index.html)
+
+Renderer: GLES 2
+
+Note: There is a GDScript version available [here](https://github.com/godotengine/godot-demo-projects/tree/master/networking/multiplayer_pong).
+
+## Screenshots
+
+
diff --git a/mono/multiplayer_pong/ball.png b/mono/multiplayer_pong/ball.png
new file mode 100644
index 00000000..465d3521
Binary files /dev/null and b/mono/multiplayer_pong/ball.png differ
diff --git a/2d/pong/left_pallete.png.import b/mono/multiplayer_pong/ball.png.import
similarity index 70%
rename from 2d/pong/left_pallete.png.import
rename to mono/multiplayer_pong/ball.png.import
index a80bf581..f239f238 100644
--- a/2d/pong/left_pallete.png.import
+++ b/mono/multiplayer_pong/ball.png.import
@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
-path="res://.import/left_pallete.png-bc33611074a0f886142e37c77bd2545a.stex"
+path="res://.import/ball.png-9a4ca347acb7532f6ae347744a6b04f7.stex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://left_pallete.png"
-dest_files=[ "res://.import/left_pallete.png-bc33611074a0f886142e37c77bd2545a.stex" ]
+source_file="res://ball.png"
+dest_files=[ "res://.import/ball.png-9a4ca347acb7532f6ae347744a6b04f7.stex" ]
[params]
diff --git a/mono/multiplayer_pong/ball.tscn b/mono/multiplayer_pong/ball.tscn
new file mode 100644
index 00000000..efafb9ad
--- /dev/null
+++ b/mono/multiplayer_pong/ball.tscn
@@ -0,0 +1,16 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://ball.png" type="Texture" id=1]
+[ext_resource path="res://logic/Ball.cs" type="Script" id=2]
+
+[sub_resource type="CircleShape2D" id=1]
+radius = 4.65663
+
+[node name="Ball" type="Area2D"]
+script = ExtResource( 2 )
+
+[node name="Sprite" type="Sprite" parent="."]
+texture = ExtResource( 1 )
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+shape = SubResource( 1 )
diff --git a/mono/multiplayer_pong/icon.png b/mono/multiplayer_pong/icon.png
new file mode 100644
index 00000000..b62e834e
Binary files /dev/null and b/mono/multiplayer_pong/icon.png differ
diff --git a/mono/pong/right_pallete.png.import b/mono/multiplayer_pong/icon.png.import
similarity index 69%
rename from mono/pong/right_pallete.png.import
rename to mono/multiplayer_pong/icon.png.import
index d94086b3..96cbf462 100644
--- a/mono/pong/right_pallete.png.import
+++ b/mono/multiplayer_pong/icon.png.import
@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
-path="res://.import/right_pallete.png-fc6e4a6a7c8197834656482b94708e47.stex"
+path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://right_pallete.png"
-dest_files=[ "res://.import/right_pallete.png-fc6e4a6a7c8197834656482b94708e47.stex" ]
+source_file="res://icon.png"
+dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
[params]
diff --git a/mono/multiplayer_pong/lobby.tscn b/mono/multiplayer_pong/lobby.tscn
new file mode 100644
index 00000000..2acae0af
--- /dev/null
+++ b/mono/multiplayer_pong/lobby.tscn
@@ -0,0 +1,102 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://logic/Lobby.cs" type="Script" id=1]
+
+[node name="Lobby" type="Control"]
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_left = -320.0
+margin_top = -200.0
+margin_right = 320.0
+margin_bottom = 200.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Title" type="Label" parent="."]
+margin_left = 210.0
+margin_top = 40.0
+margin_right = 430.0
+margin_bottom = 80.0
+size_flags_horizontal = 2
+size_flags_vertical = 0
+text = "Multiplayer Pong"
+align = 1
+valign = 1
+
+[node name="LobbyPanel" type="Panel" parent="."]
+margin_left = 210.0
+margin_top = 160.0
+margin_right = 430.0
+margin_bottom = 270.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+script = ExtResource( 1 )
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="AddressLabel" type="Label" parent="LobbyPanel"]
+margin_left = 10.0
+margin_top = 10.0
+margin_right = 62.0
+margin_bottom = 24.0
+size_flags_horizontal = 2
+size_flags_vertical = 0
+text = "Address"
+
+[node name="Address" type="LineEdit" parent="LobbyPanel"]
+margin_left = 10.0
+margin_top = 30.0
+margin_right = 210.0
+margin_bottom = 54.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "127.0.0.1"
+
+[node name="HostButton" type="Button" parent="LobbyPanel"]
+margin_left = 10.0
+margin_top = 60.0
+margin_right = 90.0
+margin_bottom = 80.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Host"
+
+[node name="JoinButton" type="Button" parent="LobbyPanel"]
+margin_left = 130.0
+margin_top = 60.0
+margin_right = 210.0
+margin_bottom = 80.0
+size_flags_horizontal = 2
+size_flags_vertical = 2
+text = "Join"
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="StatusOk" type="Label" parent="LobbyPanel"]
+margin_left = 10.0
+margin_top = 90.0
+margin_right = 210.0
+margin_bottom = 104.0
+size_flags_horizontal = 2
+size_flags_vertical = 0
+custom_colors/font_color = Color( 0, 1, 0.015625, 1 )
+align = 1
+
+[node name="StatusFail" type="Label" parent="LobbyPanel"]
+margin_left = 10.0
+margin_top = 90.0
+margin_right = 210.0
+margin_bottom = 104.0
+size_flags_horizontal = 2
+size_flags_vertical = 0
+custom_colors/font_color = Color( 1, 0, 0, 1 )
+align = 1
+[connection signal="pressed" from="LobbyPanel/HostButton" to="LobbyPanel" method="OnHostPressed"]
+[connection signal="pressed" from="LobbyPanel/JoinButton" to="LobbyPanel" method="OnJoinPressed"]
diff --git a/mono/multiplayer_pong/logic/Ball.cs b/mono/multiplayer_pong/logic/Ball.cs
new file mode 100644
index 00000000..62463308
--- /dev/null
+++ b/mono/multiplayer_pong/logic/Ball.cs
@@ -0,0 +1,97 @@
+using Godot;
+using System;
+
+public class Ball : Area2D
+{
+ private const int DefaultSpeed = 100;
+
+ private Vector2 _direction = Vector2.Left;
+ private bool _stopped = false;
+ private float _speed = DefaultSpeed;
+ private Vector2 _screenSize;
+
+ // Called when the node enters the scene tree for the first time.
+ public override void _Ready()
+ {
+ _screenSize = GetViewportRect().Size;
+ }
+
+ // Called every frame. 'delta' is the elapsed time since the previous frame.
+ public override void _Process(float delta)
+ {
+ _speed += delta;
+ // Ball will move normally for both players,
+ // even if it's slightly out of sync between them,
+ // so each player sees the motion as smooth and not jerky.
+ if (!_stopped)
+ {
+ Translate(_speed * delta * _direction);
+ }
+
+ // Check screen bounds to make ball bounce.
+ var ballPosition = Position;
+ if ((ballPosition.y < 0 && _direction.y < 0) || (ballPosition.y > _screenSize.y && _direction.y > 0))
+ {
+ _direction.y = -_direction.y;
+ }
+
+ if (IsNetworkMaster())
+ {
+ // Only the 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 (ballPosition.x < 0)
+ {
+ GetParent().Rpc("UpdateScore", false);
+ Rpc("ResetBall", false);
+ }
+ else
+ {
+ // Only the puppet will decide when the ball is out in
+ // the right side, which is 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 (ballPosition.x > _screenSize.x)
+ {
+ GetParent().Rpc("UpdateScore", true);
+ Rpc("ResetBall", true);
+ }
+ }
+ }
+ }
+
+ [Sync]
+ private void Bounce(bool left, float random)
+ {
+ // Using sync because both players can make it bounce.
+ if (left)
+ {
+ _direction.x = Mathf.Abs(_direction.x);
+ }
+ else
+ {
+ _direction.x = -Mathf.Abs(_direction.x);
+ }
+
+ _speed *= 1.1f;
+ _direction.y = random * 2.0f - 1;
+ _direction = _direction.Normalized();
+ }
+
+ [Sync]
+ private void Stop()
+ {
+ _stopped = true;
+ }
+
+ [Sync]
+ private void ResetBall(bool forLeft)
+ {
+ Position = _screenSize / 2;
+ _direction = forLeft ? Vector2.Left : Vector2.Right;
+ _speed = DefaultSpeed;
+ }
+}
diff --git a/mono/multiplayer_pong/logic/Lobby.cs b/mono/multiplayer_pong/logic/Lobby.cs
new file mode 100644
index 00000000..c770eb1f
--- /dev/null
+++ b/mono/multiplayer_pong/logic/Lobby.cs
@@ -0,0 +1,143 @@
+using Godot;
+using System;
+using Godot.Collections;
+
+public class Lobby : Control
+{
+ private const int DefaultPort = 8910; // An arbitrary number.
+ private const int MaxNumberOfPeers = 1; // How many people we want to have in a game
+
+ private LineEdit _address;
+ private Button _hostButton;
+ private Button _joinButton;
+ private Label _statusOk;
+ private Label _statusFail;
+ private NetworkedMultiplayerENet _peer;
+
+ public override void _Ready()
+ {
+ // Get nodes - the generic is a class, argument is node path.
+ _address = GetNode("Address");
+ _hostButton = GetNode