예제 #1
0
 private void HandleGrabMove(GrabInfo data, Player player, IInteractionDelegate @delegate)
 {
     if (this.Grabbables.TryGetValue(data.GrabbableId, out IGrabbable grabbable))
     {
         grabbable.Move(data.CameraInfo);
     }
 }
예제 #2
0
        public void Update(CameraInfo cameraInfo)
        {
            if (this.Delegate == null || this.GrabDelegate == null)
            {
                throw new Exception("No Delegate");
            }

            // Dispatch grab action to server so that server can test if grab succeed.
            // If grab succeed, server would update the grabbable's player for all clients
            // Note:
            // This check is done in update to counter the case of network lag
            // if touch down and up is very quick, the shouldTryRelease might not trigger right at touch up,
            // because information on grabbed grabbableID might not arrived yet
            if (this.isTouching && this.GrabbedGrabbable == null)
            {
                if (GameTime.FrameCount % 3 == 0) // Only send messages at 20 fps to save bandwidth
                {
                    // Send grab message to server if player can grab something
                    var grabbable = this.GrabbableToGrab(cameraInfo.Ray);
                    if (grabbable != null)
                    {
                        var grab = new GrabInfo(grabbable.GrabbableId, cameraInfo);
                        this.Delegate.DispatchActionToServer(new GameActionType {
                            TryGrab = grab, Type = GameActionType.GActionType.TryGrab
                        });
                        return;
                    }
                }
            }

            if (this.GrabbedGrabbable != null)
            {
                if (!this.Delegate.IsServer)
                {
                    // Client move the sling locally, ignore server's physics data to prevent lag
                    this.GrabbedGrabbable.Move(cameraInfo);
                }

                // If touch is up or the sling is pulled too far, release the ball
                if (!this.isTouching || this.GrabDelegate.ShouldForceRelease(this.GrabbedGrabbable))
                {
                    if (GameTime.FrameCount % 3 == 0)// Only send messages at 20 fps to save bandwidth
                    {
                        var grab = new GrabInfo(this.GrabbedGrabbable.GrabbableId, cameraInfo);
                        this.Delegate.DispatchActionToServer(new GameActionType {
                            TryRelease = grab, Type = GameActionType.GActionType.TryRelease
                        });
                        return;
                    }
                }

                // Dispatch slingMove to server.
                var data = new GrabInfo(this.GrabbedGrabbable.GrabbableId, cameraInfo);
                this.Delegate.DispatchActionToServer(new GameActionType {
                    GrabMove = data, Type = GameActionType.GActionType.GrabMove
                });
            }
        }
예제 #3
0
        private void HandleGrabStartAction(GrabInfo data, Player player, IInteractionDelegate @delegate)
        {
            if (this.GrabDelegate == null)
            {
                throw new Exception("GrabDelegate not set");
            }

            var grabbable = this.GrabbableById(data.GrabbableId);

            this.GrabbedGrabbable = grabbable;
            this.GrabDelegate.OnGrabStart(grabbable, data.CameraInfo, player);
        }
예제 #4
0
        private void HandleGrabbableStatus(GrabInfo status)
        {
            if (this.GrabDelegate == null)
            {
                throw new Exception("GrabDelegate not set");
            }

            if (!this.Grabbables.TryGetValue(status.GrabbableId, out IGrabbable grabbable))
            {
                throw new Exception($"No Grabbable {status.GrabbableId}");
            }

            grabbable.IsGrabbed = true;
            this.GrabDelegate.OnUpdateGrabStatus(grabbable, status.CameraInfo);
        }
예제 #5
0
        public void DidCollision(SCNNode node, SCNNode otherNode, SCNVector3 pos, float impulse)
        {
            var gameObject = node.NearestParentGameObject();

            if (gameObject != null && gameObject is Catapult catapult)
            {
                var otherGameObject = otherNode.NearestParentGameObject();
                if (otherGameObject != null)
                {
                    // Projectile case
                    if (otherGameObject is Projectile projectile)
                    {
                        var catapultNode = catapult.Base;
                        if (catapultNode.PhysicsBody == null)
                        {
                            throw new Exception("Catapult has no physicsBody");
                        }

                        // Do not let projectile from the same team kill the catapult
                        if (catapult.Team == projectile.Team)
                        {
                            catapultNode.PhysicsBody.Velocity        = SCNVector3.Zero;
                            catapultNode.PhysicsBody.AngularVelocity = SCNVector4.UnitY;
                        }
                    }

                    // Server tries to release the catapult if it got impulse from block or projectile
                    if (impulse > MinImpuseToReleaseCatapult)
                    {
                        if (this.Delegate == null)
                        {
                            throw new Exception("No delegate");
                        }

                        if (this.Delegate.IsServer)
                        {
                            // Any game objects (blocks or projectiles) case
                            var data = new GrabInfo(catapult.CatapultId, catapult.LastCameraInfo);
                            this.Delegate.DispatchActionToServer(new GameActionType {
                                TryRelease = data, Type = GameActionType.GActionType.TryRelease
                            });
                        }
                    }
                }
            }
        }
예제 #6
0
        private void HandleTryGrabAction(GrabInfo data, Player player, IInteractionDelegate @delegate)
        {
            if (this.GrabDelegate == null)
            {
                throw new Exception("GrabDelegate not set");
            }

            // since we can't send a message only to the server, make sure we're the server
            // when processing.
            if (@delegate.IsServer)
            {
                // Check if player already owned a grabbable
                // This is to filter tryGrab messages a player might send because it has not received grab message yet
                foreach (var value in this.Grabbables.Values)
                {
                    if (value.Player != null && value.Player == player)
                    {
                        return;
                    }
                }

                var grabbable = this.GrabbableById(data.GrabbableId);
                this.GrabDelegate.OnServerGrab(grabbable, data.CameraInfo, player);
                grabbable.Player = player;

                // Inform player that the grabbable was grabbed
                var newData = new GrabInfo(grabbable.GrabbableId, data.CameraInfo);
                @delegate.DispatchToPlayer(new GameActionType {
                    GrabStart = newData, Type = GameActionType.GActionType.GrabStart
                }, player);

                // Update grabbable in the server and clients with a new status
                // Note: status update only sends the information on whether
                this.HandleGrabbableStatus(newData);
                @delegate.ServerDispatchActionToAll(new GameActionType {
                    GrabbableStatus = newData, Type = GameActionType.GActionType.GrabbableStatus
                });
            }
        }
예제 #7
0
        private void HandleTryReleaseAction(GrabInfo data, Player player, IInteractionDelegate @delegate)
        {
            if (this.GrabDelegate == null)
            {
                throw new Exception("GrabDelegate not set");
            }

            if (this.Delegate.IsServer)
            {
                // Launch if player already grabbed a grabbable
                var grabbable = this.GrabbableById(data.GrabbableId);
                if (grabbable.IsGrabbed)
                {
                    this.GrabDelegate.OnServerRelease(grabbable, data.CameraInfo, player);

                    // Inform player that the grabbable was grabbed
                    var newData = new GrabInfo(grabbable.GrabbableId, data.CameraInfo);
                    @delegate.DispatchToPlayer(new GameActionType {
                        ReleaseEnd = newData, Type = GameActionType.GActionType.ReleaseEnd
                    }, player);
                }
            }
        }
예제 #8
0
 private void HandleReleaseEndAction(GrabInfo data, Player player, IInteractionDelegate @delegate)
 {
     this.isTouching = false;
 }