Skip to content

Weapon Rendering

chaubenn edited this page Sep 3, 2026 · 2 revisions

Description

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.

Implementation

RotatingTextureRenderComponent

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.

Spawning a sprite with a hitbox

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

How each weapon uses it

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.

Assets

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.

Unit Tests

  • 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.

How to Test

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.

Table of Contents

Home

Test Plan

Team 2

Features

Components
Player
Items and Inventory
Enemies
Interactable NPCs
Cutscenes and Dialogue
Music
Bosses
Rooms
Weapons
Abilities & Spells
Game Screens and Areas
Dungeons

Game Engine

Getting Started

Entities and Components

Service Locator

Loading Resources

Logging

Unit Testing

Debug Terminal

Input Handling

UI

Animations

Audio

AI

Physics

Terrain

Concurrency & Threading

Settings

Troubleshooting

MacOS Setup Guide

Clone this wiki locally