mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-25 16:03:02 +00:00
202 lines
7.2 KiB
C#
202 lines
7.2 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.GameObjects.Base.Components.AI;
|
|
using ProjectZ.InGame.Map;
|
|
using ProjectZ.InGame.SaveLoad;
|
|
using ProjectZ.InGame.Things;
|
|
|
|
namespace ProjectZ.InGame.GameObjects.Things
|
|
{
|
|
class ObjArrow : GameObject
|
|
{
|
|
private readonly Animator _animator;
|
|
private readonly AiComponent _aiComponent;
|
|
private readonly ShadowBodyDrawComponent _shadowBody;
|
|
private readonly CSprite _sprite;
|
|
private readonly BodyComponent _body;
|
|
private readonly BodyDrawComponent _drawComponent;
|
|
|
|
private readonly CBox _damageBox;
|
|
|
|
private const int DespawnTime = 375;
|
|
private const int FadeOutTime = 75;
|
|
|
|
private float _despawnPercentage = 1;
|
|
private int _dir;
|
|
private bool _isFalling;
|
|
|
|
private Vector2[] _bombOffset = new Vector2[] { new Vector2(-4, 0), new Vector2(0, -4), new Vector2(4, 0), new Vector2(0, 6) };
|
|
private ObjBomb _objBomb;
|
|
private bool _bombMode;
|
|
|
|
private Vector2 _startPosition;
|
|
private Point[] _collisionBoxSize = { new Point(2, 2), new Point(2, 2), new Point(2, 2), new Point(2, 2) };
|
|
|
|
public ObjArrow(Map.Map map, Vector3 position, int dir, float speed) : base(map)
|
|
{
|
|
EntityPosition = new CPosition(position.X, position.Y, position.Z);
|
|
EntitySize = new Rectangle(-8, -12, 16, 16);
|
|
|
|
_startPosition = new Vector2(position.X, position.Y);
|
|
|
|
_dir = dir;
|
|
var velocity = AnimationHelper.DirectionOffset[_dir] * speed;
|
|
|
|
_animator = AnimatorSaveLoad.LoadAnimator("Objects/spear");
|
|
_animator.Play(dir.ToString());
|
|
|
|
_sprite = new CSprite(EntityPosition);
|
|
var animationComponent = new AnimationComponent(_animator, _sprite, Vector2.Zero);
|
|
|
|
_body = new BodyComponent(EntityPosition,
|
|
-_collisionBoxSize[dir].X / 2, -_collisionBoxSize[dir].Y / 2,
|
|
_collisionBoxSize[dir].X, _collisionBoxSize[dir].Y, 8)
|
|
{
|
|
CollisionTypes = Values.CollisionTypes.Normal,
|
|
CollisionTypesIgnore = Values.CollisionTypes.ThrowWeaponIgnore,
|
|
MoveCollision = OnCollision,
|
|
VelocityTarget = velocity,
|
|
Bounciness = 0.35f,
|
|
Drag = 0.75f,
|
|
DragAir = 0.95f,
|
|
Gravity = -0.025f,
|
|
IgnoreHeight = true,
|
|
IgnoresZ = true,
|
|
IgnoreInsideCollision = false,
|
|
Level = MapStates.GetLevel(MapManager.ObjLink._body.CurrentFieldState)
|
|
};
|
|
|
|
_damageBox = new CBox(EntityPosition,
|
|
-_collisionBoxSize[dir].X / 2 - 1, -_collisionBoxSize[dir].Y - 1, 0,
|
|
_collisionBoxSize[dir].X + 2, _collisionBoxSize[dir].Y + 2, 8);
|
|
|
|
var stateIdle = new AiState(UpdateIdle);
|
|
var stateDespawn = new AiState() { Init = InitDespawn };
|
|
stateDespawn.Trigger.Add(new AiTriggerCountdown(DespawnTime, TickDespawn, () => TickDespawn(0)));
|
|
|
|
_aiComponent = new AiComponent();
|
|
_aiComponent.States.Add("idle", stateIdle);
|
|
_aiComponent.States.Add("despawn", stateDespawn);
|
|
_aiComponent.ChangeState("idle");
|
|
|
|
_drawComponent = new BodyDrawComponent(_body, _sprite, Values.LayerPlayer);
|
|
|
|
AddComponent(BodyComponent.Index, _body);
|
|
AddComponent(AiComponent.Index, _aiComponent);
|
|
AddComponent(BaseAnimationComponent.Index, animationComponent);
|
|
AddComponent(DrawComponent.Index, new DrawComponent(Draw, Values.LayerPlayer, EntityPosition));
|
|
AddComponent(DrawShadowComponent.Index, _shadowBody = new ShadowBodyDrawComponent(EntityPosition));
|
|
}
|
|
|
|
private void UpdateIdle()
|
|
{
|
|
var distance = _startPosition - EntityPosition.Position;
|
|
if (Math.Abs(distance.X) > 112 || Math.Abs(distance.Y) > 96)
|
|
{
|
|
_isFalling = true;
|
|
_body.IgnoresZ = false;
|
|
|
|
ExplodeBomb();
|
|
}
|
|
|
|
DealDamage();
|
|
}
|
|
|
|
private void ExplodeBomb()
|
|
{
|
|
if (!_bombMode)
|
|
return;
|
|
|
|
_bombMode = false;
|
|
_objBomb.Explode();
|
|
Map.Objects.DeleteObjects.Add(this);
|
|
}
|
|
|
|
private void InitDespawn()
|
|
{
|
|
_body.Gravity = -0.1f;
|
|
_body.IgnoresZ = false;
|
|
|
|
if (!_isFalling)
|
|
_body.Velocity = new Vector3(-_body.VelocityTarget.X * 0.35f, -_body.VelocityTarget.Y * 0.35f, 1f);
|
|
else
|
|
_body.Velocity = new Vector3(_body.VelocityTarget.X * 0.35f, _body.VelocityTarget.Y * 0.35f, 1f);
|
|
|
|
_body.VelocityTarget = Vector2.Zero;
|
|
|
|
_animator.Play(_dir == 2 ? "rotatel" : "rotate");
|
|
_animator.SetFrame((_dir + 1) % 4);
|
|
|
|
Game1.GameManager.PlaySoundEffect("D360-07-07");
|
|
}
|
|
|
|
private void TickDespawn(double time)
|
|
{
|
|
if (_animator.CurrentFrameIndex == (_dir + 2) % 4)
|
|
_animator.Pause();
|
|
|
|
_despawnPercentage = (float)(time / FadeOutTime);
|
|
if (_despawnPercentage > 1)
|
|
_despawnPercentage = 1;
|
|
|
|
_sprite.Color = Color.White * _despawnPercentage;
|
|
_shadowBody.Transparency = _despawnPercentage;
|
|
|
|
if (time <= 0)
|
|
Map.Objects.DeleteObjects.Add(this);
|
|
}
|
|
|
|
private void OnCollision(Values.BodyCollision collision)
|
|
{
|
|
if (_aiComponent.CurrentStateId == "despawn")
|
|
return;
|
|
|
|
_aiComponent.ChangeState("despawn");
|
|
|
|
// make sure the deal damage one last time
|
|
DealDamage();
|
|
|
|
ExplodeBomb();
|
|
}
|
|
|
|
private void DealDamage()
|
|
{
|
|
var collision = Map.Objects.Hit(this, EntityPosition.Position, _damageBox.Box, HitType.Bow, 2, false, false);
|
|
if ((collision & (Values.HitCollision.Blocking | Values.HitCollision.Enemy)) != 0)
|
|
{
|
|
Map.Objects.DeleteObjects.Add(this);
|
|
|
|
ExplodeBomb();
|
|
}
|
|
|
|
if ((collision & Values.HitCollision.Repelling) != 0)
|
|
{
|
|
_aiComponent.ChangeState("despawn");
|
|
|
|
ExplodeBomb();
|
|
}
|
|
}
|
|
|
|
private void Draw(SpriteBatch spriteBatch)
|
|
{
|
|
_drawComponent.Draw(spriteBatch);
|
|
|
|
// make sure to draw the bomb ontop of the arrow
|
|
if (_objBomb != null)
|
|
_objBomb.Draw(spriteBatch);
|
|
}
|
|
|
|
public void InitBombMode(ObjBomb bomb)
|
|
{
|
|
_bombMode = true;
|
|
_objBomb = bomb;
|
|
_body.CollisionTypesIgnore = Values.CollisionTypes.None;
|
|
|
|
EntityPosition.AddPositionListener(typeof(ObjBomb), (position) => bomb.EntityPosition.Set(position.Position + _bombOffset[_dir]));
|
|
}
|
|
}
|
|
} |