godot-demo-projects/mono/multiplayer_pong/logic/Ball.cs

98 lines
2.8 KiB
C#

using Godot;
using System;
public partial 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;
}
}