These 35 files and commands come from the same configuration used by the download.
Entry point: src/main.ts
import { createPhysicsDemo } from "./physics"
import { createUI } from "./ui"
import { AmbientLight, BoxGeometry, Color, DirectionalLight, Mesh, MeshStandardMaterial, PerspectiveCamera, PlaneGeometry, Scene, SphereGeometry, WebGLRenderer } from "three"
import "./style.css"
import { advanceScore } from "./score"
import { createSimulation } from "./simulation"
import { createInput } from "./input"
const simulation = createSimulation({ x: 0, y: 0, speed: 5, minX: -7.5, maxX: 7.5, minY: -5.5, maxY: 5.5 })
const host = document.querySelector<HTMLElement>("#game")
if (!host) throw new Error("Game container is missing")
const scene = new Scene()
scene.background = new Color("#101e29")
const camera = new PerspectiveCamera(50, host.clientWidth / host.clientHeight, 0.1, 100)
camera.position.set(0, 12, 14)
camera.lookAt(0, 0, 0)
const renderer = new WebGLRenderer({ antialias: true })
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.setSize(host.clientWidth, host.clientHeight)
renderer.domElement.tabIndex = 0
renderer.domElement.setAttribute("aria-label", "3D game. Use arrow keys to collect gold.")
host.append(renderer.domElement)
const controls = createInput(renderer.domElement)
scene.add(new AmbientLight(0xffffff, 1.5))
const light = new DirectionalLight(0xffffff, 2)
light.position.set(4, 8, 4)
scene.add(light)
const ground = new Mesh(new PlaneGeometry(16, 12), new MeshStandardMaterial({ color: 0x1a3340 }))
ground.rotation.x = -Math.PI / 2
scene.add(ground)
const player = new Mesh(new BoxGeometry(0.7, 0.7, 0.7), new MeshStandardMaterial({ color: 0xb5f46a }))
player.position.y = 0.35
scene.add(player)
const collectible = new Mesh(new SphereGeometry(0.28), new MeshStandardMaterial({ color: 0xffc77a }))
collectible.position.set(3, 0.5, 0)
scene.add(collectible)
const ui = createUI()
window.addEventListener("pagehide", () => ui.dispose(), { once: true })
const physicsDemo = await createPhysicsDemo()
window.addEventListener("pagehide", () => physicsDemo.dispose(), { once: true })
const physicsBall = new Mesh(new SphereGeometry(0.35), new MeshStandardMaterial({ color: 0xa78bfa }))
scene.add(physicsBall)
let score = 0
let previous = performance.now()
renderer.setAnimationLoop((now) => {
const delta = (now - previous) / 1000
if (ui.isPaused()) { previous = now; return }
const position = simulation.step(controls.read(), delta)
previous = now
const bodyPosition = physicsDemo.step(delta)
physicsBall.position.set(bodyPosition.x, bodyPosition.y, bodyPosition.z)
player.position.x = position.x
player.position.z = position.y
if (player.position.distanceTo(collectible.position) < 0.8) {
score = advanceScore(score)
const label = document.querySelector("#score")
if (label) label.textContent = "Collected: " + score
collectible.position.set(Math.random() * 14 - 7, 0.5, Math.random() * 10 - 5)
}
renderer.render(scene, camera)
})
window.addEventListener("resize", () => {
camera.aspect = host.clientWidth / host.clientHeight
camera.updateProjectionMatrix()
renderer.setSize(host.clientWidth, host.clientHeight)
})
window.addEventListener("pagehide", () => { renderer.setAnimationLoop(null); renderer.dispose() }, { once: true })