//const width = 2048; //const height = 2048; const tileSize = 128; // todo: make names better const assets = [ 'assets/ground1.svg', 'assets/ground2.svg', 'assets/player.svg', 'assets/ground3.svg', 'assets/ground4.svg', 'assets/ground5.svg', 'assets/ground6.svg' ]; function getRGBA(data, i) { let out = new Uint8Array(4); for (let j = i * 4; j < i * 4 + 4; j++) { out[j - i * 4] = data[j]; } return out; } function setRGBA(data, i, input) { for (let j = i * 4; j < i * 4 + 4; j++) { data[j] = input[j - i * 4]; } } function toPoint(x2, y2, base, fac, exp, inSize) { let isMask = 1; x2 = Math.round(x2 / tileSize); y2 = Math.round(y2 / tileSize); for (let j = 0; j < exp; j++) { isMask *= base[(y2 % inSize) * inSize + (x2 % inSize)]; x2 /= inSize; y2 /= inSize; x2 = Math.floor(x2); y2 = Math.floor(y2); } isMask *= fac; isMask = (isMask - 0.5) + 0.5; isMask = Math.max(isMask, 0); isMask = Math.min(isMask, 1); return isMask; } function getChunk(x, y) { let cx = Math.floor(x / 16); let cy = Math.floor(y / 16); let id = cx + ',' + cy; return id; } function Game(inSize, exp, cs) { this.exp = exp; this.assets = []; this.inSize = inSize; this.cs = cs; this.img = new Image(); this.base = new Float32Array(inSize * inSize); this.frames = 0; this.camera = [0, 0]; this.modChunks = {}; this.dead = false; } Game.prototype.placeBlock = function (block) { let {camera} = this; let x = Math.round(camera[0] / tileSize); let y = Math.round(camera[1] / tileSize); let bx = x % 16; let by = y % 16; let id = getChunk(x, y); let chunk = this.modChunks[id] = this.modChunks[id] || new Uint8Array(16 * 16); chunk[by * 16 + bx] = block + 1; } Game.prototype.player = function () { let { ctx, fac, base, exp, inSize, camera, cs, assets } = this; ctx.drawImage(assets[2], cs / 2 - tileSize / 1.8, cs / 2 - tileSize / 1.8, tileSize / 0.9, tileSize / 0.9); if (toPoint(camera[0], camera[1], base, fac, exp, inSize) < 0.5) { this.dead = true; } let cx = Math.floor(camera[0]) / tileSize; let cy = Math.floor(camera[1]) / tileSize; let sum = 0; for (let i in base) { sum += base[i] } sum *= (fac ** (1 / exp)); let dim = Math.log(sum) / (Math.log(base.length) / 2); document.querySelector('.ui-text').textContent = `Coordinates: ${cx},${cy}\nDimensionality: ${dim}` } Game.prototype.main = function () { var { base, inSize, ctx, cs, frames, exp, camera, dat } = this; if (this.dead) { document.querySelector('.message').style.display = 'flex'; return; } else { } ctx.clearRect(0, 0, cs, cs); this.frames++; this.fac = 0.99999 ** frames; for (let i = 0; i < (cs / tileSize) * (cs / tileSize); i++) { let x = i % (cs / tileSize) x *= tileSize; let y = Math.floor(i / (cs / tileSize)); y *= tileSize; x = x + Math.round((camera[0] - cs / 2) / tileSize) * tileSize; y = y + Math.round((camera[1] - cs / 2) / tileSize) * tileSize; let x2 = x - camera[0] + cs / 2; let y2 = y - camera[1] + cs / 2; let id = getChunk(x / tileSize, y / tileSize); let chunk = this.modChunks[id]; let bx = Math.round(x / tileSize) % 16; let by = Math.round(y / tileSize)% 16; if (chunk && chunk[by * 16 + bx] != 0) { ctx.drawImage(this.assets[chunk[by * 16 + bx] - 1], x2, y2, tileSize, tileSize); continue; } let isMask = toPoint(x, y, base, this.fac, exp, inSize); if (x < 0 || y < 0) { continue; } let assetI = ((Math.round(x / tileSize) - Math.round(y / tileSize)) % 2) == 0 ? 0 : 1; if (isMask < 0.51) assetI = 3; if (isMask < 0.501) assetI = 4; if (isMask < 0.5) continue; ctx.drawImage(this.assets[assetI], x2, y2, tileSize, tileSize); } this.player(); } Game.prototype.map = function () { var { base, inSize, exp } = this; //noise.seed(Math.random() * 1000); for (let i in base) { let x = i % inSize; let y = Math.floor(i / inSize); base[i] = Math.random(); base[i] = Math.max(base[i], 0); base[i] = Math.min(base[i], 1); base[i] = Math.pow(base[i], 0.3); base[i] = base[i] * 0.3 + 0.7; //base[i] = (Math.random() > 0.5) ? 0 : 1; } this.fac = 1; let x2 = 0, y2 = 0, mask = 0; for (let i = 0; i < 1000000; i++) { x2 = Math.random() * (1.000012 ** i) * 1e2; y2 = Math.random() * (1.000012 ** i) * 1e2; mask = toPoint(x2, y2, base, this.fac, exp, inSize); if (mask == 1) break; } this.camera = [x2, y2]; } Game.prototype.loop = function () { let that = this; setInterval(function () { that.main() }, 1000 / 60); } Game.prototype.startGame = function () { var canvas = document.querySelector("#canvas"); canvas.width = this.cs; canvas.height = this.cs; var ctx = this.ctx = canvas.getContext("2d"); ctx.imageSmoothingEnabled = false; for (let asset in assets) { this.assets[asset] = new Image(); this.assets[asset].src = assets[asset]; } this.dat = ctx.getImageData(0, 0, this.cs, this.cs); this.map(); this.loop(); } Game.prototype.init = function () { let that = this; that.startGame(); } let game = new Game(8, 8, 20 * tileSize) game.init();