Skip to content

Commit

Permalink
- Added Dig Labour enemy.
Browse files Browse the repository at this point in the history
  • Loading branch information
sharivan committed Mar 27, 2023
1 parent 48ea076 commit 2a23d8f
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 4 deletions.
Binary file modified XSharp/Assets/Sprites/Enemies/X1/Dig Labour.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
237 changes: 235 additions & 2 deletions XSharp/Engine/Entities/Enemies/DigLabour/DigLabour.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,238 @@
namespace XSharp.Engine.Entities.Enemies.DigLabour;
using SharpDX;

public class DigLabour : Enemy
using XSharp.Engine.Graphics;
using XSharp.Math;
using XSharp.Math.Geometry;

using static XSharp.Engine.Consts;

namespace XSharp.Engine.Entities.Enemies.DigLabour;

public enum DigLabourState
{
IDLE,
ATTACKING,
LAUGHING
}

public class DigLabour : Enemy, IStateEntity<DigLabourState>
{
#region StaticFields
public static readonly Color[] PALETTE = new Color[]
{
Color.Transparent, // 0
Color.FromBgra(0xFF406830), // 1
Color.FromBgra(0xFF70B888), // 2
Color.FromBgra(0xFFD0E0B0), // 3
Color.FromBgra(0xFFB85820), // 4
Color.FromBgra(0xFFE8A040), // 5
Color.FromBgra(0xFFF8D888), // 6
Color.FromBgra(0xFF405880), // 7
Color.FromBgra(0xFF6098C8), // 8
Color.FromBgra(0xFFA0D8F8), // 9
Color.FromBgra(0xFF705870), // A
Color.FromBgra(0xFFA090A0), // B
Color.FromBgra(0xFFE0D0E0), // C
Color.FromBgra(0xFF783830), // D
Color.FromBgra(0xFFF87858), // E
Color.FromBgra(0xFF302020) // F
};

public const int HEALTH = 8;
public static readonly FixedSingle CONTACT_DAMAGE = 2;
public static readonly Box HITBOX = ((0, 1), (-11, -17), (11, 17));
public static readonly Box COLLISION_BOX = ((0, 0), (-11, -17), (11, 17));

public const int IDLE_AFTER_ATTACKING_FRAMES = 90;
public const int IDLE_AFTER_LAUGHING_FRAMES = 50;
public const int ATTACKING_FRAMES = 38;
public const int LAUGHING_FRAMES = 80;
public const int FRAME_TO_THROW_PICKAXE = 18;

public static readonly FixedSingle PICKAXE_INITIAL_SPEED = 1536 / 256.0;
public static readonly Box PICKAXE_HITBOX = ((0, 0), (-11, -12), (11, 12));
public const int PICKAXE_DAMAGE = 2;
public static readonly FixedSingle PICKAXE_SPAWN_OFFSET_X = 20;
public static readonly FixedSingle PICKAXE_SPAWN_OFFSET_Y = -12;
#endregion

#region Precache
[Precache]
new internal static void Precache()
{
var palette = Engine.PrecachePalette("DigLabourPalette", PALETTE);
var spriteSheet = Engine.CreateSpriteSheet("DigLabour", true, true);

spriteSheet.CurrentTexture = Engine.CreateImageTextureFromEmbeddedResource("Sprites.Enemies.X1.Dig Labour.png");
spriteSheet.CurrentPalette = palette;

var sequence = spriteSheet.AddFrameSquence("Idle");
sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins;
sequence.Hitbox = HITBOX;
sequence.AddFrame(4, 2, 4, 13, 32, 37, 1, true);

sequence = spriteSheet.AddFrameSquence("Attacking");
sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins;
sequence.Hitbox = HITBOX;
sequence.AddFrame(4, 2, 4, 13, 32, 37, 4);
sequence.AddFrame(3, 2, 150, 14, 32, 37, 5);
sequence.AddFrame(2, 2, 199, 13, 34, 37, 4);
sequence.AddFrame(6, 3, 247, 13, 38, 38, 4);
sequence.AddFrame(9, 4, 296, 12, 40, 39, 4);
sequence.AddFrame(13, 2, 345, 13, 41, 37, 17); // pickaxe spawn here, total of 38 frames

sequence = spriteSheet.AddFrameSquence("Laughing");
sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins;
sequence.Hitbox = HITBOX;
sequence.AddFrame(4, 2, 4, 13, 32, 37, 4, true);
sequence.AddFrame(4, 2, 54, 13, 32, 37, 4);
sequence.AddFrame(5, 3, 104, 13, 32, 38, 4);
sequence.AddFrame(4, 2, 54, 13, 32, 37, 4); // this cycle is repeated 5 times, totalizing 80 frames

sequence = spriteSheet.AddFrameSquence("Pickaxe");
sequence.OriginOffset = -PICKAXE_HITBOX.Origin - PICKAXE_HITBOX.Mins;
sequence.Hitbox = PICKAXE_HITBOX;
sequence.AddFrame(1, 0, 403, 34, 24, 24, 3, true);
sequence.AddFrame(2, -2, 456, 9, 21, 20, 3);
sequence.AddFrame(1, -2, 481, 7, 24, 24, 3);
sequence.AddFrame(1, -4, 431, 9, 21, 20, 3);
sequence.AddFrame(1, -1, 403, 7, 24, 24, 3);
sequence.AddFrame(-1, -4, 431, 36, 21, 20, 3);
sequence.AddFrame(1, -2, 481, 34, 24, 24, 3);
sequence.AddFrame(-3, -2, 456, 36, 21, 20, 3);

spriteSheet.ReleaseCurrentTexture();
}
#endregion

private int idleFrames;

public DigLabourState State
{
get => GetState<DigLabourState>();
set => SetState(value);
}

public DigLabour()
{
}

protected override void OnCreate()
{
base.OnCreate();

DefaultDirection = Direction.LEFT;
SpawnFacedToPlayer = true;
AlwaysFaceToPlayer = true;

PaletteName = "DigLabourPalette";
SpriteSheetName = "DigLabour";

SetAnimationNames("Idle", "Attacking", "Laughing");

SetupStateArray<DigLabourState>();
RegisterState(DigLabourState.IDLE, OnIdle, "Idle");
RegisterState(DigLabourState.ATTACKING, OnAttacking, "Attacking");
RegisterState(DigLabourState.LAUGHING, OnLaughing, "Laughing");
}

private void OnIdle(EntityState state, long frameCounter)
{
if (frameCounter >= idleFrames)
State = DigLabourState.ATTACKING;
}

private void OnAttacking(EntityState state, long frameCounter)
{
if (frameCounter == FRAME_TO_THROW_PICKAXE)
{
ThrowPickaxe();
}
else if (frameCounter >= ATTACKING_FRAMES)
{
idleFrames = IDLE_AFTER_ATTACKING_FRAMES;
State = DigLabourState.IDLE;
}
}

private void OnLaughing(EntityState state, long frameCounter)
{
if (frameCounter >= LAUGHING_FRAMES)
{
idleFrames = IDLE_AFTER_LAUGHING_FRAMES;
State = DigLabourState.IDLE;
}
}

private EntityReference<DigLabourPickaxe> ThrowPickaxe()
{
var player = Engine.Player;
if (player == null)
return null;

var throwOrigin = Origin + (PICKAXE_SPAWN_OFFSET_X * Direction.GetHorizontalSignal(), PICKAXE_SPAWN_OFFSET_Y);

double v = PICKAXE_INITIAL_SPEED;
double v2 = v * v;
double g = GRAVITY;
double dx = player.Origin.X - throwOrigin.X;
int dxs = System.Math.Sign(dx);
double dy = player.Origin.Y - throwOrigin.Y;
double alpha = v / (g * dx);
double alpha2 = alpha * alpha;
double delta = v2 + 2 * g * dy - 1 / alpha2;

if (delta < 0)
delta = 0;

double tanTheta = alpha * (-v - System.Math.Sqrt(delta));
double theta = System.Math.Atan(tanTheta);

FixedSingle vx = dxs * v * System.Math.Cos(theta);
FixedSingle vy = dxs * v * System.Math.Sin(theta);

DigLabourPickaxe pickaxe = Engine.Entities.Create<DigLabourPickaxe>(new
{
Origin = throwOrigin,
Velocity = (vx.TruncFracPart(), vy.TruncFracPart()),
Direction
});

pickaxe.pitcher = this;
pickaxe.Spawn();
return pickaxe;
}

protected override Box GetHitbox()
{
return HITBOX;
}

protected override Box GetCollisionBox()
{
return COLLISION_BOX;
}

protected override void OnSpawn()
{
base.OnSpawn();

Health = HEALTH;
ContactDamage = CONTACT_DAMAGE;

NothingDropOdd = 9000; // 90%
SmallHealthDropOdd = 300; // 3%
BigHealthDropOdd = 100; // 1%
SmallAmmoDropOdd = 400; // 4%
BigAmmoDropOdd = 175; // 1.75%
LifeUpDropOdd = 25; // 0.25%

idleFrames = IDLE_AFTER_ATTACKING_FRAMES;
State = DigLabourState.IDLE;
}

internal void NotifyPlayerDamagedByPickaxe()
{
State = DigLabourState.LAUGHING;
}
}
62 changes: 62 additions & 0 deletions XSharp/Engine/Entities/Enemies/DigLabour/DigLabourPickaxe.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using SharpDX;

