void StateWallJumpInAir(APFsmStateEvent eEvent) { switch (eEvent) { case APFsmStateEvent.eEnter: { m_wallJumpAutoRotate = m_basic.m_autoRotate; m_wallJumpFlipDone = false; // prevent auto rotate for a while if (m_wallJumpAutoRotate) { m_basic.m_autoRotate = false; } } break; case APFsmStateEvent.eUpdate: { // go back to standard state as soon as touching ground if (m_onGround) { SetState(State.Standard); } else { // flip when needed bool bFlipEnabled = (m_wallJump.m_timeBeforeFlip >= 0f); if (!m_wallJumpFlipDone && bFlipEnabled && (m_fsm.GetFsmStateTime() >= m_wallJump.m_timeBeforeFlip)) { m_motor.Flip(); m_wallJumpFlipDone = true; } // enable back auto rotate if needed if (m_wallJumpAutoRotate && !m_basic.m_autoRotate && (m_fsm.GetFsmStateTime() >= m_wallJump.m_disableAutoRotateTime) && (m_wallJumpFlipDone || !bFlipEnabled)) { m_basic.m_autoRotate = true; } // standard process StateStandard(APFsmStateEvent.eUpdate); // leave state if work is ended and no new state is requested if (!IsNewStateRequested() && (!bFlipEnabled || m_wallJumpFlipDone) && (!m_wallJumpAutoRotate || m_basic.m_autoRotate)) { SetState(State.Standard); } } } break; case APFsmStateEvent.eLeave: { // restore initial auto rotate in all cases m_basic.m_autoRotate = m_wallJumpAutoRotate; } break; } }
void StateCrouch(APFsmStateEvent eEvent) { switch (eEvent) { case APFsmStateEvent.eEnter: { SendMessage("APOnCharacterCrouch", SendMessageOptions.DontRequireReceiver); PlayAnim(m_animations.m_crouch, GetPreviousState() == State.MeleeAttack ? 1f : 0f); } break; case APFsmStateEvent.eUpdate: { ApplyGravity(); HandleCrouch(); HandleHorizontalMove(); HandleJump(); HandleMeleeAttack(); if (m_basic.m_enableCrouchedAutoRotate) { HandleAutoRotate(); } } break; } }
/// Virtual method called when state enter, update or leave occur public override void OnStateUpdate(APFsmStateEvent eEvent, uint a_oState) { switch ((State)a_oState) { case State.Standard: m_controller.StateStandard(eEvent); break; case State.Crouch: m_controller.StateCrouch(eEvent); break; case State.WallJump: m_controller.StateWallJump(eEvent); break; case State.WallJumpInAir: m_controller.StateWallJumpInAir(eEvent); break; case State.MeleeAttack: m_controller.StateMeleeAttack(eEvent); break; } }
void StateStandard(APFsmStateEvent eEvent) { if (eEvent == APFsmStateEvent.eUpdate) { ApplyGravity(); HandleCrouch(); HandleHorizontalMove(); HandleJump(); HandleWallJump(); HandleMeleeAttack(); HandleAutoRotate(); } }
void StateWallJump(APFsmStateEvent eEvent) { switch (eEvent) { case APFsmStateEvent.eEnter: { SendMessage("APOnCharacterWallJump", SendMessageOptions.DontRequireReceiver); PlayAnim(m_animations.m_wallJump, 0f); m_wallJumpAutoRotate = m_basic.m_autoRotate; // prevent auto rotate for a while if (m_wallJumpAutoRotate) { m_basic.m_autoRotate = false; } } break; case APFsmStateEvent.eUpdate: { // cancel any velocity m_motor.m_velocity = Vector2.zero; // wait for end of timer before effective jump if (m_fsm.GetFsmStateTime() >= m_wallJump.m_timeBeforeJump) { m_motor.m_velocity.y = m_wallJump.m_jumpPower.y; m_motor.m_velocity.x = m_wallJump.m_jumpPower.x * (m_motor.FaceRight ? -1f : 1f); SetState(State.WallJumpInAir); } } break; case APFsmStateEvent.eLeave: { // restore initial auto rotate in all cases m_basic.m_autoRotate = m_wallJumpAutoRotate; } break; } }
/// Virtual method called when state enter, update or leave occur public abstract void OnStateUpdate(APFsmStateEvent a_oEvent, uint a_oState);
void StateMeleeAttack(APFsmStateEvent eEvent) { switch (eEvent) { case APFsmStateEvent.eEnter: { SendMessage("APOnCharacterMeleeAttack", SendMessageOptions.DontRequireReceiver); PlayAnim(m_curAttackAnimHash, 0f); // clear buffer of hits & disable hit zones at init APMeleeAttack curAttack = m_meleeAttacks.m_attacks[m_curAttackId]; foreach (APHitZone curHitZone in curAttack.m_hitZones) { curHitZone.attackHits.Clear(); } } break; case APFsmStateEvent.eUpdate: { // update state ApplyGravity(); HandleHorizontalMove(); // Compute all hits for current attack APMeleeAttack curAttack = m_meleeAttacks.m_attacks [m_curAttackId]; foreach (APHitZone curHitZone in curAttack.m_hitZones) { if (curHitZone.m_active && curHitZone.gameObject.activeInHierarchy) { Vector2 wsPos = curHitZone.transform.position; int hitCount = Physics2D.OverlapCircleNonAlloc(wsPos, curHitZone.m_radius, m_attackHitResult, m_motor.m_rayLayer); for (int i = 0; i < hitCount; i++) { Collider2D curHit = m_attackHitResult[i]; // notify only hitable objects and not already hit by this hit zone APHitable hitable = curHit.GetComponent <APHitable>(); if (hitable != null && !curHitZone.attackHits.Contains(hitable)) { curHitZone.attackHits.Add(hitable); // alert hitable hitable.OnMeleeAttackHit(this, curHitZone); } } } } // make sure state does not end infinitely if (m_fsm.GetFsmStateTime() > m_maxAttackDuration) { SetState(GetPreviousState()); } } break; case APFsmStateEvent.eLeave: { m_curAttackId = -1; } break; } }