Пример #1
0
        private SCNVector3 ComputeBallPosition(CameraInfo cameraInfo)
        {
            var cameraRay = cameraInfo.Ray;

            // These should be based on the projectile radius.
            // This affects centering of ball, and can hit near plane of camera
            // This is always centering to one edge of screen independent of screen orient
            // We always want the ball at the bottom of the screen.
            var distancePullToCamera = 0.21f;
            var ballShiftDown        = 0.2f;

            var targetBallPosition = cameraRay.Position + cameraRay.Direction * distancePullToCamera;

            var cameraDown = -SCNVector4.Normalize(cameraInfo.Transform.Column1).Xyz;

            targetBallPosition += cameraDown * ballShiftDown;

            // Clamp to only the valid side
            var pullWorldPosition = this.pullOrigin.WorldPosition;

            if (pullWorldPosition.Z < 0f)
            {
                targetBallPosition.Z = Math.Min(targetBallPosition.Z, pullWorldPosition.Z);
            }
            else
            {
                targetBallPosition.Z = Math.Max(targetBallPosition.Z, pullWorldPosition.Z);
            }

            // Clamp to cone/circular core
            var yDistanceFromPull       = Math.Max(0f, pullWorldPosition.Y - targetBallPosition.Y);
            var minBallDistanceFromPull = 0.5f;
            var pullBlockConeSlope      = 1.0f;
            var pullBlockConeRadius     = yDistanceFromPull / pullBlockConeSlope;
            var pullBlockCoreRadius     = Math.Max(minBallDistanceFromPull, pullBlockConeRadius);

            // if pull is in the core, move it out.
            var pullWorldPositionGrounded  = new SCNVector3(pullWorldPosition.X, 0f, pullWorldPosition.Z);
            var targetPullPositionGrounded = new SCNVector3(targetBallPosition.X, 0f, targetBallPosition.Z);
            var targetInitialToTargetPull  = targetPullPositionGrounded - pullWorldPositionGrounded;

            if (pullBlockCoreRadius > targetInitialToTargetPull.Length)
            {
                var moveOutDirection = SCNVector3.Normalize(targetInitialToTargetPull);
                var newTargetPullPositionGrounded = pullWorldPositionGrounded + moveOutDirection * pullBlockCoreRadius;
                targetBallPosition = new SCNVector3(newTargetPullPositionGrounded.X, targetBallPosition.Y, newTargetPullPositionGrounded.Z);
            }

            // only use the 2d distance, so that user can gauage stretch indepdent of mtch
            var distance2D = targetBallPosition - pullWorldPosition;
            var stretchY   = Math.Abs(distance2D.Y);

            distance2D.Y = 0f;

            var stretchDistance = distance2D.Length;

            this.stretch = DigitExtensions.Clamp((double)stretchDistance, this.properties.MinStretch, this.properties.MaxStretch);

            // clamp a little bit farther than maxStretch
            // can't let the strap move back too far right now
            var clampedStretchDistance = (float)(1.1d * this.properties.MaxStretch);

            if (stretchDistance > clampedStretchDistance)
            {
                targetBallPosition = (clampedStretchDistance / stretchDistance) * (targetBallPosition - pullWorldPosition) + pullWorldPosition;
                stretchDistance    = clampedStretchDistance;
            }

            // Make this optional, not required.  You're often at max stretch.
            // Also have a timer for auto-launch.  This makes it very difficuilt to test
            // storing state in member data
            this.IsPulledTooFar = stretchDistance > (float)(this.properties.MaxStretch) || stretchY > (float)(this.properties.MaxStretch);

            return(targetBallPosition);
        }
Пример #2
0
 public void Update(CameraInfo cameraInfo)
 {
     this.UpdateVortexState();
 }
Пример #3
0
 public GrabInfo(int grabbableId, CameraInfo cameraInfo)
 {
     this.GrabbableId = grabbableId;
     this.CameraInfo  = cameraInfo;
 }
Пример #4
0
        public void Update(CameraInfo cameraInfo)
        {
            if (this.Delegate == null)
            {
                throw new Exception("No delegate");
            }

            // Do not move the lever after it has been activated
            if (!(this.InteractionToActivate?.IsActivated ?? false))
            {
                if (this.activeSwitch != null)
                {
                    // Lever Pulling
                    var cameraOffset = this.activeSwitch.PullOffset(cameraInfo.Ray.Position - this.startLeverHoldCameraPosition);
                    var cameraMovedZ = cameraOffset.Z;

                    var targetEulerX = this.startLeverEulerX + LeverPullZtoLeverEulerRotation * cameraMovedZ;
                    targetEulerX            = DigitExtensions.Clamp(-LeverMaxEulerX, targetEulerX, LeverMaxEulerX);
                    this.activeSwitch.Angle = targetEulerX;

                    if (targetEulerX <= -LeverMaxEulerX)
                    {
                        // Interaction activation once the switch lever is turned all the way
                        this.InteractionToActivate?.Activate();

                        // Fade out the switches
                        var waitAction = SCNAction.Wait(3f);
                        var fadeAction = SCNAction.FadeOut(3d);

                        foreach (var resetSwitch in this.resetSwitches)
                        {
                            resetSwitch.Base.RunAction(SCNAction.Sequence(new SCNAction[] { waitAction, fadeAction }));
                        }
                        return;
                    }
                    else
                    {
                        // Inform peers of the movement
                        var leverId = this.resetSwitches.IndexOf(this.activeSwitch);
                        if (leverId == -1)
                        {
                            throw new Exception("No lever in array");
                        }

                        this.Delegate.DispatchActionToServer(new GameActionType {
                            LeverMove = new LeverMove(leverId, targetEulerX), Type = GameActionType.GActionType.LeverMove
                        });
                    }
                }
                else
                {
                    // Lever spring back
                    foreach (var lever in this.resetSwitches.Where(lever => lever.Angle < LeverMaxEulerX))
                    {
                        lever.Angle = Math.Min(LeverMaxEulerX, lever.Angle + LeverSpringBackSpeed * (float)GameTime.DeltaTime);
                    }
                }

                // Highlight lever when nearby, otherwise check if we should hide the highlight
                if (this.highlightedSwitch != null)
                {
                    if (!this.highlightedSwitch.ShouldHighlight(cameraInfo.Ray))
                    {
                        this.highlightedSwitch.DoHighlight(false, this.SfxCoordinator);
                        this.highlightedSwitch = null;
                    }
                }
                else
                {
                    foreach (var resetSwitch in this.resetSwitches)
                    {
                        if (resetSwitch.ShouldHighlight(cameraInfo.Ray))
                        {
                            resetSwitch.DoHighlight(true, this.SfxCoordinator);
                            this.highlightedSwitch = resetSwitch;
                        }
                    }
                }
            }
        }