Created
March 2, 2018 14:40
-
-
Save NickDiMucci/552f7737d1565906bff4eefd700edf4e to your computer and use it in GitHub Desktop.
The player movement and collision detection code for Demons with Shotguns.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace com.mindshaft.overtime.controller { | |
public class BasicEntityController : IEntityController { | |
private float gravity = 40f; | |
private float targetSpeed = 0f; | |
private IMovementModel model; | |
[Inject] | |
public IEntityCollisionDetection CollisionDetection { get; set; } | |
public IMovementModel Move(IMovementModel model) { | |
// Need to reset gravity everytime in case we | |
// reuse an object that was flying, but is now grounded. | |
// gravity would then be -1. | |
this.model = model; | |
targetSpeed = (model.HorizontalInput + model.VerticalInput) * model.Speed; | |
model.CurrentSpeed = accelerateSpeed(model.CurrentSpeed, targetSpeed, | |
model.Accel); | |
if (model.IsJumping) { | |
model.AmountToMove = new Vector3(model.AmountToMove.x, | |
model.AmountToMove.y); | |
} else if (CollisionDetection.OnGround) { | |
model.AmountToMove = new Vector3(model.AmountToMove.x, 0); | |
} | |
model.FlipAnim = flipAnimation(targetSpeed); | |
// If we're ignoring gravity, then just use the vertical input. | |
// if it's 0, then we'll just float. | |
gravity = model.IgnoreGravity ? model.VerticalInput : 40f; | |
model.AmountToMove = new Vector3(model.CurrentSpeed, model.AmountToMove.y - gravity * Time.deltaTime); | |
model.FinalTransform = | |
CollisionDetection.Move(model.AmountToMove * Time.deltaTime, | |
model.BoxCollider.gameObject, model.IgnorePlayerLayer); | |
// Prevent the entity from moving too fast on the y-axis. | |
model.FinalTransform = new Vector3(model.FinalTransform.x, | |
Mathf.Clamp(model.FinalTransform.y, -1.0f, 1.0f), | |
model.FinalTransform.z); | |
return model; | |
} | |
private float accelerateSpeed(float currSpeed, float target, float accel) { | |
if (currSpeed == target) { | |
return currSpeed; | |
} | |
// Must currSpeed be increased or decreased to get closer to target | |
float dir = Mathf.Sign(target - currSpeed); | |
currSpeed += accel * Time.deltaTime * dir; | |
// If currSpeed has now passed Target then return Target, otherwise return currSpeed | |
return (dir == Mathf.Sign(target - currSpeed)) ? currSpeed : target; | |
} | |
private bool flipAnimation(float currSpeed) { | |
bool flip = model.FlipAnim; | |
if (currSpeed < 0) { | |
flip = true; | |
} else if (currSpeed > 0) { | |
flip = false; | |
} | |
return flip; | |
} | |
} | |
} | |
namespace com.mindshaft.overtime.physics { | |
public class RaycastCollisionDetection : IEntityCollisionDetection { | |
private BoxCollider _collider; | |
private Rect _collisionRect; | |
private LayerMask _collisionMask; | |
private LayerMask _playerMask; | |
public GameObject ObjectCollidedWith { get; set; } | |
public bool OnGround { get; set; } | |
public bool SideCollision { get; set; } | |
public bool PlayerCollisionX { get; set; } | |
public bool PlayerCollisionY { get; set; } | |
public Vector3 HitNormal { get; set; } | |
public void Init(GameObject entityGo) { | |
_collisionMask = LayerMask.NameToLayer("Collisions"); | |
_playerMask = LayerMask.NameToLayer("Player"); | |
_collider = entityGo.GetComponent<BoxCollider>(); | |
} | |
public Vector3 Move(Vector3 moveAmount, GameObject entityGo, bool ignorePlayerLayer) { | |
float deltaX = moveAmount.x; | |
float deltaY = moveAmount.y; | |
Vector3 entityPosition = entityGo.transform.position; | |
if (deltaY != 0) { | |
// Resolve any possible collisions below and above the entity. | |
deltaY = YAxisCollisions(deltaY, Mathf.Sign(deltaX), entityPosition); | |
} | |
// Resolve any possible collisions left and right of the entity. | |
// Check if our deltaX value is 0 to avoid unnecessary collision detection. | |
if (deltaX != 0) { | |
deltaX = XAxisCollisions(deltaX, entityPosition, ignorePlayerLayer); | |
} | |
if (deltaX != 0 && deltaY != 0 && !SideCollision && !OnGround) { | |
DiagonalCollisions(ref deltaX, ref deltaY, entityPosition); | |
} | |
Vector3 finalTransform = new Vector3(deltaX, deltaY, 0); | |
return finalTransform; | |
} | |
private float XAxisCollisions(float deltaX, Vector3 entityPosition, bool ignorePlayerLayer) { | |
SideCollision = false; | |
PlayerCollisionX = false; | |
ObjectCollidedWith = null; | |
// It's VERY important that the entity's collider doesn't change | |
// shape during the game. This will cause irregular raycast hits | |
// and most likely cause things to go through layers. | |
// Ensure sprites use a fixed collider size for all frames. | |
_collisionRect = GetNewCollisionRect(); | |
// Increase this value if you want the rays to start and end | |
// outside of the entity's collider bounds. | |
float margin = 0.04f; | |
int numOfRays = 4; | |
Vector3 rayStartPoint = new Vector3(_collisionRect.center.x, | |
_collisionRect.yMin + margin, entityPosition.z); | |
Vector3 rayEndPoint = new Vector3(_collisionRect.center.x, | |
_collisionRect.yMax - margin, entityPosition.z); | |
float distance = (_collisionRect.width / 2) + Mathf.Abs(deltaX); | |
for (int i = 0; i < numOfRays; ++i) { | |
float lerpAmount = (float) i / ((float) numOfRays - 1); | |
Vector3 origin = Vector3.Lerp(rayStartPoint, rayEndPoint, lerpAmount); | |
Ray ray = new Ray(origin, new Vector2(Mathf.Sign(deltaX), 0)); | |
Debug.DrawRay(ray.origin, ray.direction, Color.white); | |
RaycastHit hit; | |
// Bit shift the layers to tell Unity to NOT ignore them. | |
if (Physics.Raycast(ray, out hit, distance, 1 << _collisionMask) || | |
Physics.Raycast(ray, out hit, distance, 1 << _playerMask)) { | |
HitNormal = hit.normal; | |
Debug.DrawRay(ray.origin, ray.direction, Color.yellow); | |
float x = Mathf.Sign(deltaX) == -1 | |
? _collisionRect.xMin | |
: _collisionRect.xMax; | |
// Give a small amount of skin space to prevent snagging. | |
float skinSpace = 0.005f; | |
deltaX = (_collisionRect.center.x + hit.distance * ray.direction.x - x) + skinSpace; | |
if (hit.transform.gameObject.layer == _playerMask) { | |
PlayerCollisionX = true; | |
if (!ignorePlayerLayer) { | |
deltaX = 0; | |
} | |
ObjectCollidedWith = hit.transform.gameObject; | |
} else { | |
SideCollision = true; | |
} | |
break; | |
} | |
} | |
return deltaX; | |
} | |
private float YAxisCollisions(float deltaY, float dirX, Vector3 entityPosition) { | |
OnGround = false; | |
PlayerCollisionY = false; | |
ObjectCollidedWith = null; | |
// It's VERY important that the entity's collider doesn't change | |
// shape during the game. This will cause irregular raycast hits | |
// and most likely cause things to go through layers. | |
// Ensure sprites use a fixed collider size for all frames. | |
_collisionRect = GetNewCollisionRect(); | |
// Increase this value if you want the rays to start and end | |
// outside of the entity's collider bounds. | |
float margin = 0.04f; | |
int numOfRays = 4; | |
Vector3 rayStartPoint = new Vector3(_collisionRect.xMin + margin, | |
_collisionRect.center.y, entityPosition.z); | |
Vector3 rayEndPoint = new Vector3(_collisionRect.xMax - margin, | |
_collisionRect.center.y, entityPosition.z); | |
float distance = (_collisionRect.height / 2) + Mathf.Abs(deltaY); | |
for (int i = 0; i < numOfRays; ++i) { | |
float lerpAmount = (float) i / ((float) numOfRays - 1); | |
// If we are facing left, start the rays on the left side, | |
// else start the ray rays on the right side. | |
// This will help ensure precise castings on the corners. | |
Vector3 origin = dirX == -1 | |
? Vector3.Lerp(rayStartPoint, rayEndPoint, lerpAmount) | |
: Vector3.Lerp(rayEndPoint, rayStartPoint, lerpAmount); | |
Ray ray = new Ray(origin, new Vector2(0, Mathf.Sign(deltaY))); | |
//Debug.DrawRay(ray.origin, ray.direction, Color.white); | |
RaycastHit hit; | |
// Bit shift the layers to tell Unity to NOT ignore them. | |
if (Physics.Raycast(ray, out hit, distance, 1 << _collisionMask) || | |
Physics.Raycast(ray, out hit, distance, 1 << _playerMask)) { | |
HitNormal = hit.normal; | |
//Debug.DrawRay(ray.origin, ray.direction, Color.yellow); | |
float y = Mathf.Sign(deltaY) == -1 | |
? _collisionRect.yMin | |
: _collisionRect.yMax; | |
// Give a small amount of skin space to prevent snagging. | |
float skinSpace = 0.0005f; | |
deltaY = (_collisionRect.center.y + hit.distance * ray.direction.y - y) + skinSpace; | |
// Only flag player collision if we collide with them while traveling down. | |
if (hit.collider.gameObject.layer == _playerMask && Mathf.Sign(deltaY) == -1) { | |
PlayerCollisionY = true; | |
ObjectCollidedWith = hit.transform.gameObject; | |
} | |
OnGround = true; | |
break; | |
} | |
} | |
return deltaY; | |
} | |
private void DiagonalCollisions(ref float deltaX, ref float deltaY, Vector3 entityPosition) { | |
_collisionRect = GetNewCollisionRect(); | |
float distance = (_collisionRect.height / 2) + Mathf.Abs(deltaX); | |
Ray ray = new Ray(_collisionRect.center, new Vector2(Mathf.Sign(deltaX), Mathf.Sign(deltaY))); | |
Debug.DrawRay(ray.origin, ray.direction, Color.white); | |
RaycastHit hit; | |
if (Physics.Raycast(ray, out hit, distance, 1 << _collisionMask)) { | |
HitNormal = hit.normal; | |
Debug.DrawRay(ray.origin, ray.direction, Color.yellow); | |
// Stop deltaX and let entity drop by deltaY. | |
deltaX = 0; | |
SideCollision = true; | |
} | |
} | |
private Rect GetNewCollisionRect() { | |
return new Rect( | |
_collider.bounds.min.x, | |
_collider.bounds.min.y, | |
_collider.bounds.size.x, | |
_collider.bounds.size.y); | |
} | |
} | |
} | |
namespace com.mindshaft.overtime.fsm { | |
public class StandingState : IState { | |
private enum StandingAnimations { | |
Idle, | |
Run, | |
IdleDown, | |
IdleUp, | |
RunDown, | |
RunUp | |
} | |
private static string[] _animToPlay = new string[] { "idle", "run", "idleDown", "idleUp", "runDown", "runUp" }; | |
private static SoundFx[] _jumpLandings = new SoundFx[] { SoundFx.JUMP_LANDING, SoundFx.JUMP_LANDING2, SoundFx.JUMP_LANDING3, SoundFx.JUMP_LANDING4, SoundFx.JUMP_LANDING5 }; | |
private float _time = 0.2f; | |
private float _timer; | |
private float _fallingTime; | |
private bool _wasFalling = false; | |
public void Entry(PlayerMediator mediator) { | |
_timer = _time; | |
_fallingTime = 0; | |
} | |
public void Exit(PlayerMediator mediator, IState state) { | |
mediator.ChangeState(state); | |
} | |
public void FixedUpdate(PlayerMediator mediator) { | |
} | |
public void HandleInput(PlayerMediator mediator) { | |
if (mediator.InputController.Jump() && | |
mediator.EntityController.CollisionDetection.OnGround) { | |
Exit(mediator, new JumpingState()); | |
} | |
if (mediator.View.IsTeleporting) { | |
Exit(mediator, new TeleportState()); | |
} | |
if (mediator.InputController.Taunt() && !mediator.View.IsPossessed) { | |
Exit(mediator, new TauntingState()); | |
} | |
if (mediator.InputController.MeleeAttackReleased()) { | |
if (mediator.View.ShieldView.ShieldHealth > 0 | |
&& mediator.View.MeleeCooldownTimer < 0 && !mediator.View.IsPossessed) { | |
Exit(mediator, new MeleeState()); | |
} else { | |
mediator.PlaySoundFxSignal.Dispatch(new PlaySoundFxModel(SoundFx.NEGATIVE, mediator.transform.position, SpatialBlend.ThreeDee)); | |
mediator.DisplayAlertOverPlayerSignal.Dispatch(mediator.gameObject); | |
} | |
} | |
if (mediator.InputController.MeleeAttackPressed() && mediator.View.ShieldView.ShieldHealth > 0 | |
&& mediator.View.MeleeCooldownTimer < 0 && !mediator.View.IsPossessed) { | |
mediator.View.Charge += 0.05f; | |
} else { | |
if (mediator.InputController.Shield() && mediator.View.ShieldView.ShieldHealth > 0 && !mediator.View.IsPossessed) { | |
Exit(mediator, new ShieldedState()); | |
} | |
if (mediator.InputController.ThrowGrenade() && !mediator.View.IsPossessed) { | |
mediator.ActivateGrenade(); | |
} | |
if (mediator.InputController.Dash()) { | |
if (mediator.View.DashCooldownTimer < 0 && !mediator.View.IsPossessed) { | |
Exit(mediator, new DashingState()); | |
} else { | |
mediator.PlaySoundFxSignal.Dispatch(new PlaySoundFxModel(SoundFx.NEGATIVE, mediator.transform.position, SpatialBlend.ThreeDee)); | |
mediator.DisplayAlertOverPlayerSignal.Dispatch(mediator.gameObject); | |
} | |
} | |
if (mediator.View.HasSoul && mediator.InputController.OtherAction() && !mediator.View.IsPossessed) { | |
mediator.ThrowSoulFlag(); | |
} | |
} | |
} | |
public void OnCollisionEnter(PlayerMediator mediator, Collider other) { | |
} | |
public void Update(PlayerMediator mediator) { | |
_timer -= Time.deltaTime; | |
// Keep track if the player is falling (if he's not OnGround, then obviously he is falling). | |
if (!mediator.EntityController.CollisionDetection.OnGround) { | |
_wasFalling = true; | |
_fallingTime += Time.deltaTime; | |
} | |
// Only play a landing dust anim if the player was previously falling last frame, but is now OnGround | |
// and was falling for longer than a specified time. | |
if (mediator.EntityController.CollisionDetection.OnGround && _wasFalling && _fallingTime >= 0.4f) { | |
_wasFalling = false; | |
_fallingTime = 0; | |
mediator.PlaySoundFxSignal.Dispatch(new PlaySoundFxModel(_jumpLandings[Random.Range(0, 5)], mediator.transform.position, SpatialBlend.ThreeDee)); | |
} | |
StandingAnimations animToPlay = StandingAnimations.Idle; | |
if (mediator.AmountToMove.x != 0.0f) { | |
animToPlay = StandingAnimations.Run; | |
// Give some time between dust anim dispatches. | |
if (_timer < 0 && mediator.EntityController.CollisionDetection.OnGround) { | |
mediator.PlayMovementDustAnimSignal.Dispatch(mediator.transform.position - new Vector3(0, 0.7f, 0), mediator.View.Sprite.FlipX, command.MovementDustType.STEPPING); | |
_timer = _time; | |
} | |
if (mediator.View.VerticalInput == -1) { | |
animToPlay = StandingAnimations.RunDown; | |
} else if (mediator.View.VerticalInput == 1) { | |
animToPlay = StandingAnimations.RunUp; | |
} | |
} else if (Mathf.Sign(mediator.View.VerticalInput) == -1 && mediator.View.VerticalInput != 0f) { | |
animToPlay = StandingAnimations.IdleDown; | |
} else if (Mathf.Sign(mediator.View.VerticalInput) == 1 && mediator.View.VerticalInput != 0f) { | |
animToPlay = StandingAnimations.IdleUp; | |
} | |
mediator.PlayAnim(_animToPlay[(int) animToPlay]); | |
if (mediator.View.Health < 1) { | |
Exit(mediator, new DeadState()); | |
} | |
if (mediator.View.IsGrounded) { | |
Exit(mediator, new GroundedState()); | |
} | |
} | |
public void LateUpdate(PlayerMediator mediator) { | |
if (mediator.View.IsDrunk) { | |
mediator.View.HorizontalInput *= -0.5f; | |
mediator.View.VerticalInput *= -0.5f; | |
} | |
mediator.OnInput(); | |
} | |
} | |
} | |
namespace com.mindshaft.overtime.fsm { | |
public class JumpingState : IState { | |
private static string[] _animToPlay = new string[] { "jump", "fall", "jumpDown", "jumpUp" }; | |
private static SoundFx[] _jumpLandings = new SoundFx[] { SoundFx.JUMP_LANDING, SoundFx.JUMP_LANDING2, SoundFx.JUMP_LANDING3, SoundFx.JUMP_LANDING4, SoundFx.JUMP_LANDING5 }; | |
private float _jumpingHeight = 8f; | |
private bool _canDoubleJump = true; | |
private bool _canJump = true; | |
public void Entry(PlayerMediator mediator) { | |
mediator.RecordGameStatSignal.Dispatch(GameStatType.JUMP, mediator.View.PlayerIndex); | |
PlayAudio(mediator); | |
mediator.IsJumping = true; | |
mediator.PlayMovementDustAnimSignal.Dispatch(mediator.transform.position - new Vector3(0, 0.3f, 0), mediator.View.Sprite.FlipX, command.MovementDustType.JUMPING); | |
PlayWingsAnim(mediator); | |
} | |
private static void PlayWingsAnim(PlayerMediator mediator) { | |
mediator.View.AngelWingsSpriteAnim.StopAndResetFrame(); | |
mediator.View.AngelWingsSpriteAnim.Play(); | |
mediator.View.DevilWingsSpriteAnim.StopAndResetFrame(); | |
mediator.View.DevilWingsSpriteAnim.Play(); | |
} | |
public void Exit(PlayerMediator mediator, IState state) { | |
mediator.IsJumping = false; | |
mediator.ChangeState(state); | |
} | |
public void OnCollisionEnter(PlayerMediator mediator, Collider other) { | |
} | |
public void FixedUpdate(PlayerMediator mediator) { | |
} | |
public void HandleInput(PlayerMediator mediator) { | |
if (mediator.EntityController.CollisionDetection.OnGround) { | |
// Only dispatch a movement dust anim if the player is landing downard. | |
if (mediator.AmountToMove.y <= 0) { | |
mediator.PlayMovementDustAnimSignal.Dispatch(mediator.transform.position - new Vector3(0, 0.2f, 0), mediator.View.Sprite.FlipX, MovementDustType.LANDING); | |
mediator.PlaySoundFxSignal.Dispatch(new PlaySoundFxModel(_jumpLandings[Random.Range(0, 5)], mediator.transform.position, SpatialBlend.ThreeDee)); | |
} | |
Exit(mediator, new StandingState()); | |
} | |
if (mediator.View.IsTeleporting) { | |
Exit(mediator, new TeleportState()); | |
} | |
// Once the player lets go of the jump button, they shouldn't be jumping anymore. | |
if (!mediator.InputController.Jump()) { | |
_canJump = false; | |
} | |
// This seems gnarly, but what we're checking is if the player has hit the jump button again since letting it | |
// go while in this state. We also check to see if the player isn't on a descend, which we don't want to allow | |
// a double jump then. | |
if (mediator.InputController.Jump() && !_canJump && _canDoubleJump && mediator.AmountToMove.y >= -5f) { | |
mediator.AmountToMove = new Vector3(mediator.AmountToMove.x, mediator.View.JumpHeight); | |
mediator.PlayMovementDustAnimSignal.Dispatch(mediator.transform.position - new Vector3(0, 0.3f, 0), mediator.View.Sprite.FlipX, MovementDustType.JUMPING); | |
PlayAudio(mediator); | |
PlayWingsAnim(mediator); | |
_canDoubleJump = false; | |
} | |
if (mediator.InputController.MeleeAttackReleased()) { | |
if (mediator.View.ShieldView.ShieldHealth > 0 | |
&& mediator.View.MeleeCooldownTimer < 0 && !mediator.View.IsPossessed) { | |
Exit(mediator, new MeleeState()); | |
} else { | |
mediator.PlaySoundFxSignal.Dispatch(new PlaySoundFxModel(SoundFx.NEGATIVE, mediator.transform.position, SpatialBlend.ThreeDee)); | |
mediator.DisplayAlertOverPlayerSignal.Dispatch(mediator.gameObject); | |
} | |
} | |
if (mediator.InputController.MeleeAttackPressed() && mediator.View.ShieldView.ShieldHealth > 0 | |
&& mediator.View.MeleeCooldownTimer < 0 && !mediator.View.IsPossessed) { | |
mediator.View.Charge += 0.05f; | |
} else { | |
if (mediator.InputController.Shield() && mediator.View.ShieldView.ShieldHealth > 0 && !mediator.View.IsPossessed) { | |
Exit(mediator, new ShieldedState()); | |
} | |
if (mediator.InputController.ThrowGrenade() && !mediator.View.IsPossessed) { | |
mediator.ActivateGrenade(); | |
} | |
if (mediator.InputController.Dash()) { | |
if (mediator.View.DashCooldownTimer < 0 && !mediator.View.IsPossessed) { | |
Exit(mediator, new DashingState()); | |
} else { | |
mediator.PlaySoundFxSignal.Dispatch(new PlaySoundFxModel(SoundFx.NEGATIVE, mediator.transform.position, SpatialBlend.ThreeDee)); | |
mediator.DisplayAlertOverPlayerSignal.Dispatch(mediator.gameObject); | |
} | |
} | |
if (mediator.View.HasSoul && mediator.InputController.OtherAction() && !mediator.View.IsPossessed) { | |
mediator.ThrowSoulFlag(); | |
} | |
} | |
} | |
public void Update(PlayerMediator mediator) { | |
if (_canJump) { | |
if (_jumpingHeight < mediator.View.JumpHeight) { | |
_jumpingHeight = Mathf.Lerp(_jumpingHeight, _jumpingHeight += 20, 2 * Time.deltaTime); | |
mediator.AmountToMove = new Vector3(mediator.AmountToMove.x, mediator.View.JumpHeight); | |
} | |
} | |
int animToPlay = mediator.AmountToMove.y > 0 ? 0 : 1; | |
if (mediator.View.VerticalInput == -1) { | |
animToPlay = 2; | |
} else if (mediator.View.VerticalInput == 1) { | |
animToPlay = 3; | |
} | |
mediator.PlayAnim(_animToPlay[animToPlay]); | |
if (mediator.View.Health < 1) { | |
Exit(mediator, new DeadState()); | |
} | |
if (mediator.View.IsGrounded) { | |
Exit(mediator, new GroundedState()); | |
} | |
} | |
public void LateUpdate(PlayerMediator mediator) { | |
if (mediator.View.IsDrunk) { | |
mediator.View.HorizontalInput *= 0.5f; | |
mediator.View.VerticalInput *= 0.5f; | |
} | |
mediator.OnInput(); | |
} | |
private void PlayAudio(PlayerMediator mediator) { | |
mediator.PlayJumpClip(); | |
} | |
} | |
} | |
namespace com.mindshaft.overtime.view { | |
public class PlayerMediator : Mediator { | |
// OnInput should be called from within the FSM | |
// in order to have fine control over when | |
// the player can move and how. | |
public void OnInput() { | |
_movement.HorizontalInput = View.HorizontalInput; | |
_movement.CurrentSpeed = CurrentSpeed; | |
_movement.Speed = View.Speed; | |
_movement.Accel = View.Acceleration; | |
_movement.IsJumping = IsJumping; | |
_movement.FlipAnim = _flipAnim; | |
_movement.AmountToMove = AmountToMove; | |
_movement.Position = transform.position; | |
_movement.BoxCollider = View.BoxCollider; | |
_movement = EntityController.Move(_movement); | |
OnMovementCalculated(_movement); | |
} | |
private void OnMovementCalculated(IMovementModel calculatedMovement) { | |
CurrentSpeed = calculatedMovement.CurrentSpeed; | |
View.CurrentSpeed = CurrentSpeed; | |
AmountToMove = calculatedMovement.AmountToMove; | |
View.AmountToMove = AmountToMove; | |
_flipAnim = calculatedMovement.FlipAnim; | |
// If player is grounded, let them fall but don't let them move along the X axis. | |
// This will allow us to properly flip sprites if they move left or right. | |
View.FinalTransform = View.IsGrounded ? new Vector3(0, calculatedMovement.FinalTransform.y, calculatedMovement.FinalTransform.z) : calculatedMovement.FinalTransform; | |
// To allow strafing, check if the player is holding down the shoot button | |
// if so, don't flip the sprite. | |
if (!InputController.ShootDown()) { | |
View.FlipSprite(calculatedMovement.FlipAnim); | |
} | |
transform.Translate(View.FinalTransform); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment