diff --git a/hampsterengine b/hampsterengine
index 807fd4a5128f8b010e92648b14dcc20f2ffce128..fbfeacd075bf597acf3de2b5f803cd46ca6583df 160000
--- a/hampsterengine
+++ b/hampsterengine
@@ -1 +1 @@
-Subproject commit 807fd4a5128f8b010e92648b14dcc20f2ffce128
+Subproject commit fbfeacd075bf597acf3de2b5f803cd46ca6583df
diff --git a/package-lock.json b/package-lock.json
index 3f397157df3a78f99af60d6f87aec1f57e3ff5cc..c223d6a0694775bd37dcff5b4bd9851d1cb85a56 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,7 +5,8 @@
   "packages": {
     "": {
       "dependencies": {
-        "jsfxr": "^1.2.2"
+        "jsfxr": "^1.2.2",
+        "stats.js": "^0.17.0"
       },
       "devDependencies": {
         "advzip-bin": "^2.0.0",
@@ -5943,6 +5944,12 @@
         "node": ">=0.8.0"
       }
     },
+    "node_modules/stats.js": {
+      "version": "0.17.0",
+      "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
+      "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==",
+      "license": "MIT"
+    },
     "node_modules/statuses": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
diff --git a/package.json b/package.json
index 7456c322efa58545d8d6b0a99e042f8f3d6d6726..e1117a399e14de065e451936cadcfe38d7d5ecba 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "terser": "^5.31.6"
   },
   "dependencies": {
-    "jsfxr": "^1.2.2"
+    "jsfxr": "^1.2.2",
+    "stats.js": "^0.17.0"
   }
 }
diff --git a/src/js/extras.js b/src/js/extras.js
index d1c119a0d88540130cc8d2ec7b15ce11ea9cd780..51f186c805311f86e920f7ad8b48358647f27523 100644
--- a/src/js/extras.js
+++ b/src/js/extras.js
@@ -3,3 +3,5 @@ export function drawLineThroughPoint(x, y) {
     // draws a line across the whole canvas through a point
     canvas.drawLine();
 }
+
+export const GRAVITY = 100;
diff --git a/src/js/main.js b/src/js/main.js
index 5d4df43d87274e643f2fb500b9c8f8266a0453bb..585c46e95f5ad73731a0916b24b92590ee2d142a 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -5,6 +5,9 @@ import Engine from "../../hampsterengine/src/engine.js";
 import SoundBox from "./sb-player-small";
 // import {mus_DEMOSONG} from "./songs/DEMOSONGDONOTCOMMIT";
 
+// dependencies used for debugging. comment out code that uses this and they won't be included
+import Stats from "stats.js";
+
 // Rooms
 import {rm_mainMenu} from "./rooms/mainMenu";
 import {rm_game} from "./rooms/game";
@@ -14,64 +17,100 @@ import {rm_DEBUG_music} from "./rooms/debug_music";
 import {rm_DEBUG_INCURSION} from "./rooms/debug_incursion";
 
 // Music
+// There is none
 
+// Init the engine and canvas
 const canvas = new Canvas('canvas');
 const engine = new Engine(canvas);
 const assets = engine.assetStore;
 
-// assets.addSoundBoxAudio('mus_DEMO', mus_DEMOSONG, new SoundBox());
-
 canvas.width = 640;
 canvas.height = 480;
 canvas.pixelRatio = 2;
 canvas.ctx.setTransform(canvas.pixelRatio, 0, 0, canvas.pixelRatio, 0, 0);
 canvas.ctx.imageSmoothingEnabled = false;
 
-let lastClickPos = {
-    x: 0, y: 0
-}
+engine.running = false; // Game uses this as a pause state actually
 
-window.lastClickPos = lastClickPos;
+// Parse query parameters
+const query = new URLSearchParams(window.location.search)
 
 engine.registerRoom(rm_mainMenu, 'mainMenu');
 engine.registerRoom(rm_game, 'game');
 
