summaryrefslogtreecommitdiff
path: root/public/js/components/testroom.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/js/components/testroom.js')
-rw-r--r--public/js/components/testroom.js72
1 files changed, 72 insertions, 0 deletions
diff --git a/public/js/components/testroom.js b/public/js/components/testroom.js
new file mode 100644
index 0000000..ba5a16a
--- /dev/null
+++ b/public/js/components/testroom.js
@@ -0,0 +1,72 @@
+/* global AFRAME, THREE */
+// The world: a plain, brightly lit white room with a small table in the middle,
+// for trying things out. The chess board on the table is its own entity
+// (chess.js); its reset buttons and resetChess() are passed through here.
+(function () {
+ const ROOM = { half: 4, height: 3 }; // 8 × 8 m, 3 m tall
+ const TABLE = { half: 0.4, height: 0.75, top: 0.04, leg: 0.05 };
+ const MARGIN = 0.25; // how close your head gets to a wall
+ const LEAN = 0.08; // and to the table, so you can reach across it
+
+ AFRAME.registerComponent('testroom', {
+ init() {
+ this.group = new THREE.Group();
+ this.el.setObject3D('mesh', this.group);
+ this.seats = [];
+ this.spawn = { x: 0, z: 2.5, yaw: 0 };
+ this.screen = { x: 0, y: 1.55, z: -3.85, yaw: 0, width: 3 }; // against the far wall
+ // Child entities start first, so the board is there already.
+ const chess = this.chess();
+ this.touchables = chess ? chess.touchables : [];
+
+ const white = new THREE.MeshLambertMaterial({ color: '#ffffff', side: THREE.BackSide });
+ const room = new THREE.Mesh(new THREE.BoxGeometry(ROOM.half * 2, ROOM.height, ROOM.half * 2), white);
+ room.position.y = ROOM.height / 2;
+ this.group.add(room);
+
+ const wood = new THREE.MeshLambertMaterial({ color: '#b08a60' });
+ const top = new THREE.Mesh(new THREE.BoxGeometry(TABLE.half * 2, TABLE.top, TABLE.half * 2), wood);
+ top.position.y = TABLE.height - TABLE.top / 2;
+ this.group.add(top);
+ const legHeight = TABLE.height - TABLE.top;
+ const legGeometry = new THREE.BoxGeometry(TABLE.leg, legHeight, TABLE.leg);
+ const inset = TABLE.half - TABLE.leg;
+ for (const [x, z] of [[-1, -1], [1, -1], [-1, 1], [1, 1]]) {
+ const leg = new THREE.Mesh(legGeometry, wood);
+ leg.position.set(x * inset, legHeight / 2, z * inset);
+ this.group.add(leg);
+ }
+ },
+
+ chess() {
+ const el = this.el.querySelector('[chess]');
+ return el && el.components.chess;
+ },
+
+ resetChess() {
+ const chess = this.chess();
+ if (chess) chess.resetChess();
+ },
+
+ remove() {
+ this.group.traverse((o) => {
+ if (o.geometry) o.geometry.dispose();
+ if (o.material) o.material.dispose();
+ });
+ this.el.removeObject3D('mesh');
+ },
+
+ // Keeps a head position inside the walls and out of the table.
+ confine(p) {
+ const wall = ROOM.half - MARGIN;
+ p.x = Math.min(wall, Math.max(-wall, p.x));
+ p.z = Math.min(wall, Math.max(-wall, p.z));
+ const t = TABLE.half + LEAN;
+ if (Math.abs(p.x) < t && Math.abs(p.z) < t) {
+ if (Math.abs(p.x) > Math.abs(p.z)) p.x = Math.sign(p.x) * t;
+ else p.z = (Math.sign(p.z) || 1) * t;
+ }
+ return p;
+ },
+ });
+})();