Skip to content

Repository files navigation

Super Gold Hunters

A 2.5D raycasting maze game in Java, written with no libraries and no game engine — just java.awt and javax.swing. Built by three of us as our AP Computer Science A final project in high school.

You spawn in a textured maze with a monster hunting you. Grab gold, watch the minimap, and stay ahead of it — it gets faster the longer you survive.

The raycaster: textured walls with per-side shading and a gold sprite

Running it

Needs a JDK. Tested on Temurin 17.

./run.sh

Use ./run.sh --clean to wipe bin/ and rebuild from scratch.

The game must run with its working directory set to APCS Final Project/. Every asset path is relative, and the wall textures load inside static initializers, so launching from anywhere else dies with ExceptionInInitializerError instead of a useful "file not found". run.sh handles this for you.

Controls

Input Action
W / S Move forward / back
A / D Strafe left / right
/ Turn
SPACE Pick up adjacent gold

Click the button on the title screen to begin.

How it works

The renderer is a raycaster in the Wolfenstein 3D tradition — the world is a flat 15×15 grid of integers, but it's drawn as though it had height, which is why it's "2.5D" rather than true 3D.

Walls. For each of the 640 screen columns, Screen.update() casts a ray from the camera and walks the grid with a DDA traversal until it hits a non-zero cell. The perpendicular distance to that hit determines how tall the wall slice is drawn — near walls are tall, far walls are short. The exact hit position picks the column of texture to sample, and rays that hit a north/south face get their color halved ((color >> 1) & 8355711) so adjacent faces read as distinct without any real lighting. Adapted from the tutorial at lodev.org.

Sprites. Gold and the monster are billboards. Each frame they're insertion-sorted far-to-near, then transformed into camera space with an inverse-determinant matrix so they scale and slide correctly with perspective. A per-column ZBuffer recorded during the wall pass hides sprites behind walls. Black pixels are treated as transparent, which is how the sprites get cut out from their rectangular source images.

Speed. The pixel array is aliased directly onto the BufferedImage's raster via DataBufferInt, so writing an int writes a pixel with no per-pixel method call.

The monster hunts greedily: it scores the four cardinal moves by squared distance to the player and takes the best legal one, falling back through the alternatives when walls block it. Its speed increases every move tick, so a long run is always eventually lost. It animates through a three-frame walk cycle.

The minimap redraws the grid each frame but fogs everything more than three tiles away, so you can only see your immediate surroundings. Green dot is you, with an orange wedge for your field of view; red is the monster; yellow circles are gold.

Classes

File Role
Driver.java Entry point
Game.java JFrame, game loop, minimap, HUD, gold pickup, monster AI
Screen.java The raycaster — walls, then sprites
Camera.java Player position/direction/FOV, and the key + mouse listener
Texture.java 64×64 wall textures
SpriteTexture.java Full-size sprite images
Sprite.java Interface implemented by Gold and Monster
Gold.java, Monster.java The two sprite types
Maze.java Maze generator — see below

Maze.java is a complete recursive-backtracker maze generator that nothing ever calls. Game.generateMap() picks one of three hand-drawn maps out of assets/MapOptions.txt instead. It got built and never wired in; it's kept here as-is.

Repository layout

APCS Final Project/ is the finished game and the only version that runs — it's the only one with a main. The rest are snapshots kept from development, roughly in order:

Raycasting Test/    walls only, no game
test1/              first pass at gold
TreasureUpdate/     scoring
goldAndMonster/     the monster arrives
ALMOST_DONE/        title and end screens
LoadingAndClosing/  polish
FINAL_EDITION/      feature-complete, but has no main()
APCS Final Project/ ← the one that runs

A note on the 2026 fix

The game originally sized its window with setSize(640, 480) and drew straight onto the JFrame. That sizes the whole window, title bar included, while the drawing surface starts at the window's top edge — so on macOS the title bar covered the top 28 rows of everything drawn. Game.java now draws on a Canvas sized to exactly 640×480, which sits below the title bar, and pack() grows the window around it. Every drawing coordinate is unchanged, because a canvas reports mouse clicks in the same space it draws in.

Beyond that the code is untouched, and the engine itself needed no changes at all — it compiled and ran correctly on a JDK seven major versions newer than the one it was written against.

About

First-person maze game with a 3D renderer written from scratch in Java — no engine, one ray per screen column. Case study: https://shaostassen.com/projects/super-gold-hunters

Topics

Resources

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages