< Back to projects

Web app · case study

GiraffeRun

2D arcade game: dodge rockets, collect crystals, across four levels with shield and teleport abilities.

GiraffeRun gameplay preview
My role

Sole developer · Object-Oriented Programming coursework (ISNE12)

Type

Web application

Stack

Java, libGDX, WebAssembly

Runs on

GitHub Pages, CNAME domain

Edge

GitHub Pages CDN

Why I built it

I built GiraffeRun alone for an Object-Oriented Programming course, to apply encapsulation, inheritance, abstraction and polymorphism, plus factory-based object creation, in Java.Seven months after submitting it, I took it further: TeaVM compiles the same code to WebAssembly so it runs in a browser, the interface adapts to phones, and GitHub Actions deploys it on every push.

The course was practice for writing larger Java applications.For now, it's a game.

The problem

  • Apply the four OOP principles and factory patterns in a complete Java program.

  • A desktop JAR is hard to share; the game needed to run from a link.

Features

  • Auto-detects device in browser with adaptive UI
  • Four levels, each with its own hazard layout

Architecture

Architecture diagramOne Java core holds all game logic. LWJGL3 packages it for the desktop. TeaVM compiles the same core to WebAssembly. GitHub Actions publishes the WASM build to GitHub Pages on a custom domain. It runs entirely in the browser.GRADLE BUILDGITHUB PAGEScoreJava game logiclevels, pools, adaptive HUDlwjgl3desktop build, JVMTeaVMJava → WebAssemblypatched gdx-teavmPages CDNapp.wasm + assetscustom domainBrowserruns fully client-sideadapts to the deviceActions deployHTTPS
Dev · applicationOps · infrastructureExternal · third partyScroll sideways to see all of it.
  • core to lwjgl3
  • core to TeaVM
  • TeaVM to Pages CDN: Actions deploy
  • Pages CDN to Browser: HTTPS

In words

One Java core holds all game logic.LWJGL3 packages it for the desktop.TeaVM compiles the same core to WebAssembly.GitHub Actions publishes the WASM build to GitHub Pages on a custom domain.It runs entirely in the browser.

Pipeline

push → main

  1. JDK 17

    Gradle and toolchain cached

  2. gdx-teavm

    patched, cached by patch hash

  3. :teavm:buildWasm

    Java → app.wasm

  4. deploy-pages

    OIDC token, atomic swap

Decisions

A class hierarchy for everything that falls.

Abstract GameObject and Drop classes let each drop type override only its own behaviour.

TeaVM to WebAssembly.

It runs the existing Java code in the browser without a rewrite.Screens, entities and assets are shared with the desktop build.

A small patch instead of a fork.

A 67-line patch applied in CI is easier to keep current than a fork.

GitHub Pages for hosting.

The build is static files.It deploys from GitHub Actions for free.

Challenges

libGDX didn't run cleanly under TeaVM.

Patched the backend's viewport scaling and its Windows build.

A keyboard game on a phone.

Touch controls, and a HUD that switches phone and desktop layouts on resize.

Garbage-collection stutter from falling objects.

Object pools reuse drops instead of allocating new ones.

Testing

  • CI builds the WebAssembly bundle on every push.A failed build never deploys.

  • Not yet: automated gameplay tests.

Outcome

  • Playable in any browser at girafferun.wyco-dev.com; the desktop JAR builds from the same code.

Next

  • Load assets in the background

  • Save a high score

Stack

Java

Holds the game logic shared by both builds.

libGDX

Runs the game loop, rendering, and input.

WebAssembly

TeaVM compiles the same Java core to WebAssembly for the browser.

Security

Authentication

None.Fully client-side game.

Input validation

Local input only.No data leaves the browser.

Protections

Static files only: no server, no stored data.

Operations

Runs on

GitHub Pages, CNAME domain

Edge

GitHub Pages CDN

Deploy

Push to main.Actions builds the WASM bundle and publishes it to Pages.