mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-01 04:14:22 +00:00
215 lines
8.1 KiB
C#
215 lines
8.1 KiB
C#
|
using System;
|
||
|
using Microsoft.Xna.Framework;
|
||
|
using ProjectZ.InGame.GameObjects.Base;
|
||
|
using ProjectZ.InGame.GameObjects.Base.Components;
|
||
|
using ProjectZ.InGame.GameObjects.Base.CObjects;
|
||
|
using ProjectZ.InGame.GameObjects.Base.Components.AI;
|
||
|
using ProjectZ.InGame.GameObjects.Things;
|
||
|
using ProjectZ.InGame.Map;
|
||
|
using ProjectZ.InGame.SaveLoad;
|
||
|
using ProjectZ.InGame.Things;
|
||
|
|
||
|
namespace ProjectZ.InGame.GameObjects.Enemies
|
||
|
{
|
||
|
internal class EnemyCheepCheep : GameObject
|
||
|
{
|
||
|
private readonly BodyComponent _body;
|
||
|
private readonly AiComponent _aiComponent;
|
||
|
private readonly AiDamageState _damageState;
|
||
|
private readonly Animator _animator;
|
||
|
|
||
|
private readonly CBox _damageBox;
|
||
|
private readonly CBox _headJumpBox;
|
||
|
|
||
|
private Vector2 _jumpStart;
|
||
|
private const int JumpTime = 1500;
|
||
|
|
||
|
private readonly float _movementSpeed;
|
||
|
private int _dir;
|
||
|
private readonly bool _canJump;
|
||
|
|
||
|
public EnemyCheepCheep() : base("cheep cheep") { }
|
||
|
|
||
|
public EnemyCheepCheep(Map.Map map, int posX, int posY, int dir, bool canJump) : base(map)
|
||
|
{
|
||
|
Tags = Values.GameObjectTag.Enemy;
|
||
|
|
||
|
EntityPosition = new CPosition(posX + 8, posY + 16, 0);
|
||
|
EntitySize = new Rectangle(-8, -16, 16, 16);
|
||
|
|
||
|
_dir = dir;
|
||
|
_canJump = canJump;
|
||
|
|
||
|
_movementSpeed = canJump ? 0.75f : 0.5f;
|
||
|
|
||
|
_animator = AnimatorSaveLoad.LoadAnimator("Enemies/cheep cheep");
|
||
|
|
||
|
var sprite = new CSprite(EntityPosition);
|
||
|
var animationComponent = new AnimationComponent(_animator, sprite, new Vector2(-8, -16));
|
||
|
|
||
|
_body = new BodyComponent(EntityPosition, -8, -12, 16, 10, 8)
|
||
|
{
|
||
|
MoveCollision = OnCollision,
|
||
|
AvoidTypes = Values.CollisionTypes.NPCWall,
|
||
|
CollisionTypes =
|
||
|
Values.CollisionTypes.Normal,
|
||
|
FieldRectangle = map.GetField(posX, posY),
|
||
|
DragAir = 0.8f,
|
||
|
Gravity2DWater = 0f
|
||
|
};
|
||
|
|
||
|
var stateMoving = new AiState();
|
||
|
if (_canJump)
|
||
|
{
|
||
|
stateMoving.Trigger.Add(new AiTriggerRandomTime(ToMoving, 350, 1250));
|
||
|
stateMoving.Trigger.Add(new AiTriggerRandomTime(ToJump, 750, 1250));
|
||
|
}
|
||
|
|
||
|
var statePause = new AiState();
|
||
|
statePause.Trigger.Add(new AiTriggerCountdown(700, null, ToMoving));
|
||
|
var stateJumping = new AiState();
|
||
|
stateJumping.Trigger.Add(new AiTriggerCountdown(JumpTime, UpdateJump, EndJump));
|
||
|
var stateDead = new AiState(UpdateDeath);
|
||
|
|
||
|
_aiComponent = new AiComponent();
|
||
|
_aiComponent.States.Add("moving", stateMoving);
|
||
|
_aiComponent.States.Add("pause", statePause);
|
||
|
_aiComponent.States.Add("jumping", stateJumping);
|
||
|
_aiComponent.States.Add("dead", stateDead);
|
||
|
_damageState = new AiDamageState(this, _body, _aiComponent, sprite, 1)
|
||
|
{
|
||
|
HitMultiplierX = 3.0f,
|
||
|
HitMultiplierY = 2.0f,
|
||
|
FlameOffset = new Point(0, 2),
|
||
|
OnBurn = () => _animator.Pause()
|
||
|
};
|
||
|
|
||
|
ToMoving();
|
||
|
|
||
|
var hittableBox = new CBox(EntityPosition, -8, -14, 0, 16, 12, 8);
|
||
|
_damageBox = new CBox(EntityPosition, -6, -14, 0, 12, 12, 4);
|
||
|
_headJumpBox = new CBox(EntityPosition, -6, -16, 0, 12, 6, 8);
|
||
|
|
||
|
AddComponent(DamageFieldComponent.Index, new DamageFieldComponent(_damageBox, HitType.Enemy, 2));
|
||
|
AddComponent(HittableComponent.Index, new HittableComponent(hittableBox, OnHit));
|
||
|
AddComponent(BodyComponent.Index, _body);
|
||
|
AddComponent(AiComponent.Index, _aiComponent);
|
||
|
AddComponent(BaseAnimationComponent.Index, animationComponent);
|
||
|
AddComponent(DrawComponent.Index, new BodyDrawComponent(_body, sprite, Values.LayerPlayer));
|
||
|
}
|
||
|
|
||
|
private Values.HitCollision OnHit(GameObject originObject, Vector2 direction, HitType type, int damage, bool pieceOfPower)
|
||
|
{
|
||
|
_body.IgnoresZ = false;
|
||
|
|
||
|
return _damageState.OnHit(originObject, direction, type, damage, pieceOfPower);
|
||
|
}
|
||
|
|
||
|
public override void Init()
|
||
|
{
|
||
|
// look into the direction of the player
|
||
|
if (_dir % 2 != 0 && MapManager.ObjLink.NextMapPositionStart != null)
|
||
|
_animator.Play("idle_" + (EntityPosition.X > MapManager.ObjLink.NextMapPositionStart.Value.X ? 0 : 2));
|
||
|
}
|
||
|
|
||
|
private void ToMoving()
|
||
|
{
|
||
|
_aiComponent.ChangeState("moving");
|
||
|
|
||
|
_body.VelocityTarget = AnimationHelper.DirectionOffset[_dir] * _movementSpeed;
|
||
|
|
||
|
// update the animation if the fish is going to the left or right
|
||
|
if (_dir % 2 == 0)
|
||
|
_animator.Play("idle_" + _dir);
|
||
|
|
||
|
_dir = (_dir + 2) % 4;
|
||
|
}
|
||
|
|
||
|
private void ToPausing()
|
||
|
{
|
||
|
_aiComponent.ChangeState("pause");
|
||
|
_body.VelocityTarget = Vector2.Zero;
|
||
|
}
|
||
|
|
||
|
private void ToJump()
|
||
|
{
|
||
|
_body.IgnoresZ = true;
|
||
|
_body.VelocityTarget = Vector2.Zero;
|
||
|
|
||
|
_aiComponent.ChangeState("jumping");
|
||
|
Game1.GameManager.PlaySoundEffect("D360-36-24");
|
||
|
|
||
|
// scale down the damage box
|
||
|
_damageBox.OffsetY += 8;
|
||
|
_damageBox.Box.Height -= 8;
|
||
|
|
||
|
_jumpStart = EntityPosition.Position;
|
||
|
|
||
|
// splash animation
|
||
|
var position = new Point((int)_jumpStart.X, (int)_jumpStart.Y);
|
||
|
var splashAnimator = new ObjAnimator(_body.Owner.Map, position.X, position.Y - 14, 0, 3, 1, "Particles/fishingSplash", "idle", true);
|
||
|
Map.Objects.SpawnObject(splashAnimator);
|
||
|
}
|
||
|
|
||
|
private void UpdateJump(double time)
|
||
|
{
|
||
|
var newPosition = _jumpStart - new Vector2(0, 64) * MathF.Sin((float)(time / JumpTime) * MathF.PI);
|
||
|
EntityPosition.Set(newPosition);
|
||
|
|
||
|
// player jumped on the fish?
|
||
|
if ((MapManager.ObjLink._body.Velocity.Y > 0 && !MapManager.ObjLink._body.IsGrounded || time > JumpTime / 2) &&
|
||
|
_headJumpBox.Box.Bottom >= MapManager.ObjLink._body.BodyBox.Box.Bottom &&
|
||
|
_headJumpBox.Box.Intersects(MapManager.ObjLink._body.BodyBox.Box))
|
||
|
{
|
||
|
Game1.GameManager.PlaySoundEffect("D370-14-0E");
|
||
|
|
||
|
MapManager.ObjLink._body.Velocity.Y -= 1f;
|
||
|
_aiComponent.ChangeState("dead");
|
||
|
_animator.Play("dead_" + _dir);
|
||
|
_body.VelocityTarget = Vector2.Zero;
|
||
|
_body.IgnoresZ = false;
|
||
|
_body.Gravity2DWater = 0.05f;
|
||
|
_body.CollisionTypes = Values.CollisionTypes.None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void EndJump()
|
||
|
{
|
||
|
// scale up the damage box
|
||
|
_damageBox.OffsetY -= 8;
|
||
|
_damageBox.Box.Height += 8;
|
||
|
|
||
|
_body.IgnoresZ = false;
|
||
|
UpdateJump(JumpTime);
|
||
|
ToMoving();
|
||
|
}
|
||
|
|
||
|
private void UpdateDeath()
|
||
|
{
|
||
|
if ((_body.CurrentFieldState & MapStates.FieldStates.DeepWater) != 0)
|
||
|
_body.CollisionTypes = Values.CollisionTypes.Normal;
|
||
|
}
|
||
|
|
||
|
private void OnCollision(Values.BodyCollision direction)
|
||
|
{
|
||
|
// kill the fish when it reaches the ground
|
||
|
if (_aiComponent.CurrentStateId == "dead" &&
|
||
|
(direction & Values.BodyCollision.Vertical) != 0)
|
||
|
{
|
||
|
_damageState.OnHit(MapManager.ObjLink, new Vector2(0, 1), HitType.Sword1, 1, false);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ((direction & Values.BodyCollision.Vertical) != 0)
|
||
|
_body.Velocity.Y = 0;
|
||
|
|
||
|
if (_aiComponent.CurrentStateId != "moving")
|
||
|
return;
|
||
|
|
||
|
if (_canJump)
|
||
|
ToMoving();
|
||
|
else
|
||
|
ToPausing();
|
||
|
}
|
||
|
}
|
||
|
}
|