Ejemplo n.º 1
0
        public override void LoadServer(NetSceneDeltaState deltaScene)
        {
            float   startOffset       = 30;
            float   ballSize          = 18;
            var     defaultPaddleSize = new Vector2(18, 70);
            Vector2 worldSize         = Engine.Configuration.RenderSize;

            NetworkPlayer p1 = ServerGame?.Players[0];
            NetworkPlayer p2 = ServerGame?.Players[1];

            _pad1StartingPos = new Vector3(startOffset, worldSize.Y / 2 - defaultPaddleSize.Y / 2, 0);
            _pad1            = new PongPaddle("PaddleOne")
            {
                Position = _pad1StartingPos,
                Size     = defaultPaddleSize,
                Owner    = new NetworkPlayerHandle(p1?.Id),
            };
            AddObject(_pad1);

            _pad2StartingPos = new Vector3(worldSize.X - startOffset - defaultPaddleSize.X, worldSize.Y / 2 - defaultPaddleSize.Y / 2, 0);
            _pad2            = new PongPaddle("PaddleTwo")
            {
                Position = _pad2StartingPos,
                Size     = defaultPaddleSize,
                Owner    = new NetworkPlayerHandle(p2?.Id),
            };
            AddObject(_pad2);

            _ballStartingPos = new Vector3(worldSize.X / 2 - ballSize / 2, worldSize.Y / 2 - ballSize / 2, 0);
            var ball = new PongBall("Ball")
            {
                Position = _ballStartingPos,
                Size     = new Vector2(ballSize)
            };

            AddObject(ball);

            var upperWall = new NetworkTransform("UpperWall")
            {
                Position = new Vector3(-100, 0, 0),
                Size     = new Vector2(worldSize.X + 200, 10)
            };
            var lowerWall = new NetworkTransform("LowerWall")
            {
                Position = new Vector3(-100, worldSize.Y - 10, 0),
                Size     = new Vector2(worldSize.X + 200, 10)
            };

            AddObject(upperWall);
            AddObject(lowerWall);

            _betweenMatchTimer = new After(250);
            _betweenMatchTimer.End();

            _collisionSystem = new PongCollisionProvider(this);

            base.LoadServer(deltaScene);
        }
Ejemplo n.º 2
0
        public override void PostLoadServer(NetSceneDeltaState deltaState)
        {
            for (var i = 0; i < SyncedObjects.Count; i++)
            {
                deltaState[SyncedObjects[i]] = NetworkTransformReadOperation.Update;
            }

            // These walls dont move, so no need to send information about them.
            deltaState[IdToObject["UpperWall"]] = NetworkTransformReadOperation.Skip;
            deltaState[IdToObject["LowerWall"]] = NetworkTransformReadOperation.Skip;
        }
Ejemplo n.º 3
0
        public override void UpdateServer(float delta, NetSceneDeltaState deltaState)
        {
            base.UpdateServer(delta, deltaState);

            if (!_pad1.Ready || !_pad2.Ready)
            {
                return;
            }
            _betweenMatchTimer.Update(delta);
            if (!_betweenMatchTimer.Finished)
            {
                return;
            }

            // Start game.
            var ball = (PongBall)IdToObject["Ball"];

            deltaState[ball] = NetworkTransformReadOperation.Update;
            if (ball.Velocity == Vector3.Zero)
            {
                ball.Velocity = Vector3.Normalize(new Vector3(_p1Turn ? -1 : 1, Helpers.GenerateRandomNumber(-30, 30) / 100.0f, 0));
            }

            // Since the paddles essentially teleport around (when data is received from a client) it is possible
            // for the ball to end up inside one of them. The collision system cannot resolve cases like this, so
            // we have to manually snap the ball towards the smaller overlap.
            Rectangle ballBound         = ball.Bounds;
            var       collidingPadBound = new Rectangle(0, 0, 0, 0);
            Rectangle pad1Bound         = _pad1.GetPaddleBound();
            Rectangle pad2Bound         = _pad2.GetPaddleBound();

            if (ballBound.Intersects(pad1Bound))
            {
                collidingPadBound = pad1Bound;
            }
            else if (ballBound.Intersects(pad2Bound))
            {
                collidingPadBound = pad2Bound;
            }
            if (collidingPadBound.Size != Vector2.Zero)
            {
                Vector2 intersectionDepth = ballBound.GetIntersectionDepth(ref collidingPadBound);
                ballBound.Position += intersectionDepth;
                ball.Bounds         = ballBound;
            }

            // Resolve ball collision.
            var     velocity2d = new Vector2(ball.Velocity.X, ball.Velocity.Y);
            Vector2 movement   = velocity2d * _ballSpeed * delta;

            _collisionSystem.Me = ball;
            Collision.CollisionResult <NetworkTransform> collisionResult = Collision.IncrementalGenericSegmentCollision(movement, ballBound, _collisionSystem);
            Vector2 movementAllowed = collisionResult.UnobstructedMovement;

            if (collisionResult.Collided)
            {
                Vector2 normal = collisionResult.CollidedSurfaceNormal;
                ball.Velocity = Vector2.Reflect(velocity2d, normal).ToVec3(); // (2 * Vector2.Dot(velocity2d, normal) * normal - velocity2d) * -1;
                _ballSpeed    = MathF.Min(_ballSpeed + 0.05f, 0.8f);
                if (collisionResult.UnobstructedMovement == Vector2.Zero)
                {
                    movementAllowed = ball.Velocity.ToVec2() * _ballSpeed * delta;
                }
            }

            ball.X += movementAllowed.X;
            ball.Y += movementAllowed.Y;

            // Velocity and position corrections.
            if (ball.Y < 10)
            {
                ball.Position = _ballStartingPos;
            }
            if (ball.Y + ball.Height > Engine.Configuration.RenderSize.Y)
            {
                ball.Position = _ballStartingPos;
            }
            if (MathF.Abs(ball.Velocity.X) < 0.5f)
            {
                ball.Velocity.X = 0.5f * MathF.Sign(ball.Velocity.X);
                ball.Velocity   = Vector3.Normalize(ball.Velocity);
            }

            // Check if anyone has scored.
            var restart = false;

            if (ball.X + ball.Width < 0)
            {
                _pad2.Score++;
                restart = true;
                _p1Turn = true;
            }
            else if (ball.X > Engine.Configuration.RenderSize.X)
            {
                _pad1.Score++;
                restart = true;
                _p1Turn = false;
            }

            if (restart)
            {
                _pad1.Position = _pad1StartingPos;
                _pad2.Position = _pad2StartingPos;
                ball.Position  = _ballStartingPos;
                ball.Velocity  = Vector3.Zero;
                _betweenMatchTimer.Restart();
                _ballSpeed = 0.3f;

                // Force update all objects, because they teleported.
                deltaState[_pad1] = NetworkTransformReadOperation.UpdateForce;
                deltaState[_pad2] = NetworkTransformReadOperation.UpdateForce;
                deltaState[ball]  = NetworkTransformReadOperation.UpdateForce;
            }
        }
Ejemplo n.º 4
0
 public override void PreServerUpdate(NetSceneDeltaState deltaState)
 {
     deltaState[_pad1] = NetworkTransformReadOperation.Update;
     deltaState[_pad2] = NetworkTransformReadOperation.Update;
 }