LADXHD/InGame/GameObjects/Things/ObjWeatherBird.cs

152 lines
5.5 KiB
C#
Raw Normal View History

2023-12-14 22:21:22 +00:00
using System;
using Microsoft.Xna.Framework;
using ProjectZ.InGame.GameObjects.Base;
using ProjectZ.InGame.GameObjects.Base.CObjects;
using ProjectZ.InGame.GameObjects.Base.Components;
using ProjectZ.InGame.GameObjects.Base.Components.AI;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;
namespace ProjectZ.InGame.GameObjects.Things
{
internal class ObjWeatherBird : GameObject
{
private readonly AiComponent _aiComponent;
private readonly Point[] _moveOffset = { new Point(-1, 0), new Point(0, -1), new Point(1, 0), new Point(0, 1) };
private readonly string _saveKey;
private readonly int _allowedDirection = 1;
private Vector2 _startPosition;
private Vector2 _aimPosition;
private const int PushTime = 250;
private const int MoveTime = 500;
private float _pushCounter;
private bool _wasPushed;
public ObjWeatherBird() : base("weather_bird") { }
public ObjWeatherBird(Map.Map map, int posX, int posY, string saveKey) : base(map)
{
EntityPosition = new CPosition(posX + 1, posY + 30, 0);
EntitySize = new Rectangle(0, -30, 16, 32);
_saveKey = saveKey;
var movingTrigger = new AiTriggerCountdown(MoveTime, MoveTick, MoveEnd);
_aiComponent = new AiComponent();
_aiComponent.States.Add("idle", new AiState(UpdateIdle));
_aiComponent.States.Add("moving", new AiState { Init = InitMoving, Trigger = { movingTrigger } });
_aiComponent.States.Add("moved", new AiState());
if (_saveKey != null && Game1.GameManager.SaveManager.GetString(_saveKey) == "1")
{
EntityPosition.Set(new Vector2(EntityPosition.X, EntityPosition.Y - 16));
_aiComponent.ChangeState("moved");
}
else
_aiComponent.ChangeState("idle");
var body = new BodyComponent(EntityPosition, 0, -10, 14, 12, 8)
{
FieldRectangle = map.GetField(posX, posY)
};
var animator = AnimatorSaveLoad.LoadAnimator("Objects/weatherBird");
var sprite = new CSprite(EntityPosition);
var animationComponent = new AnimationComponent(animator, sprite, new Vector2(0, -30));
animator.Play("idle");
AddComponent(InteractComponent.Index, new InteractComponent(body.BodyBox, Interact));
AddComponent(AiComponent.Index, _aiComponent);
AddComponent(BaseAnimationComponent.Index, animationComponent);
AddComponent(CollisionComponent.Index, new BoxCollisionComponent(body.BodyBox, Values.CollisionTypes.Normal));
AddComponent(DrawComponent.Index, new BodyDrawComponent(body, sprite, Values.LayerPlayer));
AddComponent(PushableComponent.Index, new PushableComponent(body.BodyBox, OnPush));
}
private bool Interact()
{
Game1.GameManager.StartDialogPath("weatherBird");
return true;
}
private bool OnPush(Vector2 direction, PushableComponent.PushType type)
{
if (_aiComponent.CurrentStateId != "idle")
return false;
// move the stone
if (type != PushableComponent.PushType.Continues)
return false;
var stoneLifter = Game1.GameManager.GetItem("stonelifter2");
if (stoneLifter == null)
return false;
var pushDirection = AnimationHelper.GetDirection(direction);
if (_allowedDirection != -1 && _allowedDirection != pushDirection)
return false;
_wasPushed = true;
_pushCounter += Game1.DeltaTime;
// start moving
if (_pushCounter < PushTime)
return false;
_startPosition = EntityPosition.Position;
_aimPosition = new Vector2(
_startPosition.X + _moveOffset[pushDirection].X * 16,
_startPosition.Y + _moveOffset[pushDirection].Y * 16);
_aiComponent.ChangeState("moving");
return true;
}
private void UpdateIdle()
{
// reset the moveCounter used for measuring how long the player is already pushing
// this is used so the stone does not move instantly after the first collision with the player
if (!_wasPushed)
_pushCounter = 0;
_wasPushed = false;
}
private void InitMoving()
{
Game1.GameManager.PlaySoundEffect("D378-17-11");
// set the key
if (_saveKey != null)
Game1.GameManager.SaveManager.SetString(_saveKey, "1");
}
private void MoveTick(double time)
{
// freeze the player
MapManager.ObjLink.FreezePlayer();
// the movement is fast in the beginning and slows down at the end
var amount = (float)Math.Sin((MoveTime - time) / MoveTime * (Math.PI / 2f));
EntityPosition.Set(Vector2.Lerp(_startPosition, _aimPosition, amount));
}
private void MoveEnd()
{
Game1.GameManager.PlaySoundEffect("D360-35-23");
// finished moving
EntityPosition.Set(_aimPosition);
_aiComponent.ChangeState("moved");
}
}
}