private void ChangeForm(PlayerForm form, bool instant = false) { IsChangingForm = true; CurrentForm = form; GD.Print("Changing form to " + form.ToString()); if (!SceneCache.ContainsKey(CurrentForm)) { SceneCache.Add(CurrentForm, GD.Load <PackedScene>(Constants.FilePath.PLAYER_FORM_SCENES + CurrentForm.ToString() + ".tscn")); } CurrentScene = SceneCache[CurrentForm]; string frameCacheKey = SpriteFolderName + "/" + CurrentForm.ToString(); if (!FrameCache.ContainsKey(frameCacheKey)) { FrameCache.Add(frameCacheKey, GD.Load <SpriteFrames>(Constants.FilePath.PLAYER_FRAMES + SpriteFolderName + "/" + CurrentForm.ToString() + ".tres")); } CurrentFrames = FrameCache[frameCacheKey]; Player oldFormScene = GetChildCount() > 0 ? GetChildOrNull <Player>(0) : null; oldFormScene?.SetName("QueuedForDeletion"); if (oldFormScene != null) { PreviousTransform = oldFormScene.GetGlobalTransform(); PreviousVelocity = oldFormScene.Velocity; AnimatedSprite3D sprite = GetNode <AnimatedSprite3D>(new NodePath("QueuedForDeletion/PlayerSprite")); PreviousSpriteFlipped = sprite.IsFlippedH(); if (!instant) { //Create blinking state transition TransitionFrames.Clear("Transition"); TransitionFrames.AddFrame("Transition", sprite.Frames.GetFrame(Player.PlayerAnimation.IDLE, 0), 0); TransitionFrames.AddFrame("Transition", CurrentFrames.GetFrame(Player.PlayerAnimation.IDLE, 0), 1); TransitionSprite.SetGlobalTransform(sprite.GetGlobalTransform().Translated(-Transform.origin)); TransitionSprite.SetFlipH(sprite.FlipH); TransitionSprite.SetPixelSize(sprite.GetPixelSize()); TransitionSprite.Play("Transition"); } oldFormScene.SetProcess(false); oldFormScene.SetPhysicsProcess(false); oldFormScene.QueueFree(); } if (instant) { FinishFormChange(form); return; } AddChild(TransitionSprite); }
public override void AProcess(float delta) { //Flip the sprite correctly if (Input.GetActionStrength("p1_right") - Input.GetActionStrength("p1_left") > 0) { PlayerSprite.SetFlipH(false); } else if (Velocity.x < 0) { PlayerSprite.SetFlipH(true); } DebugText.Display("P1_Pos", "P1 Position: " + Transform.origin.ToString()); DebugText.Display("P1_Vel", "P1 Velocity: " + Velocity.ToString()); DebugText.Display("P1_Grnd", "P1 On Ground: " + IsOnFloor()); DebugText.Display("P1_Snap", "P1 Ground Snap: " + SnapToGround); }
public virtual void SetupPlayer(InputManager input, Transform transform, Vector3 velocity, SpriteFrames spriteFrames, bool spriteFlipped) { PlayerSprite = GetNodeOrNull <AnimatedSprite3D>(new NodePath("PlayerSprite")); ActorDetectorArea = GetNodeOrNull <Area>(new NodePath("ActorDetector")); FloorRayCast = GetNodeOrNull <RayCast>(new NodePath("FloorRayCast")); if (PlayerSprite == null || ActorDetectorArea == null || FloorRayCast == null) { GD.Print("One or multiple required child nodes could not be found! Some features won't work!"); } InputManager = input; SetGlobalTransform(transform); Velocity = velocity; PlayerSprite.Frames = spriteFrames; PlayerSprite.SetFlipH(spriteFlipped); SetPlayerCollisionShape(GetDefaultCollisionShape()); }
public override void AReady() { PlayerSprite = GetNodeOrNull(new NodePath("PlayerSprite")) as AnimatedSprite3D; ActorDetectorArea = GetNodeOrNull(new NodePath("ActorDetector")) as Area; FloorRayCast = GetNodeOrNull(new NodePath("FloorRayCast")) as RayCast; if (PlayerSprite == null || ActorDetectorArea == null || FloorRayCast == null) { GD.PrintErr("One or multiple required child nodes could not be found! Some features won't work!"); } InputManager = new InputManager(PlayerNumber); StandState = new ActorState(() => { //Enter State SnapToGround = true; }, (float delta) => { //Process State if (Mathf.Abs(Velocity.x) > 0.5f) { PlayerSprite.SetAnimation(PlayerAnimation.WALK); PlayerSprite.Frames.SetAnimationSpeed(PlayerAnimation.WALK, (Mathf.Abs(Velocity.x)) + 5); } else { PlayerSprite.SetAnimation(PlayerAnimation.IDLE); } }, (float delta) => { //State Physics Processing if (InputManager.DirectionalInput.x != 0) { ChangeState(WalkState); } CanFall(); CanJump(); CanCrouch(); }, () => { //Exit State }); WalkState = new ActorState(() => { //Enter State SetSpeedLimit(WalkSpeed); SnapToGround = true; }, (float delta) => { //Process State if (Mathf.Sign(Velocity.x) == Mathf.Sign(InputManager.DirectionalInput.x) || Velocity.x == 0) { PlayerSprite.SetAnimation(PlayerAnimation.WALK); PlayerSprite.Frames.SetAnimationSpeed(PlayerAnimation.WALK, (Mathf.Abs(Velocity.x)) + 5); } else { PlayerSprite.SetAnimation(PlayerAnimation.TURN); } }, (float delta) => { //State Physics Processing if (InputManager.DirectionalInput.x == 0) { ChangeState(StandState); } if (InputManager.RunPressed || InputManager.AltRunPressed) { ChangeState(RunState); } CanFall(); CanJump(); CanCrouch(); float force = InputManager.DirectionalInput.x * WalkAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State }); RunState = new ActorState(() => { //Enter State SetSpeedLimit(RunSpeed); SnapToGround = true; }, (float delta) => { //Process State if (Mathf.Sign(Velocity.x) == Mathf.Sign(InputManager.DirectionalInput.x) || Velocity.x == 0) { PlayerSprite.SetAnimation(PlayerAnimation.WALK); PlayerSprite.Frames.SetAnimationSpeed(PlayerAnimation.WALK, (Mathf.Abs(Velocity.x)) + 7); } else { PlayerSprite.SetAnimation(PlayerAnimation.TURN); } }, (float delta) => { //State Physics Processing if (InputManager.DirectionalInput.x == 0) { ChangeState(StandState); } if (!InputManager.RunPressed && !InputManager.AltRunPressed) { ChangeState(WalkState); } if (GetElapsedTimeInState() > LongRunTime) { ChangeState(LongRunState); } CanFall(); CanJump(); CanCrouch(); float force = InputManager.DirectionalInput.x * RunAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State }); LongRunState = new ActorState(() => { //Enter State PlayerSprite.SetAnimation(PlayerAnimation.LONG_RUN); SetSpeedLimit(LongRunSpeed); SnapToGround = true; }, (float delta) => { //Process State if (Mathf.Sign(Velocity.x) == Mathf.Sign(InputManager.DirectionalInput.x) || Velocity.x == 0) { PlayerSprite.SetAnimation(PlayerAnimation.LONG_RUN); PlayerSprite.Frames.SetAnimationSpeed(PlayerAnimation.LONG_RUN, (Mathf.Abs(Velocity.x)) + 10); } else { PlayerSprite.SetAnimation(PlayerAnimation.TURN); } }, (float delta) => { //State Physics Processing if (InputManager.DirectionalInput.x == 0) { ChangeState(StandState); } if (!InputManager.RunPressed && !InputManager.AltRunPressed || Mathf.Sign(Velocity.x) != Mathf.Sign(InputManager.DirectionalInput.x)) { ChangeState(WalkState); } CanFall(); CanJump(); CanCrouch(); float force = InputManager.DirectionalInput.x * LongRunAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State }); JumpState = new ActorState(() => { //Enter State SnapToGround = false; float speed = Mathf.Abs(Velocity.x); if (speed > RunSpeed) { ApplyForce2D(new Vector2(0, LongRunJumpForce)); PlayerSprite.SetAnimation(PlayerAnimation.HIGH_JUMP); } else if (speed > 0.5f) { ApplyForce2D(new Vector2(0, WalkJumpForce)); PlayerSprite.SetAnimation(PlayerAnimation.JUMP); } else if (PreviousState == CrouchState) { ApplyForce2D(new Vector2(0, IdleJumpForce)); PlayerSprite.SetAnimation(PlayerAnimation.CROUCH); SetPlayerCollisionShape(PlayerCollisionShape.SMALL); } else { ApplyForce2D(new Vector2(0, IdleJumpForce)); PlayerSprite.SetAnimation(PlayerAnimation.JUMP); } }, (float delta) => { //Process State //DebugText.Display("P" + PlayerNumber + "_JumpSusTime", "P" + PlayerNumber + " Jump Sustain Time: " + (MaxJumpSustainTime - GetElapsedTimeInState()).ToString()); }, (float delta) => { //State Physics Processing if (IsOnFloor()) { ChangeState(StandState); } if ((!InputManager.JumpPressed && !InputManager.AltJumpPressed) || GetElapsedTimeInState() > MaxJumpSustainTime) { ChangeState(FallState); } if (SpeedLimit >= LongRunSpeed && (InputManager.RunPressed || InputManager.AltRunPressed)) { SetSpeedLimit(LongRunSpeed); } else if (InputManager.RunPressed || InputManager.AltRunPressed) { SetSpeedLimit(RunSpeed); } else { SetSpeedLimit(WalkSpeed); } //Add some force for extra air time if the jump button is held ApplyForce2D(Vector2.Up, Gravity.y * (1 - JumpSustainGravityMultiplier)); float force = InputManager.DirectionalInput.x * AirHorizontalAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State //DebugText.Remove("P" + PlayerNumber + "_JumpSusTime"); SetPlayerCollisionShape(GetDefaultCollisionShape()); }); SpinJumpState = new ActorState(() => { //Enter State SnapToGround = false; PlayerSprite.SetAnimation(PlayerAnimation.SPIN_JUMP); float speed = Mathf.Abs(Velocity.x); if (speed > RunSpeed) { ApplyForce2D(new Vector2(0, LongRunJumpForce)); } else if (speed > 0.5f) { ApplyForce2D(new Vector2(0, WalkJumpForce)); } else if (PreviousState == CrouchState) { ApplyForce2D(new Vector2(0, IdleJumpForce)); } else { ApplyForce2D(new Vector2(0, IdleJumpForce)); } }, (float delta) => { //Process State //DebugText.Display("P" + PlayerNumber + "_JumpSusTime", "P" + PlayerNumber + " Jump Sustain Time: " + (MaxJumpSustainTime - GetElapsedTimeInState()).ToString()); }, (float delta) => { //State Physics Processing if (IsOnFloor()) { ChangeState(StandState); } if ((!InputManager.JumpPressed && !InputManager.AltJumpPressed) || GetElapsedTimeInState() > MaxJumpSustainTime) { ChangeState(FallState); } if (SpeedLimit >= LongRunSpeed && (InputManager.RunPressed || InputManager.AltRunPressed)) { SetSpeedLimit(LongRunSpeed); } else if (InputManager.RunPressed || InputManager.AltRunPressed) { SetSpeedLimit(RunSpeed); } else { SetSpeedLimit(WalkSpeed); } //Add some force for extra air time if the jump button is held ApplyForce2D(Vector2.Up, Gravity.y * (1 - JumpSustainGravityMultiplier)); float force = InputManager.DirectionalInput.x * AirHorizontalAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State //DebugText.Remove("P" + PlayerNumber + "_JumpSusTime"); }); FallState = new ActorState(() => { //Enter State if (InputManager.DirectionalInput.y < CrouchInputThreshold) { PlayerSprite.SetAnimation(PlayerAnimation.CROUCH); SetPlayerCollisionShape(PlayerCollisionShape.SMALL); } else if (PreviousState == SpinJumpState) { PlayerSprite.SetAnimation(PlayerAnimation.SPIN_JUMP); } else { PlayerSprite.SetAnimation(PlayerAnimation.FALL); } SnapToGround = false; }, (float delta) => { //Process State }, (float delta) => { //State Physics Processing if (IsOnFloor()) { if (InputManager.DirectionalInput.y < CrouchInputThreshold) { ChangeState(CrouchState); } else { ChangeState(StandState); } } if (SpeedLimit >= LongRunSpeed && (InputManager.RunPressed || InputManager.AltRunPressed)) { SetSpeedLimit(LongRunSpeed); } else if (InputManager.RunPressed || InputManager.AltRunPressed) { SetSpeedLimit(RunSpeed); } else { SetSpeedLimit(WalkSpeed); } float force = InputManager.DirectionalInput.x * AirHorizontalAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State SetPlayerCollisionShape(GetDefaultCollisionShape()); }); CrouchState = new ActorState(() => { //Enter State SnapToGround = true; var angle = Mathf.Rad2Deg(Mathf.Acos(FloorRayCast.GetCollisionNormal().Dot(FloorNormal))); if (angle >= SlideMinAngle) { ChangeState(SlideState); return; } PlayerSprite.SetAnimation(PlayerAnimation.CROUCH); SetPlayerCollisionShape(PlayerCollisionShape.SMALL); }, (float delta) => { //Process State }, (float delta) => { //State Physics Processing Transform slightlyRight; slightlyRight.origin = Transform.origin; slightlyRight.basis = Transform.basis; slightlyRight.origin.x += 0.4f; Transform slightlyLeft; slightlyLeft.origin = Transform.origin; slightlyLeft.basis = Transform.basis; slightlyLeft.origin.x -= 0.4f; if (!TestMove(Transform, new Vector3(0, 0.5f, 0))) { if (InputManager.DirectionalInput.y >= CrouchInputThreshold) { ChangeState(StandState); } CanJump(); CanFall(); } else if (!TestMove(slightlyRight, new Vector3(0, 0.5f, 0))) { ApplyForce2D(new Vector2(0.4f, 0)); } else if (!TestMove(slightlyLeft, new Vector3(0, 0.5f, 0))) { ApplyForce2D(new Vector2(-0.4f, 0)); } else { if (InputManager.JumpJustPressed || InputManager.AltJumpJustPressed) { ApplyForce2D(new Vector2(CrouchBoostForce.x * InputManager.DirectionalInput.x, CrouchBoostForce.y)); } } }, () => { //Exit State SetPlayerCollisionShape(GetDefaultCollisionShape()); }); SlideState = new ActorState(() => { //Enter State SetSpeedLimit(SlideSpeed); SnapToGround = true; PlayerSprite.SetAnimation(PlayerAnimation.SLIDE); autoPlayerFacing = false; }, (float delta) => { //Process State //Manually flip the sprite according to the movement direction if (Velocity.x > 0) { PlayerSprite.SetFlipH(false); } else if (Velocity.x < 0) { PlayerSprite.SetFlipH(true); } }, (float delta) => { //State Physics Processing Vector3 normal = FloorRayCast.GetCollisionNormal(); float angle = Mathf.Rad2Deg(Mathf.Acos(normal.Dot(FloorNormal))); if (angle < SlideMinAngle) { ChangeState(InputManager.DirectionalInput.y < CrouchInputThreshold ? CrouchState : StandState); } CanFall(); CanJump(); float force = Mathf.Sign(normal.x) * SlideAcceleration; ApplyForce2D(new Vector2(force, 0)); }, () => { //Exit State autoPlayerFacing = true; }); }