Skip to content

Latest commit

 

History

117 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bridge or Bust logo

Bridge or Bust

A bridge-building puzzle game in JavaFX, powered by a physics engine written from scratch.


Draw a bridge out of road and truss beams, hit play, and watch a car try to cross it. The beams sag, stretch, glow red under tension and blue under compression — and if you put a load where it doesn't belong, they snap and the whole thing goes into the water.

There is no physics library here. Every force, every break, every sag comes from a point-mass and spring solver written for this project.


Features

  • Two beam types. Truss beams are structural only and take more load before breaking (limit 4100 vs 2700). Road beams are physical — the car actually drives on them, and it tilts to match whichever beam it's currently on.
  • Live stress visualisation. Each beam is tinted continuously in proportion to force / breakLimit, so you can see a structure approaching failure before it fails.
  • Three levels plus a tutorial, each defined by its own set of fixed anchor pins and a different gap to span.
  • Grid snap mode for clean, deliberate structures, toggleable mid-build.
  • Physics inspector. Toggle PHYSICS mode and click any beam to read out the forces acting on it.
  • Undo, reset, and pause with a confirmation dialog before you throw away a build.
  • Fully resolution-independent. Resize the window to anything and the simulation stays correct — pin positions, beam length limits, stiffness, mass per unit length, and win/loss thresholds are all rescaled together.
  • Sound and music with per-channel volume control and a mute toggle in settings.

Controls

Input Action
Left click, then left click Place a beam between two points
Right click Delete a beam
P Play / pause the simulation
Z Undo the last beam
R Reset the level
G Toggle grid snapping
PHYSICS button Toggle the beam force inspector

Switch between road and truss beams with the toolbar buttons at the bottom of the screen.


How the physics works

The simulation lives in src/main/java/com/example/bridgeorbust/physicsSimulation/ and is built from three primitives.

Vector2D — an immutable 2D vector (add, subtract, multiply, normalize, magnitude). Everything else is expressed in terms of it.

Pin — a point mass. It holds a position, a velocity, an accumulated force sum, an accumulated mass sum, and a list of the beams connected to it. A pin is either fixed (a level anchor, immovable) or free. Each tick a free pin integrates with semi-implicit Euler:

Vector2D acceleration = forceSum.multiply(1.0 / massSum);
velocity = velocity.add(acceleration.multiply(deltaTime));
position = position.add(velocity.multiply(deltaTime));

Beam — a Hookean spring between two pins. Its rest length is whatever length it was drawn at. Each tick it contributes three forces to each of its endpoints:

  • Spring force, from the displacement between current and rest length. Stiffness is stored per axis (stiffnessX, stiffnessY) rather than as a single scalar, which is what lets the constants be rescaled independently when the window resizes.
  • Gravity, from the beam's own mass — which is derived from its length via a mass-per-unit-length constant, so longer beams genuinely weigh more. Half of a beam's mass is lumped onto each of its two pins.
  • Air friction, a linear damping term proportional to the pin's velocity, which is what stops the whole structure from oscillating forever.

A beam tracks whether it is currently stretched or compressed and sets a colour coefficient from the ratio of its spring force to its break limit. Cross the limit and the beam is marked broken; the next tick removes it, drops any pin left with no connections, and refunds one beam to the level's budget.

The load. Ball is the vehicle. Each tick it checks collisions against the physical (road) beams, and its mass is transferred into whichever endpoint pin of the contacted beam it is closest to — so the load moves across the structure as the car drives, rather than being applied statically.

The loop. BridgeSimulation drives everything from a JavaFX AnimationTimer, computing a real deltaTime from the frame timestamps and stepping in the order: sweep broken beams → update the ball → accumulate forces on every pin → integrate every pin → reposition the ball onto its beam → check the win condition.

On resizing

This was the hardest part to get right and it's worth calling out. A physics simulation defined in pixels breaks the moment the window changes size — a bridge that held at 1000×600 collapses at 1400×800, because the beams got longer while the constants didn't move. So on every resize the simulation rescales itself:

  • pin positions and initial positions scale with the width and height ratios
  • maximum beam length scales with the width ratio
  • stiffness scales linearly with the ratio
  • mass per unit length scales with the square of the ratio
  • the win and loss thresholds scale with the canvas

The result is that a structure behaves identically at any window size, and the window can be dragged around mid-simulation without desyncing.


Project structure

src/main/java/com/example/
├── GUI/
│   ├── GameTitleScreen.java      # entry point — animated title screen
│   ├── LevelSelectionScene.java  # tutorial + level 1/2/3 picker
│   ├── TutorialScene.java        # guided first build
│   ├── SettingsScene.java        # volume sliders, mute, fullscreen
│   └── MusicManager.java         # background music + SFX
└── bridgeorbust/
    └── physicsSimulation/
        ├── BridgeSimulation.java # game loop, rendering, input, levels, UI
        ├── Beam.java             # spring element: forces, mass, break limit
        ├── Pin.java              # point mass: integration, force accumulation
        ├── Ball.java             # the vehicle and its collision handling
        └── Vector2D.java         # 2D vector math

src/main/resources/
├── sounds/                       # music and SFX
└── styles/style.css

Build and run

Requirements: JDK 22 and Maven. JavaFX 22 is pulled in by Maven — you do not need a separate SDK install.

git clone https://github.com/raphaelvermeil/BridgeOrBust.git
cd BridgeOrBust
mvn clean javafx:run

Run from the repository root. Image assets are loaded with file: paths relative to the working directory (file:car.png, file:style.css), so launching from anywhere else will start the game without its textures. If you run from an IDE, set the working directory to the project root and launch com.example.GUI.GameTitleScreen.


Known limitations

  • Assets are resolved relative to the working directory rather than the classpath, which is why the run instruction above matters.
  • The physics is a single-step explicit integrator with no substepping, so very stiff structures can jitter at low frame rates.
  • Beam budgets are per-level constants rather than data-driven, so adding a level means editing BridgeSimulation.
  • There is no test suite.

Team

Built as a term project by:

Roughly 80 commits across the semester.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages