Background, platform, more networking

- Add background which scrolls with viewport
- Remove box made of blocks, use simple platform
- Players below y > 9000 are teleported back
- Add a couple of Network shorthand properties:
  - IsMultiplayerReady - Is multiplayer fully ready?
  - IsAuthoratative - Is singleplayer or server?
  - Players - Enumerable of all current players
- Make LocalPlayer.Velocity public
- Add LocalPlayer.ResetPosition call
- Rpc and Rset extension methods now use
  Network shorthands and Player instances
main
copygirl 5 years ago
parent e1d83a4af1
commit 7a5d8ac29e
  1. BIN
      gfx/background.png
  2. 34
      gfx/background.png.import
  3. 17
      scene/GameScene.tscn
  4. 2
      scene/LocalPlayer.tscn
  5. 14
      src/Background.cs
  6. 2
      src/EscapeMenuAppearance.cs
  7. 43
      src/Extensions.cs
  8. 19
      src/Game.cs
  9. 21
      src/LocalPlayer.cs
  10. 6
      src/Network.cs
  11. 16
      src/Player.cs

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/background.png-34463f2717b0502091d019b33ae7e4f3.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://gfx/background.png"
dest_files=[ "res://.import/background.png-34463f2717b0502091d019b33ae7e4f3.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=1
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

@ -1,4 +1,4 @@
[gd_scene load_steps=10 format=2]
[gd_scene load_steps=12 format=2]
[ext_resource path="res://scene/EscapeMenu.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/Cursor.cs" type="Script" id=2]
@ -9,6 +9,8 @@
[ext_resource path="res://src/Viewport.cs" type="Script" id=7]
[ext_resource path="res://src/Network.cs" type="Script" id=8]
[ext_resource path="res://scene/Player.tscn" type="PackedScene" id=9]
[ext_resource path="res://gfx/background.png" type="Texture" id=10]
[ext_resource path="res://src/Background.cs" type="Script" id=11]
[node name="Game" type="Node"]
script = ExtResource( 3 )
@ -22,6 +24,19 @@ script = ExtResource( 8 )
PlayerContainerPath = NodePath("../Players")
OtherPlayerScene = ExtResource( 9 )
[node name="Background" type="TextureRect" parent="."]
modulate = Color( 0.278431, 0.286275, 0.301961, 1 )
margin_left = 1.0
margin_top = -1.0
margin_right = 1281.0
margin_bottom = 719.0
texture = ExtResource( 10 )
stretch_mode = 2
script = ExtResource( 11 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Players" type="Node" parent="."]
[node name="LocalPlayer" parent="Players" instance=ExtResource( 5 )]

@ -6,5 +6,5 @@
[node name="LocalPlayer" instance=ExtResource( 1 )]
script = ExtResource( 3 )
[node name="Camera2D" type="Camera2D" parent="." index="0"]
[node name="Camera" type="Camera2D" parent="." index="0"]
current = true

@ -0,0 +1,14 @@
using Godot;
public class Background : TextureRect
{
public override void _Process(float delta)
{
var offset = new Vector2(8, 8);
var tileSize = Texture.GetSize();
var viewportSize = GetViewport().Size;
var camera = LocalPlayer.Instance.GetNode<Camera2D>("Camera");
RectPosition = ((camera.GlobalPosition - viewportSize / 2) / tileSize).Floor() * tileSize - offset;
RectSize = ((viewportSize + offset) / tileSize + Vector2.One).Ceil() * tileSize;
}
}

@ -17,7 +17,7 @@ public class EscapeMenuAppearance : CenterContainer
ColorPreview = GetNode<TextureRect>(ColorPreviewPath);
ColorSlider = GetNode<Slider>(ColorSliderPath);
ColorSlider.Value = GD.RandRange(0.0, 1.0);
ColorSlider.Value = GD.Randf();
var color = Color.FromHsv((float)ColorSlider.Value, 1.0F, 1.0F);
LocalPlayer.Instance.Color = ColorPreview.Modulate = color;
}

@ -14,43 +14,40 @@ public static class Extensions
}
public static void Rset(this Node @this, int except, string property, string method, object value)
public static void RsetProperty(this Node @this, Node propertyOwner, string property, string method, object value)
{
if (@this.IsInsideTree() && @this.GetTree().NetworkPeer != null) {
if (@this.GetTree().IsNetworkServer())
@this.RsetExcept(except, property, value);
else if (Network.Status == NetworkStatus.ConnectedToServer)
@this.RpcId(1, method, value);
}
if (!@this.IsInsideTree()) return;
if (Network.IsServer) propertyOwner.RsetExcept(@this as Player, property, value);
else if (Network.IsMultiplayerReady) @this.RpcId(1, method, value);
}
public static void RsetUnreliable(this Node @this, int except, string property, string method, object value)
public static void RsetPropertyUnreliable(this Node @this, Node propertyOwner, string property, string method, object value)
{
if (@this.IsInsideTree() && @this.GetTree().NetworkPeer != null) {
if (@this.GetTree().IsNetworkServer())
@this.RsetUnreliableExcept(except, property, value);
else if (Network.Status == NetworkStatus.ConnectedToServer)
@this.RpcUnreliableId(1, method, value);
}
if (!@this.IsInsideTree()) return;
if (Network.IsServer) propertyOwner.RsetUnreliableExcept(@this as Player, property, value);
else if (Network.IsMultiplayerReady) @this.RpcUnreliableId(1, method, value);
}
public static void RpcExcept(this Node @this, int except, string method, params object[] args)
public static void RpcExcept(this Node @this, Player except, string method, params object[] args)
{
foreach (var peer in @this.GetTree().GetNetworkConnectedPeers())
if (peer != except) @this.RpcId(peer, method, args);
foreach (var player in Network.Players)
if (player != except)
@this.RpcId(player.NetworkId, method, args);
}
public static void RsetUnreliableExcept(this Node @this, int except, string property, object value)
public static void RsetExcept(this Node @this, Player except, string property, object value)
{
foreach (var peer in @this.GetTree().GetNetworkConnectedPeers())
if (peer != except) @this.RsetUnreliableId(peer, property, value);
foreach (var player in Network.Players)
if (player != except)
@this.RsetId(player.NetworkId, property, value);
}
public static void RsetExcept(this Node @this, int except, string property, object value)
public static void RsetUnreliableExcept(this Node @this, Player except, string property, object value)
{
foreach (var peer in @this.GetTree().GetNetworkConnectedPeers())
if (peer != except) @this.RsetId(peer, property, value);
foreach (var player in Network.Players)
if (player != except)
@this.RsetUnreliableId(player.NetworkId, property, value);
}
}

@ -4,7 +4,6 @@ public class Game : Node
{
public static Game Instance { get; private set; }
[Export] public Vector2 RoomSize { get; set; } = new Vector2(32, 18) * 16;
[Export] public PackedScene BlockScene { get; set; }
public Game() => Instance = this;
@ -18,23 +17,11 @@ public class Game : Node
private void SpawnBlocks()
{
void SpawnBlockAt(int x, int y)
{
for (var x = -6; x <= 6; x++) {
var block = BlockScene.Init<Node2D>();
block.Position = new Vector2(x, y);
block.Position = new Vector2(x * 16, 48);
block.Modulate = Color.FromHsv(GD.Randf(), 0.1F, 1.0F);
AddChild(block);
}
// Top and bottom.
for (var x = (int)RoomSize.x / -2; x <= (int)RoomSize.x / 2; x += 16) {
SpawnBlockAt(x, (int)RoomSize.y / -2);
SpawnBlockAt(x, (int)RoomSize.y / 2);
}
// Left and right.
for (var y = (int)RoomSize.y / -2 + 16; y <= (int)RoomSize.y / 2 - 16; y += 16) {
SpawnBlockAt((int)RoomSize.x / -2, y);
SpawnBlockAt((int)RoomSize.x / 2, y);
}
}
}

@ -17,7 +17,7 @@ public class LocalPlayer : Player
[Export(PropertyHint.Range, "0,1")]
public float Acceleration { get; set; } = 0.25F;
private Vector2 _velocity = Vector2.Zero;
public Vector2 Velocity = Vector2.Zero;
private DateTime? _jumpPressed = null;
private DateTime? _lastOnFloor = null;
@ -27,10 +27,10 @@ public class LocalPlayer : Player
public override void _PhysicsProcess(float delta)
{
var moveDir = Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left");
_velocity.x = (moveDir != 0) ? Mathf.Lerp(_velocity.x, moveDir * Speed, Acceleration)
: Mathf.Lerp(_velocity.x, 0, Friction);
_velocity.y += Gravity * delta;
_velocity = MoveAndSlide(_velocity, Vector2.Up);
Velocity.x = (moveDir != 0) ? Mathf.Lerp(Velocity.x, moveDir * Speed, Acceleration)
: Mathf.Lerp(Velocity.x, 0, Friction);
Velocity.y += Gravity * delta;
Velocity = MoveAndSlide(Velocity, Vector2.Up);
if (Input.IsActionJustPressed("move_jump"))
_jumpPressed = DateTime.Now;
@ -39,9 +39,18 @@ public class LocalPlayer : Player
if (((DateTime.Now - _jumpPressed) <= JumpEarlyTime) &&
((DateTime.Now - _lastOnFloor) <= JumpCoyoteTime)) {
_velocity.y = -JumpSpeed;
Velocity.y = -JumpSpeed;
_jumpPressed = null;
_lastOnFloor = null;
}
}
internal void ResetPositionInternal(Vector2 position)
{
Position = position;
Velocity = Vector2.Zero;
}
[Puppet]
internal void ResetPosition(Vector2 position)
=> ResetPositionInternal(position);
}

