Added more sound effects. Added initial weapon muzzle fire logic.

This commit is contained in:
2026-01-02 00:54:09 -05:00
parent c4a98ce03d
commit df45203227
43 changed files with 459 additions and 30 deletions

View File

@@ -0,0 +1,12 @@
namespace AlienAttack.MonoGame.Things.Weapons;
public enum Anchor
{
TopLeft,
TopCenter,
TopRight,
Center,
BottomLeft,
BottomCenter,
BottomRight
}

View File

@@ -0,0 +1,43 @@
using AlienAttack.MonoGame.Things.Bullets;
using AlienAttack.MonoGame.Things.Muzzles;
using Microsoft.Xna.Framework;
using System;
namespace AlienAttack.MonoGame.Things.Weapons;
internal record FireBulletContext
{
public Sprite Owner { get; init; }
public SpriteUpdateContext SpriteUpdateContext { get; init; }
public int BulletWidth { get; init; }
public int BulletHeight { get; init; }
public Anchor Anchor { get; init; }
public Shot[] Shots { get; init; }
public Func<float, float, float, float, Sprite, Bullet> Factory { get; init; }
}
public record Shot
{
public float OffsetX { get; init; }
public float OffsetY { get; init; }
public float XVelocity { get; init; }
public float YVelocity { get; init; }
}
internal record FireBulletFromMuzzleContext
{
public Sprite Owner { get; init; }
public SpriteUpdateContext SpriteUpdateContext { get; init; }
public int BulletWidth { get; init; }
public int BulletHeight { get; init; }
public MuzzleShot[] Shots { get; init; }
public Vector2 ExtraOffset { get; init; } = default;
public Func<float, float, float, float, Sprite, Bullet> Factory { get; init; }
}
public record MuzzleShot
{
public MuzzleId Muzzle { get; init; }
public float XVelocity { get; init; }
public float YVelocity { get; init; }
}

View File

@@ -1,9 +1,9 @@
using AlienAttack.MonoGame.Things.Bullets;
using Microsoft.Xna.Framework.Audio;
using AlienAttack.MonoGame.Things.Muzzles;
namespace AlienAttack.MonoGame.Things.Weapons;
public class Minigun : Weapon
internal class Minigun : Weapon
{
public override int FireThreshold => 15;
@@ -31,7 +31,49 @@ public class Minigun : Weapon
}
}
public class FastMinigun : Weapon
internal class MinigunSpread : Weapon
{
public override int FireThreshold => 20;
public override void Fire(Sprite owner, SpriteUpdateContext context)
{
// Calculate bullet spawn positions relative to the player's bounding box
int x1 = (int)owner.XPosition + 14;
int x2 = (int)owner.XPosition + owner.BoundBox.Width - 16;
int x3 = (int)owner.XPosition + owner.BoundBox.Width / 2 - 1;
int y = (int)owner.YPosition + 10;
MinigunBulletLarge bullet1 = new(x1, y, -1, -6, owner);
MinigunBulletLarge bullet2 = new(x2, y, 1, -6, owner);
MinigunBulletLarge bullet3 = new(x3, y-16, 0, -6, owner);
//context.SpawnSprite(bullet1);
//context.SpawnSprite(bullet2);
//context.SpawnSprite(bullet3);
FireBulletFromMuzzleContext fireBulletContext = new()
{
Owner = owner,
SpriteUpdateContext = context,
BulletWidth = MinigunBulletLarge.Width,
BulletHeight = MinigunBulletLarge.Height,
Factory = (x, y, vx, vy2, o) => new MinigunBulletLarge(x, y, vx, vy2, o),
ExtraOffset = new(4f, 0),
Shots =
[
new() { Muzzle = MuzzleId.Left, XVelocity = -1, YVelocity = -6 },
new() { Muzzle = MuzzleId.Right, XVelocity = 1, YVelocity = -6 },
new() { Muzzle = MuzzleId.Center, XVelocity = 0, YVelocity = -6 }
]
};
FireFromMuzzle(fireBulletContext);
context.AudioManager.PlayPlayerFire();
}
}
internal class FastMinigun : Weapon
{
public override int FireThreshold => 10;

View File

@@ -1,6 +1,12 @@
namespace AlienAttack.MonoGame.Things.Weapons;
using AlienAttack.MonoGame.Things.Bullets;
using AlienAttack.MonoGame.Things.Muzzles;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
public abstract class Weapon : IWeapon
namespace AlienAttack.MonoGame.Things.Weapons;
internal abstract class Weapon : IWeapon
{
public abstract int FireThreshold { get; }
public int CurrentFireThreshold { get; private set; }
@@ -23,4 +29,59 @@ public abstract class Weapon : IWeapon
}
public abstract void Fire(Sprite owner, SpriteUpdateContext context);
protected static void FireBullet(FireBulletContext context)
{
var (x, y) = ComputeAnchorPosition(context);
foreach (Shot shot in context.Shots)
{
Bullet bullet = context.Factory(x + shot.OffsetX, y + shot.OffsetY, shot.XVelocity, shot.YVelocity, context.Owner);
context.SpriteUpdateContext.SpawnSprite(bullet);
}
}
private static (float x, float y) ComputeAnchorPosition(FireBulletContext context)
{
Sprite owner = context.Owner;
int bw = context.BulletWidth;
int bh = context.BulletHeight;
Anchor anchor = context.Anchor;
float left = owner.XPosition;
float top = owner.YPosition;
float right = owner.XPosition + owner.BoundBox.Width;
float bottom = owner.YPosition + owner.BoundBox.Height;
return anchor switch
{
Anchor.TopLeft => (left, top - bh),
Anchor.TopCenter => (left + (owner.BoundBox.Width - bw) / 2f, top - bh),
Anchor.TopRight => (right - bw, top - bh),
Anchor.Center => (left + (owner.BoundBox.Width - bw) / 2f, top + (owner.BoundBox.Height - bh) / 2f),
Anchor.BottomLeft => (left, bottom),
Anchor.BottomCenter => (left + (owner.BoundBox.Width - bw) / 2f, bottom),
Anchor.BottomRight => (right - bw, bottom),
_ => (left, top)
};
}
protected static void FireFromMuzzle(FireBulletFromMuzzleContext context)
{
if (context.Owner is not Player player)
return;
foreach (MuzzleShot shot in context.Shots)
{
var m = player.Muzzles.First(x => x.Id == shot.Muzzle).LocalPx;
Vector2 worldMuzzle = MuzzleMath.GetMuzzleWorld(player, m);
Vector2 bulletPos = MuzzleMath.CenterBulletOn(worldMuzzle, context.BulletWidth, context.BulletHeight) + context.ExtraOffset;
Bullet bullet = context.Factory(bulletPos.X, bulletPos.Y, shot.XVelocity, shot.YVelocity, context.Owner);
context.SpriteUpdateContext.SpawnSprite(bullet);
}
}
}