From a618aab3163bb1ae7e098ce54f45d62151cf52ca Mon Sep 17 00:00:00 2001 From: LucienStorm Date: Sat, 18 Oct 2025 16:57:59 -0500 Subject: [PATCH 1/4] Add files via upload New commit with app.png and hopefully all errors cleared. --- apps/bmoface/ChangeLog | 11 + apps/bmoface/README.md | 48 +++ apps/bmoface/app-icon.js | 1 + apps/bmoface/app.js | 552 +++++++++++++++++++++++++++++++++++ apps/bmoface/app.png | Bin 0 -> 1729 bytes apps/bmoface/metadata.json | 26 ++ apps/bmoface/screenshot1.png | Bin 0 -> 5579 bytes apps/bmoface/screenshot2.png | Bin 0 -> 4259 bytes apps/bmoface/screenshot3.png | Bin 0 -> 6106 bytes apps/bmoface/screenshot4.png | Bin 0 -> 3893 bytes apps/bmoface/settings.js | 47 +++ 11 files changed, 685 insertions(+) create mode 100644 apps/bmoface/ChangeLog create mode 100644 apps/bmoface/README.md create mode 100644 apps/bmoface/app-icon.js create mode 100644 apps/bmoface/app.js create mode 100644 apps/bmoface/app.png create mode 100644 apps/bmoface/metadata.json create mode 100644 apps/bmoface/screenshot1.png create mode 100644 apps/bmoface/screenshot2.png create mode 100644 apps/bmoface/screenshot3.png create mode 100644 apps/bmoface/screenshot4.png create mode 100644 apps/bmoface/settings.js diff --git a/apps/bmoface/ChangeLog b/apps/bmoface/ChangeLog new file mode 100644 index 0000000000..04e533410c --- /dev/null +++ b/apps/bmoface/ChangeLog @@ -0,0 +1,11 @@ +0.0.01: Initial release with BMO character +0.0.02: Added Finn and Jake characters +0.0.03: Added settings menu for character selection +0.0.04: Added temperature unit toggle (C/F) +0.0.05: Fixed settings menu crash, added charging status indicators +0.0.06: Fixed "Invalid Settings!" error with proper settings file handling +0.0.07: Added character randomizer feature with multiple intervals +0.0.08: Fixed lock screen character variable error, separated lock screen logic +0.0.09: Improved lock screen character-specific drawing and positioning +0.0.1: Major release with all core features complete +0.1.1: Code refactoring and lock screen improvements \ No newline at end of file diff --git a/apps/bmoface/README.md b/apps/bmoface/README.md new file mode 100644 index 0000000000..44d496a845 --- /dev/null +++ b/apps/bmoface/README.md @@ -0,0 +1,48 @@ +BMO Face + +A playful Bangle.js watchface inspired by BMO from Adventure Time. Features three selectable characters (BMO, Finn, Jake) with dynamic expressions based on watch state. + +Features +- **Three Characters**: BMO (green), Finn (blue), Jake (yellow) +- **Dynamic Expressions**: + - Normal face when unlocked + - Sleeping face (`-_-`) when locked + - Lightning bolt eyes when charging +- **Information Display**: + - Time (top-center) using `7x11Numeric7Seg` font + - Temperature (upper-left) with C/F toggle + - Steps (bottom-right) + - Heart rate (above steps) +- **Settings Menu**: + - Character selection (BMO, Finn, Jake) + - Temperature unit toggle (Celsius/Fahrenheit) + - Character randomizer (Off, 5min, 10min, 30min, On Wake) +- **Lock Screen**: Light gray background with character-specific sleeping expressions +- **Charging Indicator**: Lightning bolt eyes for all characters + +Character Details +- **BMO**: Green background, black circular eyes, complex layered mouth, dark teal borders +- **Finn**: Light blue background, flesh-colored face, white hood with ears, simple curved smile +- **Jake**: Yellow background, white eyes with black outlines, horizontal pointed jowls, oval nose + +Testing Commands +Use in emulator console: +```javascript +// Test lock state +Bangle.setLocked(true); +Bangle.setLocked(false); + +// Test charging state +Bangle.setCharging(true); +Bangle.setCharging(false); + +// Test character randomizer +Bangle.emit("lock"); // Triggers "On Wake" randomizer +``` + +Installation +Upload via Bangle.js App Loader or manually install the files in the `bmoface` folder. + +Attribution +Character inspiration: BMO, Finn, and Jake from Adventure Time (Cartoon Network) + diff --git a/apps/bmoface/app-icon.js b/apps/bmoface/app-icon.js new file mode 100644 index 0000000000..012efd739c --- /dev/null +++ b/apps/bmoface/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("2GwgkIAH4AW+4A/AC0ItAA/ACqX/V/6v/AH6v/V/6v/AC1ggAADEiobQCAYOHOzw6EgAbV+AbEs4sNV/4bSsAKDAgIGEV7qRBA4tgg4RhVwQEFAILCDV7iRBDwqUJCLKvIA4qv/V6P3DQivcgCdKS4IFDCJYjNV5IAEV9ALBgFnV8nwBgivcUYKvPCJYjNV5IHEV9YFEV8EH+AbDV7iiETowLBAoqvPCI4AJB4iv/V5QAMV7lgTpYKECJgjMBIQIDAgivrCL4ABBAgNHV7j6BTp4RZV9aXCGwIACCLqvxRoYADEhYRRAA6v/V/4ADDwqEHCKZnBBQ6vrRI0HCLPwXZCvrRJQRWV5IKCAAIMHV9CXBWpavTCgIACBY6voRgQrKV5IWMABKv/V5YALV9DjCV6jHBV/6v/V6qXBV6oWMV+QRXV/4RXY4Kv/V/6XMgAADEjcIDiqpfAAjUkV/4AlRWSv/AHiX/V/6v9sEAAAMHTV/wGgUAV7hWDAALCuGgo1PPCAABsCutGgrmPMxZ5GWFo0Hgw1NVyIACV2SwPMpR5HWFo1IV7BWIPRwAcchLlNV/40JGpqv/V/4AXKxKv/V/4AlGhKv/V/4AlKxKv/V/6wvGhp6UV1IABRpDkNMpUIV2aviWBCurAAKuUV5Z7HV1gABsA1UPaJ4OAELmECh6cPhCtuGYgBCAB6cvAE6eyAEiX/V/6v/AH6v/V/6v/AH6v/V/4A/OrvgAAXnCZ3wCgav8sEAAAojMCgznfVr6xPVoixiO7SZBg4ACTxisECoYWCWLpxZTIP/AAPwAAShHAA4RBDAbFMV9dgg8PH4QAB+6yGAAwVHV/CXBIAgAWYwSv1VwKZGACrFCWDhwYR4Kve+HnV+kAV4IABKzAcDVzavZVwIAFVaoAD8Cv0sCSDABUPUgoAKgA7YV8YAZV+sATpwARV/6v/ABtgV/6v/V90AV/6vXWECv1sCu8V7KOBVz/nV+kAgCUDu4ABVKITED4Kv1+/gWAS5FABgSHDwKubV7NosCxCs6vCACiufV7SRCSTCuD86v2hCSBWAKuWuAbCV+6wDSa6ugV7QABSgSvWV0CvbAAKVXVwStdV7tosCXCWSIVDVryveWIYAHXIQMJVr6veAAUIWYgANhCtgV8AAD+CnJW4oAjPUSzBAASoGVUavnAGh/nAF6X/V/6v/AH6v/V/6v/AH6v/V/4A/S/6v/V/4A/V/6v/V/4A/V+/wgACDsEAg6v/ACgtpV86nBg6qDV06vuADVggAAChAFFV9VnAIICBAwYAXKAcAAoyvLsAJEAoJ3IZKDasN5IFGO5CONg4BBVYYGBAEyvRA4wQGAG6vRBo6wN+AOBAQX3WYav+WHqvZWBwAuV/6v/sEABwlgV/JABgAKBV6AVEAwTDnV6IACV6KnDAYR0BV+YCEW46vNU4YDCWgqvvAQi3HV6YBBV+YBHV7IBBCZavnAI6vWsATPV8ySDAgSvITRgcCgAgEV+KOEV5SaMV4IBBV+ynGWQIACAoaZMBoLJFV7QyED5CvJAoxWDAoh+MsEGEIqvaGQgfIP7IAMRY6vZDoqvRADtgVYyvZDoqvwVYyv/V/6v/V5lgEoIFDEQivmWAMARQQECWDAYCDgQFDV9awBAAIqBAgS4DV6wBHBwivnAECrDAIqvsAEFgZIStCZ46m/V5KoCVoSuGV/6vKJISvCAISv/V5wDEAIav/V6oIEV/6vSWAyv/WBUAgCsFWAim/WBQABWo6v/ADSl/AC6v/V/6v/AH6v/V/6v/AH6v/V/4A/A=")) \ No newline at end of file diff --git a/apps/bmoface/app.js b/apps/bmoface/app.js new file mode 100644 index 0000000000..088a9b2b29 --- /dev/null +++ b/apps/bmoface/app.js @@ -0,0 +1,552 @@ +const storage = require('Storage'); + +// Try to load fonts, but don't fail if they're not available (emulator compatibility) +try { require("Font6x12").add(Graphics); } catch(e) {} +try { require("Font8x12").add(Graphics); } catch(e) {} +try { require("Font7x11Numeric7Seg").add(Graphics); } catch(e) {} + +function bigThenSmall(big, small, x, y) { + g.setFont("6x8", 2); + g.drawString(big, x, y); + x += g.stringWidth(big); + g.setFont("6x8", 2); + g.drawString(small, x, y); +} + +function getBackgroundImage() { + // Cartoon face background - we'll create this + return null; // Placeholder for now +} + +function drawSmileShape(x, y, width, height, thickness) { + // New approach: stamp small circles along an ellipse arc to get + // naturally rounded ends (no polygons changed elsewhere) + var startAngle = Math.PI / 5; + var endAngle = (4 * Math.PI) / 5; + var step = Math.PI / 40; // small, keeps change minimal + var rx = width/1.57; // match previous horizontal scale + var ry = height/2; + var r = Math.max(1, thickness/2); + for (var a=startAngle; a<=endAngle; a+=step) { + var px = x + rx * Math.cos(a); + var py = y + ry * Math.sin(a); + g.fillCircle(px, py, r); + } +} + +function drawLightningBolt(x, y, width, height) { + // Draw lightning bolt using two opposing acute triangles + // x, y = center point + // width = how wide the bolt is + // height = how tall the bolt is + g.setColor(0x000000); + + var halfWidth = width / 2.5; + var halfHeight = height / 1; + + // Upper triangle (pointing down-right) + var upperTriangle = [ + x, y - halfHeight, // Top center point + x + halfWidth, y, // Right middle point + x - halfWidth/2, y + halfHeight/2 // Left lower point + ]; + g.fillPoly(upperTriangle); + + // Lower triangle (pointing up-left) + var lowerTriangle = [ + x, y + halfHeight, // Bottom center point + x - halfWidth, y, // Left middle point + x + halfWidth/2, y - halfHeight/2 // Right upper point + ]; + g.fillPoly(lowerTriangle); +} + +function drawFinnFace() { + var isCharging = Bangle.isCharging(); + + // White hood ears + g.setColor(0xFFFFFF); + g.fillCircle(30, 20, 22); // Left ear (x, y, radius) + g.fillCircle(140, 20, 22); // Right ear (x, y, radius) + + // White hood behind face + g.setColor(0xFFFFFF); // White + g.fillCircle(85, 82, 85); // Hood circle (x, y, radius) + + // Finn's face (flesh colored circle) + g.setColor(0.95, 0.8, 0.7); // Flesh color + g.fillEllipse(150, 100, 20, 10); // Face circle (x, y, radius) + + // Outlines + g.setColor(0x000000); + g.drawEllipse(150, 100, 20, 10); // Face outline + g.drawCircle(85, 85, 85); // Hood outline + + // White squared bottom for hood (behind everything) + g.setColor(0xFFFFFF); // White + g.fillRect(2, 102, 168, 180); // Squared hood bottom (x1, y1, x2, y2) + + if (isCharging) { + // Lightning bolt eyes when charging + drawLightningBolt(32, 55, 12, 20); // Left lightning bolt + drawLightningBolt(139, 55, 12, 20); // Right lightning bolt + } else { + // Normal circular eyes + g.setColor(0x000000); + g.fillCircle(35, 55, 10); // Left eye (x, y, radius) + g.fillCircle(135, 55, 10); // Right eye (x, y, radius) + } + + // Curved smile using arc + g.setColor(0x000000); + // Draw curved smile: center at (85, 100), radius 20, from 0.2*PI to 0.8*PI + var smilePoints = []; + for (var angle = 0.2 * Math.PI; angle <= 0.8 * Math.PI; angle += 0.1) { + var x = 85 + 20 * Math.cos(angle); + var y = 60 + 20 * Math.sin(angle); + smilePoints.push(x, y); + } + g.drawPoly(smilePoints); +} + +function drawBMOFace() { + var isCharging = Bangle.isCharging(); + + if (isCharging) { + // Lightning bolt eyes when charging + drawLightningBolt(32, 55, 12, 20); // Left lightning bolt (x, y, width, height) + drawLightningBolt(139, 55, 12, 20); // Right lightning bolt (x, y, width, height) + } else { + // Normal circular eyes + g.setColor(0x000000); + g.fillCircle(32, 55, 10); // Left eye - moved up and left + g.fillCircle(139, 55, 10); // Right eye - moved up and left + } + + // BMO mouth structure - all elements follow the same calculated curve + // Black mouth outline + g.setColor(0x424242); + drawSmileShape(85, 86, 40, 20, 29); // Black smile outline + + // Inside of mouth (dark green) + g.setColor(0x225c27); // Dark green + drawSmileShape(85, 85, 43, 20, 20); // Dark green inside smile + + // Tongue (medium green) + g.setColor(0x474747); // Medium green + drawSmileShape(85, 99, 40, 10, 6); // Green tongue smile + + // Curved white tooth line (smile) + g.setColor(0xFFFFFF); + drawSmileShape(85, 80, 50, 12, 4); // White tooth line smile +} + +function drawJakeFace() { + var isCharging = Bangle.isCharging(); + + // Black circles behind Jake's eyes + g.setColor(0x000000); + g.fillCircle(45, 63, 30); // Left black eye background (x, y, radius) + g.fillCircle(115, 63, 30); // Right black eye background (x, y, radius) + + // Jake's white eyes on top of black circles + g.setColor(0xFFFFFF); // White + g.fillCircle(50, 60, 25); // Left eye (x, y, radius) + g.fillCircle(120, 60, 25); // Right eye (x, y, radius) + + // Eye outlines + g.setColor(0x000000); + g.drawCircle(50, 60, 25); // Left eye outline + g.drawCircle(120, 60, 25); // Right eye outline + + if (isCharging) { + // Lightning bolt eyes when charging (inside the white circles) + drawLightningBolt(50, 60, 8, 15); // Left lightning bolt (x, y, width, height) + drawLightningBolt(120, 60, 8, 15); // Right lightning bolt (x, y, width, height) + } + + // Jake's jowls - horizontal pointed oval (like an eye shape) + g.setColor(0xFFFF00); // Yellow + g.fillEllipse(130, 140, 45, 65); // Main jowl oval (center x, center y, width, height) + + // Jowl outline + g.setColor(0x000000); + g.drawEllipse(130, 120, 45, 65); // Main jowl outline (center x, center y, width, height) + g.drawEllipse(45, 130, 70, 77); // Left droop outline + g.drawEllipse(105, 130, 130, 77); // Right droop outline + + g.setColor(0xFFFF00); + g.fillEllipse(47, 125, 68, 75); // Inner left droop oval (center x, center y, width, height) + g.fillEllipse(107, 125, 128, 75); // Inner right droop oval (center x, center y, width, height) + + // Black horizontal oval nose + g.setColor(0x000000); + g.fillEllipse(107, 105, 68, 80); // Nose oval (center x, center y, width, height) +} + // g.fillEllipse(105, 105, 68, 80); // Nose oval (center x, center y, width, height) + +function drawCartoonFace() { + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + var character = settings.character || "BMO"; + + if (character === "Finn") { + drawFinnFace(); + } else if (character === "Jake") { + drawJakeFace(); + } else { + drawBMOFace(); // Default BMO face + } +} + +// Global variables for randomizer +var randomizerTimeout = null; +var currentCharacter = null; + +// schedule a draw for the next minute +var drawTimeout; +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +function clearIntervals() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + if (randomizerTimeout) { + clearTimeout(randomizerTimeout); + randomizerTimeout = null; + } +} + +// Start character randomizer +function startCharacterRandomizer() { + clearIntervals(); + + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + var interval = settings.randomizerInterval || 0; + + if (interval === 0) return; // Off + if (interval === 4) return; // On Wake - handled in lock event + + var intervals = [0, 5, 10, 30]; // minutes + var intervalMs = intervals[interval] * 60 * 1000; + + if (intervalMs > 0) { + randomizerTimeout = setTimeout(function() { + cycleCharacter(); + startCharacterRandomizer(); // Restart timer + }, intervalMs); + } +} + +// Cycle to next character +function cycleCharacter() { + var characters = ["BMO", "Finn", "Jake"]; + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + var currentIndex = characters.indexOf(currentCharacter || settings.character || "BMO"); + var nextIndex = (currentIndex + 1) % characters.length; + currentCharacter = characters[nextIndex]; + + // Update settings + settings.character = currentCharacter; + require("Storage").writeJSON("bmoface.settings.json", settings); + + // Redraw + if (Bangle.isLocked()) { + drawLockedScreen(); + } else { + draw(); + } +} + +function drawClock() { + g.setFont("7x11Numeric7Seg", 3); + g.setColor(0, 0, 0); // Black text directly on green background + // Top-center time + var t = require("locale").time(new Date(), 1); + var tx = (g.getWidth() - g.stringWidth(t)) / 2; + g.drawString(t, tx, 8); + g.setFont("6x8", 2); + g.drawString(require("locale").dow(new Date(), 2).toUpperCase(), 18, 140); + g.setFont("6x8", 2); + g.drawString(require("locale").month(new Date(), 2).toUpperCase(), 77, 126); + g.setFont("6x8", 2); + const time = new Date().getDate(); + g.drawString(time < 10 ? "0" + time : time, 78, 145); +} + +function drawBattery() { + bigThenSmall(E.getBattery(), "%", 146, 8); +} + +function getTemperature(){ + try { + var temperature = E.getTemperature(); + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + var useFahrenheit = settings.tempUnit === "F"; + + if (useFahrenheit) { + temperature = (temperature * 9/5) + 32; + return Math.round(temperature) + "F"; + } else { + var formatted = require("locale").temp(temperature).replace(/[^\d-]/g, ''); + return formatted; + } + } catch(ex) { + print(ex) + return "--" + } +} + +function getSteps() { + var steps = Bangle.getHealthStatus("day").steps; + steps = Math.round(steps/1000); + return steps + "k"; +} + +function drawBorders() { + // Top border - thin dark teal/green line + g.setColor(0.1, 0.4, 0.3); // Dark teal/green + g.fillRect(0, 0, g.getWidth(), 6); + + // Bottom border - thicker bar (no progress indicator) + g.fillRect(0, g.getHeight() - 8, g.getWidth(), g.getHeight()); +} + +function draw() { + queueDraw(); + + // Clear to character-appropriate background + g.clear(); + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + var character = settings.character || "BMO"; + + if (character === "Finn") { + g.setColor(0.1, 0.3, 1.0); // Light blue for Finn + } else if (character === "Jake") { + g.setColor(1.0, 1.0, 0.0); // Yellow for Jake + } else { + g.setColor(0.35, 0.78, 0.45); // Light green for BMO + } + g.fillRect(0, 0, g.getWidth(), g.getHeight()); + + // Draw borders (only for BMO, not Finn or Jake) + if (character === "BMO") { + drawBorders(); + } + + // Draw cartoon face + drawCartoonFace(); + + // Draw AdvCasio information like the original + g.setColor(0x000000); // Black text + + g.setFontAlign(-1,-1); + g.setFont("6x8", 2); + // Temperature - upper left + g.drawString(getTemperature(), 6, 6); + + // Steps - bottom right + var stepsStr = getSteps(); + var sx = g.getWidth() - g.stringWidth(stepsStr) - 6; + var sy = g.getHeight() - g.getFontHeight() - 6; + g.drawString(stepsStr, sx, sy); + + // Heart rate just above steps + var hr = Bangle.getHealthStatus().bpm || Bangle.getHealthStatus("last").bpm; + var hrStr = (hr && isFinite(hr)) ? String(Math.round(hr)) : "--"; + var hx = g.getWidth() - g.stringWidth(hrStr) - 6; + var hy = sy - g.getFontHeight() - 2; + g.drawString(hrStr, hx, hy); + + g.setFontAlign(-1,-1); + drawClock(); + drawBattery(); + + // Hide widgets + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} +} + +// Draw BMO's locked face +function drawBMOLockedFace() { + // BMO horizontal mouth slit + g.setColor(0x000000); + g.fillRect(60, 90, 120, 83); +} + +// Draw Finn's locked face +function drawFinnLockedFace() { + // Black outlines on top + g.setColor(0x000000); + g.drawEllipse(150, 100, 20, 10); // Face outline + g.drawCircle(85, 85, 85); // Hood outline + + // Gray hood bottom rectangle (same as white one but gray) + g.setColor(0.8, 0.8, 0.8); // Same gray as lock screen background + g.fillRect(2, 102, 168, 180); // Squared hood bottom (x1, y1, x2, y2) + + // Finn's shorter horizontal mouth slit + g.setColor(0x000000); + g.fillRect(70, 85, 105, 83); +} + +// Draw Jake's locked face +function drawJakeLockedFace() { + // Black jowl outlines on top + g.setColor(0x000000); + g.drawEllipse(130, 120, 45, 65); // Main jowl outline + + g.setColor(0.8, 0.8, 0.8); // Same gray as lock screen background + g.fillEllipse(130, 140, 45, 65); // Main jowl oval + + g.setColor(0x000000); + g.drawEllipse(45, 130, 70, 77); // Left droop outline + g.drawEllipse(105, 130, 130, 77); // Right droop outline + g.setColor(0.8, 0.8, 0.8); // Same gray as lock screen background + g.fillEllipse(47, 125, 68, 75); // Inner left droop oval + g.fillEllipse(107, 125, 128, 75); // Inner right droop oval + + // Jake's upside-down V mouth (^) - two intersecting lines, centered on nose + g.setColor(0x000000); + g.drawLine(65, 120, 85, 85); // Left line: bottom-left to apex + g.drawLine(105, 120, 85, 85); // Right line: bottom-right to apex + + // Black horizontal oval nose + g.setColor(0x000000); + g.fillEllipse(95, 95, 75, 80); // Nose oval (center x, center y, width, height) +} + +// Draw the sleeping overlay version when locked +function drawLockedScreen() { + // Light gray background like LCD + g.clear(); + g.setColor(0.8, 0.8, 0.8); + g.fillRect(0, 0, g.getWidth(), g.getHeight()); + + // Get character setting first + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + var character = settings.character || "BMO"; + + // Draw borders only for BMO + if (character === "BMO") { + drawBorders(); + } + + // Schedule next update for time refresh + queueDraw(); + + var isCharging = Bangle.isCharging(); + + if (isCharging) { + // Lightning bolt eyes when charging (even when locked) + if (character === "Jake") { + // Jake's lightning bolts in white eye circles + g.setColor(0xFFFFFF); // White eye background + g.fillCircle(50, 60, 25); // Left eye + g.fillCircle(120, 60, 25); // Right eye + g.setColor(0x000000); + g.drawCircle(50, 60, 25); // Left eye outline + g.drawCircle(120, 60, 25); // Right eye outline + drawLightningBolt(50, 60, 8, 15); // Left lightning bolt + drawLightningBolt(120, 60, 8, 15); // Right lightning bolt + } else { + // BMO/Finn lightning bolts + drawLightningBolt(32, 55, 12, 20); // Left lightning bolt (x, y, width, height) + drawLightningBolt(139, 55, 12, 20); // Right lightning bolt (x, y, width, height) + } + } else { + // Sleeping face: horizontal slits + g.setColor(0x000000); + if (character === "Jake") { + // Jake's sleeping eyes in white circles + g.setColor(0xFFFFFF); // White eye background + g.fillCircle(50, 60, 25); // Left eye + g.fillCircle(120, 60, 25); // Right eye + g.setColor(0x000000); + g.drawCircle(50, 60, 25); // Left eye outline + g.drawCircle(120, 60, 25); // Right eye outline + // Horizontal slits inside the white circles + g.fillRect(30, 60, 70, 63); // left slit + g.fillRect(100, 60, 140, 63); // right slit + } else { + // BMO/Finn sleeping eyes + g.fillRect(22, 55, 42, 58); // left slit: y fixed by height of 3 px + g.fillRect(129, 55, 149, 58); // right slit + } +} + + // Draw character-specific locked faces + if (character === "Finn") { + drawFinnLockedFace(); + } else if (character === "Jake") { + drawJakeLockedFace(); + } else { + drawBMOLockedFace(); + } + + // Redraw information in black at same positions + g.setColor(0x000000); + g.setFontAlign(-1,-1); + g.setFont("6x8", 2); + g.drawString(getTemperature(), 6, 6); + + var stepsStr = getSteps(); + var sx = g.getWidth() - g.stringWidth(stepsStr) - 6; + var sy = g.getHeight() - g.getFontHeight() - 6; + g.drawString(stepsStr, sx, sy); + + var hr = Bangle.getHealthStatus().bpm || Bangle.getHealthStatus("last").bpm; + var hrStr = (hr && isFinite(hr)) ? String(Math.round(hr)) : "--"; + var hx = g.getWidth() - g.stringWidth(hrStr) - 6; + var hy = sy - g.getFontHeight() - 2; + g.drawString(hrStr, hx, hy); + + g.setFontAlign(-1,-1); + drawClock(); + drawBattery(); + + // Keep widgets hidden + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} +} + +Bangle.on("lcdPower", (on) => { + if (on) { + draw(); + } else { + clearIntervals(); + } +}); + +Bangle.on("lock", (locked) => { + clearIntervals(); + if (locked) { + drawLockedScreen(); + } else { + // Check if "On Wake" randomizer is enabled + var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; + if (settings.randomizerInterval === 4) { + cycleCharacter(); + } + draw(); + startCharacterRandomizer(); + } +}); + +Bangle.setUI("clock"); + +// Load widgets, but don't show them +Bangle.loadWidgets(); +require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe + +// Initialize current character from settings +var settings = require("Storage").readJSON("bmoface.settings.json", 1) || {}; +currentCharacter = settings.character || "BMO"; + +// Start character randomizer +startCharacterRandomizer(); + +g.clear(); +draw(); \ No newline at end of file diff --git a/apps/bmoface/app.png b/apps/bmoface/app.png new file mode 100644 index 0000000000000000000000000000000000000000..cb52e9f1b7c26effb5a928c46b887950d45710d4 GIT binary patch literal 1729 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 Dl5u7? literal 0 HcmV?d00001 diff --git a/apps/bmoface/screenshot2.png b/apps/bmoface/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..5834256113ee3b5ab3ff54662d1ef2aaf6843b25 GIT binary patch literal 4259 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 literal 0 HcmV?d00001 diff --git a/apps/bmoface/screenshot3.png b/apps/bmoface/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..f1cbc687213d2861067d797042b6299b94db1696 GIT binary patch literal 6106 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 literal 0 HcmV?d00001 diff --git a/apps/bmoface/screenshot4.png b/apps/bmoface/screenshot4.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ba4fd1d34371dae054c0cbbc4fd17375c781bd GIT binary patch literal 3893 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 DPcdvu literal 0 HcmV?d00001 diff --git a/apps/bmoface/settings.js b/apps/bmoface/settings.js new file mode 100644 index 0000000000..5269c27f31 --- /dev/null +++ b/apps/bmoface/settings.js @@ -0,0 +1,47 @@ +(function(back) { + var FILE = "bmoface.settings.json"; + + // Load settings with proper defaults + var settings = Object.assign({ + character: "BMO", + tempUnit: "F", + randomizerInterval: 0 // 0=off, 1=5min, 2=10min, 3=30min + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + // Show the menu + E.showMenu({ + "" : { "title" : "BMO Face Settings" }, + "< Back" : back, + 'Character': { + value: 0 | ["BMO", "Finn", "Jake"].indexOf(settings.character), + min: 0, max: 2, + format: v => ["BMO", "Finn", "Jake"][v], + onchange: v => { + settings.character = ["BMO", "Finn", "Jake"][v]; + writeSettings(); + } + }, + 'Temperature Unit': { + value: settings.tempUnit === "F" ? 1 : 0, + min: 0, max: 1, + format: v => v ? "Fahrenheit" : "Celsius", + onchange: v => { + settings.tempUnit = v ? "F" : "C"; + writeSettings(); + } + }, + 'Character Randomizer': { + value: settings.randomizerInterval, + min: 0, max: 4, + format: v => ["Off", "5 min", "10 min", "30 min", "On Wake"][v], + onchange: v => { + settings.randomizerInterval = v; + writeSettings(); + } + } + }); +})(back); \ No newline at end of file From 1da274f7f5c4587a039ce9ecbd287b9b1ac0df32 Mon Sep 17 00:00:00 2001 From: LucienStorm Date: Mon, 20 Oct 2025 18:39:53 -0500 Subject: [PATCH 2/4] Add files via upload Committing BMOface, Doomguy, and Mr MeSeeks, hopefully all errors have finally been cleared. --- apps/bmoface/ChangeLog | 5 +- apps/bmoface/README.md | 9 +- apps/bmoface/app-icon.js | 2 +- apps/bmoface/metadata.json | 5 +- apps/doomguy/ChangeLog | 13 + apps/doomguy/README.md | 78 +++++ apps/doomguy/app-icon.js | 1 + apps/doomguy/app.js | 499 +++++++++++++++++++++++++++++++ apps/doomguy/app.png | Bin 0 -> 4466 bytes apps/doomguy/data.json | 1 + apps/doomguy/doomguy.settings.js | 66 ++++ apps/doomguy/metadata.json | 23 ++ apps/doomguy/screenshot01.png | Bin 0 -> 5470 bytes apps/meseeks/ChangeLog | 5 + apps/meseeks/README.md | 59 ++++ apps/meseeks/app-icon.js | 1 + apps/meseeks/app.js | 385 ++++++++++++++++++++++++ apps/meseeks/app.png | Bin 0 -> 5987 bytes apps/meseeks/data.json | 1 + apps/meseeks/metadata.json | 17 ++ apps/meseeks/screenshot01.png | Bin 0 -> 8931 bytes apps/meseeks/screenshot02.png | Bin 0 -> 8516 bytes apps/meseeks/screenshot03.png | Bin 0 -> 5482 bytes 23 files changed, 1164 insertions(+), 6 deletions(-) create mode 100644 apps/doomguy/ChangeLog create mode 100644 apps/doomguy/README.md create mode 100644 apps/doomguy/app-icon.js create mode 100644 apps/doomguy/app.js create mode 100644 apps/doomguy/app.png create mode 100644 apps/doomguy/data.json create mode 100644 apps/doomguy/doomguy.settings.js create mode 100644 apps/doomguy/metadata.json create mode 100644 apps/doomguy/screenshot01.png create mode 100644 apps/meseeks/ChangeLog create mode 100644 apps/meseeks/README.md create mode 100644 apps/meseeks/app-icon.js create mode 100644 apps/meseeks/app.js create mode 100644 apps/meseeks/app.png create mode 100644 apps/meseeks/data.json create mode 100644 apps/meseeks/metadata.json create mode 100644 apps/meseeks/screenshot01.png create mode 100644 apps/meseeks/screenshot02.png create mode 100644 apps/meseeks/screenshot03.png diff --git a/apps/bmoface/ChangeLog b/apps/bmoface/ChangeLog index 04e533410c..0511931c9d 100644 --- a/apps/bmoface/ChangeLog +++ b/apps/bmoface/ChangeLog @@ -8,4 +8,7 @@ 0.0.08: Fixed lock screen character variable error, separated lock screen logic 0.0.09: Improved lock screen character-specific drawing and positioning 0.0.1: Major release with all core features complete -0.1.1: Code refactoring and lock screen improvements \ No newline at end of file +0.1.1: Code refactoring and lock screen improvements + +## Attribution +Based on the Advanced Casio Clock by dotgreg (https://github.com/dotgreg/advCasioBangleClock) \ No newline at end of file diff --git a/apps/bmoface/README.md b/apps/bmoface/README.md index 44d496a845..13a46d8f3b 100644 --- a/apps/bmoface/README.md +++ b/apps/bmoface/README.md @@ -43,6 +43,11 @@ Bangle.emit("lock"); // Triggers "On Wake" randomizer Installation Upload via Bangle.js App Loader or manually install the files in the `bmoface` folder. -Attribution -Character inspiration: BMO, Finn, and Jake from Adventure Time (Cartoon Network) +## Attribution + +**Character Inspiration**: BMO, Finn, and Jake from Adventure Time (Cartoon Network) + +**Code Base**: Based on the Advanced Casio Clock by [dotgreg](https://github.com/dotgreg/advCasioBangleClock) +- Original template: [Advanced Casio Clock](https://github.com/dotgreg/advCasioBangleClock) +- Creator: [dotgreg](https://github.com/dotgreg) diff --git a/apps/bmoface/app-icon.js b/apps/bmoface/app-icon.js index 012efd739c..b69774dd79 100644 --- a/apps/bmoface/app-icon.js +++ b/apps/bmoface/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("2GwgkIAH4AW+4A/AC0ItAA/ACqX/V/6v/AH6v/V/6v/AC1ggAADEiobQCAYOHOzw6EgAbV+AbEs4sNV/4bSsAKDAgIGEV7qRBA4tgg4RhVwQEFAILCDV7iRBDwqUJCLKvIA4qv/V6P3DQivcgCdKS4IFDCJYjNV5IAEV9ALBgFnV8nwBgivcUYKvPCJYjNV5IHEV9YFEV8EH+AbDV7iiETowLBAoqvPCI4AJB4iv/V5QAMV7lgTpYKECJgjMBIQIDAgivrCL4ABBAgNHV7j6BTp4RZV9aXCGwIACCLqvxRoYADEhYRRAA6v/V/4ADDwqEHCKZnBBQ6vrRI0HCLPwXZCvrRJQRWV5IKCAAIMHV9CXBWpavTCgIACBY6voRgQrKV5IWMABKv/V5YALV9DjCV6jHBV/6v/V6qXBV6oWMV+QRXV/4RXY4Kv/V/6XMgAADEjcIDiqpfAAjUkV/4AlRWSv/AHiX/V/6v9sEAAAMHTV/wGgUAV7hWDAALCuGgo1PPCAABsCutGgrmPMxZ5GWFo0Hgw1NVyIACV2SwPMpR5HWFo1IV7BWIPRwAcchLlNV/40JGpqv/V/4AXKxKv/V/4AlGhKv/V/4AlKxKv/V/6wvGhp6UV1IABRpDkNMpUIV2aviWBCurAAKuUV5Z7HV1gABsA1UPaJ4OAELmECh6cPhCtuGYgBCAB6cvAE6eyAEiX/V/6v/AH6v/V/6v/AH6v/V/4A/OrvgAAXnCZ3wCgav8sEAAAojMCgznfVr6xPVoixiO7SZBg4ACTxisECoYWCWLpxZTIP/AAPwAAShHAA4RBDAbFMV9dgg8PH4QAB+6yGAAwVHV/CXBIAgAWYwSv1VwKZGACrFCWDhwYR4Kve+HnV+kAV4IABKzAcDVzavZVwIAFVaoAD8Cv0sCSDABUPUgoAKgA7YV8YAZV+sATpwARV/6v/ABtgV/6v/V90AV/6vXWECv1sCu8V7KOBVz/nV+kAgCUDu4ABVKITED4Kv1+/gWAS5FABgSHDwKubV7NosCxCs6vCACiufV7SRCSTCuD86v2hCSBWAKuWuAbCV+6wDSa6ugV7QABSgSvWV0CvbAAKVXVwStdV7tosCXCWSIVDVryveWIYAHXIQMJVr6veAAUIWYgANhCtgV8AAD+CnJW4oAjPUSzBAASoGVUavnAGh/nAF6X/V/6v/AH6v/V/6v/AH6v/V/4A/S/6v/V/4A/V/6v/V/4A/V+/wgACDsEAg6v/ACgtpV86nBg6qDV06vuADVggAAChAFFV9VnAIICBAwYAXKAcAAoyvLsAJEAoJ3IZKDasN5IFGO5CONg4BBVYYGBAEyvRA4wQGAG6vRBo6wN+AOBAQX3WYav+WHqvZWBwAuV/6v/sEABwlgV/JABgAKBV6AVEAwTDnV6IACV6KnDAYR0BV+YCEW46vNU4YDCWgqvvAQi3HV6YBBV+YBHV7IBBCZavnAI6vWsATPV8ySDAgSvITRgcCgAgEV+KOEV5SaMV4IBBV+ynGWQIACAoaZMBoLJFV7QyED5CvJAoxWDAoh+MsEGEIqvaGQgfIP7IAMRY6vZDoqvRADtgVYyvZDoqvwVYyv/V/6v/V5lgEoIFDEQivmWAMARQQECWDAYCDgQFDV9awBAAIqBAgS4DV6wBHBwivnAECrDAIqvsAEFgZIStCZ46m/V5KoCVoSuGV/6vKJISvCAISv/V5wDEAIav/V6oIEV/6vSWAyv/WBUAgCsFWAim/WBQABWo6v/ADSl/AC6v/V/6v/AH6v/V/6v/AH6v/V/4A/A=")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwgJC/AD8f/F4vE/wEf/l8vF/4Ef/18/H/8Een18/PzAoMeAoPh+Eenl+/PA+AdBv/7Aom/AoX+u4FCEYIFEjwFEh9zj4LDuEd8I7C+EdHYIjB+Ec/5NB/gFE/AFBn6k/ADQA==")) \ No newline at end of file diff --git a/apps/bmoface/metadata.json b/apps/bmoface/metadata.json index 875b06b87b..cfedf2e3f3 100644 --- a/apps/bmoface/metadata.json +++ b/apps/bmoface/metadata.json @@ -2,10 +2,10 @@ "id": "bmoface", "name": "BMO Face", "shortName": "BMO", - "version": "0.1.1", + "version": "0.1.2", "description": "A watch face inspired by BMO that shows time, temp, steps and HR. Sleeps to -_- when locked.", "icon": "app.png", - "tags": ["clock"], + "tags": "clock", "type": "clock", "supports": ["BANGLEJS", "BANGLEJS2"], "allow_emulator": true, @@ -18,6 +18,7 @@ ], "storage": [ { "name": "bmoface.app.js", "url": "app.js" }, + { "name": "bmoface.img", "url": "app-icon.js", "evaluate": true }, { "name": "bmoface.settings.js", "url": "settings.js" } ], "data": [ diff --git a/apps/doomguy/ChangeLog b/apps/doomguy/ChangeLog new file mode 100644 index 0000000000..850baa4ec5 --- /dev/null +++ b/apps/doomguy/ChangeLog @@ -0,0 +1,13 @@ +0.01: Initial Doomguy watch face +0.02: Added animated Doomguy face that changes with battery level +0.03: Face animation - Doomguy looks left, right, and center +0.04: Added heart icon in lower right corner +0.05: Added yellow lightning bolt charging indicators in lower left +0.06: Added "BATT" label above battery percentage in white text +0.07: Changed date text color to yellow +0.08: Optimized memory usage with 4-bit color sprites and heatshrink compression +0.09: Added interactive tap feature - tap Doomguy's face to flash yellow and show damage, daily hit counter with persistent storage +0.10: Added temperature unit settings (Fahrenheit/Celsius toggle) + +## Attribution +Based on the Advanced Casio Clock by dotgreg (https://github.com/dotgreg/advCasioBangleClock) diff --git a/apps/doomguy/README.md b/apps/doomguy/README.md new file mode 100644 index 0000000000..ddcc9010e8 --- /dev/null +++ b/apps/doomguy/README.md @@ -0,0 +1,78 @@ +# Doomguy Clock + + + +A DOOM-inspired watch face featuring the iconic Doomguy face that reacts to your battery level! + +## Features + +### Dynamic Doomguy Face +- **Battery-Reactive**: Doomguy's face changes based on your battery level: + - 80-100%: Normal face + - 60-80%: Slightly damaged + - 40-60%: More damaged + - 20-40%: Heavily damaged + - 0-20%: Critical damage + - **Charging**: God mode (invincibility face)! + +### Face Animation +- Doomguy periodically looks left, right, and center +- Animation occurs every 2-3 seconds when unlocked +- Pauses when watch is locked to save battery + +### HUD Display +- **Time**: Large red digital time display +- **Date**: Yellow date text (day of week, month, day) +- **Battery**: Shows percentage with "BATT" label +- **Heart Rate**: Current BPM displayed with heart icon +- **Steps**: Daily step count +- **Temperature**: Current watch temperature +- **Charging Indicator**: Yellow lightning bolts appear when charging + +### Visual Elements +- **Heart Icon**: Red heart in lower right corner +- **Lightning Bolts**: Two yellow triangles in lower left when charging +- **Gray HUD Panels**: Left (battery) and right (stats) panels +- **Hit Counter**: Displays daily tap count + +## Interactive Features + +### Tap to Hit +- **Tap Doomguy's Face**: Interactive hit counter + - Screen flashes yellow twice + - Face shows damage reaction (damaged2_center) + - Hit counter increments + - Counter resets automatically each day + - Hit count persists through app restarts + +## Controls + +- **Tap Face**: Trigger hit animation and increment daily counter +- **Swipe Down**: Show widgets +- **Lock Watch**: Pauses face animation to save battery +- **Unlock Watch**: Resumes face animation + +## Technical Details + +- Uses 4-bit color depth for memory efficiency +- Heatshrink compression for sprite storage +- 16 different face sprites (5 damage levels × 3 directions + 1 god mode) +- Each sprite: 60×60 pixels +- Optimized for Bangle.js 2 + +## Memory Optimization + +This watch face uses advanced memory optimization techniques: +- Sprites stored as compressed 4-bit palette images +- On-demand decompression +- Efficient animation timer management +- Persistent storage for daily hit counter +- Minimal memory footprint for smooth operation + +## Credits + +**Character Inspiration**: Inspired by the classic DOOM game's status bar face by id Software. + +**Code Base**: Based on the Advanced Casio Clock by [dotgreg](https://github.com/dotgreg/advCasioBangleClock) +- Original template: [Advanced Casio Clock](https://github.com/dotgreg/advCasioBangleClock) +- Creator: [dotgreg](https://github.com/dotgreg) diff --git a/apps/doomguy/app-icon.js b/apps/doomguy/app-icon.js new file mode 100644 index 0000000000..fafa4d9d0b --- /dev/null +++ b/apps/doomguy/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("nk8wkHu4A/AH4A/AEdyCidRqNUoICBokVAAIbRuoUBilBolFogACEYNXDp8hGwQADkgiBqlFiMnDp0FiocF6Q6BokUHiBXBDYVD6QcBHQNRPYMHLCVC6XT6YeCop4BqSUPK4ctmYdB6lBTgUQDptwqITBoVNnoACkgbBaiFxqh3BD4NDLIjZBHZ5ZBNoIXBHgMtHQIABqo7QVAQ9Bmi0CHgMUiJ3RAAI7CHINC6jSBHYMFHZ9RqsUpZVCEAURBYNQHZ1QiDTEHYZ1BgMBHZ0FspZCPYchoJkCHZ11sISBqjTBoIDBoruBiALBSp9QG4LTBAgYcDHZw5CDANRHQJ8BHQIKCiFCDhd0F4NEEAVFEANUAQIDBX4IdNCoQ0Bio7CSwKxBH4MRDpoZBWAQABOoNUpdD6XSHYNEDplQilC6SsCqjOBok9AAIFBiTuMLINDCYKxCokEonTAAJGBqhZNC4JaEAoQACHYKVPoq0BqFVisRooZBqT3BXgIdLuQdBoOyqsAZgIfBLwNbIoUiDpd3FwIAB2lLqqzBrkcpckLQQcMu52BloSBCoPTmfSogKBoRZBDpoZB6ckGYMjV4QeBoVNkg7PqVN+c9mY6BmYEE6kVDpt3GIIVB6fULIQCBnphBq4dOqlEoZVBAQM+klNns9MQMXHZ4dBns8TQIZBpYHBBYNHDpypBGgNEqo8BotU7s0XoJZPukUoStBqI1BqtUkfUQYM3Dp11oI7BknFqkUqtLpstkh2PHgVC2m0qNVqPB4lLoVFDiA8BKoJWBPoMcim0OwIdRuNEpYACldEDgMkHaTxCnpYBqtVoVE6KTPeQvTplCoScBkjsPDo0k4Wynu02XUDqqXBqlNmlFokTDijUCrkU6jRBDiy2BqPCoNciIdXAH4A/AH4AFA==")) \ No newline at end of file diff --git a/apps/doomguy/app.js b/apps/doomguy/app.js new file mode 100644 index 0000000000..7698c6b20d --- /dev/null +++ b/apps/doomguy/app.js @@ -0,0 +1,499 @@ +const storage = require('Storage'); + +require("Font6x12").add(Graphics); +require("Font8x12").add(Graphics); +require("Font7x11Numeric7Seg").add(Graphics); + +// Load settings from storage +function loadSettings() { + return storage.readJSON("doomguy.settings.json", true) || { + faceMetric: "battery", + tempUnit: "C" + }; +} + +// Reset hit counter +function resetHitCounter() { + hitCount = 0; + saveHitCounter(); +} + +function bigThenSmall(big, small, x, y) { + g.setFont("7x11Numeric7Seg", 2); + g.drawString(big, x, y); + x += g.stringWidth(big); + g.setFont("8x12"); + g.drawString(small, x, y); +} + + +// schedule a draw for the next minute +var drawTimeout; +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function clearIntervals() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + stopFaceAnimation(); +} + +function drawClock() { + g.setFont("7x11Numeric7Seg", 3); + g.setColor(1, 0, 0); + g.drawString(require("locale").time(new Date(), 1), 70, 10); + g.setFont("8x12", 2); + // Yellow color for date + g.setColor(1, 1, 0); + g.drawString(require("locale").dow(new Date(), 2).toUpperCase(), 8, 8); + g.setFont("8x12"); + const time = new Date().getDate(); + g.drawString(time < 10 ? "0" + time : time, 50, 8); + g.setFont("8x12", 1); + g.drawString(require("locale").month(new Date(), 2).toUpperCase(), 8, 30); + g.setFont("8x12", 2); +} + +function drawBattery() { + // Draw "Batt" label in white + g.setFont("6x8", 2); + g.setColor(1, 1, 1); + g.drawString("BATT", 5, 95); + + // Draw battery percentage in red + g.setColor(1, 0, 0); + g.setFont("8x12", 3); + bigThenSmall(E.getBattery(), "%", 8, 120); + + // Draw lightning bolt (two yellow triangles) for charging indicator + if (Bangle.isCharging()) { + g.setColor(1, 1, 0); // Yellow + // First triangle (left bolt) + g.fillPoly([ + 20, 155, // Top vertex + 5, 155, // Bottom left vertex + 20, 165 // Bottom right vertex + ]); + // Second triangle (right bolt) + g.fillPoly([ + 20, 148, // Top vertex + 20, 160, // Bottom left vertex + 35, 160 // Bottom right vertex + ]); + } +} + + +function getTemperature(){ + try { + var temperature = E.getTemperature(); + var settings = require("Storage").readJSON("doomguy.settings.json", 1) || {}; + var useFahrenheit = settings.tempUnit === "F"; + + if (useFahrenheit) { + temperature = (temperature * 9/5) + 32; + return Math.round(temperature) + "F"; + } else { + var formatted = require("locale").temp(temperature).replace(/[^\d-]/g, ''); + return formatted || "--"; + } + } catch(ex) { + print(ex) + return "--" + } +} + +function getSteps() { + var steps = Bangle.getHealthStatus("day").steps; + steps = Math.round(steps/1000); + return steps + "k"; +} + + +// Doomguy face sprites - stored as base64 strings (NOT decompressed yet!) +// We'll decompress ONE at a time when drawing to save memory +var doomguySprites = { + normal_center: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AG91ioABoNFAIVRqNXDqNxqlEAAtUisXDZ9yGINBDAMtnstklEHgVRDp0RqI1CDYYACotFisSDptRK4VNDgtBHgUCDpsEig8BDYNNDwUUBINRgodNOwNUoo2CDgR1DqEWPBsBCYSwEiJzBAAMBgsAahlQDocUAIVVDgRYBiEVg47OorRBoNVoMUqhaBHwMFeRtQGIIaCAINUXQRBBJAQ7PHII2BLIIAEHwNQO5w0BZQNEAgNCDoaZCHZxSDAANCpYeEHgNnDpZYBqlC6XSd4O0olNkmyBIJ3OgtkilDDoPS6gcConT6fUT4IdMiCUBpsz6Y8BHoND6c9nohBaJrgBoktmYWBmgeB6Q6BAwKWBHZtUik9mfjDAIZBIIMzmZDBO5lyqg7BAAJ5BLwIBBloDBWYVSm4dJuhKBoruBppYBkhyBkb4BYAIBBo4dKFgNEotRiNVIIImBqrdCSoMUDpYNBJoMBiK5CC4IFBiRABiNEHZgWBkQdCisj6gbBgMiMINBLJd1KQIvBnapBonUmhjCDgNCBQNXHZRSCok9EAIDBnoDBpYIBpaZBi4dKilC2fSZ4LOBdwIFCoj2BoizMHYI1Bnstmcz6YeBAwQdCiqzMpoTDAAXjAgZfCHZd3cINC6g2CAQIjBAoRbBoJ2KAAKzBOYR0CGwMtMQSeCWRQABWYU0GwPUAgLLB6c+EIMkoIdMu8UVAU9mqvCoK3EoQcMu9EklDGYIaBDwVEPAM0Dp9UOQPTAQIbCoXT7sz6lLogdNig7BDwNDPQNDewQ7SO4KsCeYT2D6ktiQdNudEltDolUWgNNLgTRCDht3uVEoYaBAAPU6geC6SzBDp9UppvBAIK3BmgFBOwNFDp13uhQBKINCHAIkDkgcPLQZRBLgS7C6SxOAAZPBWoI3BAQQ6Bo4dRu61CZ4LQBSQIcTu8VOYLwBHgVEi4dTeYTuDoIbUAAk3DTIA/AH4AKA=")) + }, + normal_left: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AHFRAANUigBBAwVXDaFykNUogAB6QDColRqUnDp91HANEoXTofTD4NBHgNQDh8RDgfS6g7DokVisXDptwqlBC4ckAYUUio7BPJ1xqIVBDYlBqlULIMBg6wPoodBHAdFiIKBgsFsoeNgprBLYglCBIMBso8OiAWBN4KOBSAUVBQMFgNRDpocBqlFDQLMBLodFAwKWOLINBR4IBBDgZgBIAQ7NB4KPBK4TWED4I7BeBo7BC4lE2lCLYg7PZ4ND6VElskoXU2gEBkiFBaJwdB6QABGoICC6fT6lBLJztBoU9mYeCklD6c9nskLJ8BR4JZB6YeB6lNEgM9mieBDptVitQgtEGoIABmZYBmZZBO5osBO4NFgtDG4QDBltViLcCDptBosRgFEmndHQQLBDYNRqg7PqNQgEEaANQDYILCAQIdLNANEoMAkURgsViIiBgMiktEigdMBwJ2BqMioMBqhxBEIMikgqBO5hnBojRCIANEltBOgM9olCFQIdLosUDYPSDYIYBmYECoVCBQJ3NHIPTpskofUWQQZBpr1BoKzMHYPS6YTBnv9mYeBAoLVDDpl0SoM9HoIWCAQI+EosXDpdySoQVBAAQbCHgMtWgIdPodDDINEPQJ1Bmc9DgI7Nu9xCoMj6fUWASxBn09mlEo4cMPALpBGYR9BGoJhBmYlBDp11lstN4Q0BMAPS6g7B6dXDp1CoSqBVoS4BbARZQuNNpoWCLgLyBAwU9WRoACkkkVQVNSwaBBBAIcODoNNCgQeBD4a7CDp8loVDRwM9ZoKbEoIdPu43BNwIAEDwMkDiDxCGwJbCXQK4BoQdRu8UC4IABLAQjBdpw8Fig3BmczHINEqYcSu9ykXSHgctkUnDqaYCAAdHDaoA/AH4A/AEoA=")) + }, + normal_right: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AHFRAANUigBCisVi4dSitBogADoNFoNXDaF1isUDQUtlskAgI8BisnDhtyDgdD6fSHoY8BqMSDptwqNFCwPS6g6DokUqNVqAdNuNUCgNCO4o5BqNQiAdNkpZBD4KUFitFiEQqwdNiBZBSoYcBojYCgsBgsCDpkFU4MUDIIBBV4QABHQNRgIdMGISqBDYMUIINUDoI9CiIdMgNRqgBBDgZeDHwRZNFwKUBipzBTIp7DO5yRDAAW0W4kQLJpLBGgjyBkkkAQIeBqqzPoVC6QbBHIPS6ktlskosRLJqQBonT6fUHgM9HAO0ns9HaAdBCgIABDYIGDAoI7PqNEmcz6fSAARCBMAKWBHZsBolNnszHoYABmlFQgLRNolVipMBptDHoMz6U0oD1BHYMVo4dLiNEqNVig+BofTpodBQYQgBDph2BojyBisBqlNisAgAaBSoQdMiqJBkUhiBwBoNRgIHBQgNEigdLoNUVAMimkQgNRDoVCkRIDDpYVBCAND6VUKQNNklUij1DLJlFigbB6QTBki1BAgImB6gBBHZhZBV4MtGQPSWYPUmhFDO4MXHZdEls9dQMzd4XTnoADmhZMuSVB6YAE8YkBAoRkCDhQdBigPBLYIYCAQhIBLIIdLu6tBHgIWB6lCoYkBLYT8BqQdMkI7BPAQiBSQR9BLAUnDpl0GYMzc4L1CKYPdn0tEgIcMu91oaWC6XUDoR0BMINNkodNuNNoTGBZIRfBAAb5BHZ1CWQM9OQIDBAQQjCoIdNPARYC7qtBnpzBofS6SUNDoR3BOgdNoh7BEwNEm4dOuIYBNwJzE6VNklFDhwABVYMtPAPUXAPToZEBo4dQigVBaIoGCi4dQu9UDwJ7BoYcBHSaXCaYQAEoixPS4o3B78zWATsPAA0kkiYBmkkK6YdESgZXUAH4A/AFY")) + }, + damaged1_center: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AG91ioABoNFAIVRqMnDiEUiNEAAVD6gDBosVqNBDp44Cok9AAMkmgeBisUiocOqNUCoNNlskAgI8CqgpBg4dNgsUilEoXSppcCBAIcBgNXLBwxBDwIADilUSoNRqFnDhlwCIJ2BDwIDBG4MRBQMFgMFLRlxCQNVip6BR4LPBA4JYBssQi47MqDtCDQVRZwIACHYNQPBg7CogBBagMFgjQCqMViFRLJh3BqhXBHYKRCAwI/BIYR3Pc4VFSwNRgK2CLwTwNGYUkC4QBB6LWDLgJZNSQLtEAAIjCDoUQSpl1ioSBloYED4hgBSp9C6c9kgfDls9ndEPAKVOolDnoABHAVL6YlBmg7RpszmYXBnYbC+YdBolQO5g7CkgYCHYM0EgPdDgNFiIdLuhoBoLSBLYMkpofBIIL4BihKBDpbDBU4MVqtRqNBoNVqrsBFALgBDpY5CoMRiMQqo6BiERgMSXQIsBLJkUkkSiEhiEBls0qESgMjPAItBShoADAoPT6RFCAAZZMJIMtWAQABeQYABoXTUoIdLGoKvBlpuBDgMz6QcD2S2BSplE2buBdQIDB8czEwIjBntBLJdyDoIYBHAQBCA4IJCltEq4dKu91NoQVCHQXTEAJ7CoMXDpdxCANDDgM0PYM0ps9nzQBWQI7MukUV4Y0BkiZBEoPT6g7Bo4dLu47CKgNFL4XBohaBmlCDht3qkkWIIyBAAVS6g7DDp0U6kj6ZTBdgXCWAMzPgKUMHYh3CLgPSAwfUkgcNPAQ5B6g8C6W0oXS6ZBBDqA0BOwdMAYSVBDqEUGYNCSAPdKwMtlsk6lBDp7oBCwM0OYU0K4KbBk4dPLQLJDolUEgMzDoIcQu90N4JVBkQCBno6Tu9yWoQACWINNkk3DqJ5CHoR4CokXDiR6DZgVCOiQdHAAVFDq4A/AH4A/AAo")) + }, + damaged1_left: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AHFRqNUigBCitBqNXDqUVokUogADotBDqN1isVDgdD6QDBihFBHKA6BAAM9mlNkgGCDwI9Pgo6DHAQACPANFi47QHgQ4DoNBotFiodOgsBWQQfBqKUCEwMQqMFg46OLQVBDoNUiIlBAAUBPBo7BspbCoNQiFFWIQ6BqBaNiFQHQNFKwIgBgNULQUVsJZNgo6BqiPBOga6BBIJ5BLJsQCwdFkgDBKwLvCEgI7OKILqDAgIfBBAbSOOwVEoQfDAAodOgMFDRMkegQdNNwVC6cz6QbCoW0mc9kh3PLANEls9ns0LoQFBnstoKzORYNBHwPT6m9mm+mcz6fSLJtyZAYfBKwIZBolNA4IoBgQdLulFLIIBBHoc9WAUVqkVgodMcoVRgMRC4NE6gjCEgICBDpo5BisDmcRghUBiNQgMSHwQdLuNBSoUSDoNRotEqsQqNCkg/BDpd1DgMtkk7EANUoXSAYNLmh7BLJsRokj6RyBeYYEEmlFDpg7B6fToVEofS6czAYIKC6h3MuiUBok9AAMzAAIFCno7BkhZMu6NBloTBAAfzHAJXBIoMXDpjRCoQXCHoICC6aBCq4dMiqMCkczOQNEV4J6BLANBDpo8BZYI7BWwgeBPANHDht3ilNkgzCDYVRTwU0Dp9UklNVgRXBolblsjBAKUNaYTuBLIJyB6bzB6fdHYIcODoMtCwIACns7obwDDqFEprwBO4NFqiVCIAIdPDwJZBofUH4I3BofS6U3DqI8CHoPzXAIfBnocQeIUkRoJZBLAK7BkgdSu54CHoNNdwM064dTogdBnpYCEQMnDqZ5BeQTxB6VHDiY9DHIR7BDiwdBHoPS6gdYAH4A/AH4AiA")) + }, + damaged1_right: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AH4AWqIABotBAIUVisXDaF1CgNEAAtBEwVHDp1xqNUigaCoQCBoo9SqFFDYo7CLgUQDhtygNBLA46CAAJYQDwMkHgVBqgaBHYU3LBqUCO4dESQQABgsVgIdMiASBio9BqMEohWDgNRgNQdhouBqMUKIMBqg8Eq1VSxsFKwIBBdIYGBSoQ6BDpp2Cog3BK4YjBHwUFgo7PSoY3BAgL4BilRHZ7rED4YHDaINWSptUdQIAGeoJaDDpg1CoYbEEgO0PwazOoktns9GoKRB2k9mfTHgQ7NZIIVBmYeB2kkps9IIdFHZsEonTAAIdBH4M9mhXBfIQ7MqNBqgTColNmfSKgI7DoNRo7QLWYKJBaoNC6fUokRAwI7CogdLqNFiguBGoNUoklisRoERIoQdMG4UiiEAgIkBokAiczkAkBAAMXHZdUilCklFPQcViUybAMkoNFHZcUC4U7LYNEoaUD2b0BEgI7LqsUoaQCpstZ4NNHIL6BaoKzNdwQ4B6dDmfTmfUXAPTa4JZMqNSofSCgIACnofBAgU9a4IdLu6mCDAIVB+c9DQQbBoQNBDhaWBOgIWCkczmgjCmlCQQIdNHYMkCwMk6iTCPIPSDgK+BDplyqnSVIQADps+EoIjBDhgdBoVNGYNEL4NFoktIYNEBIIdOrskO4QzBpkjWYQhBoIdOigbBlqRB6UkdYIdC6UnDpt3RoIACdgPbd4ZYBm4dOujvBSIKsBotNPYIICHZ9xZgSvB6nTEAIIDDp91OIJZCZoIAClskoNHDpxaBCwTvDoZ2CDiA8BoQWBpocBXAM0olCDiB4CHgSxBaAJ5BqYdRu6sBKgMzEIKTBoIcSPIQ9CK4R0RDoskoXSAIIdXAH4A/AH4AGA=")) + }, + damaged2_center: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AH4AWusVitBooBCqNRq4dSuNUogAEqkVi4cRGQNEilEoQcBoI8CqI5QDgIABns9lskHoZbQOoIVBpocBDwg9Bg4dOuFUK4Mk6fT6XSDgVFiodOuFRDgJZCohZEilRqCYNuMFgiyCSgQcFHh1wq0VHgVND4JZBDgIABgIdNusBgodBoI7DDYQ7BqC0NuEQCYNUoNEgLXBSQIABgNWHZ4dBVYIaCoNUAYJ3CSptwGIRxBDYIjBO4ZIBHZ0FSoQ7BigeBXQJDBeB47CDYLMCEIJ8BAAIMBHZw6BDIMkDAQcDAgJZOuBRCAAokBpacCDpsgSYNEkfT2g9D2k0mlBqEDDplFHYXTns9loeB2XT6fUPAMEDphpBHQMzmfj6Q5BnwGBmlEFYI7NdQNVonUmdNkfSmfUopGBUYIdMoAdCqtD6ZdBps9mlRAAYdMcIMViIwBog1BoICBDgZZOilQqkAgtQiNRqoEBgtAQgJZNoNFZQMRilVHAIfBoJCBih6BHZocBoUkXAIYBTwUiBYIhBDplxokiZoNEltDmfSAwc9olXDpl1iisBCgMz6YABAgIgBoVBDpo7BAAMzDgICBEIb4BosXDpl3kgdBnpUBDwIaBoc9BYIcOu8lNoMzEANNn0tqlNmfUklHDpwvBofT6lEkY6B4hDBmlEDqdCVYNNpcUTgM0ppZQoSNB6h2CoS7BAANCWRoACHYXS2jVBldC6QHBok3DqDmBplVokUqnEkizCDh93iiNBkm0d4Q+BofUoIdQujsB6VC7ocBki6CDiF3uTwBGwJTBoidBoYdSHgQ3BTIL2DWKC1FVwLSBTgNCDiaXC6c9SoUkHShbD6XUdaQA/AH4A/AFQA=")) + }, + damaged2_left: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AG91isVoNFAIVRqNXDqVxCwNUqlEAAIfBDqVQHQMUqlBDoQ+BBIMnHKNFDQQAFqNQDp1wGAIVBoVEls0AYNEigLBSaFRGgVNmlNnpcDHZ1wiFWWII7B6fUkhACLINRg46NgsBqkUCwMtknSHQUUilQWxo7BiEVZQIZCHYIcBqg7RssBoLQEDIIADDpo7Bd4NUHoKPBa4KwBAAMFi47NgMVgIxBiNEisQAoNVDoMQHZwcBgsUoo9Ba4NRL4JZCSpo7BgoZBK4J1BdQK6BLQQ7PsrvCSoY9BqlEXoI7PJoIaCZoIhEEQI7PLAVCDAYAEHZ52BGgNNlskDYkrDoI7NoDJBNwMj6fS6QbBoW0ns0orwNVgKtBqlNns9HgW0n0z6VBgJaMJYNUosQilDHgWy8cz6c9osVHZkUSgNBopcBmYfCnvSosBawI7MqhZBF4MVHgPUodEmk0qNVqI7NaAUViFQCwLvBotE6IpBHZx2BolAgEEoofCisAgFEqsBDptFGgIABiklLYNEIYMRoSCBoI7NKAIABkKbBLIQDBawR3NulEkk9mgUBpstmdE6QGBlskHRgdBilNknSc4LqBdgUyegPRo4dMuqVBHoUzmYCBEIU9LQJYMAANxKwUz6lMoYbBA4RcBDhp4CNoIdBolD8fS4lDQINFDp11DoMjGwIdBAYVE6YlBDp13ok06ZQBnstVwPEokzmlBDqHUG4PUKYM92lCnoHBk4dQkgdB7dLSAM03oHB6U3Dp4eBcwNEqlFotMO4JfBHaF3qQVBkm0oY4BoXSHYIdRilNSQUzmc9AAIGBDqLTBSYLKBAAVDMIIcQAAN0LQXUD4IcBXoIdSutNkfSkczawUko4dSPIc9O4VEoQcTagVC6avBOqg8ESgckoIdWAH4A/AH4AFA")) + }, + damaged2_right: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AHEikkiAQskDqdVitFotEAQNBA4IbRusVitBogADqIACq4cOuURDQgADoI+BqMnHR45CoVD6QcFqMHDp0UDgXS6ktlskD4cVi4dNiNVDwU9DYNCDgkVgQdNJgJxC6XSpo6CogcBiFQDpsEilUig3CAAUUitRqFRgodNCQNFijtBG4bRDgsBDpsBCQNUiskoKuCAAVQLJ9Rqo1Bio5BgoFCAAVRiAdNCwJYCCoIYBqixBHoVWO5wdBoLLBqlRgNULgLRCO5w7BqgcBV4NEbIcVEAJ3OOgQACEIIfBXAkVHZ0RojuFAAdFoI7OiA2BAA8kMQJZOZQVC6c9mgYBIIO0AwJaCojuMVYND6cz6XUkgcB6XT6SbDHZgOBnvz6YXBpdNn0koEEHYKcBHZgABHoUzH4NDKwL4CqNUWhjDCqsUps9ofUAYKSBqoCBqNFHZxrCoK4BoNAgsAFQRaBHZrSBoEAXAMUiEFokAgC5BSptUqg5CGIVFTwNLiJ3BoNFLJikCokhNwJZCqkRegQGBHZl3ilCcoIABWoIECbYMtEAIcMLQITBkXTnoABls9mi5B6Y7BDppZC789mffmYAC6XUBYNVDpt1KoM9CgMznzwBppdDo4dNukUK4JtB6YZCEoM0AgMXDpx3BCgVNEIPESgQ7QuNUSIY9B6kUEIM0oQ7PO4PT6SrBEIMrpazBmlNoQcNHYNEkfT7ZyBHoKVBAgNCLBx4C6XSovFosU4m0ki7CDh4dBOoNEoVDoR5B6RiBDqVC6VLlczmfT6dNXYNBDqLSC6hTBAALQCDiAABWgTvBDgLWCSaAACqg1CLAJ1B6dEDqd3igeBO4JeBolXDiZ6CG4IAB6gbVTAZ4BaIIdXAH4A/AH4AGA=")) + }, + damaged3_center: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AEdyCidRqNUoICBokVAAIbRuoUBilBolFogACEYNXDp8hGwQADkgiBqlFiMnDp0FiocF6Q6BokUHiBXBDYVD6QcBHQNRPYMHLCVC6XT6YeCop4BqSUPK4ctmYdB6lBTgUQDptwqITBoVNnoACkgbBaiFxqh3BD4NDLIjZBHZ5ZBNoIXBHgMtHQIABqo7QVAQ9Bmi0CHgMUiJ3RAAI7CHINC6jSBHYMFHZ9RqsUpZVCEAURBYNQHZ1QiDTEHYZ1BgMBHZ0FspZCPYchoJkCHZ11sISBqjTBoIDBoruBiALBSp9QG4LTBAgYcDHZw5CDANRHQJ8BHQIKCiFCDhd0F4NEEAVFEANUAQIDBX4IdNCoQ0Bio7CSwKxBH4MRDpoZBWAQABOoNUpdD6XSHYNEDplQilC6SsCqjOBok9AAIFBiTuMLINDCYKxCokEonTAAJGBqhZNC4JaEAoQACHYKVPoq0BqFVisRooZBqT3BXgIdLuQdBoOyqsAZgIfBLwNbIoUiDpd3FwIAB2lLqqzBrkcpckLQQcMu52BloSBCoPTmfSogKBoRZBDpoZB6ckGYMjV4QeBoVNkg7PqVN+c9mY6BmYEE6kVDpt3GIIVB6fULIQCBnphBq4dOqlEoZVBAQM+klNns9MQMXHZ4dBns8TQIZBpYHBBYNHDpypBGgNEqo8BotU7s0XoJZPukUoStBqI1BqtUkfUQYM3Dp11oI7BknFqkUqtLpstkh2PHgVC2m0qNVqPB4lLoVFDiA8BKoJWBPoMcim0OwIdRuNEpYACldEDgMkHaTxCnpYBqtVoVE6KTPeQvTplCoScBkjsPDo0k4Wynu02XUDqqXBqlNmlFokTDijUCrkU6jRBDiy2BqPCoNciIdXAH4A/AH4AFA")) + }, + damaged3_left: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/ADV1isUqkVoNFoNRqIcSqNUolEoICDosVisXDqEUDQQADHgIBBq5XQDYs9ktEEwNVHh91igaCoVElpaCotEisQk4dNuJ1CoXTAAIjCoKbBiA7PKAIXBoYeDPwMUqNVgIdNio0Cls9AARbBoq0BgNQDpsEO4dNmY6B6SVCqNQiDtOKAIBBknT6XSoYkBd4MQqI7ORQI9B2dNlpYB6VUoNQqMFHZxsBWYPUaQNC6VLaQI7BO50BqNRqlNklNKwMkolVLAVhHZwABDAQAC6jQCqEVLJ0FgAdBAANBihbBSgTQBWZ0QCYIdCTIVBZ4QeBqqzOqx3BDAVVDoNUDgLSCO6EUHAIECWAIABPIMFm4cMgsUio4BG4JeBdgMVgghCoQdLCII3CdAI0BTYJeBMQICBDplRDoKSBDQMEHoLVDAoQ7NKQMkoAEBjslitLls0DoNEmlSShtFF4NFiCXBSIM9noeBBQI7PC4NBqodBAAVC6RbCHZo5BZAgdDPAY7OUwMAgtVgsQiIGBplFW4JACDpd3HYMFpbmBLINR4JiCSwQcMHgNEqvCDoIjBilMpdR4g7CDprnCiJOB6cz6kkE4MjSwMVDpsRoUznsjDgPTAAQIBklFoIdNolNmYaDAYM9A4IdBoIdOulDC4IABmfj6hdB7skolFk4dNuNEDQPTogiBPwM9+XUWYNHHZwVBKAIdCSAJeBWQQ7OuoVC6lVps9agNC6Q7Bi4cNLIUtmjyBa4MVrdLIYMUq4dQonS2nBqMVrkUA4NEqI7PPANC2g7BgsVivEpYnBigcPHge0qm0AAMbMQMlDiC0Cog1BoVCpgFDDqN3ZwXF4NUqtTaAJ1QDwg9Cmg5BltHDid3kh4BoTNBDwMnDql1olU3stpkUoIcUAAVVqlCqNXDi93kQABoRXVAH4A/AH4AJA")) + }, + damaged3_right: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AHNRqNUoNUogCBi4aRuQbBqNEilEAAVBolRDqFxioaBHAIABkgCBIIIdQisVoo4DonT6VFHgNXDp8FKoktmg7CPINBDx8VOoJWCoQ6B6R5DTB1wSYtNns9loHBqNFo6UOgsVLAc9mY8BAwNFilAHaBPBDwc9kk9aQQdOusBZwRaBoY6BptCA4MVHZ7RBCYNEpaTBpq0B2g7BqI7PRQKXBkgaBoR3CDgIdOHYNlHoKyBPQQ8CBIMQHaEFikUOQLzCWQVRqA7OiFQHYQABAYdBFAI7PLAI9BDoa3BitFLAJ3QDgNVZQI2BbANRisFO51yF4IABiNUigGCbANRiAGBiQdLuinCoNVilUOwIBBH4IIBIQIdNcQIWCqNBqhaCTwUQiIdLuIaBCoNEWwNRoVRilLTgVAHZl1oKRBok0HgVNitUoXT6QrBig7MHINUlszKYMQC4MVofTns0opZMuiTBJ4VEZQMReYaCBSp4ACH4MBqFQA4VVFQNFLJgdBHYJxB4MAgJ5BqFVqEAbIIdMHgbnCpjtDqPCooFBDhgdBWQMtkpvBokkmlEKoJHBoodNuoYBnskGYOzV4M9MQKYCDptxG4PTmcz2fkmc9AIUz2hZOu4vBd4I3Bls+mfdmYmB6lHDpx3BoQVCoZZBmgGB6dEDp7nCkYVBPgKVBlohBokXDpyvCHANFqlD6iaBMAMkq5ZQilNnodBps0ovEEoQ7PuVUqlC6VEqsUqtRoW9lsVDp48BitLpdMitRitcQISUPAAMVoIVBoNVitFoO02ktHSF3uKXBHgNbpcrpg7CDqI8BZYKSBolFqOyPwIcRu8iZwXEiJcBlskoQdSHgRbCnu06Y6TPIlULgIiBq4dUuUiolboXUqsyk4dUAANRqqVBqobWAH4A/AH4AG")) + }, + critical_center: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/AHFRqNUoICCosViobRuoUBilBolFolEAgIjBq4dPuI2BDIIACkghCisXK6I1CAAXSDgMULgMHDp0FigaCoXSoZaCD4JaQOoIdC6YAB6gFBqNBoNSSh46DoYdB6RgCqlRqAdNuFRVwVNnszDwgLBiKyOqhZBoJ2BDYVNSoJZBHZxZBCQJaCDoKXDqNViruPNoI9BnstAAJ/CFIJ3QAANUKgI+Com0ioABgI7PAANEkQdCpskolFDoMQHZ1QCQMUHYYcBLAIcBLJ1xgtgHYIABoJ7BaAQACWZ1hVANUZYI/BDgJYBqFRHZxLBgsRc4QiBolAWAJ3PugQBoI7Big2BiNUA4IiBHYNCDplQiNEgMVqIdBgpABgsFqo7BoYdMiFUqgxBDoT0Bio7CLgNEDpjtCqsFLwMFgIdBgtUpgIBLJo7BcwLICEAMUqPBqlKIYMUaBgOBoXBqsQLYUEitFqVLFIMSLJqwBWYI7CogABBQLzBM4LRNVYNMiNQVgK6BEoVBHYJ3NGAISBqEAHgNQioFBrY5BoodMu4bBoSUCKgQDBaIJdBoIcMu8UokkovBCoMkmXUbINUoQdPHYRsBolD6cz6dE4PBBQNFHZ1UnsrkfTnocBAQOzoc9kkVDpt3KoO+2c9HYPz6XT6W9mlEo4dOPAU9nstmc+mhaBoR7Bq47QppQBAYQHB2nCAYMXDp10olLofUqhaBoscDYIdTltNpi1BnsVqnB4XSoR3PuIwBpcVdQNRqtRDoJ2QHgdUpdVqtcqvB2gnBDiA8C4W0qPKokcXgPCqIdRutEC4PE2my2gDBigdSu8V4mzoNEplUawPBDiV3uUUWgNLa4VEWB4AFGwNLoQeBptLWKJ5FqPEHYNCDioABktcjdbqjOSag1R4LuBWCYA/AH4A/ABQ")) + }, + critical_left: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/ADN1isVoNFilUilRAAIcRCYNUolEoICBooEBqsVi4dPisUDQQADilFIQIdPK4IbFmgeDMYMnDptxK4VEklC6XUDgJ6BisQDp11HAfTAAJaDqlRqBaNuBYBig6Bls9AAMkS4I7BgNQHRsUDgNEps9mfT6XSSgRZBio7NOwlDDgVNA4KUBqMAShrtCHoJ2B6VEobYBoNRgo7PoJ5BWINNPINEpdUHYMQsA7OHgMUpdElrTBMIUVqC0BWZwABDYMtTIUk6QoBWYMFWZsBHYQbBOYNC6kkilVgNViA7ORAJTCDoICCHYNQiDvOgNlDoTpBH4LtEAQI7NiAxBDALKBAgIcCqoCBqw7NC4J4CDIJABEIIcBioMBm4dLJgIVBijzBEQVBSINVqgCBoQdLcINFAQNRoFVgsUbQUVigpBDpgQBolVLgVQDAQ5BotBqjZBDpYTBolQDQLWBLIJzB4NMikdmlSHZsVoo8BD4R/B4NLmjbBoo7NJYKqCWQSzBrhkBokUoJ3NC4NcWwUBDANEFAQABio7NB4MAiu0gpaBiEAqu0oI7BSpt1HAKOBokReIdVLIQABDhd3uIPBZIMVqgYBEoNVDwcUDpl1HANFPQMtmc9nskrkbofSPgI7Ooc7oez6fTmYCB2VDEINFoodMukUCYM9n09mfjDoPS2YdBoNBDpgeBCwIACHQPUklE7s0olUk4dNLQJXBRgPTGwNE2lC6lEoIdOuh4B6fbSwIdCpdEAYNFHZ9D6k9oNUVoNFrlFog7BiodOuozCdINUAYNR4PCMINHDhp3COAPBqsViodC2h2QAANElgeBDQIbB4m0IANCDh93ihvBokbLoO1oIkBokSDqCnB2m04lCDIIFBqlBi4dQu8Vok0oPEqnEoi6BqIcReIVE5dC2VLpsk4KTQAAVyDoNElZYBkiTSagu1D4KbBoNXDql3otV4nE4PBDapbCkQADDq4A/AH4A/AAw=")) + }, + critical_right: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A/ADVxoNBokkilCokUigdTksRqkUD4IABikVDiVRqIcBqgcColFokVi4cRCoIADlskH4VRk4dOgNRDQR0BDgPSolBqkVDp9Rqo5DpodBklEPwQdOuEQiqOBK4Uz6fULAQBBDpt1godBLAU9AAJ4DqkQHZ0VcwJYCno7B6YGBoKhBHZyVBGQNBoQeBSwTSCLJw7BO4UUps06fSO4O0ilRoA7QoqMBoXSpskPgIABFQI7Pso9CdYJ7CaQJYBqA7PWgMUqgYBAAIDBSgIABO6BbBDYSaBAANFilQaJ11g0BqFUOIcUpcUHYILBHZ5NBDINBooDBolRqsQqqVOupZBD4NUGwVVWAQABLJt0RIQCBqlUHYK4BqMFHYUXDpgxColQisRoAXBii8BipbBq4dNGQNEqpWBoNQIAJhBBANRDplxRgIBBqFQiNQqsBqkBrkV4IdNujrDoo0BKgJ9BotFiIEBDpo5BAAPBKgMQaIVEqlV2qVOopZCjkUgJYBEoVViKjBWZ1BDwNLosAgKPBqG0iEAqhZNWgYwBDQJ+Be4VVqgrBDhh4ESoIiCkgkBqsUoNFDpt1C4M7SwIEBmc9loGB4ghBDptxG4PTmdDnoABmYGB2kzkhZOu60BlobCDgIDClsz6lDDpyzBolD6YCCHYPSpYCBk4dOqiWB2k9SQI5BolLIoMkDp8UYwNNkfEqnT6hEBpkjogcOu7NCnlNoNUls0qvE4lNaBwABirrCpdV4NRqtViscklHDp4eCWwNBqodBjkcpXSDqcsjdMiFRovB4W1ogdRuMVHYOx4my2lEjksoQcQDwVF2jRBAAO12QDBDqVyqtD6XE2tMijxBHad3iK2Dkm06VMDiZaBqtE5dEO4KTSAAtEawXBm4cWaoNV4PB4ocXAH4A/AH4AjA=")) + }, + godMode: { + width : 60, height : 60, bpp : 4, + transparent : 7, + buffer : require("heatshrink").decompress(atob("u4A/AH4A8qIABqkUAIUVAAIbQuVCisUogABloDCosVkUXDp1wio5CoXT6VCDoI8CDp11io0Cps9AYUkAYNBqoeOuEUAAJWBkg5CDYIcCgIdNutRolUogbDoiWBToNWiAdNgJ1CDYYcBXQVRgFVgLOQDgdBaAcQqMBqAdMgoTBigZCijNBAAVQiABBDpguBNwJbBAIJeCoqWBJANVHZw6CoMVoqcBAASXCsAdMJwNBoggBDYiYBBIMVqI7ODAgABpabEqMFHZwbEoVLeYMkewS2BHZ8tnsklstolNknS7c9olRaJpzBDoU9HAUkogGBlskJQI7Pnsz6fULgXTAAI7BLJw7CmYdBGwIACA4JiBopZNgodB78+KYQBBEYPfDoL5BDhbDBqkUitUN4JZCps9otBotFNAIdLLITPCeYzRCDptRqgUDAoVBignDoNRDpgSCp//OgNEndE6nv/80BgIPBDpQrColDn8+OgJ6Bp0j+bRBQ4QdKDgVEp3eG4NCeQXepoLBaQMRDpVFilDofSCYLsCAQMkoXSofUiJZMqlL6bMDnvj6YkBogGBmlFSptD6fTHIQcBAYYAB6lBDpd3ZQMtDghZBLYS7BklBDhd3aIQ9B8ez6ffEYRcDoodMHYKuBKoIEBXYRhCklEWRYABuIVGkixBIQKgCo4dMug2BKQPSIIIABqhhBIYIdOutC6hvBOAadCBANEmkXLKIYBLQK6CoY7B6g7OLISuCGwLQDEgMlHZp4BptD6gyB6XULoVNDoI6NDoSrBOoYADoYjBDp54CGQJVDpstlp9BLBwABKAKQBZgPeAQJDB6VCDh4dBHIMtH4NBLAXTLCAeDGwYBCDgNEDiN3kirBlsjZ4kiDqV3iiXBeIM9mhdBDid3uq2CDgSwRAAlwiruEoIdVAH4A/AH4AkA")) + } + } + +// Animation state +var faceDirection = "center"; // current direction: "center", "left", or "right" +var faceAnimationTimer; + +// Hit counter state +var hitCount = 0; +var hitCountDate = ""; + +// Get today's date as a simple string (YYYY-MM-DD) +function getTodayString() { + var d = new Date(); + return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDate(); +} + +// Load hit counter from storage +function loadHitCounter() { + var today = getTodayString(); + var stored = storage.readJSON("doomguy.hits.json", true) || {}; + + if (stored.date === today) { + // Same day, restore the count + hitCount = stored.count || 0; + } else { + // New day, reset counter + hitCount = 0; + saveHitCounter(); + } + hitCountDate = today; +} + +// Save hit counter to storage +function saveHitCounter() { + var today = getTodayString(); + storage.writeJSON("doomguy.hits.json", { + date: today, + count: hitCount + }); +} + +function animateFace() { + // Randomly look left or right occasionally + var rand = Math.random(); + if (rand < 0.1) { + faceDirection = "left"; + } else if (rand < 0.2) { + faceDirection = "right"; + } else { + faceDirection = "center"; + } +} + +// Helper functions for different metrics +function getBatteryLevel() { + return E.getBattery(); +} + +function getHeartRateLevel() { + var hr = Bangle.getHealthStatus().bpm || Bangle.getHealthStatus("last").bpm; + if (!hr || !isFinite(hr)) return 0; + // Normalize heart rate to 0-100 scale (inverted - lower HR = more damage) + // Assuming normal range is 60-180 bpm + var normalized = Math.max(0, Math.min(100, ((hr - 60) / 120) * 100)); + return 100 - normalized; // Invert the scale +} + +function getTemperatureLevel() { + try { + var temp = E.getTemperature(); + var settings = loadSettings(); + var useFahrenheit = settings.tempUnit === "F"; + + if (useFahrenheit) { + temp = (temp * 9/5) + 32; + } + + // Normalize temperature to 0-100 scale (inverted - extreme temps = more damage) + // Assuming normal range is 20-40°C (68-104°F) + var minTemp = useFahrenheit ? 68 : 20; + var maxTemp = useFahrenheit ? 104 : 40; + var normalized = Math.max(0, Math.min(100, ((temp - minTemp) / (maxTemp - minTemp)) * 100)); + + // Invert so that extreme temperatures (both high and low) cause more damage + // Normal temp (around 50% of range) = healthy, extremes = damaged + var distanceFromCenter = Math.abs(normalized - 50); + return distanceFromCenter * 2; // Scale to 0-100 + } catch(ex) { + return 50; // Default middle value + } +} + +function getStepsLevel() { + var steps = Bangle.getHealthStatus("day").steps; + var stepGoal = 10000; // Default step goal + return Math.min(100, (steps / stepGoal) * 100); +} + +function getHitsLevel() { + // Normalize hit count to 0-100 scale + // More hits = more damage (inverted scale) + return Math.max(0, 100 - Math.min(100, hitCount * 2)); +} + +function getMetricValue() { + var settings = loadSettings(); + switch(settings.faceMetric) { + case "battery": return getBatteryLevel(); + case "heartrate": return getHeartRateLevel(); + case "temperature": return getTemperatureLevel(); + case "steps": return getStepsLevel(); + case "hits": return getHitsLevel(); + default: return getBatteryLevel(); + } +} + +function drawDoomguyFace() { + var isCharging = Bangle.isCharging(); + var faceImage; + + // God mode when charging + if (isCharging) { + faceImage = doomguySprites.godMode; + } else { + // Select face based on selected metric + var metricValue = getMetricValue(); + var spriteKey; + + if (metricValue > 80) spriteKey = "normal"; + else if (metricValue > 60) spriteKey = "damaged1"; + else if (metricValue > 40) spriteKey = "damaged2"; + else if (metricValue > 20) spriteKey = "damaged3"; + else spriteKey = "critical"; + + faceImage = doomguySprites[spriteKey + "_" + faceDirection]; + } + // Draw the face in the middle section (between the HUD panels) + // Adjust x, y coordinates to center the face + g.drawImage(faceImage, 60, 105); +} + +function startFaceAnimation() { + if (faceAnimationTimer) clearInterval(faceAnimationTimer); + // Animate face every 2-3 seconds + faceAnimationTimer = setInterval(function() { + animateFace(); + draw(); + }, 2500); +} + +function stopFaceAnimation() { + if (faceAnimationTimer) clearInterval(faceAnimationTimer); + faceAnimationTimer = undefined; +} + +function flashYellow() { + // Flash between two background colors twice + var flashCount = 0; + var flashInterval = setInterval(function() { + if (flashCount % 2 === 0) { + // First color flash - red background + g.setBgColor(1, 0, 0); // Red background + g.clear(); + // Draw damaged2_center face during flash + g.drawImage(doomguySprites.damaged2_center, 60, 105); + } else { + // Second color flash - yellow background + g.setBgColor(1, 1, 0); // Yellow background + g.clear(); + // Draw damaged2_center face during flash + g.drawImage(doomguySprites.damaged2_center, 60, 105); + } + flashCount++; + if (flashCount >= 4) { // 2 flashes = 4 toggles + clearInterval(flashInterval); + draw(); // Ensure we end on normal display + } + }, 100); // Flash every 100ms +} + +function onFaceTap() { + // Check if we've moved to a new day + var today = getTodayString(); + if (hitCountDate !== today) { + hitCount = 0; + hitCountDate = today; + } + + hitCount++; + saveHitCounter(); + flashYellow(); +} + +function drawHeart(x, y, size) { + // Draw a heart using filled circles and triangle + g.setColor(1, 0, 0); // Red + + // Left circle (top-left lobe) + g.fillCircle(x - 5, y, 5); + + // Right circle (top-right lobe) + g.fillCircle(x + 5, y, 5); + + // Bottom triangle (point of heart) + g.fillPoly([ + x - 8, y, // Left top corner + x + 8, y, // Right top corner + x, y + 16 // Bottom point + ]); +} + +function drawHUD() { + // Left section - Battery area + g.setColor(0.4, 0.4, 0.4); // Solid gray for battery section + g.fillRect(0, 95, 50, 176); + + // Right section - Heart rate area + g.setColor(0.4, 0.4, 0.4); // Solid gray for BPM section + g.fillRect(180, 95, 130, 176); + // Connecting line across the top + g.setColor(0.3, 0.3, 0.3); + g.fillRect(0, 95, g.getWidth(), 93); + + // Draw heart in lower right corner + drawHeart(150, 155, 16); + + // Draw hit counter + g.setFont("8x12", 1); + g.setColor(1, 1, 1); // White + g.drawString("Hit:" + hitCount, 60, 98); +} + +function draw() { + queueDraw(); + + g.clear(1); + g.setColor(0, 0, 0); + g.fillRect(0, 0, g.getWidth(), g.getHeight()); + + // Draw HUD panel first + drawHUD(); + + // Draw Doomguy face + drawDoomguyFace(); + + g.setFontAlign(1,1); + g.setFont("8x12", 2); + g.setColor(1, 0, 0); + var hr = Bangle.getHealthStatus().bpm || Bangle.getHealthStatus("last").bpm; + var hrStr = (hr && isFinite(hr)) ? String(Math.round(hr)) : "--"; + g.drawString(hrStr, 165, 140); + g.drawString(getSteps(), 170, 85); + g.drawString(getTemperature(), 35, 85); + + g.setFontAlign(-1,-1); + drawClock(); + drawBattery(); + + // Hide widgets + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} +} + +Bangle.on("lcdPower", (on) => { + if (on) { + draw(); + } else { + clearIntervals(); + } +}); + + +Bangle.on("lock", (locked) => { + clearIntervals(); + draw(); + if (!locked) { + startFaceAnimation(); + } +}); + +Bangle.setUI("clock"); + +// Set up touch handler for double-tap on Doomguy face +Bangle.on('touch', function(button, xy) { + // Check if tap is within Doomguy face area (60x60 sprite at position 60, 105) + if (xy && xy.x >= 60 && xy.x <= 120 && xy.y >= 105 && xy.y <= 165) { + onFaceTap(); + } +}); + +// Load hit counter from storage +loadHitCounter(); + +// Load widgets, but don't show them +Bangle.loadWidgets(); +require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe +g.clear(1); +draw(); +startFaceAnimation(); // Start the face animation diff --git a/apps/doomguy/app.png b/apps/doomguy/app.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc952f77a08a8417495e7df878030aeb0a397dd GIT binary patch literal 4466 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 literal 0 HcmV?d00001 diff --git a/apps/meseeks/ChangeLog b/apps/meseeks/ChangeLog new file mode 100644 index 0000000000..632228d829 --- /dev/null +++ b/apps/meseeks/ChangeLog @@ -0,0 +1,5 @@ +0.0.1: Initial release with Mr Meeseeks character faces +0.0.2: Added battery-dependent aging spots overlay, tap-to-cycle faces, temperature in Fahrenheit + +## Attribution +Based on the Advanced Casio Clock by dotgreg (https://github.com/dotgreg/advCasioBangleClock) \ No newline at end of file diff --git a/apps/meseeks/README.md b/apps/meseeks/README.md new file mode 100644 index 0000000000..344e6e0c64 --- /dev/null +++ b/apps/meseeks/README.md @@ -0,0 +1,59 @@ +# Mr Meeseeks Clock + +A Rick and Morty inspired watch face featuring Mr Meeseeks with multiple expressions and battery-dependent aging effects! + +## Features + +### Dynamic Mr Meeseeks Faces +- **12 Different Expressions**: Various Mr Meeseeks faces to cycle through +- **Tap to Cycle**: Tap anywhere on the face to cycle through expressions +- **Swipe/BTN1 Fallback**: Alternative controls for devices with touch issues + +### Battery-Dependent Aging +- **Aging Spots**: Blue spots appear on screen as battery decreases +- **Progressive Aging**: + - 100% battery: No spots + - 80% battery: Few spots + - 50% battery: Moderate spots + - 20% battery: Many spots +- **Transparent Overlay**: Spots are drawn over background but under the face + +### Information Display +- **Time**: Large digital time display +- **Date**: Current date +- **Battery**: Battery percentage with charging indicator +- **Heart Rate**: Current BPM +- **Steps**: Daily step count +- **Temperature**: Current watch temperature in Fahrenheit + +### Visual Elements +- **Transparent Sprites**: Proper transparency handling for clean appearance +- **Stippled Spots**: Light stipple pattern for semi-transparent aging effect +- **Charging State**: Different behavior when charging (no aging spots, no face cycling) + +## Controls + +- **Tap Face**: Cycle through Mr Meeseeks expressions +- **Swipe**: Alternative face cycling (if tap doesn't work) +- **BTN1**: Physical button fallback for face cycling +- **Swipe Down**: Show widgets + +## Technical Details + +- Uses raw Image Object format for optimal transparency +- 4-bit color depth with custom palettes +- Cached spot generation to prevent flicker +- Multiple input methods for maximum compatibility +- Optimized for Bangle.js 2 + +## Attribution + +**Character Inspiration**: Mr Meeseeks from Rick and Morty (Adult Swim) + +**Code Base**: Based on the Advanced Casio Clock by [dotgreg](https://github.com/dotgreg/advCasioBangleClock) +- Original template: [Advanced Casio Clock](https://github.com/dotgreg/advCasioBangleClock) +- Creator: [dotgreg](https://github.com/dotgreg) + +## Installation + +Upload via Bangle.js App Loader or manually install the files in the `meseeks` folder. \ No newline at end of file diff --git a/apps/meseeks/app-icon.js b/apps/meseeks/app-icon.js new file mode 100644 index 0000000000..400739092e --- /dev/null +++ b/apps/meseeks/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4n/80Zpsb+9XylVBoNNlexoksjdMjdzquUrtPomTqvGiMvom0rtEAC1RiIAVC7EWswAEtwOFjYNFswXBieqAAOvAYWxC4lj1/61X///6nIXC2CjErU2CwdZnNwBomWC5EHzWWHwWTsDJFC5MAgw+BAAP7cIwXKABgXX1IX5gu7AAO2RwwXL8UiAAYXQhwWEkUgC54uFGA4XCjQXEFwwwHC4UZ1wuLkUvfYk7C4MV0dQFxQwF2dhC4MR9WVBANSC5JhChxGBC4UbnYJBCxUi4EAh+VC4cRC6JGBC/4XL1YX/C4sVC6EKC4kZ1wXB+QXK8EAg2rC4dq2AXBh4WJlwNBgFj8IXBi02BAQwKFwIABg0+C4MayAXDGBAuDAAOmC4RGCGBQuDC4kTC4owGFwoXKGAwuFC4cfC4wwElYLFL5QANI5QXPF64Xfgu7AAQjHC5Xj1Wq0cznJ3Qh2pqMRiMVseXC5OWs1r3dm3djyoWBAAMW1RNDAAJHDHoJBBAAIJBAAhNEmejmwXBB4oAQC64=")) \ No newline at end of file diff --git a/apps/meseeks/app.js b/apps/meseeks/app.js new file mode 100644 index 0000000000..70a16ce64a --- /dev/null +++ b/apps/meseeks/app.js @@ -0,0 +1,385 @@ +const storage = require('Storage'); + +require("Font6x12").add(Graphics); +require("Font8x12").add(Graphics); +require("Font7x11Numeric7Seg").add(Graphics); + +// Meeseeks face sprites - stored as base64 strings (decompressed on demand to save memory) +var meeseeksSprites = { + face1: { + width : 117, height : 104, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24579,24580,22531,65399,192,1,22532,22530,47112,39904,20482,0,9,45952,8]), + buffer : require("heatshrink").decompress(atob("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")) + }, + face2: { + width : 115, height : 111, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24579,65534,65532,65502,6368,24580,22531,10,0,22532,29280,27232,1,9,65435]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4AShGABzY4bxAOOHMwoRxBJNHFKDPVMoAF93gHEMOLyntHMMOESpzhHCw5B6DjzVolQHGznfHDI5BOTo4Zfy4A/AH4A/AH4A/AH4A/AH4A/AC8FqvuGFuIwAHFzuZzve6A3q93e9vtqA4ErNd7vdHNVd71d9vdHIfd7kMzPZHNXu647BNII5C93VgcFrKtBHFEO6sCkA5BF4UO7uyn+1OQPuHE8NcINEguZHIfd65yBzOd7vgHM/e6twhdZyrcChvdqvFrNZOVXd6tXM4IBBOQXdrOZzJCBOVPd7ItByudOQMJyo3BHQOdWoQAlh3dzNdGQRyC9vZG4JBBHFAvBN4I4DuAJCAwIICPYKsoOQNdUQIvDPgOZ7PdqA4oF4IADyAJD7OdBAI4qgGV7wvBUItVyvVHFatB73ubVIA/AH4A/AH4A/AH4Ak7Xu93qxXgGl0I93d73e9Xa9XuAoIGBG1MFzvt9Xn7Vau+q09XAYOt1vt92KG8vd9ta7QzB1QCBvQEBu45BBAVe9vpN0Xe7vXFwIAKvV6u+nu9d73QHD9d9uuNIIuBNwI2Fi8XBgIOCvWq9Xl0AdCxBwZrqaBGAenFoURiMXuIDBiK1CuMXHIOlfAIeBhA5UCgcN87fCHAWqUIUXGoQACi0R0IFCHoNn1vtHKoTEryoBOIl2s6kBGwhzCu1204MBuOqsN60vlqAlBwBxVvvnVQZmCszaCHQKjBHYS5DAQQKBjWl1pfC8A4U9ulHAOnMoUWUAI+COAg4CW4OmAAOqCgI5B7oiBxw4RQoXacQOqtRwDHIMWGgVxWwdxi12BgNms1hCgTHB6pgFABkOQgVeDQJbBjQlCsMRAIMWsMXHAayBB4IQCG4QGB1Wt6DmRHAdd7WniOhiNnEYSrBHIMRi45BVQZBBJQoUBs967zmCOR/uHgSpBFQOhuwhBE4IACGggzBWII3DAAQGBixyBLwQCCOR8FcYOni9h0NntQuCVAI4GGwSCCB4KECsOn1XlqAoBOR7kDOQNxGAOhOAyrBu43DAAMXuNxuzzBiI/BjQ5B9pyRVYRyBMgMXs9htUas2mdgQ3Bq5xEAAIVBAAMaJANmjV6coJyRhBJCrQhCi2h0JbBix5BLoN1urvBAAll0ulRYI0B01qvWncqeOAQMN844B1TiBs9xMYet9Xe72qGwWGs2OBAPt9XaHYI5B1Wu7QlBxByS891HAVh042CNwItB92gDY8O13q9xGC1Q+B7AoCwByRgvVu9xbgLdBu9a7pbBGxAAFHQPtxwDB9xFCVZ5yDh3au7MBG4NVrvu9QdOAAeKxHqEYUNHB68E7zLC1Wt7vu1w3SW4/VCSCsCgCMB13tNwPQG7I4B9ISQhDBCgGoxHu1DeOS5rnDHKC+QESOIxyOTHMWIxDAV7wwYKD0O93tRSY4CwCLffgIAB9A4zHYY4JhyiHHEgALhAxFAwI3uNYYACx3uHGQ6Dxw30AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ADg")) + }, + face3: { + width : 125, height : 99, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,22531,65400,0,24579,160,24580,8,4,32,9,27264,5,3,2,1]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AE1QMLhQ9vhWgBi4+xRJi7wHuIyL1S6wHxb4xGYQ+Ig49yHxN3uA9yHwN3YYw90AAN8G4aDBXOZ2EHAbBHAG8FznM4A0wrF3fI2Z/3u9NVHl0H5vu7vdqAJDz3vmc1zI+ugvdmc5jM1HwcFzPzjcgqfhH1uezORgUFqo+ChOZyebkUr9uAHtnN8eZ2Ui3+VBIWPzMzBIO9xg9shnunMxOQPfOQUM/OTn2wh3o5R8t+eZrcAqvYuAJBx2ZjNVrPzw+gPlg9BysVr+e44JBhB8BnP5if9Plvfyo+BrMV9C7CnOZ/+TmeT7g9shB8BAAOVn2FBIMJzOf+Mzmf94A+s5nemOZOYPdBIUJ/48BzM+6A9sgF878z+czz1QBIUF/8f/P+6I9tgHI9/+9+VHoZ9B9uI5i5tAAXN7vY6uwBIkF896GMmqBhcH1VgN1mMvlwEkMK07GVquM5GNMcWn5HMH6cN7nMiCij1Hs5nFCqPMu64iAAkM5HZCaHc448mAAVdxARPw/MAwnhrewP0d3CB0HPYcKvHpqoABqA+hg96Jxw9DhnM6e7rY/Cqo+ghQ+OXIcM5EfiEikEA3dV7GDQCtVr2IxHI5obDHx14CYUMwPhyOykUiBANR2sVyuYHaED72VzOf90x/uINIcHuDKM4A9C4PUoNbHoIAB2OwgEL2uexmnEJlc7/5yu7DAMAgsfjmM+AGBu+gDhd3AQMB7thoMRzY9CgpDDYIPt8f5qoACrYBCAAJ3BHYO12AXCkFRyMRxCpCGAQAJ1RLC5sRAAQ5BkGxrMSQQcLiEL3Y2B/46DrNZyo6BgEgqsCCwW7mgkB7w+Bg/HHpUK1S6CiMWskRqO73cVLwImDkG1gUgCgO7nYQBAAUbgA4DTIcLmI9BjuIfRw9Cg/Is1molBjMxnKBDAAW1qBDDipJDkUl2QEClcxXYUrjMRokRjHAFwN6Pha6CvkRs1kDIMRTQORicbModRHAZDEIgNbBYMClezysbgULiqiBoMRjmQNgIxCPhcBvB8DfoYAB3cCE4M1QQcLnJ2DkW5IgUg2bYBrexqIcBsJ8B7wxCHxR8DhmBDINGHwszre72bhBiA9Cma7E3a1BkEAHoMRqsxma6BAAUf+AxBOAR8LgHICwMUswbCihCBiczicfNQMbgGxzMVYwg1Bje7zI3DyJ7DiMZ/J8RgPNW4sRokUAYMTFQcZyqpC2A9B2g0ByJ1FAAUWAYU+qB8OXYw+FojBFipEDyMx3dBqJzCHoy6F9ZwFXZmdicZmOTFAQABoI+FiL9BAAWTiYTEaYRVCJgOTIAMe6IsBg58LJQmNHwMV2cZHIZ+DAYKLGIYg9ECIIgBqNZBIMYXQL5MBgNwAYMF5sz2EA3InDFIjAEIZA9EokZje7hexrPY4B8CHpcK04EChHT2EikGxVAQCBFQJCBHwMUGIY+IAAdbgUikW1jI9ChF6HpQ+BBocFzYcBkEViuZiatCGog9HAwSJBiczyIABHoUg2ucFYXMHpaKFHwlVisbitTGYfxYgZEJiZXBrNV2Q9DqoqCviACHxYOD5nVXgMryoiBhcZFoPhmOZHIWRzJwBHoI6BBIMx2EghZYBHo/Iwo9MJoNwAgUMitbgG5MAULqI3Bre7irCBmOV2tRyK1CmJEBiAWBlYbChdV6AtDHpwQB1QFDqNV2NbEwIjBysZqEigGxyNRJoML2ZDByOxqoJBCwUrrZ6CqAlBhWIfBoACvWnAocKvtV2EAE4O7ysQgQFB2qLBAoI+BjMbgA1CSYQWBzdVJ4IkCvHoHp8AtWgAwkFEAI/CjJrDkG5OIkVnY4DRgIPBhcz+p6CcIN8fgYAVbQIAB3cFOoQ4CnJxDleRBYe1gUA3dVnvhEIcHvnAHrAACHwM1zNb3YIC2NQkAFC2uwHwJUCXoOZiofFhQ8bAAUJ+KBCAANbytbAAZKBrYLBmfzyufGrwAK1Vq5v+73YxuI73l8uNxndxHI+vwHdIA/AH4A/AH4A/ABWqHvugHv4A5u49wu9wBREKHuMK1WqBQ8MHuLtCH42q0/Md+mn096u93IgTEJAFv8vg+BvS3yAH4A/AH4A/AH4A/AH4A/ADYA=")) + }, + face4: { + width : 106, height : 85, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,2,65534,65533,65340,23008,65437,37664,8416,5,31264,0,14528,9,32,12736]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A2zIAB8AqmjPu9GQBAkBj3hjMe+EA6EN6AzghOR93uzoIDhGR9GO8MR98A7sJGkORjG+90RSoY9BqEP30Rzw0BNYJogiNQhhqB9wJDjkCkGLiMRGgQBBADUNyENgHZFQMw9BrBiByCjlCkG4jERiHd6A0eDwPZ35fB9w0BwA0CjeghmL3eLGgIVCGjZTCzMbuyeB3Y0D3e+3g9C32wNMGdNIMRxnO8O+3ewBoMRjcb33rboJnBGkOZiJhB92O8LTCBIXr2Ph8I0g6A0EGYPuFQINCyIKBwMRiMAGQPQab2QhI0CAAPoBoUJH4IzC94wbGg3QGgMbGYPhjAODzI1BBgPwGj6JBGwKfCAAMZwANDhPZzMZjgzgXwiVBAAQPGzPMGcKkGGZAA/AH4A/AH4A/AH4A/ADndGmnQGn4Anho00alsBGmcJyDUFTFo0zNIcNAQOZGmBmCGmXQgEbT2OQh2RGmEJzOJGmMNzOZiA0xzgztGgnd6AztMoI007o0CGdwxEGmWQhudGmHZzPZaV41DTuIA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AhA==")) + }, + face5: { + width : 111, height : 99, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24579,65503,22531,61343,7,24580,6,160,47112,9,5,8,10,4,3]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/hva1va7vQGt8K1Xa03atpsy6EM1nK1Rvw7sK4t3u915Xd7o3vqu+mAGDOEIiB1XK5gMI7SuGG8EN1orB1XM1otG6wWH5nATsmtLwjVKqo3kSyPsb8BwF6EFCBq4FG8SiJQAhulVIYOMhQ2mMB5uh7poFNxrZj1WtAwesAgeAhGP/EwA4UOgHMHEOq0oECgtwAgUIxGO9e73wHB/fwhmgG8MG096GIP4GwmL/2+u9Vvd3vBuj2tT3d84o2Bh++v42B/83rnF4tVq8AhlQGr4uB/3v/d8FIMAutX32DweACQcD0EN6AzchkA6EI90///4mAMD4uwCw7uB7o2cguw8sA90EgeIx4WOqBue98IuH+8EgnGIxwWNGwJudh+A/cO/8wGwOP8AND1QWH46legH4h+z///xAAB/wMDTRHFIJJuW+HnnA2D/+wG5d8uEKbjsAu8M1mI/H4GwP/hVwG4d/Cgl1qEH0A2dgBWB4Y3C//vhlXBocHu93mEAgvF4EAAIIAghGPNgP7gFaBgus1Wq5lcqEKNr4AEvfv/EA5jOH7vaqEAhWtGsUN7oECrRgLgoRDAEHd1kAh98GxfKNsY3C4u7rg2L1SxHAD0Mq+wBxfaGsoA/AH4AJxGAEL8IxGO3YAF2973/4nAUG/3AGjna4/vxGI+f/n//AAQGC/GP/dc6A3E2+gNDM3utVrc+n8zweDAYIAGBQP//d8GIcHq43XMwP+907nc3mc4mcxGo44Dmfz9ZxDgtVU50NGo+InE/MwM2scziMTGxQAC8c//0wN4V1N5sN7oFDg/o/CaEsw2BmI3BAII6N/+4EIMMqo2N7QFDrfvTgIAFm02iIABHQIACG5foEQMK542LhXMAgV13fj+Y1GNwNhGYY4BcYoHBi1mG4eDEgPauA3Ldgf+9wiETQQrBsY2BUYIACBoKsBV4cWAwcz9/wEoPV2A2Ku9QVAPvNYhhCAYM2G4MWG4oADG4R8Ei1jn3gFQNXGxUOIYMNn0/NooADi0xAAM2NIYAEmxDBAILqCs0+/0wE4NbG5Xub4N7NgpZCNoUTsYHBAgNhAAJBCAgMWG4axCeYP+UwSZBABGrdQNfwY3DAAJkBmw3BAQQmBIgJzDNgTaCJgJBBYAU/3orBqo2Jht1gEHGweDnEzcQgACLwIIGJAI2BNgI3CCQI3B/3QgEFNxXXboPoxH4////GIAAWPHgKwDIoQADAwJyBAQI1BW4MxHoM//YrBuo6BNxFXgEIxH//273w3DAYP/+Z0DHoUxs0TweBIIQxBOAgCBnBfBg9dNxPc2wDBhE6sALEgeD/++9e3m6vCi2ZzOWyJ5DGIQABsw7BiymBD4O1NxMA4oLKAAXG6t79/zwNpGwIAByM4VAIwCAAsTn/ggELNxUFvg3NgGqq/v/9mG4mWVALWCUoQCDn+ObphDButeG5qsBre1G47cGHgc4NwMH5olKhHr9167o4Nhd80tWHAeWnDeCAAIzBHQU4xAXBrlgG5e7uvKVJw4Bnk8OIbfBmcRicxmMzm02mcz/GAgGsExsNNpwTE6+2G4SmCNwQ6Bs1jmf/+EAhVaE6IAQ4fHm1py0YG4szs07/7cBgFVG0S9ButT4ymCU4JuCAoJtCgF3qA3jgEM4ezmeDwYyBAAWD/+DB4W7G0gABr3/FwI1DnA2B2A2CrY2mVII3Bx+IAAX4/8wGwXFHYQAmweO/w6BAQKjCAAPF0A2oAAXj2dz2YIEq/AG1axI242Y/A2b9bbYr3wGzNcq/gDbHvDLEOqtcqAcYh6mXhXM5mq0CKZxyJXGwPdfDUA9w3WhnAGrY3CuAfdAC0I/dVG+kAuu3wAHEhVV9A3s4u/+9XAAN+89XrSoux+3ut3u+72utVOEM1ut7vQcmoA/AH4A/AH4A/AH4A/ADIA=")) + }, + face6: { + width : 108, height : 72, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,8,65501,29248,27296,25184,12512,224,10464,32,0,8416,4576,6624,7,9]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH3u92q9w0whw0BzOa0AKE32uIII1m9Hq1W73OZBIcKBIOu12wGsuu1erqEFzNwBIWaGgOo3WpGkkLMAOmgUgGomu1OamEG3Rskh2q1WoGoWrBIepzIJB1XgGsmuGwNQg2a9wJC9WpzA1BzXvNc2q1eZUoIJBhWqzepoEGvQ1lNYLOBGoOoH4eZzN7vOZGskK9RqBZ4OZyAJD3IzBy41lMII2BGgOauAJBhOaGQI2BzPwGscA3yiBzOe1IIChp0CzWp13gGsiYB9WZ9wqE3w+B1Xu1w0kAAPu1W59w/GOgOuiI1mgGL5gIGx2X13uiA1nABPdxYzxAEf/+AecDqkP///KmXuGjxWCGyMO9zBgh8eCJ8HGkIAB8KOPhPgGsTaBap40jGu0f+DoNIp4AViLHNGsIhBM4URIp4ZETbX/K4fhCp0edghPDM6nx8IZD3ygNDAQvEGwI3RGQIADBQnuiAcPbAwfBiMecZIwEGQyPCj6FRMg/u8I4BAII7BA4MeA4P/jxeJh77ENh5+KiPxGgIACLZvxap4ADgJ/RRhpqTNgSjHACoeWh71HDtpscDjJsbDbMPbLoA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACo")) + }, + face7: { + width : 132, height : 97, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24579,65433,65400,65367,7,1,128,22530,8,22531,3,2,35552,0,192]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AH4AuyAMLhINMAE2ZIP40NJxhBzQWh3MzJB1PBTE0G5bE2XZSC3PQI5GJJAAxrJCEJA7H4IAKC5ABH733vG+kG83/BAuP5m83lvIGUL4xBBuoJE3lmAANrIOV+93ut3FqAICgu292AgHrrKCx933vsA9hBD3ZBBwUi7dVIOFc8/n+Ui7nFIIfOs5BC2uQIN++u9+6RBB9ZBD41nYoOM2qODAFi6Bv3AkGPvY3CIINuv2Hs3LIOFct3uu+v+y7D3dm93nv3utmwIOHO8/n+/sIIYJB9wACthAvPIPOw9392H3YJD21mAANu5hBy8/u9F83gJChe2tnMs1s3RBwgvGXQXr34KDu3mQQNrqBBwgHGXANmG4v/9m8514IGMAg+73e28wKF/dV3HwIOUA2tVr430AH4A/AH4A/AH4A/AH4A/ADEF/4ACs/Gs93u/m5e13fL34MB+A+srdb3+P7/f7v3vvdAAX3tvd7HfKAd3H00PFYWPOIvX+EgAgMC7+AkAGBhv97vf73m94hEhOQHKtVqAGE3fvx/d6EAx+NmU0ocgx99ocikUt739oUiknf+kikEN7H+LImZzJCUhOVCwcP23svp1Bkct//96lEmVNvHu6A3B7H3xxRBhuPwEiohMB/7NCIS8FIAt3xsI/p2BkgEBQgI1B72Hx197vY/+IvHo/H+x/9olEkbKBCgJCEqtbIKOZrhGD2+NgUI/EAmkN7+IxH3x4/BAoPux2PAgOIBAWI9CIBbYJGBmBCBrQpC/byFABeVCQe7wEykUPOYPdx/4GQV4vAECxGHxBCCwJFD8+Px/3xtDRIMN2ugNYVZIB8JyoECg1tgT2BFYOP9w6DAAeq1AECwMa1Wh1WKBQRSC/8EolDkGG36zDegbEMCAfM9/QkjEBHYh1BxWo1QABIIWKHgIADiMaSImNQYMIvFs+ByCIKADCgvI9H47BAFxERAAQ/DHIMYY4JDDIIKPDxH4aYP4vG72BBRhJBDze6YAPnEgMYIQ4yB9C3BOwPo93oJAOqIwIBB0INCIAP4BgNbGIWbIKMJrQmBHYiFFAAOO92OHYJFB7vdx9+w4ABBQTaBAAhBCYwJBQSYUFqpBExSDDu9+PoV47vY+4EB6kikUNx6MB/oDBIYWOB4OHaQW7wAxBzRBRhYaCQYhqBvA8BO4WNoc07vnx8DkciknY//dgkN7w/BSYLQDAANc4AxBypBS3WpPwYAD9HQklA73v6dEokwx99oczmcjnv4gSJBhH3w+IxuH9hAC0uL2EAhT3CABcFIImq0Oq12HP4LDBIAJ+BhvogckmUih/wkdCIQMg/sCmdDJoP46lEpuPxWhjTFB0BzEIJlZIIXKIIOK0/o++ONQIpBokikH/gQYCh/9DwcN/4DBI4Pf/oWBokI/CDC2q1FABcOIIe11WoX4QuB+9/ggpBoEAx8AFoP/AAP3/93v/vAQONJoWAIIUt/HB0u7qAMBYhwcBKoUI3eqxGOxp9CHAMDmh2C/+73/4/Hf7+PAIX42tV24PB6/wgFEocA/GHxm12CCBIJ8A4pWCqu7xF4X4R9B//dPYQABMh3Xs1nv/9/vf+/M5egYgRBQ+pBChdb5lnX4MA7vfHgP9/5vBACELxlvK4W724aD/OQDp8FqoEChlbraxBEgX4HySQOtITRyqECTYOpq6oBXpwAThNbuAURQgJCDAEsJqtZCydVrewIE2ZyryDACW1IYL/ZyA/JAAQlXrdV3a3YGhJAaAAMFqtQXC6DJAGxB/TgSC/rbdXADkJBRMLQWsJzIKI2uQIOxCH+qC1IQWVIQsF2tQIOyFCqp9CzOVQW6FEqqHBzObIHLACrJABZQoA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AxA==")) + }, + face8: { + width : 109, height : 92, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24580,65470,65468,24579,22531,0,33440,6304,22532,47112,29408,6272,8,6368,25024]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4Ag7vQFlfAA41mtts8A0n91t5ttGo2Gs1sGtHms1m6xjD7vO/1ss1oGs3O91/GwPdBAXmtcDhAJBszWmt0Cl9m5qaCg3WgUj9lus1gGskN43gkUMtnG6AJBs1rmcM4xsBVoYAh61ogZsBFoIsBhtm9+1GgNttpsls1o//mFgKjCGQIHB6wJB4A2kGAIuBw2GtqjBH4IACOoPONk3GAANoTIY9DHAQ1kgHNsxtBG4LPDtptD7p1BUco2BAAKiCgEMawIABbA48fhieBFgVgVoY2CNY/dBQQ2chw2C6wsFFYNtyAVH91t7o3UYZHdGwPgBQwHHC4o2RhoTBGxHZQ64hIGpLxfGwg1QF7vN7vcAwduPjwAM5PcAAPZ6wiChwmNhoOChud7udyAzShHM7ts6vJzNc5ojDGxihD7vd7ICB43uGh4aB5vF5OVrOZyuZ5raQBoUNzIACy3Ws2O9ozMQANZNAOZqtUog4B6xsPGoXuso2DyvJ41mOgPc5ngCwi0B7PZ6ouBAANUotJAgOdUZ4MCh1sqqHCqtFrOVzmcfwXWAIPWttt5mdJAQ2CoNBjI7C5jLFNhnd4o2BquVKoNZLgeZ5IAFBQYAByMUikRiORHAJoC7psOhvVqo2CiMUio2DOwQ8EGgoyBoICDjPNbKXZGoKJBogCBpI1DOwQOBHIo0BoJqBGYIYBimcNgY1LNgtEoiLBAAIfBoMVyuVMwlBrMZMoJnCimRCYIFByttNiXdqtUNYI2DomRqJdBymUTAjQCiNRoIBBAAcV5vAEoI1MIYUJ7lFGgSlCfgVByheBAwQAGpIMBrJrCotWGoSiMUYnFqhrDKoVRqlUqtFotUO4YRBisUIQJ4BO4UV5hoCURpEDww2BNIInCotJqmUqIABHINEFgIACOYUZymRC4MZrlsGqDaE4ooBAAVJqriBAQNEIIJyBWAQCBUgRNDqudGoaiNIonc5OVGAIeBGYQAEGoIrBF4Q1CJINBBwPN5hcFGyFdtosCK4TVBHYIAEBYVZGwLfCokVGoOQGqQQBGwSFB4vEMYJgBGwIEBFYJwGU4QKBzOdGqoREhilBzOZyKSBFoOqAAOkotVAII+Ca4MUpOc7gwEho1QAAvN7vZ6KTBGogABGgJtCNQVEzNt5vVGCxzH7udytcGoNKGwdV4rfE5nM63NqA1dQwOd7rfBoJsE0lcAAQzBAAXAGjw3Es3Nb4YABzmWGQfc4ozhAAkOOAOdAAbmB7nc8AzmAH4A/AH4AphvQG2ndGv41rUWg11hpr/Gv6ZZ7oGGNdovBGAQECTmAADsDUxUwwA/AH4A/AH4A/AH4A/AH4A/AH4A/ADIA=")) + }, + face9: { + width : 113, height : 101, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,0,65534,65469,24580,31392,29344,65404,3,32,4,9,27232,1,5,8]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AHW72ANLhf/3Y2mE5/7HEu7+ARPhaBNACsP/43QHEkO/aEU8A3fLYIWU92AG+sAzy+RG8kAz7jdG7EA/Y4cG7MADLIddKTQA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4ARhe73YJGhOa8A3qhFP93u+AJEzOZzWNG9OZzsR7vY0AJD9o4BzPYOVEIzPArIuF/Wc5g4BxQ4nh/p48jrMdxyqC32pg81HAOuOE/q6kzkuRiOvIIXo4cjhOZzGJG83+7OQuFJFwKfC9WJgU8OAPd6DgmxuZygtBzOOBIMOBILhCzuZOEwqB7I3CzJwCGQIAEyA3laYOROIZwChJwBjI4DOE0IxIsDxXwBIOe1p6DxA3mgGa7MdzudxCoCgHu1o3C7HQHE+ZGoPY7BmE91NOIPa0A3nHAOq1WozgJE/2oN4J5DAE0O///oAJFpztBBIwA/AH4A/AH4A/AH4A/AFu0G2sP//6xQ3zhuupWI1w3yhOU6lE6mIG+WZogAB6mNHGPpG4VExHgG+Hqyg4DxXwG98O0g3DomOOGGNG4naVOEJpJw27o3EpugG98Kwg3DpNIOGHoOAlJOGEOxo3ExRww9RwEpGAG98JOAmY1JwwhvZN4eOgEL2A4uzOUptEptK0EA3Y1s/Y4CztNpGKcAO7OFkLMwWYzPd1VAVF5mDzOZxRBCPQQ4vAAn+G9qpDG4ugHGvu8A3tHAP4Awn/+A3ugG+1IECh/vG+EA13u/e73/vU95sD/4ACG2LjC3e72A3zAH4A/AH4A/AH4A/AH4A/ADgA=")) + }, + face10: { + width : 156, height : 116, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,10,53856,6304,9,11,41664,65533,1,51712,25280,0,2,8,29344,7]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AHcwIH4AKh8zmfUGFn/GAJ/Z4c+8czJlcEmfjGDMNnOZzOeTdnpGAPjTi8PDgVuJtnmzOWyZNayxNvzMun4bWhhNC9xNty2Sz3DDa2jn2Wy3gJtmmtOZ8bpWgczmfunxNt11u90zdK0zn3pnJpQqoNMqAdOh3u92e8czTSuZAAQVPJpkFJqAyDmbrTnfpDIWeCp5AMJqEKtIzCsacTnZnDJqCcMexqbDJoeWnhNS4eZyUpJqaPJgpNQTYmWn5NVkUiJqMBJpNBdB5NFzPsJqXTCwKbBtwXRSBENoobQJoaBBdKddn3p93uTaLfBSI8EoBNRs3u9Oe8czJqUEmZOBJ4IYSqpOFgtUDSKbC90zmcwGiUA8c59OZTaRGBdYgFBUY7pO8ZMUgEzJgOWtwYTiMQUJJNRyc6JqnfJoOZJqkEJoYAC//9JqeemZNUgfmyycBCqP/4YIFh88xk4HB5NCyWTJqsI31ps3jJiE85n8Fws/nG7AAOwJp3uTYNjmBNUgGDmYABCZ5MB5k73nAKwfzxez804/5rO4cz8czJq0M+YZQgf85cz90755WE2cwu8DBIYALP4RMWACcPTIM2IYPMJofInZNC5lAHdIAR/nMwZDBueM6AJBnGIxE+u9rxhN8//I3ZDBsZNDnnD5HDnU7BIYA5+fD3czn0z3nwJoXMxnMxGzBIYA5nmLnezme73BDC/+7BIOz3e8wBN8ne4nE7xZNDh+D3YABneImBN7hnIxGI5E8xhND5G7TYOI5hM7IYPMxHDAQJDE5nIxgIB+ZN8gHf3eMnG4wamE/nM5nPJnpDBxeM5E7mAKE5//5jxCAHsz//8JgoA/AAsPIH4A/AH4A/AH4A/AH4A/AGUFqpB/ABlVqBB/Tn4AaoicvPzkBoLM/ABkU7qa/dZtFJlUBqANL6kUogAFiIgJ6ghMTU/0///5/RiIAEilBiMVqNRiNEC4kEipMogp4H5n//pNB/4XJqtRUQf/NganJJj6aGqtE7pJJABNRqtVNoUEdU6aFhv0bAIhXEAS/IAD5EE3n8xhyiAEMPooECxn8mDAjAEMNiAECqIlfJs9NEslVJkpNlqqamgFUEcUFTU7DkTVB3BTkMFJlAAB//wFdIAhh//IP4AMhvfTqrgrABVP/8QCydVTu1BHClFen4ALh/xIP4AL//QIP6aL+BB/ABfdJv4ALqsRIP5FFqBM/ABUFqNEond/tEoJTEAH4AC//9JoPUoBF/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AlA=")) + }, + face11: { + width : 109, height : 111, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24579,65271,24580,22531,7,35552,47112,2240,65431,65434,39776,22532,43872,65335,35712]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AGVVBpkFqA0kgtVE5tVIppqXGpxGQGqwSRG0IiTG0LGUgo2ffio2ehA1VGwIXWGro2erAYXUjlVDjA2bDbSjcAH4A/AH4A/AH4A/AH4A/AGNVqtQFlOIxAHFhFYGwNVGk8IGoJjFhGFBII4BGtOIF4IIEowKCG00FxGAsg2BwqqDtWgIATbmquA1RmBFgdYxeq0g2orGE1RjFOoJsEUcpoBxuqtDQEAgOEcgZslFguIFgI/BAAZsnrAtENgg2EbMwtFbIQJBOwVVGsosCGooJBwp0DxA1kGw7jEBQLYmFgQ2CMwIJFA4I1ngGFrAACO4tVquAGs8AhFYqo1FAH4A/AH4A/AH4ABrGIAAY0uxA1BwmEww2BwuAGlUIF4OAh2ZzPqtA4CG9NVTYOGl3p9Xq82A0EGG1NVoEK1GAkUil0gxEJzOQotcUE1YgGq0FIsUu93gpGGlWqhGFqo1kguIoHqkFoxEdgFmxFEoEig2EplVUseFxmIpfWpGEpAABwlEG4IEBpnMrA2iGoNUxGEFwIABGgIABGgIABpnI4o1hrHFiItBwIxCAAgLConM5GFGsFVqgqEAA1BigNBiczolVGsGM5nBFQIxEHocRmMUiIOBoo2fa4PM4YpBTwo2CikTodDpjgCqA1dxA1BGwIvBAA0Uikcjk8jhEBpnFGzsIa4NMGpMxNIPDAQUzJIKjdgtUwjRBiY0GiczNAIADikx4dMGztY4g1BZoJrHFwPBNgIBBmkxmlVUblV5lEMgQ2FAwMzmdDGwQABmMzolFGzEFAQWFoJkDGwgrBGoQ2DAIPBidFUbEFJ4VYUIIwDNQY2CibZEikUBoNEpBsYJ4UFwiiDbQjWBiMzGQI3Bmg6CocRphsdLAQzBogACA4bbBAAMUmkUoKABmnFNjguDSAQABHwLfBG4LWCoNDoPB4JsBwpSCbLQ0BijdBmYDCHwVBUwJsECgMUNgVVN6psDwIsCpEzu93OgKYBFgIxBmkzA4IACIoIcCNjNUNgVEi41Bug2DNgKkBjg4BmlENwVIDgIfDGysFwgrBGod3pA2CbgJsBmJsDGwMUpBsBgpvCUa2IFoNEo41CHYLaDNgMUjgABNQSiBovAbK5sChA2CoI1Cu4nBAAdMpjZBNAI9BBINIrhsYUYlIwI1DumBFIOEAANE5kzmc0dYQ1BGQQ1WC4dYwg1EuJsBxHFxFYrFU5nM4PBiJ5CqqiBKgRsVbQeEi5sEwlYqtcqlV4o3CWYI1BpFYQ4RsXbQjYEuNIwtIPwlVrHFcIWExBoCGq4YBGwVYoY1CmfFqmACQtcqoyBpGIxANCwqiWJ4kFSgMzmfMqvICZHFOANVxAHCGrI2EEgIoBrgVMF4iICGzZeCDKlUGrL0YQQJraGwQ3VCwI1cD6QRBAAY0cRgY4OCAZqeAAeILMAA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AFg=")) + }, + face12: { + width : 136, height : 135, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,24579,24580,22531,65400,8,65270,22532,65369,22530,47112,9,11,20482,0,10]), + buffer : require("heatshrink").decompress(atob("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")) + }, + charge: { + width : 176, height : 176, bpp : 4, + transparent : 0, + palette : new Uint16Array([65535,65535,0,19967,2040,61309,2041,17919,44373,2048,19935,40607,2008,38559,17918,2009]), + buffer : require("heatshrink").decompress(atob("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")) + } + } + +// Current face state +var currentFace = "face1"; +// Ordered list of faces for cycling +var faceNumbers = [ + "face1", "face2", "face3", "face4", "face5", "face6", + "face7", "face8", "face9", "face10", "face11", "face12" +]; + +// Get a random Meeseeks face +function getRandomFace() { + return faceNumbers[Math.floor(Math.random() * faceNumbers.length)]; +} + +// Set a new random face +function setRandomFace() { + currentFace = getRandomFace(); +} + +// Cycle to the next face in order +function setNextFace() { + var idx = faceNumbers.indexOf(currentFace); + if (idx < 0) idx = 0; + currentFace = faceNumbers[(idx + 1) % faceNumbers.length]; +} + +// Decompress sprite on demand to save memory +function getSprite(spriteName) { + var sprite = meeseeksSprites[spriteName]; + if (!sprite.buffer) { + // Support legacy heatshrink-compressed base64 (sprite.data) + if (sprite.data) { + sprite.buffer = require("heatshrink").decompress(atob(sprite.data)); + // Support raw base64 pixel data from Espruino Image Converter (Image Object, no compression) + } else if (sprite.raw) { + sprite.buffer = E.toArrayBuffer(atob(sprite.raw)); + } + } + return sprite; +} + +// Draw the Meeseeks face +function drawMeeseeksFace() { + var isCharging = Bangle.isCharging(); + var faceImage; + + // Show charge face when charging + if (isCharging) { + faceImage = getSprite("charge"); + } else { + faceImage = getSprite(currentFace); + } + + // Draw the face centered on screen based on actual sprite dimensions + var centerX = (g.getWidth() - faceImage.width) / 2; + var centerY = (g.getHeight() - faceImage.height) / 2; + g.drawImage(faceImage, centerX, centerY, {transparent: faceImage.transparent}); +} + +// ------- Aging spots overlay (more as battery goes down) ------- +var spotCache = { batteryBucket : -1, w:0, h:0, spots : [] }; + +function randomBetween(min, max) { + return Math.floor(min + Math.random() * (max - min + 1)); +} + +function computeSpots(centerX, centerY, width, height, count) { + var spots = []; + var margin = 6; // keep a small inset from edges + for (var i = 0; i < count; i++) { + var x = randomBetween(centerX + margin, centerX + width - margin); + var y = randomBetween(centerY + margin, centerY + height - margin); + var baseR = randomBetween(1, 3); // base radius + var blobs = randomBetween(1, 3); // draw 1-3 small blobs around base + var blobList = []; + for (var b = 0; b < blobs; b++) { + var ox = randomBetween(-2, 2); + var oy = randomBetween(-2, 2); + var r = Math.max(1, baseR + randomBetween(-1, 1)); + blobList.push({ x:x+ox, y:y+oy, r:r }); + } + spots.push(blobList); + } + return spots; +} + +// Lightweight stipple fill to simulate translucency +function fillCircleStipple(cx, cy, r, spacing, phase) { + if (r <= 0) return; + var rr = r*r; + for (var dy = -r; dy <= r; dy++) { + var y = cy + dy; + var dxMax = Math.floor(Math.sqrt(rr - dy*dy)); + for (var dx = -dxMax; dx <= dxMax; dx++) { + var x = cx + dx; + if (((dx + dy + phase) % spacing) === 0) g.setPixel(x, y); + } + } +} + +function drawSpotsOverlay() { + if (Bangle.isCharging()) return; // no aging while charging + var w = g.getWidth(); + var h = g.getHeight(); + var centerX = 0; + var centerY = 0; + var b = E.getBattery(); + // Bucketize to reduce flicker/regen + var bucket = Math.max(0, Math.min(20, Math.floor((100 - b) / 5))); // 0..20 + var maxSpots = 60; // many at low battery + var spotsWanted = Math.round(maxSpots * Math.min(1, Math.max(0, (100 - b) / 80))); // 100->0, 20->~max + + if (spotCache.batteryBucket !== bucket || spotCache.w !== w || spotCache.h !== h) { + spotCache.batteryBucket = bucket; + spotCache.w = w; + spotCache.h = h; + spotCache.spots = computeSpots(centerX, centerY, w, h, spotsWanted); + } + // Color: dev blue; outlines + stipple for quasi-transparency + g.setColor(0, 0, 0.5); + for (var i = 0; i < spotCache.spots.length; i++) { + var cluster = spotCache.spots[i]; + for (var j = 0; j < cluster.length; j++) { + var c = cluster[j]; + g.drawCircle(c.x, c.y, c.r); + // sparse interior points; spacing 3 gives light fill + fillCircleStipple(c.x, c.y, c.r-1, 3, (i*7 + j*3) % 3); + } + } +} + +function bigThenSmall(big, small, x, y) { + g.setFont("7x11Numeric7Seg", 2); + g.drawString(big, x, y); + x += g.stringWidth(big); + g.setFont("8x12"); + g.drawString(small, x, y); +} + + + + +// schedule a draw for the next minute +var drawTimeout; +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function clearIntervals() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; +} + +function drawClock() { + g.setFont("7x11Numeric7Seg", 3); + g.setColor(1, 1, 1); + g.drawString(require("locale").time(new Date(), 1), 75, 135); + g.setFont("8x12", 2); + g.drawString(require("locale").dow(new Date(), 2).toUpperCase(), 8, 145); + g.setFont("8x12"); + g.drawString(require("locale").month(new Date(), 2).toUpperCase(), 8, 130); + g.setFont("8x12", 2); + const time = new Date().getDate(); + g.drawString(time < 10 ? "0" + time : time, 28, 120); +} + +function drawBattery() { + bigThenSmall(E.getBattery(), "%", 10, 10); +} + + +function getTemperature(){ + try { + var temperature = E.getTemperature(); + if (!temperature || !isFinite(temperature)) return "--"; + // Show Fahrenheit + var f = (temperature * 9/5) + 32; + return Math.round(f) + "F"; + + } catch(ex) { + print(ex) + return "--" + } +} + +function getSteps() { + var steps = Bangle.getHealthStatus("day").steps; + steps = Math.round(steps/1000); + return steps + "k"; +} + + +function draw() { + queueDraw(); + + g.clear(1); + g.setColor(0, 0.7, 1); + g.fillRect(0, 0, g.getWidth(), g.getHeight()); + + // Spots should be above background but below the face + drawSpotsOverlay(); + // Draw the Meeseeks face on top of spots + drawMeeseeksFace(); + + // Foreground metrics + g.setFontAlign(0,-1); + g.setFont("8x12", 2); + g.setColor(1, 1, 1); + g.drawString(getTemperature(), 20, 40); + var hr = Bangle.getHealthStatus().bpm || Bangle.getHealthStatus("last").bpm; + var hrStr = (hr && isFinite(hr)) ? String(Math.round(hr)) : "--"; + g.drawString(hrStr, 15, 70); + g.drawString(getSteps(), 160, 10); + + g.setFontAlign(-1,-1); + drawClock(); + drawBattery(); + + // Hide widgets + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} +} + +Bangle.on("lcdPower", (on) => { + if (on) { + // Set a random face when waking up + setRandomFace(); + draw(); + } else { + clearIntervals(); + } +}); + + +Bangle.on("lock", (locked) => { + clearIntervals(); + draw(); +}); + +Bangle.setUI("clock"); + +// Touch debouncing to prevent rapid face changes +var lastTouchTime = 0; +var touchDebounceMs = 500; // 500ms debounce + +// Independent touch listener so it's not overridden by UI helpers +Bangle.on('touch', function(button, xy) { + var now = Date.now(); + + // Debounce rapid touches + if (now - lastTouchTime < touchDebounceMs) { + return; + } + + // Get current sprite to check its dimensions + var currentSprite = Bangle.isCharging() ? getSprite("charge") : getSprite(currentFace); + var centerX = (g.getWidth() - currentSprite.width) / 2; + var centerY = (g.getHeight() - currentSprite.height) / 2; + + // Define touch zones - exclude top area for widget bar access + var widgetBarHeight = 40; // Reserve top 40px for widget bar gestures + var faceTouchMargin = 20; // Reduce touch area to center of face + + // Check if tap is within the center area of Meeseeks face (excluding top for widget bar) + if (xy && xy.x >= centerX + faceTouchMargin && xy.x <= centerX + currentSprite.width - faceTouchMargin && + xy.y >= centerY + faceTouchMargin && xy.y <= centerY + currentSprite.height - faceTouchMargin && + xy.y > widgetBarHeight) { // Exclude top area for widget bar access + // Only change face if not charging + if (!Bangle.isCharging()) { + lastTouchTime = now; + setNextFace(); + draw(); + } + } +}); + +// Fallbacks for devices/firmware without touch delivery +if (typeof BTN1 !== 'undefined') { + setWatch(function() { + if (!Bangle.isCharging()) { setNextFace(); draw(); } + }, BTN1, {repeat:true, edge:'falling'}); +} + +Bangle.on('swipe', function(LR, UD) { + if (!Bangle.isCharging()) { setNextFace(); draw(); } +}); + +// Load widgets, but don't show them +Bangle.loadWidgets(); +require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe +g.clear(1); +// Set initial random face +setRandomFace(); +draw(); diff --git a/apps/meseeks/app.png b/apps/meseeks/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e54ea5cc6c1812a8ab2c104f5f531321ff807dff GIT binary patch literal 5987 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 literal 0 HcmV?d00001 diff --git a/apps/meseeks/data.json b/apps/meseeks/data.json new file mode 100644 index 0000000000..0fcf7dd7dd --- /dev/null +++ b/apps/meseeks/data.json @@ -0,0 +1 @@ +{"tasks":"", "weather":[]}; diff --git a/apps/meseeks/metadata.json b/apps/meseeks/metadata.json new file mode 100644 index 0000000000..4f404d0605 --- /dev/null +++ b/apps/meseeks/metadata.json @@ -0,0 +1,17 @@ +{ "id": "meseeks", + "name": "Mr Meeseeks", + "shortName":"MeSeeks", + "version":"0.0.2", + "description": "Mr Meeseeks clock with random faces and battery-dependent freckles overlay.", + "icon": "app.png", + "tags": "clock", + "type": "clock", + "supports" : ["BANGLEJS", "BANGLEJS2"], + "screenshots": [{"url":"screenshot01.png"}, {"url":"screenshot02.png"}, {"url":"screenshot03.png"}], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"meseeks.app.js","url":"app.js"}, + {"name":"meseeks.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/meseeks/screenshot01.png b/apps/meseeks/screenshot01.png new file mode 100644 index 0000000000000000000000000000000000000000..9c23d3e23f34b80237f29bd5c7c238c13f74157a GIT binary patch literal 8931 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 uQ{e^%u{T-kv|p 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