@ -18,8 +18,11 @@ public class Network : Node
public static Network Instance { get; private set; }
public static NetworkStatus Status { get; private set; } = NetworkStatus.NoConnection;
public static bool IsServer => Instance.GetTree().IsNetworkServer();
public static bool IsMultiplayerReady => (Status == NetworkStatus.ServerRunning) || (Status == NetworkStatus.ConnectedToServer);
public static bool IsAuthoratative => Status <= NetworkStatus.ServerRunning;
public static bool IsServer => Status == NetworkStatus.ServerRunning;
public static int LocalNetworkId => Instance.GetTree().GetNetworkUniqueId();
public static IEnumerable<Player> Players => Instance._playersById.Values;
private readonly Dictionary<int, Player> _playersById = new Dictionary<int, Player>();
@ -162,6 +165,7 @@ public class Network : Node
EmitSignal(nameof(StatusChanged), Status);
LocalPlayer.Instance.Position = position;
LocalPlayer.Instance.Velocity = Vector2.Zero;
return LocalPlayer.Instance;
}

@ -24,7 +24,7 @@ public class Player : KinematicBody2D, IInitializer
get => Sprite.Modulate;
set {
Sprite.Modulate = value;
Sprite.Rset(NetworkId, "modulate", nameof(OnColorChanged), value);
this.RsetProperty(Sprite, "modulate", nameof(OnColorChanged), value);
}
}
@ -32,7 +32,7 @@ public class Player : KinematicBody2D, IInitializer
get => DisplayNameLabel.Text;
set {
DisplayNameLabel.Text = value;
DisplayNameLabel.Rset(NetworkId, "text", nameof(OnDisplayNameChanged), value);
this.RsetProperty(DisplayNameLabel, "text", nameof(OnDisplayNameChanged), value);
}
}
@ -54,11 +54,19 @@ public class Player : KinematicBody2D, IInitializer
}
public override void _Process(float delta)
=> this.RsetUnreliable(NetworkId, "position", nameof(OnPositionChanged), Position);
{
this.RsetPropertyUnreliable(this, "position", nameof(OnPositionChanged), Position);
if (Network.IsAuthoratative && (Position.y > 9000)) {
if (this is LocalPlayer localPlayer) localPlayer.ResetPositionInternal(Vector2.Zero);
else RpcId(NetworkId, nameof(LocalPlayer.ResetPosition), Vector2.Zero);
}
}
[Master]
private void OnPositionChanged(Vector2 value)
{ if (GetTree().GetRpcSenderId() == NetworkId) Position = value; }
{ if (GetTree().GetRpcSenderId() == NetworkId) Position = value.Floor(); }
[Master]
private void OnColorChanged(Color value)

Loading…
Cancel
Save