LADXHD/InGame/GameObjects/Things/ObjPullLever.cs
2023-12-14 17:21:22 -05:00

172 lines
6 KiB
C#

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ProjectZ.InGame.GameObjects.Base;
using ProjectZ.InGame.GameObjects.Base.CObjects;
using ProjectZ.InGame.GameObjects.Base.Components;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;
namespace ProjectZ.InGame.GameObjects.Things
{
internal class ObjPullLever : GameObject
{
private readonly DictAtlasEntry _dictLever;
private readonly DictAtlasEntry _dictLeverTop;
// currently only supports one lever per map
public static float LeverState;
private CPosition _position;
private Rectangle _field;
private Point _startPosition;
private string _openStrKey;
private const int MinLeverLength = 4;
private const int MaxLeverLength = 47;
private const float PullSpeed = 0.24f;
private readonly float RetractingSpeed;
private const float OpenSpeed = 0.25f;
private float _length = MinLeverLength; // 4 - 47
private bool _isOpening;
private bool _isGrabbed;
private bool _wasPulled;
public ObjPullLever() : base("pull_lever") { }
public ObjPullLever(Map.Map map, int posX, int posY, float retractingSpeed, string openStrKey) : base(map)
{
_startPosition = new Point(posX + 8, posY);
_position = new CPosition(posX + 8, posY + _length + 16, 0);
//EntitySize = new Rectangle(-8, -56, 16, 56);
RetractingSpeed = retractingSpeed;
_openStrKey = openStrKey;
LeverState = 1;
_field = map.GetField(posX, posY, 12);
_dictLever = Resources.GetSprite("pull_lever");
_dictLeverTop = Resources.GetSprite("pull_lever_top");
var collisionBox = new CBox(_position, -2, -56, 0, 4, 54, 8);
if (!string.IsNullOrEmpty(_openStrKey))
AddComponent(KeyChangeListenerComponent.Index, new KeyChangeListenerComponent(OnKeyChange));
AddComponent(CarriableComponent.Index, new CarriableComponent(
new CRectangle(_position, new Rectangle(-3, -4, 6, 2)), null, null, null)
{ StartGrabbing = StartGrabbing, Pull = OnPull });
AddComponent(CollisionComponent.Index, new BoxCollisionComponent(collisionBox, Values.CollisionTypes.Normal));
AddComponent(UpdateComponent.Index, new UpdateComponent(Update));
AddComponent(DrawComponent.Index, new DrawComponent(Draw, Values.LayerBottom, _position));
}
private void OnKeyChange()
{
var openState = Game1.GameManager.SaveManager.GetString(_openStrKey, "0");
if (openState == "1")
{
_isOpening = true;
Game1.GameManager.SaveManager.SetString(_openStrKey, "0");
}
}
private void StartGrabbing()
{
if (MapManager.ObjLink.Direction != 1)
return;
UpdatePlayerPosition();
}
private bool OnPull(Vector2 direction)
{
if (MapManager.ObjLink.Direction != 1)
return false;
_isGrabbed = true;
if (direction.X != 0 || direction.Y < 0)
return true;
// play soundeffect on pull
if (!_wasPulled && direction.Y > 0)
Game1.GameManager.PlaySoundEffect("D378-17-11");
_wasPulled = direction.Y > 0;
_position.Move(direction * PullSpeed);
_length = _position.Y - 16 - _startPosition.Y;
if (_length > MaxLeverLength)
{
_length = MaxLeverLength;
_position.Set(new Vector2(_startPosition.X, _startPosition.Y + 16 + _length));
}
UpdateLeverState(direction.Y * (PullSpeed + 0.01f) * Game1.TimeMultiplier);
UpdatePlayerPosition();
// this is used to not continuously play the pull animation
if (_length == MaxLeverLength)
return false;
return true;
}
private void UpdatePlayerPosition()
{
// set the position of the player
MapManager.ObjLink.EntityPosition.Set(new Vector2(
_position.X, _position.Y + MapManager.ObjLink.BodyRectangle.Height - 2));
}
private void UpdateLeverState(float offset)
{
LeverState += offset / (MaxLeverLength - MinLeverLength);
LeverState = Math.Clamp(LeverState, 0, 1);
}
private void Update()
{
var insideRoom = _field.Contains(MapManager.ObjLink.EntityPosition.Position);
if (insideRoom)
_isOpening = false;
if (_isOpening)
UpdateLeverState(OpenSpeed * Game1.TimeMultiplier);
else if (!_isGrabbed && insideRoom)
UpdateLeverState(-RetractingSpeed * Game1.TimeMultiplier);
// move the lever back to the starting position
if (!_isGrabbed)
{
_position.Move(new Vector2(0, -RetractingSpeed));
if (_position.Y < _startPosition.Y + 16 + MinLeverLength)
_position.Set(new Vector2(_startPosition.X, _startPosition.Y + 16 + MinLeverLength));
_length = _position.Y - 16 - _startPosition.Y;
}
_isGrabbed = false;
}
private void Draw(SpriteBatch spriteBatch)
{
// thing
spriteBatch.Draw(_dictLeverTop.Texture,
new Rectangle(_startPosition.X - 2, _startPosition.Y, 4, (int)_length + 1), _dictLeverTop.ScaledRectangle, Color.White);
// pull thing
spriteBatch.Draw(_dictLever.Texture,
new Vector2(_position.X - 8, _position.Y - 16), _dictLever.ScaledRectangle, Color.White);
}
}
}