public override ICodeBlock GenerateInitialize(ICodeBlock codeBlock, IElement element) { /////////////////Early Out////////////////////// if (TopDownEntityPropertyLogic.GetIfIsTopDown(element) == false) { return(codeBlock); } //////////////End Early Out////////////////////// // The platformer plugin sets events here, but we don't need to // here on the top-down (yet) since there are no events // Update 1 - actually we should prob assign the default movement // here if there is one... codeBlock.Line("InitializeInput();"); var ifBlock = codeBlock.If("TopDownValues?.Count > 0"); { ifBlock.Line("mCurrentMovement = TopDownValues.Values.FirstOrDefault();"); } codeBlock.Line("PossibleDirections = PossibleDirections.FourWay;"); codeBlock.Line("mTopDownAnimationLayer = new TopDown.DirectionBasedAnimationLayer();"); codeBlock.Line("mTopDownAnimationLayer.TopDownEntity = this;"); return(codeBlock); }
public override ICodeBlock GenerateFields(ICodeBlock codeBlock, IElement element) { /////////////////Early Out////////////////////// if (TopDownEntityPropertyLogic.GetIfIsTopDown(element) == false) { return(codeBlock); } //////////////End Early Out////////////////////// /// return(codeBlock); }
public override ICodeBlock GenerateActivity(ICodeBlock codeBlock, IElement element) { ///////////////////Early Out/////////////////////////////// if (!TopDownEntityPropertyLogic.GetIfIsTopDown(element)) { return(codeBlock); } /////////////////End Early Out///////////////////////////// codeBlock.Line("ApplyMovementInput();"); return(codeBlock); }
public void CheckForNoTopDownEntities() { var areAnyEntitiesTopDown = GlueState.Self.CurrentGlueProject.Entities .Any(item => TopDownEntityPropertyLogic.GetIfIsTopDown(item)); if (!areAnyEntitiesTopDown) { FilePath absoluteFile = GlueState.Self.CurrentGlueProjectDirectory + AiCodeGenerator.Self.RelativeFile; TaskManager.Self.Add(() => GlueCommands.Self.ProjectCommands.RemoveFromProjects(absoluteFile), "Removing " + AiCodeGenerator.Self.RelativeFile); // todo - probably need to remove all the other files that are created for top down } }
public override ICodeBlock GenerateAdditionalMethods(ICodeBlock codeBlock, IElement element) { ///////////////////Early Out/////////////////////////////// if (!TopDownEntityPropertyLogic.GetIfIsTopDown(element)) { return(codeBlock); } /////////////////End Early Out///////////////////////////// codeBlock.Line( @" #region Top-Down Methods /// <summary> /// Sets the MovementInput to either the keyboard or /// Xbox360GamePad index 0. This can be overridden by base classes to default /// to different input devices. /// </summary> protected virtual void InitializeInput() { if (FlatRedBall.Input.InputManager.Xbox360GamePads[0].IsConnected) { InitializeTopDownInput(FlatRedBall.Input.InputManager.Xbox360GamePads[0]); } else { InitializeTopDownInput(FlatRedBall.Input.InputManager.Keyboard); } InputEnabled = true; } public void InitializeTopDownInput(FlatRedBall.Input.IInputDevice inputDevice) { this.MovementInput = inputDevice.Default2DInput; this.InputDevice = inputDevice; InputEnabled = true; CustomInitializeTopDownInput(); } partial void CustomInitializeTopDownInput(); private void ApplyMovementInput() { ////////early out///////// if(mCurrentMovement == null) { return; } //////end early out var velocity = this.Velocity; var desiredVelocity = Microsoft.Xna.Framework.Vector3.Zero; if(InputEnabled) { desiredVelocity = new Microsoft.Xna.Framework.Vector3(MovementInput.X, MovementInput.Y, velocity.Z) * mCurrentMovement.MaxSpeed * TopDownSpeedMultiplier; } var difference = desiredVelocity - velocity; Acceleration = Microsoft.Xna.Framework.Vector3.Zero; var differenceLength = difference.Length(); const float differenceEpsilon = .1f; if (differenceLength > differenceEpsilon) { var isMoving = velocity.X != 0 || velocity.Y != 0; var isDesiredVelocityNonZero = desiredVelocity.X != 0 || desiredVelocity.Y != 0; // A 0 to 1 ratio of acceleration to deceleration, where 1 means the player is accelerating completely, // and 0 means decelerating completely. This value will often be between 0 and 1 because the player may // set desired velocity perpendicular to the current velocity float accelerationRatio = 1; if(isMoving && isDesiredVelocityNonZero == false) { // slowing down completely accelerationRatio = 0; } else if(isMoving == false && isDesiredVelocityNonZero) { accelerationRatio = 1; } else { // both is moving and has a non-zero desired value var movementAngle = (float)Math.Atan2(velocity.Y, velocity.X); var desiredAngle = (float)Math.Atan2(difference.Y, difference.X); accelerationRatio = 1- Math.Abs(FlatRedBall.Math.MathFunctions.AngleToAngle(movementAngle, desiredAngle)) / (float)Math.PI; } var secondsToTake = Microsoft.Xna.Framework.MathHelper.Lerp( mCurrentMovement.DecelerationTime, mCurrentMovement.AccelerationTime, accelerationRatio); if(!mCurrentMovement.UsesAcceleration || secondsToTake == 0) { this.Acceleration = Microsoft.Xna.Framework.Vector3.Zero; this.Velocity = desiredVelocity; } else { var accelerationMagnitude = TopDownSpeedMultiplier * mCurrentMovement.MaxSpeed / secondsToTake; var nonNormalizedDifference = difference; difference.Normalize(); var accelerationToSet = accelerationMagnitude * difference; var expectedVelocityToAdd = accelerationToSet * TimeManager.SecondDifference; if(expectedVelocityToAdd.Length() > nonNormalizedDifference.Length()) { // we will overshoot it, so let's adjust the acceleration accordingly: var ratioOfToAdd = nonNormalizedDifference.Length() / expectedVelocityToAdd.Length(); this.Acceleration = accelerationToSet * ratioOfToAdd; } else { this.Acceleration = accelerationToSet; } } const float velocityEpsilon = .1f; var shouldAssignDirection = this.Velocity.Length() > velocityEpsilon || difference.Length() > 0; // player stopped moving, don't apply direction if(this.Velocity.LengthSquared() == 0) { shouldAssignDirection = false; } if (shouldAssignDirection && mCurrentMovement.UpdateDirectionFromVelocity) { mDirectionFacing = TopDownDirectionExtensions.FromDirection(XVelocity, YVelocity, PossibleDirections); } } else { Velocity = desiredVelocity; Acceleration = Microsoft.Xna.Framework.Vector3.Zero; } } #endregion "); return(codeBlock); }
public override void GenerateAdditionalClasses(ICodeBlock codeBlock, IElement element) { /////////////////Early Out////////////////////// if (TopDownEntityPropertyLogic.GetIfIsTopDown(element) == false) { return; } //////////////End Early Out////////////////////// /// var className = element.GetStrippedName(); codeBlock = codeBlock.Class("public partial", className, ": TopDown.ITopDownEntity"); codeBlock.Line("#region Top Down Fields"); WriteAnimationFields(element, codeBlock); codeBlock.Line("DataTypes.TopDownValues mCurrentMovement;"); codeBlock.Line("public float TopDownSpeedMultiplier { get; set; } = 1;"); codeBlock.Line("/// <summary>"); codeBlock.Line("/// The current movement variables used when applying input."); codeBlock.Line("/// </summary>"); codeBlock.Property("public DataTypes.TopDownValues", "CurrentMovement") .Get() .Line("return mCurrentMovement;").End() .Set("private") .Line("mCurrentMovement = value;"); codeBlock.Property("public FlatRedBall.Input.IInputDevice", "InputDevice") .Line("get;") .Line("private set;"); codeBlock.Line("TopDownDirection mDirectionFacing;"); codeBlock.Line("/// <summary>"); codeBlock.Line("/// Which direciton the character is facing."); codeBlock.Line("/// </summary>"); codeBlock.Property("public TopDownDirection", "DirectionFacing") .Get() .Line("return mDirectionFacing;"); codeBlock.Property("public PossibleDirections", "PossibleDirections") .AutoGet().End() .AutoSet(); codeBlock.Line("/// <summary>"); codeBlock.Line("/// The input object which controls the horizontal movement of the character."); codeBlock.Line("/// Common examples include a d-pad, analog stick, or keyboard keys."); codeBlock.Line("/// </summary>"); codeBlock.AutoProperty("public FlatRedBall.Input.I2DInput", "MovementInput"); codeBlock.Line("/// <summary>"); codeBlock.Line("/// Whether input is read to control the movement of the character."); codeBlock.Line("/// This can be turned off if the player should not be able to control"); codeBlock.Line("/// the character."); codeBlock.Line("/// </summary>"); codeBlock.AutoProperty("public bool", "InputEnabled"); codeBlock.Line("TopDown.DirectionBasedAnimationLayer mTopDownAnimationLayer;"); codeBlock.Line("#endregion"); }