using XSharp.Engine.Graphics;
using XSharp.Math;
using XSharp.Math.Geometry;

namespace XSharp.Engine.Entities.Enemies.DigLabour;

public class DigLabourPickaxe : Enemy
{
#region Precache
[Precache]
new internal static void Precache()
{
Engine.CallPrecacheAction<DigLabour>();
}
#endregion

internal EntityReference<DigLabour> pitcher;

public DigLabour Pitcher => pitcher;

public DigLabourPickaxe()
{
}

protected override void OnCreate()
{
base.OnCreate();

DefaultDirection = Direction.LEFT;
SpawnFacedToPlayer = false;

PaletteName = "DigLabourPalette";
SpriteSheetName = "DigLabour";

SetAnimationNames("Pickaxe");
InitialAnimationName = "Pickaxe";
}

protected override Box GetHitbox()
{
return DigLabour.PICKAXE_HITBOX;
}

protected override void OnSpawn()
{
base.OnSpawn();

CheckCollisionWithWorld = false;
ContactDamage = DigLabour.PICKAXE_DAMAGE;
HitResponse = HitResponse.IGNORE;
Invincible = true;
}

protected override void OnContactDamage(Player player)
{
base.OnContactDamage(player);

Pitcher?.NotifyPlayerDamagedByPickaxe();
}
}
14 changes: 14 additions & 0 deletions XSharp/Engine/Entities/Enemies/Enemy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ public bool SpawnFacedToPlayer
set;
} = true;

