Skip to content

Commit 2a23d8f

Browse files
committed
- Added Dig Labour enemy.
1 parent 48ea076 commit 2a23d8f

File tree

7 files changed

+326
-4
lines changed

7 files changed

+326
-4
lines changed
1.56 KB
Loading
Lines changed: 235 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,238 @@
1-
namespace XSharp.Engine.Entities.Enemies.DigLabour;
1+
using SharpDX;
22

3-
public class DigLabour : Enemy
3+
using XSharp.Engine.Graphics;
4+
using XSharp.Math;
5+
using XSharp.Math.Geometry;
6+
7+
using static XSharp.Engine.Consts;
8+
9+
namespace XSharp.Engine.Entities.Enemies.DigLabour;
10+
11+
public enum DigLabourState
412
{
13+
IDLE,
14+
ATTACKING,
15+
LAUGHING
16+
}
17+
18+
public class DigLabour : Enemy, IStateEntity<DigLabourState>
19+
{
20+
#region StaticFields
21+
public static readonly Color[] PALETTE = new Color[]
22+
{
23+
Color.Transparent, // 0
24+
Color.FromBgra(0xFF406830), // 1
25+
Color.FromBgra(0xFF70B888), // 2
26+
Color.FromBgra(0xFFD0E0B0), // 3
27+
Color.FromBgra(0xFFB85820), // 4
28+
Color.FromBgra(0xFFE8A040), // 5
29+
Color.FromBgra(0xFFF8D888), // 6
30+
Color.FromBgra(0xFF405880), // 7
31+
Color.FromBgra(0xFF6098C8), // 8
32+
Color.FromBgra(0xFFA0D8F8), // 9
33+
Color.FromBgra(0xFF705870), // A
34+
Color.FromBgra(0xFFA090A0), // B
35+
Color.FromBgra(0xFFE0D0E0), // C
36+
Color.FromBgra(0xFF783830), // D
37+
Color.FromBgra(0xFFF87858), // E
38+
Color.FromBgra(0xFF302020) // F
39+
};
40+
41+
public const int HEALTH = 8;
42+
public static readonly FixedSingle CONTACT_DAMAGE = 2;
43+
public static readonly Box HITBOX = ((0, 1), (-11, -17), (11, 17));
44+
public static readonly Box COLLISION_BOX = ((0, 0), (-11, -17), (11, 17));
45+
46+
public const int IDLE_AFTER_ATTACKING_FRAMES = 90;
47+
public const int IDLE_AFTER_LAUGHING_FRAMES = 50;
48+
public const int ATTACKING_FRAMES = 38;
49+
public const int LAUGHING_FRAMES = 80;
50+
public const int FRAME_TO_THROW_PICKAXE = 18;
51+
52+
public static readonly FixedSingle PICKAXE_INITIAL_SPEED = 1536 / 256.0;
53+
public static readonly Box PICKAXE_HITBOX = ((0, 0), (-11, -12), (11, 12));
54+
public const int PICKAXE_DAMAGE = 2;
55+
public static readonly FixedSingle PICKAXE_SPAWN_OFFSET_X = 20;
56+
public static readonly FixedSingle PICKAXE_SPAWN_OFFSET_Y = -12;
57+
#endregion
58+
59+
#region Precache
60+
[Precache]
61+
new internal static void Precache()
62+
{
63+
var palette = Engine.PrecachePalette("DigLabourPalette", PALETTE);
64+
var spriteSheet = Engine.CreateSpriteSheet("DigLabour", true, true);
65+
66+
spriteSheet.CurrentTexture = Engine.CreateImageTextureFromEmbeddedResource("Sprites.Enemies.X1.Dig Labour.png");
67+
spriteSheet.CurrentPalette = palette;
68+
69+
var sequence = spriteSheet.AddFrameSquence("Idle");
70+
sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins;
71+
sequence.Hitbox = HITBOX;
72+
sequence.AddFrame(4, 2, 4, 13, 32, 37, 1, true);
73+
74+
sequence = spriteSheet.AddFrameSquence("Attacking");
75+
sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins;
76+
sequence.Hitbox = HITBOX;
77+
sequence.AddFrame(4, 2, 4, 13, 32, 37, 4);
78+
sequence.AddFrame(3, 2, 150, 14, 32, 37, 5);
79+
sequence.AddFrame(2, 2, 199, 13, 34, 37, 4);
80+
sequence.AddFrame(6, 3, 247, 13, 38, 38, 4);
81+
sequence.AddFrame(9, 4, 296, 12, 40, 39, 4);
82+
sequence.AddFrame(13, 2, 345, 13, 41, 37, 17); // pickaxe spawn here, total of 38 frames
83+
84+
sequence = spriteSheet.AddFrameSquence("Laughing");
85+
sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins;
86+
sequence.Hitbox = HITBOX;
87+
sequence.AddFrame(4, 2, 4, 13, 32, 37, 4, true);
88+
sequence.AddFrame(4, 2, 54, 13, 32, 37, 4);
89+
sequence.AddFrame(5, 3, 104, 13, 32, 38, 4);
90+
sequence.AddFrame(4, 2, 54, 13, 32, 37, 4); // this cycle is repeated 5 times, totalizing 80 frames
91+
92+
sequence = spriteSheet.AddFrameSquence("Pickaxe");
93+
sequence.OriginOffset = -PICKAXE_HITBOX.Origin - PICKAXE_HITBOX.Mins;
94+
sequence.Hitbox = PICKAXE_HITBOX;
95+
sequence.AddFrame(1, 0, 403, 34, 24, 24, 3, true);
96+
sequence.AddFrame(2, -2, 456, 9, 21, 20, 3);
97+
sequence.AddFrame(1, -2, 481, 7, 24, 24, 3);
98+
sequence.AddFrame(1, -4, 431, 9, 21, 20, 3);
99+
sequence.AddFrame(1, -1, 403, 7, 24, 24, 3);
100+
sequence.AddFrame(-1, -4, 431, 36, 21, 20, 3);
101+
sequence.AddFrame(1, -2, 481, 34, 24, 24, 3);
102+
sequence.AddFrame(-3, -2, 456, 36, 21, 20, 3);
103+
104+
spriteSheet.ReleaseCurrentTexture();
105+
}
106+
#endregion
107+
108+
private int idleFrames;
109+
110+
public DigLabourState State
111+
{
112+
get => GetState<DigLabourState>();
113+
set => SetState(value);
114+
}
115+
116+
public DigLabour()
117+
{
118+
}
119+
120+
protected override void OnCreate()
121+
{
122+
base.OnCreate();
123+
124+
DefaultDirection = Direction.LEFT;
125+
SpawnFacedToPlayer = true;
126+
AlwaysFaceToPlayer = true;
127+
128+
PaletteName = "DigLabourPalette";
129+
SpriteSheetName = "DigLabour";
130+
131+
SetAnimationNames("Idle", "Attacking", "Laughing");
132+
133+
SetupStateArray<DigLabourState>();
134+
RegisterState(DigLabourState.IDLE, OnIdle, "Idle");
135+
RegisterState(DigLabourState.ATTACKING, OnAttacking, "Attacking");
136+
RegisterState(DigLabourState.LAUGHING, OnLaughing, "Laughing");
137+
}
138+
139+
private void OnIdle(EntityState state, long frameCounter)
140+
{
141+
if (frameCounter >= idleFrames)
142+
State = DigLabourState.ATTACKING;
143+
}
144+
145+
private void OnAttacking(EntityState state, long frameCounter)
146+
{
147+
if (frameCounter == FRAME_TO_THROW_PICKAXE)
148+
{
149+
ThrowPickaxe();
150+
}
151+
else if (frameCounter >= ATTACKING_FRAMES)
152+
{
153+
idleFrames = IDLE_AFTER_ATTACKING_FRAMES;
154+
State = DigLabourState.IDLE;
155+
}
156+
}
157+
158+
private void OnLaughing(EntityState state, long frameCounter)
159+
{
160+
if (frameCounter >= LAUGHING_FRAMES)
161+
{
162+
idleFrames = IDLE_AFTER_LAUGHING_FRAMES;
163+
State = DigLabourState.IDLE;
164+
}
165+
}
166+
167+
private EntityReference<DigLabourPickaxe> ThrowPickaxe()
168+
{
169+
var player = Engine.Player;
170+
if (player == null)
171+
return null;
172+
173+
var throwOrigin = Origin + (PICKAXE_SPAWN_OFFSET_X * Direction.GetHorizontalSignal(), PICKAXE_SPAWN_OFFSET_Y);
174+
175+
double v = PICKAXE_INITIAL_SPEED;
176+
double v2 = v * v;
177+
double g = GRAVITY;
178+
double dx = player.Origin.X - throwOrigin.X;
179+
int dxs = System.Math.Sign(dx);
180+
double dy = player.Origin.Y - throwOrigin.Y;
181+
double alpha = v / (g * dx);
182+
double alpha2 = alpha * alpha;
183+
double delta = v2 + 2 * g * dy - 1 / alpha2;
184+
185+
if (delta < 0)
186+
delta = 0;
187+
188+
double tanTheta = alpha * (-v - System.Math.Sqrt(delta));
189+
double theta = System.Math.Atan(tanTheta);
190+
191+
FixedSingle vx = dxs * v * System.Math.Cos(theta);
192+
FixedSingle vy = dxs * v * System.Math.Sin(theta);
193+
194+
DigLabourPickaxe pickaxe = Engine.Entities.Create<DigLabourPickaxe>(new
195+
{
196+
Origin = throwOrigin,
197+
Velocity = (vx.TruncFracPart(), vy.TruncFracPart()),
198+
Direction
199+
});
200+
201+
pickaxe.pitcher = this;
202+
pickaxe.Spawn();
203+
return pickaxe;
204+
}
205+
206+
protected override Box GetHitbox()
207+
{
208+
return HITBOX;
209+
}
210+
211+
protected override Box GetCollisionBox()
212+
{
213+
return COLLISION_BOX;
214+
}
215+
216+
protected override void OnSpawn()
217+
{
218+
base.OnSpawn();
219+
220+
Health = HEALTH;
221+
ContactDamage = CONTACT_DAMAGE;
222+
223+
NothingDropOdd = 9000; // 90%
224+
SmallHealthDropOdd = 300; // 3%
225+
BigHealthDropOdd = 100; // 1%
226+
SmallAmmoDropOdd = 400; // 4%
227+
BigAmmoDropOdd = 175; // 1.75%
228+
LifeUpDropOdd = 25; // 0.25%
229+
230+
idleFrames = IDLE_AFTER_ATTACKING_FRAMES;
231+
State = DigLabourState.IDLE;
232+
}
233+
234+
internal void NotifyPlayerDamagedByPickaxe()
235+
{
236+
State = DigLabourState.LAUGHING;
237+
}
5238
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using SharpDX;
2+
3+
using XSharp.Engine.Graphics;
4+
using XSharp.Math;
5+
using XSharp.Math.Geometry;
6+
7+
namespace XSharp.Engine.Entities.Enemies.DigLabour;
8+
9+
public class DigLabourPickaxe : Enemy
10+
{
11+
#region Precache
12+
[Precache]
13+
new internal static void Precache()
14+
{
15+
Engine.CallPrecacheAction<DigLabour>();
16+
}
17+
#endregion
18+
19+
internal EntityReference<DigLabour> pitcher;
20+
21+
public DigLabour Pitcher => pitcher;
22+
23+
public DigLabourPickaxe()
24+
{
25+
}
26+
27+
protected override void OnCreate()
28+
{
29+
base.OnCreate();
30+
31+
DefaultDirection = Direction.LEFT;
32+
SpawnFacedToPlayer = false;
33+
34+
PaletteName = "DigLabourPalette";
35+
SpriteSheetName = "DigLabour";
36+
37+
SetAnimationNames("Pickaxe");
38+
InitialAnimationName = "Pickaxe";
39+
}
40+
41+
protected override Box GetHitbox()
42+
{
43+
return DigLabour.PICKAXE_HITBOX;
44+
}
45+
46+
protected override void OnSpawn()
47+
{
48+
base.OnSpawn();
49+
50+
CheckCollisionWithWorld = false;
51+
ContactDamage = DigLabour.PICKAXE_DAMAGE;
52+
HitResponse = HitResponse.IGNORE;
53+
Invincible = true;
54+
}
55+
56+
protected override void OnContactDamage(Player player)
57+
{
58+
base.OnContactDamage(player);
59+
60+
Pitcher?.NotifyPlayerDamagedByPickaxe();
61+
}
62+
}

XSharp/Engine/Entities/Enemies/Enemy.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ public bool SpawnFacedToPlayer
6060
set;
6161
} = true;
6262

