Inspired by the LCD games from my childhood, comes Coin Miner 2018 for the Apple Watch!
for(_='],V8,U===D,c.CStyle="#BCfillZZBYY753"XVi+t[`t[0`1_0,^29,9^5,144,Math.,g=!1),12,19,5UU24,1ect(var =1c.font=&&(]lineTo(t[2`3h-_n+314px serif" strokeText(ZR^^e,l)ClineWidthmDy.lengthCbeginPath(V[BFFFl=39^e=31t=22i=21f9n89,r56,o2Uh2F=9S=3^T="💎",s="💣",y=[[^^3,U43,U6,1^106,61,32^2411,32363^4827^36027^4^759914^5^12244^57555]Vv=-r,x=T,d=3,k=^m=0;b.addEventListener("click",l=>{m>=8g=!0)}function p(P){R=y[m];P-v>=rv=PXY000"arc(r,f,r,^PI,!0r^f,e,ffill(g&&-1xDT?(k+Y00F8"):xDsd-YF008")),[m-4,m-m,m+2].forEach((l,e)=>{if(y[l]){t=y[lVf=(63*e).toString(16)[0];c."+fX+fmoveTo(h-_]fill(()}}"24 Yffb"ZT+k,1^Sfills.repeat(dt,Sd<=0&&c.fill"Game Over",F,r12*m+" Zx,r-R[4Vi+R[5]A"^c.RF,t,o,o++m=^x=random()<.5?s:T)d>0&&requestAnimationFrame(p)}(0);';G=/[-^-`X-ZB-DUV]/.exec(_);)with(_.split(G))_=join(shift());eval(_)
Zm9yKF89J10sVjgsVT09PUQsYy5DU3R5bGU9IiNCQ2ZpbGxaWkJZWTc1MyJYVmkrdFtgdFswYDFfMCxeMjksOV4fNSweMR40NCwdTWF0aC4cLGc9ITEbKSwaHjEZMiwYMTksNVUXVTI0LDEWZWN0KBV2YXIgFD0xExpjLhISZm9udD0RJiYoEF0SbGluZVRvKA90WzJgMw9oLQ5fD24rDDMZMRg0HgtweCBzZXJpZiIJc3Ryb2tlCFRleHQoB1pSFV5eZSxsKQZDbGluZVdpZHRoEwVtRHkubGVuZ3RoBENiZWdpblBhdGgoEgNWWwIIQkZGRgEUbD0zOV5lPTMxGHQ9MjIeaT0yMR5mEzkebhM4OSxyEzU2LG8TMlVoEzIeRj05HlM9M15UPSLwn5KOIixzPSLwn5KjIix5PVtbXl4zLFUeNAIzLFUZNiwxXjEwAhk2LBYZNgIWMSwzGDJeMjQCMTEsMxgdMh4zNgIdFzNeNDgCFzIYN14zHjYwAjIYN14fNF43NQIfCzk5AgsxNF41XjEyMgI0GTReNRk3HjUZNTVdVnY9LXIseD1ULGQ9Mxssaz1ebT0wO2IuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGw9PnttPj04EGc9ITApfRpmdW5jdGlvbiBwKFApexRSPXlbbV07UC12Pj1yEHY9UFgGWTAwMCIDYXJjKHIsZixyLF4cUEksITASchVeZixlLGYSZmlsbCgaZyYmBC0xEHhEVD8oaysTWTAwRjgiKTp4RHMQZC0TWUYwMDgiKQYpBSxbbS00LG0tGG0sbSsyXS5mb3JFYWNoKChsLGUpPT57aWYoeVtsXSl7FHQ9eVtsVmY9KDYzKmUpLnRvU3RyaW5nKDE2KVswXTtjLgEiK2ZYK2YDbW92ZVRvKGgtDAwODl9dEmZpbGwoEggoKX19ESIyNAlZZmZiIloHVCtrLDFeUxJmaWxsB3MucmVwZWF0KGQadCxTGmQ8PTAmJmMuZmlsbAciR2FtZSBPdmVyIixGLHIRMTIqbSsiCVoHeCxyLVJbNFZpK1JbNV0SAUEiBV5jLghSFUYsdCxvLG8aKysEEG09Xng9HHJhbmRvbSgpPC41P3M6VBspGmQ+MCYmcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHApfSgwKTsnO0c9L1sBLR9eLWBYLVpCLURVVl0vLmV4ZWMoXyk7KXdpdGgoXy5zcGxpdChHKSlfPWpvaW4oc2hpZnQoKSk7ZXZhbChfKQ==
// source: https://github.com/ripter/js1k/tree/master/2018
const WIDTH = 312;
const HALF_WIDTH = 156;// WIDTH/2;
// const WIDTH_FLOOR = 32;
const HEIGHT = 390;
const HALF_HEIGHT = 195;// HEIGHT/2;
const FRAME_RATE = 250;
const GAMEOVER_X = 86;// HALF_WIDTH - 70;
const GAMEOVER_Y = 170;// HALF_HEIGHT - 25;
const HEADER_Y = 30;
const LIVES_X = 222;// WIDTH-90;
const SCORE_WIDTH = 128;// WIDTH_FLOOR*4;
// Vanishing Point
// const VPOINT = {
// X: 157,
// Y: 215,
// }
const SCORE_X = 95;// 157 - 62;// VPOINT.X - 62;
const SCORE_Y = 225;// 215 + 10;// VPOINT.Y + 10;
const PLANK_X1 = 125;// 157 - 32;// VPOINT.X - WIDTH_FLOOR;
const PLANK_X2 = 189;// 157 + 32;// VPOINT.X + WIDTH_FLOOR;
const PLANK_Y = 215;// VPOINT.Y;
const PLANK_X = 157;// VPOINT.X;
const NONE = false;
const COIN = '💎';
const BOMB = '💣';
const RECT_TOP = 0;
const RECT_LEFT = 1;
const RECT_BOTTOM = 2;
const RECT_RIGHT = 3;
const ITEM_X = 4;
const ITEM_Y = 5;
const FRAMES = [
// each array is a rectangle's
// offsets for rect, item
// [RECT_TOP, RECT_LEFT, RECT_BOTTOM, RECT_RIGHT, ITEM_X, ITEM_Y]
[ 0, 0, 3, 8, 5, 4 ], // frame 0
[ 3, 8, 5, 16, 10, 10 ], // frame 1
[ 5, 16, 8, 24, 15, 16 ], // frame 2
[ 8, 24, 11, 32, 20, 24 ], // frame 3
[ 11, 32, 15, 44, 25, 36 ], // frame 4
[ 15, 44, 19, 58, 30, 48 ], // frame 5
[ 19, 58, 22, 70, 35, 60 ], // frame 6
[ 22, 70, 29, 90, 40, 75 ], // frame 7
[ 29, 90, 35, 112, 45, 99 ], // frame 8
[ 35, 112, 45, 140, 50, 122 ], // frame 9
[ 45, 140, 55, 175, 55, 155 ], // frame 10
];
let lastTimestamp = -FRAME_RATE;
let isKeyDown = false;
let currentItem = COIN;
let score = 0; // player score
let lives = 3;
let frame = 0; // current frame1
// console.log('Coin Miner 2018');
['click', 'touchend'].forEach((eventName) => {
b.addEventListener(eventName, (event) => {
if ( frame >= 9 ) {
isKeyDown = true;
}
});
});
function drawPlank(points) {
c.beginPath();
c.moveTo(PLANK_X1 - points[RECT_TOP], PLANK_Y + points[RECT_LEFT]); // move to top, left corner
c.lineTo(PLANK_X2 + points[RECT_TOP], PLANK_Y + points[RECT_LEFT]); // draw line to top, right corner
c.lineTo(PLANK_X2 + points[RECT_BOTTOM], PLANK_Y + points[RECT_RIGHT]); // draw line to bottom, right corner
c.lineTo(PLANK_X1 - points[RECT_BOTTOM], PLANK_Y + points[RECT_RIGHT]); // draw line to bottom, left corner
c.lineTo(PLANK_X1 - points[RECT_TOP], PLANK_Y + points[RECT_LEFT]); // draw line to top, left corner
c.fill();
c.stroke();
}
/**
* Game Loop.
* Self calling.
* @param {Number} [timestamp=0] [description]
*/
function tick(timestamp = 0) {
timestamp = 0 | timestamp; // round to milliseconds
const diff = 0| (timestamp - lastTimestamp);
const points = FRAMES[frame];
let x, y;
// console.log('tick', diff);
if (diff >= FRAME_RATE) {
// console.log('%cframe', 'color: #ddd;', frame);
lastTimestamp = timestamp;
//
// draw "dirt" over the entire screen to clear it.
c.fillStyle = '#725636'; // brown dirt
c.fillRect(0, 0, WIDTH, HEIGHT);
//
// cut out a hole for the cave and path from the dirt.
c.fillStyle = '#000';
c.beginPath();
c.arc(HALF_WIDTH, HALF_HEIGHT, HALF_WIDTH, 0, Math.PI, true);
c.rect(0, HALF_HEIGHT, WIDTH, HALF_HEIGHT);
c.fill();
//
// Check for Score/Game Over
// Collect if the key is down on the last frame.
if (isKeyDown && frame === FRAMES.length-1) {
if (currentItem === COIN) {
score += 1;
c.fillStyle = 'rgba(0, 0, 255, .8)'; // Blue Score Flash
}
else if (currentItem === BOMB) {
lives -= 1;
c.fillStyle = 'rgba(255, 0, 0, .8)'; // Red Fail Flash
}
c.fillRect(0, 0, WIDTH, HEIGHT);
}
//
// draw planks
c.lineWidth = 1;
// draw up to 4 plans with fading opacity
[frame-4, frame-2, frame, frame+2].forEach((distance, i) => {
if (!FRAMES[distance]) { return; }
c.strokeStyle = `rgba(255, 255, 255, ${i*.25})`;
c.fillStyle = `rgba(57, 43, 27, ${i*.25})`,
drawPlank(FRAMES[distance]);
});
//
// render the score/lives
c.font = '24px serif';
c.fillStyle = '#f0f0b5'; // light sand color
c.fillText(`${COIN} ${score}`, 10, HEADER_Y);
c.fillText(BOMB.repeat(lives), LIVES_X, HEADER_Y);
//
// Draw game over
if (lives <= 0) {
c.fillText(`Game Over`, GAMEOVER_X, GAMEOVER_Y);
currentItem = NONE;
}
//
// Draw the item (Coin/Bomb)
if (currentItem !== NONE) {
c.font = `${12*frame}px serif`;
c.fillText(
currentItem,
PLANK_X - points[ITEM_X],
PLANK_Y + points[ITEM_Y]);
}
//
// Draw the score box
// That tells the user where the item needs to be in order to collect it.
c.strokeStyle = 'rgba(255, 255, 255, .75)';
c.lineWidth = 10;
c.strokeRect(SCORE_X, SCORE_Y, SCORE_WIDTH, SCORE_WIDTH);
// Update the animation Frame
frame += 1;
if (frame === FRAMES.length) {
// reset the loop values
frame = 0;
currentItem = (Math.random() > .5) ? COIN : BOMB;
isKeyDown = false;
}
}
// allow pausing for debugging.
if (lives > 0 && !window.pause){
window.requestAnimationFrame(tick);
}
};
// Start Game
tick();