Repository navigation
Weapon Rendering
Weapon attacks now draw sprites: a knife thrusts, a sword blade turns through its swing, and the bow's projectile points along its flight. Before this, attacks were invisible outside of debug hitbox outlines.
The core problem is that a weapon's hitbox and its sprite want different things. The hitbox is sized and placed for collision — long, thin, hugging the wielder. The sprite is sized and placed for looking right — square artwork, handle in the player's hand, blade pointing where the swing points. Rendering the texture stretched across the hitbox would squash a square sprite into an oblong and leave it axis-aligned mid-swing.
The engine's existing TextureRenderComponent can't express this: it draws axis-aligned from the entity's bottom-left corner at the entity's own scale, which suits terrain and fixtures but not a rotating blade.
A new render component (com.csse3200.game.rendering) that draws a texture independently of its entity's collision shape:
- Centred on the entity's centre, so the sprite pivots about its middle instead of orbiting a corner.
- Visual scale — an optional draw size in metres, separate from the entity's scale. The hitbox stays sized for collision; the sprite keeps its aspect ratio. Falls back to the entity scale when unset.
- Rotation — the sprite's facing in degrees, safe to update every frame (the sword sweep and the arrow both do).
-
Rotation offset — a constant correction for how the artwork was drawn. The sprite pack draws every weapon as an inventory icon pointing up-and-left (135°), so each weapon applies a fixed
-135°offset. Correcting at draw time keeps the pixel art crisp — rotating the PNG itself off-axis would resample and soften it. - Visual offset — shifts the sprite along its facing direction without moving the hitbox. This anchors a held weapon: a swept blade wants its handle near the wielder, not its midpoint riding the arc.
Rotation happens on the GPU at draw time, so there is no per-frame image processing.
HitboxSpec gained matching fluent fields — texture, visualScale, visualOffset, rotation, rotationOffset — and HitboxFactory attaches a configured RotatingTextureRenderComponent whenever a texture is set. Weapons that want no sprite simply omit the texture; nothing else changes.
new HitboxSpec()
// ... collision fields as before ...
.texture("images/weapons/sword.png")
.visualScale(new Vector2(1.0f, 1.0f)) // square art, not the thin hitbox
.visualOffset(new Vector2(-0.45f, 0f)) // pull the handle back to the wielder
.rotation(startAngle) // point along the start of the swing
.rotationOffset(-135f); // correct the sprite pack's icon angle| Weapon | Sprite | Rotation behaviour |
|---|---|---|
| Knife | knife.png |
Fixed for the stab, pointing along the (cardinal) attack direction, pulled in so it reads as a thrust. |
| Sword | sword.png |
SweepComponent updates the rotation every frame so the blade turns with the arc, handle anchored at the wielder. |
| Bow | throwing_knife.png |
Set once to the flight direction; drawn larger than the small hitbox so it reads at speed without widening what it hits. |
Weapon sprites live in source/core/assets/images/weapons/ and are cut from a CC-licensed OpenGameArt pack; attribution is recorded in source/core/assets/licenses/OPENGAMEART-ATTRIBUTION.md. Textures are loaded through the room assets pipeline like every other game texture.
-
RotatingTextureRenderComponentTest— centring, visual scale override and fallback, rotation offset applied at draw time only, facing-relative sprite offset that never moves the entity, defensive copying. -
KnifeWeaponComponentTest.shouldAttachSpriteFacingTheAttackDirection— the knife sprite points along the stab. -
SwordWeaponComponentTest.shouldAimTheSpriteAlongTheStartOfTheArc/shouldTurnTheBladeAsTheSweepProgresses— the sword sprite tracks the swing.
See the Weapons Test Plan for the full table.
Run the game, open the debug terminal (F1), type weapon knife (or sword / bow) and press Enter, then debug on to show hitbox outlines, and close the terminal (F1). Attack with J while facing different directions with WASD. Each attack should draw its weapon sprite alongside the hitbox outline: the knife pointing along the stab, the sword turning through its 90° arc with the handle at the player, and the bow's projectile pointing along its flight. The sprite and the outline will visibly differ in shape — that is the point: collision size and draw size are independent.