63+
public bool AlwaysFaceToPlayer
64+
{
65+
get;
66+
set;
67+
} = false;
68+
6369
public HitResponse HitResponse
6470
{
6571
get;
@@ -264,6 +270,14 @@ protected override void OnBroke()
264270
Engine.DropSmallAmmoRecover(Origin, ITEM_DURATION_FRAMES);
265271
}
266272

273+
protected override void OnThink()
274+
{
275+
base.OnThink();
276+
277+
if (AlwaysFaceToPlayer)
278+
FaceToPlayer();
279+
}
280+
267281
protected override void OnDeath()
268282
{
269283
if (flashing && lastPaletteName != null)

XSharp/Engine/Entities/Enemies/GunVolt/GunVolt.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public class GunVolt : Enemy, IStateEntity<GunVoltState>
4444
public static readonly Box HITBOX = ((0, 1), (-16, -29), (16, 29));
4545
public static readonly Box COLLISION_BOX = ((0, 0), (-16, -29), (16, 29));
4646

47-
public static readonly FixedSingle ATTACK_DISTANCE_X = 104;
4847
public const int SHORT_IDLE_FRAMES = 40;
4948
public const int LONG_IDLE_FRAMES = 100;
5049
public const int PRE_SHOOTING_FRAMES = 72;

XSharp/Engine/Entities/Sprite.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,7 +2008,8 @@ public void FaceToEntity(Entity entity)
20082008

20092009
public void FaceToPlayer()
20102010
{
2011-
FaceToEntity(Engine.Player);
2011+
if (Engine.Player != null)
2012+
FaceToEntity(Engine.Player);
20122013
}
20132014

20142015
public void FaceToScreenCenter()

XSharp/Engine/GameEngine.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using XSharp.Engine.Entities.Enemies.BombBeen;
2525
using XSharp.Engine.Entities.Enemies.Bosses;
2626
using XSharp.Engine.Entities.Enemies.Bosses.ChillPenguin;
27+
using XSharp.Engine.Entities.Enemies.DigLabour;
2728
using XSharp.Engine.Entities.Enemies.Flammingle;
2829
using XSharp.Engine.Entities.Enemies.GunVolt;
2930
using XSharp.Engine.Entities.Enemies.RayBit;
@@ -3941,6 +3942,7 @@ public Sprite AddObjectEvent(ushort id, ushort subid, Vector origin)
39413942
0x2C when mmx.Type == 1 => AddProbe8201U(subid, origin),
39423943
0x2D when mmx.Type == 0 => AddBattonBoneG(subid, origin),
39433944
0x2F => AddArmorSoldier(subid, origin),
3945+
0x30 when mmx.Type == 0 => AddDigLabour(subid, origin),
39443946
0x36 when mmx.Type == 0 => AddJamminger(subid, origin),
39453947
0x3A when mmx.Type == 0 => AddTombot(subid, origin),
39463948
0x4D => AddCapsule(subid, origin),
@@ -4327,6 +4329,17 @@ public ArmorSoldier AddArmorSoldier(ushort subid, Vector origin)
43274329
return Entities.GetReferenceTo(entity);
43284330
}
43294331

4332+
public EntityReference<DigLabour> AddDigLabour(ushort subid, Vector origin)
4333+
{
4334+
DigLabour entity = Entities.Create<DigLabour>(new
4335+
{
4336+
Origin = origin
4337+
});
4338+
4339+
entity.Place();
4340+
return Entities.GetReferenceTo(entity);
4341+
}
4342+
43304343
public EntityReference<Jamminger> AddJamminger(ushort subid, Vector origin)
43314344
{
43324345
Jamminger entity = Entities.Create<Jamminger>(new

0 commit comments

Comments
 (0)