LADXHD/InGame/GameObjects/Enemies/EnemyStalfosGreen.cs

224 lines
8.1 KiB
C#
Raw Normal View History

2023-12-14 22:21:22 +00:00
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 EnemyStalfosGreen : GameObject
{
private readonly BodyComponent _body;
private readonly AiComponent _aiComponent;
private readonly Animator _animator;
private readonly AnimationComponent _animatorComponent;
private readonly Rectangle _fieldRectangle;
private float _walkSpeed = 0.5f;
private float _changeDirCount;
private int _dir;
private bool _jumpMoving;
public EnemyStalfosGreen() : base("stalfos green") { }
public EnemyStalfosGreen(Map.Map map, int posX, int posY) : base(map)
{
Tags = Values.GameObjectTag.Enemy;
EntityPosition = new CPosition(posX + 8, posY + 16, 0);
EntitySize = new Rectangle(-8, -40, 16, 40);
_animator = AnimatorSaveLoad.LoadAnimator("Enemies/stalfos green");
_animator.Play("walk");
var sprite = new CSprite(EntityPosition);
_animatorComponent = new AnimationComponent(_animator, sprite, new Vector2(-8, -16));
_fieldRectangle = map.GetField(posX, posY);
_body = new BodyComponent(EntityPosition, -6, -10, 11, 10, 8)
{
MoveCollision = OnCollision,
Gravity = -0.075f,
AvoidTypes = Values.CollisionTypes.Hole | Values.CollisionTypes.NPCWall,
FieldRectangle = _fieldRectangle
};
_aiComponent = new AiComponent();
var stateWalking = new AiState(UpdateWalking);
var stateMoveUp = new AiState(UpdateMoveUp);
var stateWait = new AiState();
stateWait.Trigger.Add(new AiTriggerCountdown(250, null, ToMoveDown));
var stateMoveDown = new AiState(UpdateMoveDown);
var stateWaitFloor = new AiState();
stateWaitFloor.Trigger.Add(new AiTriggerCountdown(250, null, ToWalk));
_aiComponent.States.Add("walking", stateWalking);
_aiComponent.States.Add("moveUp", stateMoveUp);
_aiComponent.States.Add("wait", stateWait);
_aiComponent.States.Add("moveDown", stateMoveDown);
_aiComponent.States.Add("waitFloor", stateWaitFloor);
new AiFallState(_aiComponent, _body, null, null, 300);
var damageState = new AiDamageState(this, _body, _aiComponent, sprite, 2) { OnBurn = () => _animator.Pause() };
_aiComponent.ChangeState("walking");
var damageBox = new CBox(EntityPosition, -7, -15, 2, 13, 15, 4);
var hittableBox = new CBox(EntityPosition, -7, -15, 2, 13, 15, 8);
var pushableBox = new CBox(EntityPosition, -6, -14, 2, 12, 14, 4);
AddComponent(DamageFieldComponent.Index, new DamageFieldComponent(damageBox, HitType.Enemy, 2));
AddComponent(HittableComponent.Index, new HittableComponent(hittableBox, damageState.OnHit));
AddComponent(AiComponent.Index, _aiComponent);
AddComponent(BodyComponent.Index, _body);
AddComponent(BaseAnimationComponent.Index, _animatorComponent);
AddComponent(PushableComponent.Index, new PushableComponent(pushableBox, OnPush));
AddComponent(DrawComponent.Index, new BodyDrawComponent(_body, sprite, Values.LayerPlayer));
AddComponent(DrawShadowComponent.Index, new BodyDrawShadowComponent(_body, sprite) { ShadowWidth = 10 });
}
public void SetAirPosition(int posZ)
{
EntityPosition.SetZ(posZ);
_animator.Play("jump");
ToMoveDown();
// randomize the walk speed so that when two are spawned at the same position they will not
// stay at the same position
_walkSpeed = Game1.RandomNumber.Next(45, 55) / 100f;
}
private bool OnPush(Vector2 direction, PushableComponent.PushType type)
{
if (type == PushableComponent.PushType.Impact)
_body.Velocity = new Vector3(direction.X * 1.75f, direction.Y * 1.75f, _body.Velocity.Z);
return true;
}
private void ToWalk()
{
_aiComponent.ChangeState("walking");
}
private void UpdateWalking()
{
_animator.Play("walk");
// jump away when the player is pressing the use key
var direction = MapManager.ObjLink.EntityPosition.Position - EntityPosition.Position;
var distance = direction.Length();
if (_fieldRectangle.Contains(MapManager.ObjLink.EntityPosition.Position) && distance < 56)
{
if (distance < 24)
ToJumping();
else if (distance < 56)
{
// move towards the player
direction.Normalize();
_body.VelocityTarget = direction * _walkSpeed;
}
}
else
{
_changeDirCount -= Game1.DeltaTime;
// change direction
if (_changeDirCount <= 0)
ChangeDirection();
}
}
private void ToJumping()
{
_aiComponent.ChangeState("moveUp");
Game1.GameManager.PlaySoundEffect("D360-36-24");
_animator.Play("jump");
_body.Velocity.Z = 2;
_jumpMoving = true;
}
private void UpdateMoveUp()
{
// start waiting in the air
if (EntityPosition.Z > 26 || _body.Velocity.Z <= 0)
{
ToWait();
return;
}
// move towards the player
if (_jumpMoving)
{
var vecDirection = MapManager.ObjLink.EntityPosition.Position - EntityPosition.Position;
if (vecDirection.Length() < 2)
{
_jumpMoving = false;
return;
}
vecDirection.Normalize();
_body.VelocityTarget = vecDirection * _walkSpeed * 2;
}
}
private void ToWait()
{
_aiComponent.ChangeState("wait");
_body.VelocityTarget = Vector2.Zero;
_body.IgnoresZ = true;
}
private void ToMoveDown()
{
_aiComponent.ChangeState("moveDown");
_body.Velocity.Z = -3.5f;
_body.IgnoresZ = false;
}
private void UpdateMoveDown()
{
if (_body.IsGrounded)
ToWaitFloor();
}
private void ToWaitFloor()
{
_aiComponent.ChangeState("waitFloor");
Game1.GameManager.PlaySoundEffect("D360-07-07");
// this is green in the original
var animation = new ObjAnimator(Map, 0, 0, Values.LayerTop, "Particles/swordPoke", "run", true);
animation.EntityPosition.Set(new Vector2(EntityPosition.X, EntityPosition.Y + 4));
Map.Objects.SpawnObject(animation);
}
private void OnCollision(Values.BodyCollision collision)
{
if ((collision & Values.BodyCollision.Floor) != 0 && _aiComponent.CurrentStateId == "moveDown")
ToWaitFloor();
if ((collision & (Values.BodyCollision.Horizontal | Values.BodyCollision.Vertical)) != 0)
ChangeDirection();
}
private void ChangeDirection()
{
_changeDirCount = Game1.RandomNumber.Next(200, 600);
_dir = Game1.RandomNumber.Next(0, 4);
_body.VelocityTarget = AnimationHelper.DirectionOffset[_dir] * _walkSpeed;
}
}
}