Spin the Wheel - UQcsse3200/2026-studio-2 GitHub Wiki

Introduction

Spin the Wheel is a minigame where the player spins a wheel and is awarded whatever item the pointer lands on.

Key Components

  • Wheel Item - A single segment on the wheel, holding the item awarded and the amount: WheelItem.
  • Wheel Config - The wheel's contents and the assets they need: WheelConfig.
  • Wheel Logic - Picks the winner and calculates the wheel's angles, with no rendering: WheelLogic.
  • Wheel Display - Builds the wheel, animates the spin and shows the prize: SpinTheWheelDisplay, extends UIComponent.
  • Wheel Actions - Returns the player to the minigame select menu: SpinTheWheelActions.
  • Wheel Screen - Loads the wheel's textures and builds its UI entity: SpinTheWheelScreen, extends MinigameScreen.
  • Wheel Overlay - Shows the wheel over the paused game instead of on its own screen: SpinTheWheelOverlay.
  • Overlay Actions - Closes the overlay rather than changing screen: SpinTheWheelOverlayActions.
  • Blurred Backdrop - Draws the blurred snapshot behind the overlay: BlurredBackdropDisplay.
  • Screen Blur - Captures and blurs the frame the overlay opened on: ScreenBlur.
  • Wheel Token - A pickup in Level 1 that opens the wheel when collected: WheelTokenPickupComponent.
  • Spin the Wheel Command - A debug terminal command that opens the wheel on any screen: SpinTheWheelCommand.

Implementation

Wheel items

Each segment is a record holding the item awarded and the amount. The item is an ItemType, which supplies both the name shown when it wins and the sprite drawn on the segment:

public record WheelItem(ItemType type, int value) {}

Wheel layout

The wheel is drawn inside two nested groups. The inner group holds the disc, spokes and labels and is the thing that rotates. The pointer sits in the outer container so it stays fixed while the wheel turns beneath it.

container (fixed)
├── wheelGroup (rotates)
│   ├── disc
│   ├── spoke × n        at seg * i
│   └── label × n        at (seg * i) + seg / 2
└── pointer              at 90 degrees (top)

seg = 360 / n degrees

Landing on the winner

spin() picks the winning index first, then the display asks getTargetRotation() where to animate to. The wheel always rotates forwards through at least FULL_TURNS whole turns before settling:

float landing = pointerAngle - getWinningAngle();
float delta = wrap360(landing - currentRotation);
return currentRotation + delta + (fullTurns * 360f);

UML Diagram

classDiagram
    class WheelLogic {
        -List~WheelItem~ items
        -Random random
        -int winningIndex
        +spin() WheelItem
        +getItems() List~WheelItem~
        +getWinningAngle() float
        +getTargetRotation(float, float, int) float
    }

    class WheelItem {
        +type() ItemType
        +value() int
    }

    class WheelConfig {
        +ITEMS List~WheelItem~
        +TEXTURES String[]
    }

    class SpinTheWheelDisplay {
        -WheelLogic wheel
        -Group wheelGroup
        -Group prizeCard
        +texturesFor(List~WheelItem~) String[]
        +toFront()
    }

    class SpinTheWheelActions {
        -GdxGame game
    }

    class SpinTheWheelOverlay {
        -Entity overlay
        +request()
        +afterRender()
    }

    class SpinTheWheelOverlayActions {
        -Runnable onClose
    }

    class BlurredBackdropDisplay {
        -TextureRegion backdrop
        +toFront()
    }

    class ScreenBlur {
        +capture() TextureRegion
    }

    class SpinTheWheelScreen

    WheelLogic "1" *-- "*" WheelItem
    WheelConfig ..> WheelItem
    WheelConfig ..> SpinTheWheelDisplay
    SpinTheWheelDisplay --> WheelLogic
    SpinTheWheelScreen --> SpinTheWheelDisplay
    SpinTheWheelScreen --> SpinTheWheelActions
    SpinTheWheelOverlay --> SpinTheWheelDisplay
    SpinTheWheelOverlay --> SpinTheWheelOverlayActions
    SpinTheWheelOverlay --> BlurredBackdropDisplay
    SpinTheWheelOverlay ..> ScreenBlur
Loading

Usage

Key Public Methods

Method Purpose
WheelLogic(items) Create a wheel from a list of items
spin() Randomly select and return a winning item
getItems() Get a unmodifiable copy of the wheel's items
getWinningAngle() Get the centre angle of the winning segment, in degrees
getTargetRotation(currentRotation, pointerAngle, fullTurns) Get the rotation to animate to so the winner lands under the pointer

Example Usage

List<WheelItem> items =
    List.of(
        new WheelItem(ItemType.STANDARD_ARROW, 10),
        new WheelItem(ItemType.FIRE_ARROW, 5),
        new WheelItem(ItemType.HEALTH_POTION, 1));

WheelLogic wheel = new WheelLogic(items);

WheelItem result = wheel.spin();
float target = wheel.getTargetRotation(wheelGroup.getRotation(), 90f, 4);

Changing the items on the wheel

The wheel's contents are defined in WheelConfig.ITEMS, in the order they appear around the wheel. Segment sizes, spokes and sprites are all derived from the list size, so adding or removing an item needs no other changes:

public static final List<WheelItem> ITEMS =
    List.of(
        new WheelItem(ItemType.STANDARD_ARROW, 8),
        new WheelItem(ItemType.FIRE_ARROW, 5),
        new WheelItem(ItemType.ICE_ARROW, 5),
        new WheelItem(ItemType.HEALTH_POTION, 2));

Opening the wheel in game

The wheel opens when an event is triggered on the player. Each game screen that owns a SpinTheWheelOverlay listens for it and calls request():

player.getEvents().addListener("spinTheWheel", wheelOverlay::request);

Assets

Asset File Sprite
Wheel disc images/minigames/spinthewheel/wheel-disc.png
Segment divider images/minigames/spinthewheel/wheel-spoke.png
Pointer images/minigames/spinthewheel/wheel-pointer.png
Spin button images/Buttons/spin_up_btn.png
Spin button, pressed images/Buttons/spin_down_btn.png
Back button images/Buttons/back_up_btn.png
Back button, pressed images/Buttons/back_down_btn.png
Prize glow images/minigames/spinthewheel/glow-radial.png
Prize rays images/minigames/spinthewheel/glow-rays.png
Wheel token images/minigames/spinthewheel/wheel-token.png

Testing

Test Covers
WheelLogicTest Picking the winner, the winning angle and the spin's target rotation
SpinTheWheelDisplayTest Building the wheel, spinning, awarding and showing the prize, the buttons, sounds and closing
SpinTheWheelOverlayTest Pausing the game, opening at the end of the frame, not opening over another minigame, closing and resuming
SpinTheWheelOverlayActionsTest "back" closes the overlay
SpinTheWheelActionsTest "back" returns to minigame select
SpinTheWheelScreenTest The screen loads the wheel's assets and builds its UI
WheelConfigTest The wheel has items, and every sprite and sound exists
SpinTheWheelCommandTest The terminal command opens the wheel on the player
⚠️ **GitHub.com Fallback** ⚠️