-//Debug rooms. Comment out to not include in build (esbuild will not import them if they arent used)
 engine.registerRoom(rm_DEBUG_button, 'debug_button');
 engine.registerRoom(rm_DEBUG_mouse, 'debug_mouse');
-engine.registerRoom(rm_DEBUG_music, 'debug_music');
-engine.registerRoom(rm_DEBUG_INCURSION, 'debug_incursion')
+// engine.registerRoom(rm_DEBUG_music, 'debug_music');
+engine.registerRoom(rm_DEBUG_INCURSION, 'debug_incursion');
+
+// Init stats.js
+const stats = new Stats();
+stats.showPanel(0);
+document.body.appendChild( stats.dom );
 
 function main() {
-    requestAnimationFrame(main);
-    engine.frames++;
-    canvas.fill(engine.room.bgColor ?? 'black');
+    try {
+        stats.begin();
+        engine.frames++;
+        canvas.fill(engine.room.bgColor ?? 'black');
+
+        engine.step();
+        engine.draw();
+        engine.drawGui();
+
+        // engine.drawCursor();
+
+        stats.end();
 
-    engine.step();
-    engine.draw();
-    engine.drawGui();
+        // Ask to run at the next frame
+        requestAnimationFrame(main);
+    } catch (e) {
+        engine.running = false;
 
-    engine.drawCursor();
+        canvas.pixelRatio = 2;
+        canvas.ctx.setTransform(canvas.pixelRatio, 0, 0, canvas.pixelRatio, 0, 0);
+        canvas.fill('#a05555d0');
+
+        const logo = assets.get('splash')
+        canvas.drawImage(logo, 10, 10, logo.width, logo.height)
+
+        canvas.setFillColor('black');
+        canvas.drawText(e, 10, canvas.height-10, {
+            maxWidth: canvas.width-20,
+            textBaseline: 'bottom'
+        });
+    }
+}
+
+function physicsTick() {
+    if (!engine.running) return; // Paused
+    // Tell every object to process physics
+    for (let thing of engine.room.entities) {
+        thing.physicsTick();
+    }
 }
 
 console.debug(engine.rooms);
 
