From a78babc7b4058456bb2dcea66bbf7cb98b136489 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 26 Mar 2020 12:45:53 +0000 Subject: [PATCH 1/2] Add Mario Clock application Mario Clock is a low-res (80x80) watch face with Mario running through a level. He jumps to hit the bricks, which changes the time displayed. Pressing BTN1 will make Mario jump, and extend the display for a futher 10 seconds. --- apps.json | 13 + apps/marioclock/ChangeLog | 1 + apps/marioclock/marioclock-app.js | 380 +++++++++++++++++++++++++++++ apps/marioclock/marioclock-icon.js | 1 + apps/marioclock/marioclock.png | Bin 0 -> 11222 bytes 5 files changed, 395 insertions(+) create mode 100644 apps/marioclock/ChangeLog create mode 100644 apps/marioclock/marioclock-app.js create mode 100644 apps/marioclock/marioclock-icon.js create mode 100644 apps/marioclock/marioclock.png diff --git a/apps.json b/apps.json index d5b079f7a..95a6e634b 100644 --- a/apps.json +++ b/apps.json @@ -823,5 +823,18 @@ "storage": [ {"name":"widid.wid.js","url":"widget.js"} ] + }, + { "id": "marioclock", + "name": "Mario Clock", + "icon": "marioclock.png", + "version":"0.01", + "description": "Animated Mario clock, jumps to change the time!", + "tags": "clock,mario,retro", + "type": "clock", + "allow_emulator":true, + "storage": [ + {"name":"marioclock.app.js","url":"marioclock-app.js"}, + {"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true} + ] } ] diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog new file mode 100644 index 000000000..5f3bf84db --- /dev/null +++ b/apps/marioclock/ChangeLog @@ -0,0 +1 @@ +0.01: Create mario app diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js new file mode 100644 index 000000000..e8cb8c0e9 --- /dev/null +++ b/apps/marioclock/marioclock-app.js @@ -0,0 +1,380 @@ +/********************************** + BangleJS MARIO CLOCK V0.1.0 + + Based on Espruino Mario Clock V3 https://github.com/paulcockrell/espruino-mario-clock + + Converting images to 1bit BMP: Image > Mode > Indexed and tick the "Use black and white (1-bit) palette", Then export as BMP. + + Online Image convertor: https://www.espruino.com/Image+Converter +**********************************/ + +var locale = require("locale"); + +// Screen dimensions +let W, H; + +let intervalRef, displayTimeoutRef = null; + +// Space to draw watch widgets (e.g battery, bluetooth status) +const WIDGETS_GUTTER = 10; + +// Colours +const LIGHTEST = "#effedd"; +const LIGHT = "#add795"; +const DARK = "#588d77"; +const DARKEST = "#122d3e"; + +// Mario Images +const marioRunningImage1 = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("B8AfwH+B/8f/z4M+KExcnAUSCw87w4L8CJQRNB/YH+AxgCEAPAA=")) +}; + +const marioRunningImage1Neg = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAHwB0DOgY/jt8PDAPAEAB2gOyAAgAAAOAB4AAAA=")) +}; + +const marioRunningImage2 = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("B8AfwH+B/8f/z4M+KExcnAUSCw87w4J6BEsPnSfyT+S+OMAAAAA=")) +}; + +const marioRunningImage2Neg = { + width : 15, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAHwB0DOgY/jt8PDAPAGEA7QAYhgMMBhAAAAAAAA=")) +}; + +const pyramid = { + width : 20, height : 20, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAkAAQgAIEAEAgCAEBAAggAEQAAoAAE=")) +}; + +const pipe = { + width : 9, height : 6, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("/8BxaCRSCA==")) +}; + +const floor = { + width : 8, height : 3, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("/6pE")) +}; + +const sky = { + width : 128, height : 30, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("VVVVVVVVVVVVVVVVVVVVVQAAAAAAAAAAAAAAAAAAAABVVVVVVVVVVVVVVVVVVVVVIiIiIiIiIiIiIiIiIiIiIlVVVVVVVVVVVVVVVVVVVVWIiIiIiIiIiIiIiIiIiIiIVVVVVVVVVVVVVVVVVVVVVSIiIiIiIiICIiIiIiIiIiJVVVVVVVVVAVVVVVVVVVVViIiIiIiIiACIiIiIiIiIiFVVVVVVVVQAVVVVVVVVVVUiIiIiIiIgACIiIiIiIiIiVVVVVVVVUAAVVVUBVVVVUKqqqqqqqggAKCqqAKqqqoBVUBVVVVQAABAVVABVVVUAIiACIiIgAAAgAiAAIiIiAFVABVVVUAAAUAVUABRVVQCqgAKCqqAAACAAAAAgCqoAVUABAVVAAAAAAAAAAAVQAKqAAACqoAAAAAAAAAACgABAAAAAUEAAAAAAAAAABQAAgAAAACAAAAAAAAAAAAIAAAAAAABQAAAAAAAAAAAEAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) +}; + +const brick = { + width : 21, height : 15, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("f//0AABoAAsAABgAAMAABgAAMAABgAAMAABgAAMAABoAAsAABf//wA==")) +}; + +const flower = { + width : 7, height : 7, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("fY3wjW+OAA==")) +}; + +const pipePlant = { + width : 9, height : 15, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("FBsNhsHDWPn/gOLQSKQSKQQ=")) +}; + +const marioSprite = { + frameIdx: 0, + frames: [ + marioRunningImage1, + marioRunningImage2 + ], + negFrames: [ + marioRunningImage1Neg, + marioRunningImage2Neg + ], + x: 35, + y: 55, + jumpCounter: 0, + jumpIncrement: Math.PI / 10, + isJumping: false +}; + +const STATIC_TILES = { + "_": {img: floor, x: 16 * 8, y: 75}, + "X": {img: sky, x: 0, y: 10}, + "#": {img: brick, x: 0, y: 0}, +}; + +const TILES = { + "T": {img: pipe, x: 16 * 8, y: 69}, + "^": {img: pyramid, x: 16 * 8, y: 55}, + "*": {img: flower, x: 16 * 8, y: 68}, + "V": {img: pipePlant, x: 16 * 8, y: 60} +}; + +const ONE_SECOND = 1000; + +let timer = 0; +let backgroundArr = []; + +function incrementTimer() { + if (timer > 1000) { + timer = 0; + } + else { + timer += 50; + } +} + +function drawTile(sprite) { + g.drawImage(sprite.img, sprite.x, sprite.y); +} + +function drawBackground() { + g.setColor(LIGHTEST); + g.fillRect(0, 10, W, H); + + // draw floor + g.setColor(DARK); + for (var x = 0; x < 16; x++) { + var floorSprite = Object.assign({}, STATIC_TILES._, {x: x * 8}); + drawTile(floorSprite); + } + + // draw sky + var skySprite = STATIC_TILES.X; + g.setColor(LIGHT); + drawTile(skySprite); +} + +function drawScenery() { + // new random sprite + const spriteKeys = Object.keys(TILES); + const key = spriteKeys[Math.floor(Math.random() * spriteKeys.length)]; + let newSprite = Object.assign({}, TILES[key]); + + // remove first sprite if offscreen + let firstBackgroundSprite = backgroundArr[0]; + if (firstBackgroundSprite) { + if (firstBackgroundSprite.x < -20) backgroundArr.splice(0, 1); + } + + // set background sprite if array empty + var lastBackgroundSprite = backgroundArr[backgroundArr.length - 1]; + if (!lastBackgroundSprite) { + lastBackgroundSprite = newSprite; + backgroundArr.push(lastBackgroundSprite); + } + + // add random sprites + if (backgroundArr.length < 6 && lastBackgroundSprite.x < (16 * 7)) { + var randIdx = Math.floor(Math.random() * 25); + if (randIdx < spriteKeys.length - 1) { + backgroundArr.push(newSprite); + } + } + + for (x = 0; x < backgroundArr.length; x++) { + let scenerySprite = backgroundArr[x]; + + // clear sprite at previous position + g.setColor(LIGHTEST); + drawTile(scenerySprite); + + // draw sprite in new position + g.setColor(LIGHT); + scenerySprite.x -= 5; + drawTile(scenerySprite); + } +} + +function drawMario() { + // clear old mario frame + g.setColor(LIGHTEST); + g.drawImage( + marioSprite.negFrames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); + g.drawImage( + marioSprite.frames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); + + // calculate jumping + const t = new Date(), + seconds = t.getSeconds(), + milliseconds = t.getMilliseconds(); + + if (seconds == 59 && milliseconds > 800 && !marioSprite.isJumping) { + marioSprite.isJumping = true; + } + + if (marioSprite.isJumping) { + marioSprite.y = (Math.sin(marioSprite.jumpCounter) * -10) + 50 /* Mario Y base value */; + marioSprite.jumpCounter += marioSprite.jumpIncrement; + + if (marioSprite.jumpCounter.toFixed(1) >= 4) { + marioSprite.jumpCounter = 0; + marioSprite.isJumping = false; + } + } + + // calculate animation timing + if (timer % 100 === 0) { + // shift to next frame + marioSprite.frameIdx ^= 1; + } + + // colour in mario + g.setColor(LIGHT); + g.drawImage( + marioSprite.negFrames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); + + // draw mario + g.setColor(DARKEST); + g.drawImage( + marioSprite.frames[marioSprite.frameIdx], + marioSprite.x, + marioSprite.y + ); +} + + +function drawBrick(x, y) { + const brickSprite = Object.assign({}, STATIC_TILES['#'], {x: x, y: y}); + + // draw brick background colour + g.setColor(LIGHT); + g.fillRect(x, y, x + 20, y+14); + + // draw brick sprite + g.setColor(DARK); + drawTile(brickSprite); +} + +function drawTime() { + // draw hour brick + drawBrick(20, 25); + // draw minute brick + drawBrick(42, 25); + + const t = new Date(); + const hours = ("0" + t.getHours()).substr(-2); + const mins = ("0" + t.getMinutes()).substr(-2); + + g.setFont("6x8"); + g.setColor(DARKEST); + g.drawString(hours, 25, 29); + g.drawString(mins, 47, 29); +} + +function drawDate() { + const date = new Date(); + const day = locale.dow(date).substr(0, 3); + const dayNum = date.getDay(); + const month = locale.month(date).substr(0, 3); + const year = date.getFullYear(); + + g.setFont("6x8"); + g.setColor(LIGHTEST); + g.drawString(`${day}, ${dayNum} ${month}`, 14, 0, true); +} + +function redraw() { + // Update timers + incrementTimer(); + + // Draw frame + drawScenery(); + drawTime(); + drawDate(); + drawMario(); + + // Render new frame + g.flip(); +} + +function clearTimers(){ + if(intervalRef) { + clearInterval(intervalRef); + intervalRef = null; + } + + if(displayTimeoutRef) { + clearInterval(displayTimeoutRef); + displayTimeoutRef = null; + } +} + +function resetDisplayTimeout() { + if (displayTimeoutRef) clearInterval(displayTimeoutRef); + + displayTimeoutRef = setInterval(() => { + if (Bangle.isLCDOn()) Bangle.setLCDPower(false); + clearTimers(); + }, ONE_SECOND * 10); +} + +function startTimers(){ + if(intervalRef) clearTimers(); + intervalRef = setInterval(redraw, 50); + + resetDisplayTimeout(); + + drawBackground(); + redraw(); +} + +// Main +function init() { + clearInterval(); + + // Initialise display + Bangle.setLCDMode("80x80"); + g.clear(); + + // Store screen dimensions + W = g.getWidth(); + H = g.getHeight(); + + // Get Mario to jump! + setWatch(() => { + if (intervalRef && !marioSprite.isJumping) marioSprite.isJumping = true; + resetDisplayTimeout(); + }, BTN1, {repeat:true}); + + setWatch(() => { + Bangle.setLCDMode(); + Bangle.showLauncher(); + }, BTN2, {repeat:false,edge:"falling"}); + + Bangle.on('lcdPower', (on) => { + if (on) { + startTimers(); + } else { + clearTimers(); + } + }); + + Bangle.on('faceUp',function(up){ + if (up && !Bangle.isLCDOn()) { + clearTimers(); + Bangle.setLCDPower(true); + } + }); +} + +// Initialise! +init(); +startTimers(); diff --git a/apps/marioclock/marioclock-icon.js b/apps/marioclock/marioclock-icon.js new file mode 100644 index 000000000..223d911f4 --- /dev/null +++ b/apps/marioclock/marioclock-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AAmBAEgrFAAZelFo+s1krAEgnBFwo5BBIIAi64nBSQgvnE4QvCwMAM4SRCXsAlFqwvGdsPXF5QHBRsYvJBYXWAD4vdw4ABF9gRBF8xYGF4plLF6xYMw4NBF74SBF9ocHAATvpFwgwOF6J9IFwwNIUIgvZFw4xGF7IABFxwwECxC/WE4gkCAALBMF64uHAYLvfC4xXDF4pflF4aPFBIQvZVo5bFAQYvIDQgvYFIjEFSIwvVAALwJGQyKGDQi/XSIYyDdhjvaYBIwNF8AwOF6LBHRoqVDXpIvUWQ4wGBpAvhSQaNHF7DCNdxwvcSIgRNF659GAAqUJF/4vIXAQGJBgy/hMxov/F6QARF/es64NBAD/XEwQvCqwvBBIYvhEgQvD/3+RoYAkFoOBFoIvqE4IvE/2BwMrAEgnBFwgACXsIADFo4ABeoIAjFQgA=")) diff --git a/apps/marioclock/marioclock.png b/apps/marioclock/marioclock.png new file mode 100644 index 0000000000000000000000000000000000000000..a462cdea1b5037590ac4d5655bb6be0ae95c7437 GIT binary patch literal 11222 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 Al>h($ literal 0 HcmV?d00001 From fa718d87461d73a977aca1bb0e47af1f3d8580bc Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Thu, 26 Mar 2020 20:45:16 +0000 Subject: [PATCH 2/2] Fix day of the week bug --- apps/marioclock/ChangeLog | 1 + apps/marioclock/marioclock-app.js | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/marioclock/ChangeLog b/apps/marioclock/ChangeLog index 5f3bf84db..e81e2f78c 100644 --- a/apps/marioclock/ChangeLog +++ b/apps/marioclock/ChangeLog @@ -1 +1,2 @@ 0.01: Create mario app +0.02: Fix day of the week and add padding diff --git a/apps/marioclock/marioclock-app.js b/apps/marioclock/marioclock-app.js index e8cb8c0e9..248b15387 100644 --- a/apps/marioclock/marioclock-app.js +++ b/apps/marioclock/marioclock-app.js @@ -282,13 +282,12 @@ function drawTime() { function drawDate() { const date = new Date(); const day = locale.dow(date).substr(0, 3); - const dayNum = date.getDay(); + const dayNum = ("0" + date.getDate()).substr(-2); const month = locale.month(date).substr(0, 3); - const year = date.getFullYear(); g.setFont("6x8"); g.setColor(LIGHTEST); - g.drawString(`${day}, ${dayNum} ${month}`, 14, 0, true); + g.drawString(`${day} ${dayNum} ${month}`, 10, 0, true); } function redraw() {