mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-25 16:03:02 +00:00
215 lines
8.7 KiB
C#
215 lines
8.7 KiB
C#
using System;
|
|
using System.Globalization;
|
|
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.GameObjects.Base.Systems;
|
|
using ProjectZ.InGame.Map;
|
|
using ProjectZ.InGame.SaveLoad;
|
|
using ProjectZ.InGame.Things;
|
|
|
|
namespace ProjectZ.InGame.GameObjects.Things
|
|
{
|
|
class ObjChainPlatform : GameObject
|
|
{
|
|
private readonly DictAtlasEntry _spritePlatform;
|
|
private readonly DictAtlasEntry _spriteChain;
|
|
|
|
private readonly BoxCollisionComponent _cBoxCollision;
|
|
|
|
private readonly CBox _moveBox;
|
|
|
|
private readonly CBox _collisionBox;
|
|
|
|
private Vector2 _chainPosition;
|
|
|
|
private Vector2 _startPosition;
|
|
private Vector2 _bottomPosition;
|
|
private Vector2 _currentVelocity;
|
|
|
|
private string _strPlatformKey;
|
|
private string _strPlatformMovedKey;
|
|
private string _strPlatformRestKey;
|
|
|
|
private const float MaxSpeed = 1.0f;
|
|
private float _resetVelocity;
|
|
|
|
private bool _wasMoved;
|
|
private bool _resettingPlatforms;
|
|
|
|
public ObjChainPlatform(Map.Map map, int posX, int posY, string strPlatformKey, int bottom, int chainTop) : base(map)
|
|
{
|
|
_spritePlatform = Resources.GetSprite("small_platform");
|
|
_spriteChain = Resources.GetSprite("platformchain");
|
|
|
|
_strPlatformKey = strPlatformKey;
|
|
_strPlatformMovedKey = strPlatformKey + "moved";
|
|
_strPlatformRestKey = strPlatformKey + "reset";
|
|
|
|
SprEditorImage = _spritePlatform.Texture;
|
|
EditorIconSource = _spritePlatform.SourceRectangle;
|
|
|
|
EntityPosition = new CPosition(posX, posY, 0);
|
|
EntitySize = new Rectangle(0, chainTop, 16, -chainTop + bottom + 16);
|
|
|
|
_chainPosition = new Vector2(posX + 8 - _spriteChain.SourceRectangle.Width / 2, posY + chainTop);
|
|
|
|
_startPosition = new Vector2(posX, posY);
|
|
_bottomPosition = new Vector2(posX, posY + bottom);
|
|
|
|
_moveBox = new CBox(EntityPosition, 0, -1, 0, 16, 16, 16);
|
|
_collisionBox = new CBox(EntityPosition, 0, 0, 16, 16, 16);
|
|
|
|
AddComponent(CollisionComponent.Index, _cBoxCollision = new BoxCollisionComponent(_collisionBox, Values.CollisionTypes.Normal) { DirectionFlag = 8 });
|
|
AddComponent(UpdateComponent.Index, new UpdateComponent(Update));
|
|
AddComponent(DrawComponent.Index, new DrawComponent(Draw, Values.LayerBottom, EntityPosition));
|
|
|
|
if (_strPlatformKey != null)
|
|
{
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformKey, "0");
|
|
AddComponent(KeyChangeListenerComponent.Index, new KeyChangeListenerComponent(OnKeyChange));
|
|
}
|
|
}
|
|
|
|
private void OnKeyChange()
|
|
{
|
|
if (!_wasMoved && Game1.GameManager.SaveManager.GetString(_strPlatformMovedKey) == "true")
|
|
{
|
|
var strPlatformOffset = Game1.GameManager.SaveManager.GetString(_strPlatformKey);
|
|
if (!string.IsNullOrEmpty(strPlatformOffset))
|
|
{
|
|
var newOffset = float.Parse(strPlatformOffset, CultureInfo.InvariantCulture);
|
|
EntityPosition.Set(_startPosition + new Vector2(0, newOffset));
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformMovedKey, "false");
|
|
_resettingPlatforms = false;
|
|
}
|
|
}
|
|
|
|
// reset the platforms?
|
|
var strReset = Game1.GameManager.SaveManager.GetString(_strPlatformRestKey);
|
|
if (strReset != null && strReset == "true")
|
|
{
|
|
_resettingPlatforms = true;
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformRestKey, "false");
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
_wasMoved = false;
|
|
|
|
// is the player standing on the platform?
|
|
var standingOnTop = MapManager.ObjLink._body.BodyBox.Box.Intersects(_moveBox.Box) && MapManager.ObjLink._body.IsGrounded;
|
|
|
|
if (standingOnTop && PlayerIsMovable())
|
|
{
|
|
// accelerate the platform
|
|
_currentVelocity += new Vector2(0, 0.025f * Game1.TimeMultiplier);
|
|
_currentVelocity.Y = MathHelper.Clamp(_currentVelocity.Y, 0, MaxSpeed);
|
|
|
|
_resettingPlatforms = false;
|
|
}
|
|
else
|
|
{
|
|
// slow down the platform
|
|
_currentVelocity *= (float)Math.Pow(0.85f, Game1.TimeMultiplier);
|
|
}
|
|
|
|
if (_currentVelocity.Length() > 0.1f)
|
|
MovePlatform(_currentVelocity);
|
|
|
|
// move back to the start position
|
|
if (_resettingPlatforms)
|
|
{
|
|
var offset = _startPosition.Y - EntityPosition.Y;
|
|
|
|
_resetVelocity += 0.035f * Game1.TimeMultiplier;
|
|
_resetVelocity = MathHelper.Clamp(_resetVelocity, 0, 0.4f);
|
|
|
|
if (Math.Abs(offset) > _resetVelocity)
|
|
{
|
|
offset = Math.Sign(offset) * MathHelper.Clamp(Math.Abs(offset), 0, _resetVelocity * Game1.TimeMultiplier);
|
|
SetPosition(EntityPosition.Y + offset);
|
|
}
|
|
else
|
|
{
|
|
_resettingPlatforms = false;
|
|
SetPosition(_startPosition.Y);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_resetVelocity = 0;
|
|
}
|
|
}
|
|
|
|
private void SetPosition(float newPositionY)
|
|
{
|
|
_wasMoved = true;
|
|
EntityPosition.Set(new Vector2(EntityPosition.X, newPositionY));
|
|
|
|
var platformOffset = _startPosition.Y - EntityPosition.Position.Y;
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformKey, platformOffset.ToString(CultureInfo.InvariantCulture));
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformMovedKey, "true");
|
|
}
|
|
|
|
private void MovePlatform(Vector2 offset)
|
|
{
|
|
// do not allow the platform to move lower than the max
|
|
var maxOffset = _bottomPosition.Y - EntityPosition.Y;
|
|
if (maxOffset <= 0)
|
|
return;
|
|
if (offset.Y > maxOffset)
|
|
offset.Y = maxOffset;
|
|
|
|
// make sure to not move the platform more than the player was able to move
|
|
EntityPosition.Move(offset);
|
|
|
|
// move the player down
|
|
SystemBody.MoveBody(MapManager.ObjLink._body, offset * Game1.TimeMultiplier,
|
|
Values.CollisionTypes.Normal, false, false, false);
|
|
|
|
_wasMoved = true;
|
|
if (_strPlatformKey != null)
|
|
{
|
|
// make sure other linked platforms will also be moved
|
|
var platformOffset = _startPosition.Y - EntityPosition.Position.Y;
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformKey, platformOffset.ToString(CultureInfo.InvariantCulture));
|
|
Game1.GameManager.SaveManager.SetString(_strPlatformMovedKey, "true");
|
|
}
|
|
}
|
|
|
|
// this checks if the player can be moved down with the platform or if the player
|
|
// is also standing on a ledge and is not really pushing down on the platform
|
|
private bool PlayerIsMovable()
|
|
{
|
|
var lastPosition = MapManager.ObjLink.EntityPosition.Position;
|
|
|
|
_cBoxCollision.IsActive = false;
|
|
SystemBody.MoveBody(MapManager.ObjLink._body, new Vector2(0, 1), Values.CollisionTypes.Normal, false, false, false);
|
|
_cBoxCollision.IsActive = true;
|
|
|
|
// check if the player was moved
|
|
var playerCanMove = MapManager.ObjLink.EntityPosition.Y != lastPosition.Y;
|
|
|
|
// move the player back to the original position
|
|
MapManager.ObjLink.EntityPosition.Set(lastPosition);
|
|
|
|
return playerCanMove;
|
|
}
|
|
|
|
private void Draw(SpriteBatch spriteBatch)
|
|
{
|
|
// draw the chain
|
|
var chainLinkCount = (int)Math.Ceiling((EntityPosition.Y - _chainPosition.Y) / 16);
|
|
for (var i = 0; i < chainLinkCount; i++)
|
|
spriteBatch.Draw(_spriteChain.Texture, new Vector2(_chainPosition.X, _chainPosition.Y + i * 16), _spriteChain.ScaledRectangle, Color.White);
|
|
|
|
// draw the platform
|
|
spriteBatch.Draw(_spritePlatform.Texture, EntityPosition.Position, _spritePlatform.ScaledRectangle, Color.White);
|
|
}
|
|
}
|
|
}
|