public bool AlwaysFaceToPlayer
{
get;
set;
} = false;

public HitResponse HitResponse
{
get;
Expand Down Expand Up @@ -264,6 +270,14 @@ protected override void OnBroke()
Engine.DropSmallAmmoRecover(Origin, ITEM_DURATION_FRAMES);
}

protected override void OnThink()
{
base.OnThink();

if (AlwaysFaceToPlayer)
FaceToPlayer();
}

protected override void OnDeath()
{
if (flashing && lastPaletteName != null)
Expand Down
1 change: 0 additions & 1 deletion XSharp/Engine/Entities/Enemies/GunVolt/GunVolt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public class GunVolt : Enemy, IStateEntity<GunVoltState>
public static readonly Box HITBOX = ((0, 1), (-16, -29), (16, 29));
public static readonly Box COLLISION_BOX = ((0, 0), (-16, -29), (16, 29));

public static readonly FixedSingle ATTACK_DISTANCE_X = 104;
public const int SHORT_IDLE_FRAMES = 40;
public const int LONG_IDLE_FRAMES = 100;
public const int PRE_SHOOTING_FRAMES = 72;
Expand Down
3 changes: 2 additions & 1 deletion XSharp/Engine/Entities/Sprite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2008,7 +2008,8 @@ public void FaceToEntity(Entity entity)

public void FaceToPlayer()
{
FaceToEntity(Engine.Player);
if (Engine.Player != null)
FaceToEntity(Engine.Player);
}

public void FaceToScreenCenter()
Expand Down
13 changes: 13 additions & 0 deletions XSharp/Engine/GameEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using XSharp.Engine.Entities.Enemies.BombBeen;
using XSharp.Engine.Entities.Enemies.Bosses;
using XSharp.Engine.Entities.Enemies.Bosses.ChillPenguin;
using XSharp.Engine.Entities.Enemies.DigLabour;
using XSharp.Engine.Entities.Enemies.Flammingle;
using XSharp.Engine.Entities.Enemies.GunVolt;
using XSharp.Engine.Entities.Enemies.RayBit;
Expand Down Expand Up @@ -3941,6 +3942,7 @@ public Sprite AddObjectEvent(ushort id, ushort subid, Vector origin)
0x2C when mmx.Type == 1 => AddProbe8201U(subid, origin),
0x2D when mmx.Type == 0 => AddBattonBoneG(subid, origin),
0x2F => AddArmorSoldier(subid, origin),
0x30 when mmx.Type == 0 => AddDigLabour(subid, origin),
0x36 when mmx.Type == 0 => AddJamminger(subid, origin),
0x3A when mmx.Type == 0 => AddTombot(subid, origin),
0x4D => AddCapsule(subid, origin),
Expand Down Expand Up @@ -4327,6 +4329,17 @@ public ArmorSoldier AddArmorSoldier(ushort subid, Vector origin)
return Entities.GetReferenceTo(entity);
}

public EntityReference<DigLabour> AddDigLabour(ushort subid, Vector origin)
{
DigLabour entity = Entities.Create<DigLabour>(new
{
Origin = origin
});

entity.Place();
return Entities.GetReferenceTo(entity);
}

public EntityReference<Jamminger> AddJamminger(ushort subid, Vector origin)
{
Jamminger entity = Entities.Create<Jamminger>(new
Expand Down

0 comments on commit 2a23d8f

Please sign in to comment.