-
The version below minifes to 1086 bytes.
let g = 14; let width = 784; let height = 210; let d = document; let cE = (tag) => d.createElement(tag) let qA = (tag) => d.querySelectorAll(tag) let setText = (text) => l.innerText = text; let c = qA(".user-calendar")[0]; let append = (element) => c.append(element) let l = cE("div"); let left; let can; let ctx; let ival; let s; let a; let fillSquare = (col,coordinates) => { ctx.fillStyle = col; ctx.fillRect(coordinates.x,coordinates.y,g-1,g-1) }; let r = (max) => ~~(Math.random() * (max)); let placeFood = () => { a = { x: r(56) * g,y: r(15) * g} }; let reset = text => { setText(`You ${text}!`); clearInterval(ival); setTimeout(init, 5000); }; let check = () => { if (left > 0) { setText(`${left} contributions left`); } else { reset("win"); } }; let ranCol = () => { let colors = ["#d2dcff", "#7992f5", "#3f51ae", "#2a2b59"]; return colors[r(3)]; }; let sameCell = (a,b) => a && a.x == b.x && a.y == b.y let loop = () => { // Reset the canvas ctx.reset(); // Advance the snake's head s.x += s.dx; s.y += s.dy; // Wrap the snake's head when out of bounds s.x = s.x < 0 ? width - g : s.x < width ? s.x : 0; s.y = s.y < 0 ? height - g : s.y < height ? s.y : 0; // prepend the snake's head and truncate to snake's length s.c = [{ x: s.x, y: s.y },...s.c].slice(0,s.m); // paint food fillSquare("#fc6d26", a); // `some` is shorter than `forEach` // Paint the snake s.c.some((cell, idx) => { fillSquare(ranCol(), cell); // Nom-nom-nom if (sameCell(cell,a)) { s.m++; placeFood() left -=100; check(); } // Ouch // We do not return because we want to paint the whole Snake! if (idx > 0 && sameCell(s.c[0], cell)) { reset("lose"); } }); }; let init = () => { // reset state placeFood() s = {x: 140,y : 70,c: [],m: 30,dx:g,dy:0} // count contributions left = [...qA("rect")] .map(rect => +rect.getAttribute("title").slice(0,2)) .reduce((acc, t) => t ? acc + t: acc, 0); // have we won yet? check(); if (can) can.remove(); can = cE("canvas"); can.width = width; can.height = height; ctx = can.getContext("2d"); append(can); ival = setInterval(loop, 50); } d.addEventListener("keydown", (e) => { e.preventDefault(); let r; if (s.dx == 0) { r = { 37: [0, -g], 39: [0, g] }[e.which]; } else if (s.dy == 0) { r = { 38: [-g, 0], 40: [g, 0] }[e.which]; } if (r) { [s.dy, s.dx] = r; } }); append(l); init();
- Edit: Realized that
min
in our random function was always0
. Some more bytes gone! - Edit2: Without the
trim()
the map is smaller!
Edited by Lukas 'ai-pi' Eipert - Edit: Realized that
-
Here is the compress to less than 1024B version (1019 to be exact)
let blockSize = 14; let canvasWidth = 784; let canvasHeight = 210; /** * Elements and stuff */ let doc = document; let createElement = (tag) => doc.createElement(tag); let querySelectorAll = (tag) => doc.querySelectorAll(tag); let calendarContainer = querySelectorAll(".user-calendar")[0]; let append = (element) => calendarContainer.append(element); let textContainer = createElement("div"); let canvas; let context; /** * Global state */ // How many contributions to play down let contributions; // Current loop interval let interval; // Direction the snake head is gonna go let direction; let fillSquare = (col, coordinates) => { context.fillStyle = col; context.fillRect(coordinates.x, coordinates.y, blockSize - 1, blockSize - 1); }; let r = (max) => ~~(Math.random() * max); let setText = (text, done = 1) => { textContainer.innerText = text; if (done) { clearInterval(interval); setTimeout(init, 5000); } }; let check = () => { if (contributions > 0) { setText(`${contributions} contributions left`, 0); } else { setText("Win!"); } }; let randomColor = () => { let colors = ["#d2dcff", "#7992f5", "#3f51ae", "#2a2b59"]; return colors[r(3)]; }; let sameCell = (a, b) => a && a.x == b.x && a.y == b.y; let init = () => { // reset state let snakeLength = 4; let coordinates = []; let x = 140; let y = 70; let food; let placeFood = () => { food = { x: r(56) * blockSize, y: r(15) * blockSize }; }; placeFood(); direction = { x: blockSize, y: 0 }; let loop = () => { // Reset the canvas context.reset(); // Advance the snake's head x += direction.x; y += direction.y; // Wrap the snake's head when out of bounds x = x < 0 ? canvasWidth - blockSize : x < canvasWidth ? x : 0; y = y < 0 ? canvasHeight - blockSize : y < canvasHeight ? y : 0; // prepend the snake's head and truncate to snake's length coordinates = [{ x, y }, ...coordinates].slice(0, snakeLength); // paint food fillSquare("#fc6d26", food); // `some` is shorter than `forEach` // Paint the snake coordinates.some((cell, index) => { fillSquare(randomColor(), cell); // Nom-nom-nom if (sameCell(cell, food)) { snakeLength++; placeFood(); contributions -= 100; check(); } // Ouch // We do not return because we want to paint the whole Snake! if (index > 0 && sameCell(coordinates[0], cell)) { setText("Loss!"); } }); }; // count contributions contributions = [...querySelectorAll("rect")] .map((rect) => +rect.getAttribute("title").slice(0, 2)) .reduce((acc, t) => (t ? acc + t : acc), 0); // have we won yet? check(); if (canvas) canvas.remove(); canvas = createElement("canvas"); canvas.width = canvasWidth; canvas.height = canvasHeight; context = canvas.getContext("2d"); append(canvas); interval = setInterval(loop, 50); }; doc.addEventListener("keydown", (e) => { e.preventDefault(); let r = ( !direction.x ? { 37: [0, -blockSize], 39: [0, blockSize] } : !direction.y ? { 38: [-blockSize, 0], 40: [blockSize, 0], } : direction )[e.which]; if (r) { [direction.y, direction.x] = r; } }); append(textContainer); init();
Biggest jump was the move of some state to the
init
function rather than having it in a global state object. -
Thanks @leipert for turning this into a valid submission!
🙏 I'll update the description to reflect this one is below 1024 Bytes!
Please register or sign in to comment