mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-01 04:14:22 +00:00
178 lines
6.8 KiB
C#
178 lines
6.8 KiB
C#
using System;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
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.Things;
|
|
using ProjectZ.InGame.Map;
|
|
using ProjectZ.InGame.SaveLoad;
|
|
|
|
namespace ProjectZ.InGame.GameObjects.Enemies
|
|
{
|
|
internal class EnemyPokey : GameObject
|
|
{
|
|
private readonly BodyComponent _body;
|
|
private readonly AiComponent _aiComponent;
|
|
private readonly AiDamageState _aiDamageState;
|
|
private readonly CSprite _sprite;
|
|
|
|
private readonly DictAtlasEntry _spriteHead;
|
|
private readonly DictAtlasEntry _spriteBody;
|
|
|
|
private float _moveSpeed = 1 / 3f;
|
|
private int _direction;
|
|
private int _state;
|
|
|
|
public EnemyPokey() : base("pokey") { }
|
|
|
|
public EnemyPokey(Map.Map map, int posX, int posY) : base(map)
|
|
{
|
|
Tags = Values.GameObjectTag.Enemy;
|
|
|
|
EntityPosition = new CPosition(posX + 8, posY + 16, 0);
|
|
EntitySize = new Rectangle(-10, -48, 20, 48);
|
|
|
|
_spriteHead = Resources.GetSprite("pokey");
|
|
_spriteBody = Resources.GetSprite("pokey body");
|
|
|
|
_sprite = new CSprite("pokey body", EntityPosition);
|
|
_body = new BodyComponent(EntityPosition, -7, -14, 14, 14, 8)
|
|
{
|
|
CollisionTypes = Values.CollisionTypes.Normal |
|
|
Values.CollisionTypes.Enemy,
|
|
AvoidTypes = Values.CollisionTypes.Hole | Values.CollisionTypes.NPCWall,
|
|
FieldRectangle = map.GetField(posX, posY),
|
|
Gravity = -0.15f,
|
|
Bounciness = 0.35f,
|
|
Drag = 0.8f,
|
|
DragAir = 0.8f,
|
|
MaxJumpHeight = 4f,
|
|
IgnoreHeight = true
|
|
};
|
|
|
|
var stateMoving = new AiState { Init = InitWalking };
|
|
stateMoving.Trigger.Add(new AiTriggerRandomTime(ChangeDirection, 550, 850));
|
|
|
|
_aiComponent = new AiComponent();
|
|
_aiComponent.States.Add("moving", stateMoving);
|
|
new AiFallState(_aiComponent, _body, null);
|
|
_aiDamageState = new AiDamageState(this, _body, _aiComponent, _sprite, 4);
|
|
|
|
_aiComponent.ChangeState("moving");
|
|
|
|
var damageBox = new CBox(EntityPosition, -7, -14, 0, 14, 14, 16);
|
|
var hittableBox = new CBox(EntityPosition, -7, -14, 14, 14, 24);
|
|
|
|
AddComponent(DamageFieldComponent.Index, new DamageFieldComponent(damageBox, HitType.Enemy, 2));
|
|
AddComponent(HittableComponent.Index, new HittableComponent(hittableBox, OnHit));
|
|
AddComponent(BodyComponent.Index, _body);
|
|
AddComponent(AiComponent.Index, _aiComponent);
|
|
AddComponent(PushableComponent.Index, new PushableComponent(_body.BodyBox, OnPush));
|
|
AddComponent(DrawComponent.Index, new DrawComponent(Draw, Values.LayerPlayer, EntityPosition));
|
|
AddComponent(DrawShadowComponent.Index, new BodyDrawShadowComponent(_body, _sprite) { ShadowWidth = 10, ShadowHeight = 5 });
|
|
}
|
|
|
|
private void InitWalking()
|
|
{
|
|
ChangeDirection();
|
|
}
|
|
|
|
private void ChangeDirection()
|
|
{
|
|
// random new direction
|
|
_direction = Game1.RandomNumber.Next(0, 4);
|
|
_body.VelocityTarget = AnimationHelper.DirectionOffset[_direction] * _moveSpeed;
|
|
}
|
|
|
|
private Values.HitCollision OnHit(GameObject gameObject, Vector2 direction, HitType damageType, int damage, bool pieceOfPower)
|
|
{
|
|
if (_aiDamageState.IsInDamageState())
|
|
return Values.HitCollision.None;
|
|
|
|
if (damageType == HitType.Bomb || damageType == HitType.Bow)
|
|
damage /= 2;
|
|
|
|
if ((damageType & HitType.Sword2) != 0 ||
|
|
damageType == HitType.Hookshot ||
|
|
damageType == HitType.MagicPowder ||
|
|
damageType == HitType.MagicRod ||
|
|
pieceOfPower)
|
|
damage *= 2;
|
|
|
|
var hitType = _aiDamageState.OnHit(gameObject, direction, damageType, damage, pieceOfPower);
|
|
|
|
if (_aiDamageState.CurrentLives > 0)
|
|
{
|
|
_state += 1;
|
|
if (_state <= 2)
|
|
{
|
|
EntityPosition.Z = 14;
|
|
_body.Velocity.Z = -0.5f;
|
|
|
|
var bodyPart = new EnemyPokeyPart(Map, EntityPosition.X, EntityPosition.Y, direction * 2f, _body.Velocity);
|
|
Map.Objects.SpawnObject(bodyPart);
|
|
}
|
|
}
|
|
|
|
if (_state == 2)
|
|
_sprite.SetSprite(_spriteHead);
|
|
|
|
return hitType;
|
|
}
|
|
|
|
private bool OnPush(Vector2 direction, PushableComponent.PushType type)
|
|
{
|
|
if (type == PushableComponent.PushType.Impact)
|
|
_body.Velocity = new Vector3(direction.X, direction.Y, _body.Velocity.Z);
|
|
|
|
return true;
|
|
}
|
|
|
|
private void Draw(SpriteBatch spriteBatch)
|
|
{
|
|
// change the draw effect
|
|
if (_sprite.SpriteShader != null)
|
|
{
|
|
spriteBatch.End();
|
|
ObjectManager.SpriteBatchBegin(spriteBatch, _sprite.SpriteShader);
|
|
}
|
|
|
|
// draw the body
|
|
var posY = EntityPosition.Y - EntityPosition.Z;
|
|
if (_state == 0)
|
|
{
|
|
DrawHelper.DrawNormalized(spriteBatch, _spriteBody, new Vector2(EntityPosition.X, posY), _sprite.Color);
|
|
posY -= 12;
|
|
}
|
|
|
|
var offsetX = 0.0f;
|
|
if (_state <= 1)
|
|
{
|
|
// dont wobble at the floor
|
|
if (_state == 0)
|
|
offsetX = (float)Math.Sin(Game1.TotalGameTime * 0.0125);
|
|
|
|
DrawHelper.DrawNormalized(spriteBatch, _spriteBody, new Vector2(EntityPosition.X + offsetX, posY), _sprite.Color);
|
|
posY -= 12;
|
|
}
|
|
|
|
// draw the head
|
|
offsetX = -(float)Math.Sin(Game1.TotalGameTime * 0.0125) * (_state == 0 ? 2 : 1);
|
|
DrawHelper.DrawNormalized(spriteBatch, _spriteHead, new Vector2(EntityPosition.X + offsetX, posY), _sprite.Color);
|
|
|
|
// make sure to also move the shadow
|
|
if (_state >= 2)
|
|
_sprite.DrawOffset.X = offsetX;
|
|
|
|
// change the draw effect
|
|
// this would not be very efficient if a lot of sprite used effects
|
|
if (_sprite.SpriteShader != null)
|
|
{
|
|
spriteBatch.End();
|
|
ObjectManager.SpriteBatchBegin(spriteBatch, null);
|
|
}
|
|
}
|
|
}
|
|
} |