-if (document.location.hash) {
-    console.log('Requesting room', document.location.hash.substring(1));
+if (query.get('room')) {
+    console.log('Requesting room', query.get('room'));
     engine.loadDelay = 0;
-    engine.room = engine.getRoomIndex(document.location.hash.substring(1));
+    engine.room = engine.getRoomIndex(query.get('room'));
 } else {
     engine.room = engine.getRoomIndex('mainMenu');
 }
 
 // Ensure assets are loaded.
 function load() {
+    stats.begin();
     if (engine.loading) {
         engine.loadLoop();
         setTimeout(load, 1000/60);
     } else {
         main();
+        setInterval(physicsTick, 1000/60); // Update physics 60 times a second
     }
+    stats.end();
 }
 
 load();
diff --git a/src/js/objects.js b/src/js/objects.js
index 6054b517c3aa0621eaef01a134956032a2e6282d..f9dbd59ed57dfc4e0b2f4eae304f3f20e17b7cac 100644
--- a/src/js/objects.js
+++ b/src/js/objects.js
@@ -1,4 +1,4 @@
-import {Thing} from "../../hampsterengine/src/things";
+import {Entity} from "../../hampsterengine/src/things";
 import ButtonBorder from "../img/button.webp";
 
 // Private
@@ -24,7 +24,7 @@ function drawButton(x, y, width, height, sprite, clicked, depressedColour) {
 
 // Public
 
-export class Button extends Thing {
+export class Button extends Entity {
     constructor(props) {
         super(props);
         this.sprite = ButtonBorder;
@@ -99,7 +99,7 @@ export class MainMenuButton extends Button {
     }
 }
 
-export class Logo extends Thing {
+export class Logo extends Entity {
     constructor(props) {
         super(props);
         this.spriteImage = null;
@@ -117,16 +117,35 @@ export class Logo extends Thing {
                 case 3: return  'right';
             }
         })
-        canvas.drawText('Committee of', this.x, this.y, {
+        canvas.drawText('Untitled', this.x, this.y, {
             textAlign: align,
             textBaseline: 'bottom',
             font: `12px ${font}`
         })
-        canvas.drawText('THIRTEEN', this.x, this.y, {
-            textAlign: align,
-            textBaseline: 'top',
-            font: `24px ${font}`
-        });
     }
 
 }
+
+// ENTITIES
+
+export class Player extends Entity {
+    constructor() {
+        super();
+        this.height=16;
+        this.width=10;
+        this.velocity = {
+            x:0, y:0
+        };
+    }
+
+    draw() {
+        canvas.setFillColor('red');
+        canvas.fillRect(this.x,this.y,this.width,this.height);
+    }
+
+    physicsTick() {
+        // Physics update 60 times a second
+        this.y += this.velocity.y/60;
+        this.x += this.velocity.x/60;
+    }
+}
diff --git a/src/js/rooms/debug_button.js b/src/js/rooms/debug_button.js
index dd17d0314ec524ff65e655734472c725158539ca..e4b8c953261c14152e734b1e2467cf149accfcef 100644
--- a/src/js/rooms/debug_button.js
+++ b/src/js/rooms/debug_button.js
@@ -1,9 +1,9 @@
 
-import {Room, Thing} from "../../../hampsterengine/src/things";
+import {Room, Entity} from "../../../hampsterengine/src/things";
 import {Button} from "../objects";
 
 export const rm_DEBUG_button = new Room();
 rm_DEBUG_button.bgColor = 'gray';
 
 const demoButton = new Button();
-rm_DEBUG_button.things.push(demoButton);
+rm_DEBUG_button.entities.push(demoButton);
diff --git a/src/js/rooms/game.js b/src/js/rooms/game.js
index 3d22f136793b627125dff0f4c744821e298ec5df..02ded7a3a0b49976625cdf3a960c0c24ac1f07a0 100644
--- a/src/js/rooms/game.js
+++ b/src/js/rooms/game.js
@@ -1,5 +1,26 @@
 
 import {Room} from "../../../hampsterengine/src/things";
+import {Player} from "../objects";
+import {GRAVITY} from "../extras";
 
 export const rm_game = new Room();
+rm_game.start = _=>{
+    canvas.pixelRatio = 3;
+    canvas.ctx.setTransform(canvas.pixelRatio, 0, 0, canvas.pixelRatio, 0, 0);
+    canvas.canvas.style.cursor = 'none';
+    engine.running = true;
+}
+rm_game.stop = _=>{
+    canvas.canvas.style.cursor = 'auto';
+    engine.running = false;
 
+}
+rm_game.step = _=>{
+
+}
+
+const player = new Player();
+player.velocity.x = 0;
+player.velocity.y = 0;
+player.direction = 0;// Radians
+rm_game.entities.push(player);
diff --git a/src/js/rooms/mainMenu.js b/src/js/rooms/mainMenu.js
index cefe8ac2889e93d3387964c6888ba107f114d016..3b4782bb515ff26e957e8502cd9a4d128125bfa1 100644
--- a/src/js/rooms/mainMenu.js
+++ b/src/js/rooms/mainMenu.js
@@ -8,14 +8,14 @@ const logo = new Logo();
 logo.x = 30;
 logo.y = 45;
 logo.align = 2
-rm_mainMenu.things.push(logo);
+rm_mainMenu.entities.push(logo);
 
 const newGameButton = new MainMenuButton('New Game', _=>{
     engine.room = engine.getRoomIndex('game');
 });
 newGameButton.x = 30;
 newGameButton.y = 70;
-rm_mainMenu.things.push(newGameButton);
+rm_mainMenu.entities.push(newGameButton);
 
 rm_mainMenu.drawGui = _ => {
     canvas.setFillColor('#0f0f0f');