6OW^B=)4q=?B3e3qLs(PA>*iuPh z>&C>tJ;Z%rdY!JY&FwGkE-|*Fmgv7<-l2z8dZ}J1BZ`1lHT(PU?V{5CB_PSI%Z-nu ztetxH^g~Ad6mHy^q&$S9UU@X;$JriGLhd8V0OgjD+z{e@_HHjZMHn8^q<*w;=76PS z0#$QeLfog~OIlgSCk)z%rneI-$O7Z#x@QCHZgiQmT}`BGwX2XX{Sa26gx>k^ZdL3*!p-y+bpy_T6$xoi zy7!V(T`nA=M1Z-D>4Q>J=lo|t`XGKs{@%2UO?G$ zSw3gOYPXk#)k0MmhAr25T+P;wpAl0sbAc*_tbKMs1a(f%Wl!MticQ%GLMLXBRap_q za7%F3e|xBsjjeKqQzC!D^z{nJ08cgqH6Oy_?$`{nPcvm4V)luGeys$@*^%?)iS5dCCN!I5)iR@sNJJ>G%y!GlK~PDdbX$YzlLmr}xgf*fwr|2#Q5 zsAd1QL?Ahww}X<2fv?ja`Th0BA-c9(MTE`#gbm?a+h_;KQrs*86OEwHCfJ{EYV_s8 ztI%C&671|~(X<5echLEq-e}>{I)V%P#I(;zcWa%g@{tcK8s4k2Ik=cDHF+$1IcLL} zz!PQec;yGLd~osX+q#%`U?gN&?HpovD`&eR8fE1WdzOse_G|F?TV<+@BZzoolA^{@ zosg*MUYzeQa4Y7I5Bo32*`;%K^$*{*@rk)xS}?W0d6*>jJRVz=WwKy>40cSoSqzDw z?QtHbbPLBn8HuAbZTIVZ-X53TYTHTZcptY7c09?NK9_p(9scM1c)-HHa{)3uyQ+dgOuh~dfL2eY}*Yg7daTV&wL$Z1FXp!$St zIMPKHUer4vul`|P*H42}9nDZJ`Il`NtmsE7!orRMa77c4Zb_Nlf#kDxwVTMBgF2^3 zgWcyqwt%^y97Ht&4!euQ&q2cOf{y3u*ddSc-rJPfB>D-so7of%Ogxsq1O8zMReG)= zM7DcvS0fW5cb@lwt_m`*Wx3x09n-gxhNXMa6gLpL1?W4hh9ALDQ^tj p*)Lq6P)5eA+|I#X`3IKjLf!F!`rT}3#`%{EFO=1kN)^lk{s&XrmOTIf literal 0 HcmV?d00001 diff --git a/apps/meseeks/screenshot03.png b/apps/meseeks/screenshot03.png new file mode 100644 index 0000000000000000000000000000000000000000..93c5fd6e9c33f1346c875a639a8c3fdfd4ff5327 GIT binary patch literal 5482 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 literal 0 HcmV?d00001 From c5216eabe1cdb03ce4febdd46a64e78e94a405c2 Mon Sep 17 00:00:00 2001 From: LucienStorm Date: Wed, 22 Oct 2025 21:08:50 -0500 Subject: [PATCH 3/4] Updates to all three: bmoface, doomguy, and meseeks Sorry about it being 3 apps at once. I finally figured out how to run the npm test locally and worked on it until the errors were cleared. --- apps/bmoface/ChangeLog | 2 +- apps/bmoface/metadata.json | 2 +- apps/bmoface/settings.js | 2 +- apps/doomguy/ChangeLog | 2 +- apps/doomguy/app-icon.js | 2 +- apps/doomguy/doomguy.settings.js | 2 +- apps/doomguy/metadata.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/bmoface/ChangeLog b/apps/bmoface/ChangeLog index 0511931c9d..c503e7b873 100644 --- a/apps/bmoface/ChangeLog +++ b/apps/bmoface/ChangeLog @@ -8,7 +8,7 @@ 0.0.08: Fixed lock screen character variable error, separated lock screen logic 0.0.09: Improved lock screen character-specific drawing and positioning 0.0.1: Major release with all core features complete -0.1.1: Code refactoring and lock screen improvements +0.11: Code refactoring and lock screen improvements ## Attribution Based on the Advanced Casio Clock by dotgreg (https://github.com/dotgreg/advCasioBangleClock) \ No newline at end of file diff --git a/apps/bmoface/metadata.json b/apps/bmoface/metadata.json index cfedf2e3f3..5dbda351b9 100644 --- a/apps/bmoface/metadata.json +++ b/apps/bmoface/metadata.json @@ -2,7 +2,7 @@ "id": "bmoface", "name": "BMO Face", "shortName": "BMO", - "version": "0.1.2", + "version": "0.11", "description": "A watch face inspired by BMO that shows time, temp, steps and HR. Sleeps to -_- when locked.", "icon": "app.png", "tags": "clock", diff --git a/apps/bmoface/settings.js b/apps/bmoface/settings.js index 5269c27f31..c2341d0934 100644 --- a/apps/bmoface/settings.js +++ b/apps/bmoface/settings.js @@ -44,4 +44,4 @@ } } }); -})(back); \ No newline at end of file +})(back) \ No newline at end of file diff --git a/apps/doomguy/ChangeLog b/apps/doomguy/ChangeLog index 850baa4ec5..f5332531a2 100644 --- a/apps/doomguy/ChangeLog +++ b/apps/doomguy/ChangeLog @@ -7,7 +7,7 @@ 0.07: Changed date text color to yellow 0.08: Optimized memory usage with 4-bit color sprites and heatshrink compression 0.09: Added interactive tap feature - tap Doomguy's face to flash yellow and show damage, daily hit counter with persistent storage -0.10: Added temperature unit settings (Fahrenheit/Celsius toggle) +0.11: Added temperature unit settings (Fahrenheit/Celsius toggle) ## Attribution Based on the Advanced Casio Clock by dotgreg (https://github.com/dotgreg/advCasioBangleClock) diff --git a/apps/doomguy/app-icon.js b/apps/doomguy/app-icon.js index fafa4d9d0b..400739092e 100644 --- a/apps/doomguy/app-icon.js +++ b/apps/doomguy/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("nk8wkHu4A/AH4A/AEdyCidRqNUoICBokVAAIbRuoUBilBolFogACEYNXDp8hGwQADkgiBqlFiMnDp0FiocF6Q6BokUHiBXBDYVD6QcBHQNRPYMHLCVC6XT6YeCop4BqSUPK4ctmYdB6lBTgUQDptwqITBoVNnoACkgbBaiFxqh3BD4NDLIjZBHZ5ZBNoIXBHgMtHQIABqo7QVAQ9Bmi0CHgMUiJ3RAAI7CHINC6jSBHYMFHZ9RqsUpZVCEAURBYNQHZ1QiDTEHYZ1BgMBHZ0FspZCPYchoJkCHZ11sISBqjTBoIDBoruBiALBSp9QG4LTBAgYcDHZw5CDANRHQJ8BHQIKCiFCDhd0F4NEEAVFEANUAQIDBX4IdNCoQ0Bio7CSwKxBH4MRDpoZBWAQABOoNUpdD6XSHYNEDplQilC6SsCqjOBok9AAIFBiTuMLINDCYKxCokEonTAAJGBqhZNC4JaEAoQACHYKVPoq0BqFVisRooZBqT3BXgIdLuQdBoOyqsAZgIfBLwNbIoUiDpd3FwIAB2lLqqzBrkcpckLQQcMu52BloSBCoPTmfSogKBoRZBDpoZB6ckGYMjV4QeBoVNkg7PqVN+c9mY6BmYEE6kVDpt3GIIVB6fULIQCBnphBq4dOqlEoZVBAQM+klNns9MQMXHZ4dBns8TQIZBpYHBBYNHDpypBGgNEqo8BotU7s0XoJZPukUoStBqI1BqtUkfUQYM3Dp11oI7BknFqkUqtLpstkh2PHgVC2m0qNVqPB4lLoVFDiA8BKoJWBPoMcim0OwIdRuNEpYACldEDgMkHaTxCnpYBqtVoVE6KTPeQvTplCoScBkjsPDo0k4Wynu02XUDqqXBqlNmlFokTDijUCrkU6jRBDiy2BqPCoNciIdXAH4A/AH4AFA==")) \ No newline at end of file +require("heatshrink").decompress(atob("mEw4n/80Zpsb+9XylVBoNNlexoksjdMjdzquUrtPomTqvGiMvom0rtEAC1RiIAVC7EWswAEtwOFjYNFswXBieqAAOvAYWxC4lj1/61X///6nIXC2CjErU2CwdZnNwBomWC5EHzWWHwWTsDJFC5MAgw+BAAP7cIwXKABgXX1IX5gu7AAO2RwwXL8UiAAYXQhwWEkUgC54uFGA4XCjQXEFwwwHC4UZ1wuLkUvfYk7C4MV0dQFxQwF2dhC4MR9WVBANSC5JhChxGBC4UbnYJBCxUi4EAh+VC4cRC6JGBC/4XL1YX/C4sVC6EKC4kZ1wXB+QXK8EAg2rC4dq2AXBh4WJlwNBgFj8IXBi02BAQwKFwIABg0+C4MayAXDGBAuDAAOmC4RGCGBQuDC4kTC4owGFwoXKGAwuFC4cfC4wwElYLFL5QANI5QXPF64Xfgu7AAQjHC5Xj1Wq0cznJ3Qh2pqMRiMVseXC5OWs1r3dm3djyoWBAAMW1RNDAAJHDHoJBBAAIJBAAhNEmejmwXBB4oAQC64=")) \ No newline at end of file diff --git a/apps/doomguy/doomguy.settings.js b/apps/doomguy/doomguy.settings.js index c6c3a3e9d0..94b3648fa4 100644 --- a/apps/doomguy/doomguy.settings.js +++ b/apps/doomguy/doomguy.settings.js @@ -63,4 +63,4 @@ // Show the menu showSettingsMenu(); -})(back); +})(back) diff --git a/apps/doomguy/metadata.json b/apps/doomguy/metadata.json index aff59b6110..c965894c10 100644 --- a/apps/doomguy/metadata.json +++ b/apps/doomguy/metadata.json @@ -4,7 +4,7 @@ "version":"0.11", "description": "DOOM-inspired watch face with animated Doomguy face that reacts to battery level. Interactive tap feature lets you hit Doomguy with yellow flash effects and damage reactions. Features daily hit counter, battery-reactive faces, animated glances, heart rate, steps, temperature, and charging indicators.", "icon": "app.png", - "tags": "clock,game,retro,doom", + "tags": "clock,retro,doom", "type": "clock", "screenshots": [ { "url": "screenshot01.png" } From e517b27a107d1ad2e3db6df20ad43c831d357336 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Tue, 25 Nov 2025 08:26:07 +0000 Subject: [PATCH 4/4] meseeks: fix version mismatch, match espruino style --- apps/meseeks/ChangeLog | 7 ++----- apps/meseeks/README.md | 4 ++-- apps/meseeks/metadata.json | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/meseeks/ChangeLog b/apps/meseeks/ChangeLog index 632228d829..07131b672f 100644 --- a/apps/meseeks/ChangeLog +++ b/apps/meseeks/ChangeLog @@ -1,5 +1,2 @@ -0.0.1: Initial release with Mr Meeseeks character faces -0.0.2: Added battery-dependent aging spots overlay, tap-to-cycle faces, temperature in Fahrenheit - -## Attribution -Based on the Advanced Casio Clock by dotgreg (https://github.com/dotgreg/advCasioBangleClock) \ No newline at end of file +0.01: Initial release with Mr Meeseeks character faces +0.02: Added battery-dependent aging spots overlay, tap-to-cycle faces, temperature in Fahrenheit diff --git a/apps/meseeks/README.md b/apps/meseeks/README.md index 344e6e0c64..ecc79412f1 100644 --- a/apps/meseeks/README.md +++ b/apps/meseeks/README.md @@ -11,7 +11,7 @@ A Rick and Morty inspired watch face featuring Mr Meeseeks with multiple express ### Battery-Dependent Aging - **Aging Spots**: Blue spots appear on screen as battery decreases -- **Progressive Aging**: +- **Progressive Aging**: - 100% battery: No spots - 80% battery: Few spots - 50% battery: Moderate spots @@ -56,4 +56,4 @@ A Rick and Morty inspired watch face featuring Mr Meeseeks with multiple express ## Installation -Upload via Bangle.js App Loader or manually install the files in the `meseeks` folder. \ No newline at end of file +Upload via Bangle.js App Loader or manually install the files in the `meseeks` folder. diff --git a/apps/meseeks/metadata.json b/apps/meseeks/metadata.json index 4f404d0605..d3fc54a439 100644 --- a/apps/meseeks/metadata.json +++ b/apps/meseeks/metadata.json @@ -1,7 +1,7 @@ { "id": "meseeks", "name": "Mr Meeseeks", "shortName":"MeSeeks", - "version":"0.0.2", + "version":"0.02", "description": "Mr Meeseeks clock with random faces and battery-dependent freckles overlay.", "icon": "app.png", "tags": "clock",