From f95e1508872efb78effa55324fc3ea1c2b3ee6f5 Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:35:03 -0400 Subject: [PATCH 01/13] Create app.js Added the code for the app. --- apps/bblobface/app.js | 768 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 768 insertions(+) create mode 100644 apps/bblobface/app.js diff --git a/apps/bblobface/app.js b/apps/bblobface/app.js new file mode 100644 index 0000000000..579a6bbb43 --- /dev/null +++ b/apps/bblobface/app.js @@ -0,0 +1,768 @@ +{ + // ~~ Variables for clock ~~ + let clockDrawTimeout; + let twelveHourTime = require('Storage').readJSON('setting.json', 1)['12hour']; + let updateSeconds = !Bangle.isLocked(); + let batteryLevel = E.getBattery(); + + // ~~ Variables for game logic ~~ + const NUM_COLORS = 6; + const NUISANCE_COLOR = 7; + let grid = [ + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]) + ]; + let hiddenRow = new Uint8Array([0, 0, 0, 0, 0, 0]); + let nextQueue = [{pivot: 1, leaf: 1}, {pivot: 1, leaf: 1}]; + let currentPair = {pivot: 0, leaf: 0}; + let dropCoordinates = {pivotX: 2, pivotY: 11, leafX: 2, leafY: 10}; + let pairX = 2; + let pairOrientation = 0; //0 is up, 1 is right, 2 is down, 3 is left + let slotsToCheck = []; + let selectedColors; + let lastChain = 0; + let gameLost = false; + let gamePaused = false; + let midChain = false; + + /* + Sets up a new game. + Must be called once before the first round. + */ + let restartGame = function() { + grid = [ + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]) + ]; + hiddenRow = new Uint8Array([0, 0, 0, 0, 0, 0]); + currentPair = {pivot: 0, leaf: 0}; + pairX = 2; + pairOrientation = 0; //0 is up, 1 is right, 2 is down, 3 is left + slotsToCheck = []; + gameLost = false; + lastChain = 0; + + //Set up random colors + selectedColors = new Uint8Array([1, 2, 3, 4, 5, 6]); + for (let i = NUM_COLORS - 1; i > 0; i--) { + let swap = selectedColors[i]; + let swapIndex = Math.floor(Math.random() * (i + 1)); + selectedColors[i] = selectedColors[swapIndex]; + selectedColors[swapIndex] = swap; + } + + //Create the first two pairs (Always in the first three colors) + nextQueue[0].pivot = selectedColors[Math.floor(Math.random() * 3)]; + nextQueue[0].leaf = selectedColors[Math.floor(Math.random() * 3)]; + nextQueue[1].pivot = selectedColors[Math.floor(Math.random() * 3)]; + nextQueue[1].leaf = selectedColors[Math.floor(Math.random() * 3)]; + }; + + /* + Readies the next pair and generates a new one for the queue. + */ + let newPair = function() { + currentPair.pivot = nextQueue[0].pivot; + currentPair.leaf = nextQueue[0].leaf; + + nextQueue[0].pivot = nextQueue[1].pivot; + nextQueue[0].leaf = nextQueue[1].leaf; + + nextQueue[1].pivot = selectedColors[Math.floor(Math.random() * 4)]; + nextQueue[1].leaf = selectedColors[Math.floor(Math.random() * 4)]; + + pairX = 2; + pairOrientation = 0; + + calcDropCoordinates(); + }; + + /* + Calculates the coordinates at which the current pair will be placed when quick dropped. + */ + let calcDropCoordinates = function() { + dropCoordinates.pivotX = pairX; + + //Find Y coordinate of pivot + dropCoordinates.pivotY = -2; + for (let i = 11; i >= 0; i--) { + if (grid[i][pairX] == 0) { + dropCoordinates.pivotY = i; + break; + } + } + if (dropCoordinates.pivotY == -2 && hiddenRow[pairX] == 0) + dropCoordinates.pivotY = -1; + + //Find coordinates of leaf + if (pairOrientation == 1) { + dropCoordinates.leafX = pairX + 1; + + dropCoordinates.leafY = -2; + for (let i = 11; i >= 0; i--) { + if (grid[i][pairX + 1] == 0) { + dropCoordinates.leafY = i; + break; + } + } + if (dropCoordinates.leafY == -2 && hiddenRow[pairX + 1] == 0) + dropCoordinates.leafY = -1; + } else if (pairOrientation == 3) { + dropCoordinates.leafX = pairX - 1; + + dropCoordinates.leafY = -2; + for (let i = 11; i >= 0; i--) { + if (grid[i][pairX - 1] == 0) { + dropCoordinates.leafY = i; + break; + } + } + if (dropCoordinates.leafY == -2 && hiddenRow[pairX - 1] == 0) + dropCoordinates.leafY = -1; + } else if (pairOrientation == 2) { + dropCoordinates.leafX = pairX; + dropCoordinates.leafY = dropCoordinates.pivotY; + dropCoordinates.pivotY--; + } else { + dropCoordinates.leafX = pairX; + dropCoordinates.leafY = dropCoordinates.pivotY - 1; + } + }; + + /* + Moves the current pair a certain number of slots. + */ + let movePair = function(dx) { + pairX += dx; + + if (dx < 0) { + if (pairX < (pairOrientation == 3 ? 1 : 0)) + pairX = (pairOrientation == 3 ? 1 : 0); + } + if (dx > 0) { + if (pairX > (pairOrientation == 1 ? 4 : 5)) + pairX = (pairOrientation == 1 ? 4 : 5); + } + + calcDropCoordinates(); + }; + + /* + Rotates the pair in the given direction around the pivot. + */ + let rotatePair = function(clockwise) { + pairOrientation += (clockwise ? 1 : -1); + if (pairOrientation > 3) + pairOrientation = 0; + if (pairOrientation < 0) + pairOrientation = 3; + + if (pairOrientation == 1 && pairX == 5) + pairX = 4; + if (pairOrientation == 3 && pairX == 0) + pairX = 1; + + calcDropCoordinates(); + }; + + /* + Places the current pair at the drop coordinates. + */ + let quickDrop = function() { + if (dropCoordinates.pivotY == -1) { + hiddenRow[dropCoordinates.pivotX] = currentPair.pivot; + } else if (dropCoordinates.pivotY > -1) { + grid[dropCoordinates.pivotY][dropCoordinates.pivotX] = currentPair.pivot; + } + + if (dropCoordinates.leafY == -1) { + hiddenRow[dropCoordinates.leafX] = currentPair.leaf; + } else if (dropCoordinates.leafY > -1) { + grid[dropCoordinates.leafY][dropCoordinates.leafX] = currentPair.leaf; + } + + currentPair.pivot = 0; + currentPair.leaf = 0; + }; + + /* + Makes all blobs fall to the lowest available slot. + All blobs that fall will be added to slotsToCheck. + */ + let settleBlobs = function() { + for (let x = 0; x < 6; x++) { + let lowestOpen = 11; + for (let y = 11; y >= 0; y--) { + if (grid[y][x] != 0) { + if (y != lowestOpen) { + grid[lowestOpen][x] = grid[y][x]; + grid[y][x] = 0; + addSlotToCheck(x, lowestOpen); + } + lowestOpen--; + } + } + + if (lowestOpen >= 0 && hiddenRow[x] != 0) { + grid[lowestOpen][x] = hiddenRow[x]; + hiddenRow[x] = 0; + addSlotToCheck(x, lowestOpen); + } + } + }; + + /* + Adds a slot to slotsToCheck. This slot will be checked for a pop + next time popAll is called. + */ + let addSlotToCheck = function(x, y) { + slotsToCheck.push({x: x, y: y}); + }; + + /* + Checks for a pop at every slot in slotsToCheck. + Pops at all locations. + */ + let popAll = function() { + let result = {pops: 0}; + while(slotsToCheck.length > 0) { + let coord = slotsToCheck.pop(); + if (grid[coord.y][coord.x] != 0 && grid[coord.y][coord.x] != NUISANCE_COLOR) { + if (checkSlotForPop(coord.x, coord.y)) + result.pops += 1; + } + } + return result; + }; + + /* + Checks a specific slot for a pop. + If there are four or more adjacent blobs of the same color, they are removed. + */ + let checkSlotForPop = function(x, y) { + let toDelete = [ + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]), + new Uint8Array([0, 0, 0, 0, 0, 0]) + ]; + let blobsInClump = 0; + let color = grid[y][x]; + let toCheck = [{x: x, y: y}]; + + //Count every blob in this clump + while (toCheck.length > 0) { + let coord = toCheck.pop(); + if (grid[coord.y][coord.x] == color && toDelete[coord.y][coord.x] == 0) { + blobsInClump++; + toDelete[coord.y][coord.x] = 1; + if (coord.x > 0) toCheck.push({x: coord.x - 1, y: coord.y}); + if (coord.x < 5) toCheck.push({x: coord.x + 1, y: coord.y}); + if (coord.y > 0) toCheck.push({x: coord.x, y: coord.y - 1}); + if (coord.y < 11) toCheck.push({x: coord.x, y: coord.y + 1}); + } + if (grid[coord.y][coord.x] == NUISANCE_COLOR && toDelete[coord.y][coord.x] == 0) + toDelete[coord.y][coord.x] = 1; //For erasing garbage + } + + //If there are at least four blobs in this clump, remove them from the grid and draw a pop. + if (blobsInClump >= 4) { + for (let y = 0; y < 12; y++) { + for (let x = 0; x < 6; x++) { + if (toDelete[y][x] == 1) { + grid[y][x] = 0; + + //Clear the blob out of the slot + g.setBgColor(0, 0, 0); + g.clearRect((x*18)+34, (y*14)+7, (x*18)+52, (y*14)+21); + + //Draw the pop + let colorInfo = getColor(color); + g.setColor(colorInfo.r, colorInfo.g, colorInfo.b); + if (color < NUISANCE_COLOR) { + //A fancy pop for popped colors! + g.drawEllipse((x*18)+36, (y*14)+7, (x*18)+50, (y*14)+21); + g.drawEllipse((x*18)+27, (y*14)-2, (x*18)+59, (y*14)+30); + } else if (color == NUISANCE_COLOR) { + //Nuisance Blobs are simply crossed out. + //TODO: Nuisance Blobs are currently unusued, but also untested. Test before use. + g.drawLine((x*18)+34, (y*14)+7, (x*18)+52, (y*14)+21); + } + } + } + } + return true; + } + return false; + }; + + // Variables for graphics + let oldGhost = {pivotX: 0, pivotY: 0, leafX: 0, leafY: 0}; + + /* + Draws the time on the side. + */ + let drawTime = function(scheduleNext) { + //Change this to alter the y-coordinate of the top edge. + let dy = 25; + + g.setBgColor(0, 0, 0); + g.clearRect(2, dy, 30, dy + 121); + + //Draw the time + let d = new Date(); + let h = d.getHours(), m = d.getMinutes(); + if (twelveHourTime) { + let mer = 'A'; + if (h >= 12) mer = 'P'; + if (h >= 13) h -= 12; + if (h == 0) h = 12; + + g.setColor(1, 1, 1); + g.setFont("Vector", 12); + g.drawString(mer, 23, dy + 63); + } + let hs = h.toString().padStart(2, 0); + let ms = m.toString().padStart(2, 0); + g.setFont("Vector", 24); + g.setColor(1, 0.2, 1); + g.drawString(hs, 3, dy + 21); + g.setColor(0.5, 0.5, 1); + g.drawString(ms, 3, dy + 42); + + //Draw seconds + let s = d.getSeconds(); + if (updateSeconds) { + let ss = s.toString().padStart(2, 0); + g.setFont("Vector", 12); + g.setColor(0.2, 1, 0.2); + g.drawString(ss, 3, dy + 63); + } + + //Draw the date + let dayString = d.getDate().toString(); + let dayNames = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]; + let dayName = dayNames[d.getDay()]; + let monthNames = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JLY", "AUG", "SEP", "OCT", "NOV", "DEC"]; + let monthName = monthNames[d.getMonth()]; + g.setColor(1, 1, 1); + g.setFont("Vector", 12); + g.drawString(monthName, 3, dy + 84); + g.drawString(dayString, 3, dy + 97); + g.setColor(0.5, 0.5, 0.5); + g.drawString(dayName, 3, dy + 110); + + //Draw battery + if (s == 0) batteryLevel = E.getBattery(); + if (Bangle.isCharging()) { + g.setColor(0, 0, 1); + } else if (batteryLevel <= 15) { + g.setColor(1, 0, 0); + } else { + g.setColor(0, 1, 0); + } + g.drawString(batteryLevel + "%", 3, dy + 1); + + //Schedule the next draw if requested. + if (!scheduleNext) return; + if (clockDrawTimeout) clearTimeout(clockDrawTimeout); + let interval = updateSeconds ? 1000 : 60000; + clockDrawTimeout = setTimeout(function() { + clockDrawTimeout = undefined; + drawTime(true); + }, interval - (Date.now() % interval)); + }; + + /* + Returns a tuple in the format {r, g, b} with the color + of the blob with the given ID. + This saves memory compared to having the colors stored in an array. + */ + let getColor = function(color) { + if (color == 1) + return {r: 1, g: 0, b: 0}; + if (color == 2) + return {r: 0, g: 1, b: 0}; + if (color == 3) + return {r: 0, g: 0, b: 1}; + if (color == 4) + return {r: 1, g: 1, b: 0}; + if (color == 5) + return {r: 1, g: 0, b: 1}; + if (color == 6) + return {r: 0, g: 1, b: 1}; + if (color == 7) + return {r: 0.5, g: 0.5, b: 0.5}; + return {r: 1, g: 1, b: 1}; + }; + + /* + Clears the screen and draws the background. + */ + let drawBackground = function() { + //Background + g.setBgColor(0.5, 0.2, 0.1); + g.clear(); + g.setBgColor(0, 0, 0); + g.clearRect(33, 0, 142, 176); + g.setBgColor(0.5, 0.5, 0.5); + g.clearRect(33, 4, 142, 6); + + //Reset button + g.setBgColor(0.5, 0.5, 0.5); + g.setColor(0, 0, 0); + g.clearRect(143, 150, 175, 175); + g.setFont("Vector", 30); + g.drawString("R", 152, 150); + + //Pause button + g.clearRect(0, 150, 32, 175); + g.fillRect(9, 154, 13, 171); + g.fillRect(18, 154, 22, 171); + }; + + /* + Draws a box under the next queue that displays + the current value of lastChain. + */ + let drawChainCount = function() { + g.setBgColor(0, 0, 0); + g.setColor(1, 0.2, 0.2); + g.setFont("Vector", 23); + g.clearRect(145, 42, 173, 64); + + if (lastChain > 0) { + if (lastChain < 10) g.drawString(lastChain, 154, 44); + if (lastChain >= 10) g.drawString(lastChain, 147, 44); + } + }; + + /* + Draws the blob at the given slot. + */ + let drawBlobAtSlot = function(x, y) { + //If this blob is in the hidden row, clear it out and stop. + if (y < 0) { + g.setBgColor(0, 0, 0); + g.clearRect((x*18)+34, 0, (x*18)+52, 3); + return; + } + + //First, clear what was in that slot. + g.setBgColor(0, 0, 0); + g.clearRect((x*18)+34, (y*14)+7, (x*18)+52, (y*14)+21); + + let color = grid[y][x]; + + if (color != 0) { + let myColor = getColor(color); + g.setColor(myColor.r, myColor.g, myColor.b); + g.fillEllipse((x*18)+34, (y*14)+7, (x*18)+52, (y*14)+21); + g.setColor(1, 1, 1); + g.drawEllipse((x*18)+34, (y*14)+7, (x*18)+52, (y*14)+21); + } + }; + + /* + Draws the ghost piece. + clearOld: if the previous location of the ghost piece should be cleared. + */ + let drawGhostPiece = function(clearOld) { + if (clearOld) { + g.setColor(0, 0, 0); + g.fillRect((oldGhost.pivotX*18)+38, (oldGhost.pivotY*14)+8, (oldGhost.pivotX*18)+47, (oldGhost.pivotY*14)+17); + g.fillRect((oldGhost.leafX*18)+38, (oldGhost.leafY*14)+8, (oldGhost.leafX*18)+47, (oldGhost.leafY*14)+17); + } + + let pivotX = dropCoordinates.pivotX; + let pivotY = dropCoordinates.pivotY; + let leafX = dropCoordinates.leafX; + let leafY = dropCoordinates.leafY; + let pivotColor = getColor(currentPair.pivot); + let leafColor = getColor(currentPair.leaf); + + g.setColor(pivotColor.r, pivotColor.g, pivotColor.b); + g.fillRect((pivotX*18)+40, (pivotY*14)+10, (pivotX*18)+45, (pivotY*14)+15); + g.setColor(1, 1, 1); + g.drawRect((pivotX*18)+38, (pivotY*14)+8, (pivotX*18)+47, (pivotY*14)+17); + g.setColor(leafColor.r, leafColor.g, leafColor.b); + g.fillRect((leafX*18)+40, (leafY*14)+10, (leafX*18)+45, (leafY*14)+15); + + oldGhost = {pivotX: pivotX, pivotY: pivotY, leafX: leafX, leafY: leafY}; + }; + + /* + Draws the next queue. + */ + let drawNextQueue = function() { + g.setBgColor(0, 0, 0); + g.clearRect(145, 4, 173, 28); + + let p1 = nextQueue[0].pivot; + let l1 = nextQueue[0].leaf; + let p2 = nextQueue[1].pivot; + let l2 = nextQueue[1].leaf; + let p1C = getColor(p1); + let l1C = getColor(l1); + let p2C = getColor(p2); + let l2C = getColor(l2); + + g.setColor(p1C.r, p1C.g, p1C.b); + g.fillEllipse(146, 17, 157, 28); + g.setColor(l1C.r, l1C.g, l1C.b); + g.fillEllipse(146, 5, 157, 16); + g.setColor(p2C.r, p2C.g, p2C.b); + g.fillEllipse(162, 17, 173, 28); + g.setColor(l2C.r, l2C.g, l2C.b); + g.fillEllipse(162, 5, 173, 16); + + g.setColor(1, 1, 1); + g.drawLine(159, 4, 159, 28); + g.drawEllipse(146, 17, 157, 28); + g.drawEllipse(146, 5, 157, 16); + g.drawEllipse(162, 17, 173, 28); + g.drawEllipse(162, 5, 173, 16); + }; + + /* + Redraws the screen, except for the ghost piece. + */ + let redrawBoard = function() { + drawBackground(); + drawNextQueue(); + drawChainCount(); + drawTime(false); + for (let y = 0; y < 12; y++) { + for (let x = 0; x < 6; x++) { + drawBlobAtSlot(x, y); + } + } + }; + + /* + Toggles the pause screen. + */ + let togglePause = function() { + gamePaused = !gamePaused; + + if (gamePaused) { + g.setBgColor(0.5, 0.2, 0.1); + g.clear(); + drawTime(false); + + g.setBgColor(0, 0, 0); + g.setColor(1, 1, 1); + g.clearRect(48, 66, 157, 110); + g.setFont("Vector", 20); + g.drawString("Tap here\nto unpause", 50, 68); + + require("widget_utils").show(); + Bangle.drawWidgets(); + } else { + require("widget_utils").hide(); + + redrawBoard(); + drawGhostPiece(false); + + //Display the loss text if the game is lost. + if (gameLost) { + g.setBgColor(0, 0, 0); + g.setColor(1, 1, 1); + g.clearRect(33, 73, 142, 103); + g.setFont("Vector", 20); + g.drawString("You Lose", 43, 80); + } + } + }; + + // ~~ Events ~~ + let dragAmnt = 0; + + let onTouch = (z, e) => { + if (midChain) return; + + if (gamePaused) { + if (e.x >= 40 && e.y >= 58 && e.x <= 165 && e.y <= 118) { + g.setBgColor(1, 1, 1); + g.clearRect(48, 66, 157, 110); + g.flip(); + togglePause(); + } + } else { + //Tap reset button + if (e.x >= 143 && e.y >= 150) { + restartGame(); + newPair(); + redrawBoard(); + drawGhostPiece(false); + g.flip(); + return; + } + + //Tap pause button + if (e.x <= 32 && e.y >= 150) { + togglePause(); + return; + } + + //While playing, rotate pieces. + if (!gameLost && !gamePaused) { + if (e.x < 88) { + rotatePair(false); + drawGhostPiece(true); + } else { + rotatePair(true); + drawGhostPiece(true); + } + } + } + }; + + Bangle.on("touch", onTouch); + + let onDrag = (e) => { + if (gameLost || gamePaused || midChain) return; + + //Do nothing if the user is dragging down so that they don't accidentally move while dropping + if (e.dy >= 5) { + return; + } + + dragAmnt += e.dx; + if (e.b == 0) { + dragAmnt = 0; + } + if (dragAmnt >= 20) { + movePair(Math.floor(dragAmnt / 20)); + drawGhostPiece(true); + dragAmnt = dragAmnt % 20; + } + if (dragAmnt <= -20) { + movePair(Math.ceil(dragAmnt / 20)); + drawGhostPiece(true); + dragAmnt = dragAmnt % 20; + } + }; + + Bangle.on("drag", onDrag); + + let onSwipe = (x, y) => { + if (gameLost || gamePaused || midChain) return; + + if (y > 0) { + let pivotX = dropCoordinates.pivotX; + let pivotY = dropCoordinates.pivotY; + let leafX = dropCoordinates.leafX; + let leafY = dropCoordinates.leafY; + + if (pivotY < -1 && leafY < -1) return; + + quickDrop(); + drawBlobAtSlot(pivotX, pivotY); + drawBlobAtSlot(leafX, leafY); + g.flip(); + + //Check for pops + if (pivotY >= 0) addSlotToCheck(pivotX, pivotY); + if (leafY >= 0) addSlotToCheck(leafX, leafY); + midChain = true; + let currentChain = 0; + while (popAll().pops > 0) { + currentChain++; + lastChain = currentChain; + drawChainCount(); + g.flip(); + settleBlobs(); + redrawBoard(); + g.flip(); + } + + newPair(); + drawNextQueue(); + drawGhostPiece(false); + + //If the top slot of the third column is taken, lose the game. + if (grid[0][2] != 0) { + gameLost = true; + g.setBgColor(0, 0, 0); + g.setColor(1, 1, 1); + g.clearRect(33, 73, 142, 103); + g.setFont("Vector", 20); + g.drawString("You Lose", 43, 80); + } + + midChain = false; + } + }; + + Bangle.on("swipe", onSwipe); + + let onLock = on => { + updateSeconds = !on; + drawTime(true); + }; + + Bangle.on('lock', onLock); + + let onCharging = charging => { + drawTime(false); + }; + + Bangle.on('charging', onCharging); + + Bangle.setUI({mode:"clock", remove:function() { + //Remove listeners + Bangle.removeListener("touch", onTouch); + Bangle.removeListener("drag", onDrag); + Bangle.removeListener("swipe", onSwipe); + Bangle.removeListener('lock', onLock); + Bangle.removeListener('charging', onCharging); + + if (clockDrawTimeout) clearTimeout(clockDrawTimeout); + require("widget_utils").show(); + }}); + + g.reset(); + + Bangle.loadWidgets(); + require("widget_utils").hide(); + + drawBackground(); + drawTime(true); + + restartGame(); + + newPair(); + drawGhostPiece(false); + + drawNextQueue(); + drawChainCount(); +} From a109cfd391e109d84a1d6f07d0486fd551fa7ecc Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:35:34 -0400 Subject: [PATCH 02/13] Create ChangeLog Added the changelog. --- apps/bblobface/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/bblobface/ChangeLog diff --git a/apps/bblobface/ChangeLog b/apps/bblobface/ChangeLog new file mode 100644 index 0000000000..6a29fdb729 --- /dev/null +++ b/apps/bblobface/ChangeLog @@ -0,0 +1 @@ +1.00: Initial release of Bangle Blobs Clock! From fd367c06dcf7d17ba1352c232b0f7ff266369e70 Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:35:56 -0400 Subject: [PATCH 03/13] Create app-icon.js --- apps/bblobface/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/bblobface/app-icon.js diff --git a/apps/bblobface/app-icon.js b/apps/bblobface/app-icon.js new file mode 100644 index 0000000000..e8d9baced0 --- /dev/null +++ b/apps/bblobface/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+HGm56+5BQ4JBAJItXAAoMMCJQAPJ5pfhJApPQL65HHKIbTU2nXAAu0I5xQNBo4tC2gAFGIxHIL5oNGEoItGGIgwDL6oMGFxgwFL6oVFFxwwEL7YuPGARfVBYwvUL6YLGL84THL84KHL7YHCL6AeBFx+0JggAGLx4wQFwa3DAIwvHNJQwMFwhgIEQ7ILGAYxHBAQWJADUeFAIAEjwtnjwAFGMglBFowxEGA/XgrgICJouMGA4aBAIgvMB4ouOGAouGMZgNGFx4wCPQ5hMN44vTK44wLNo5fUcRwuHL67iOHAxfhFxYJBBooeBFx8ecRY4KBowwOFxDgHM5BtHGBguZfhIkBGI4ICFyILFAIxBHAAoOGXIgLHBowBGFo0FAAoxHFxhfPAoQAJCIguNGxRtGABYpDQB72LFxwwEcCJfJFx4wCL7gvTADYv/F/4APYoQuOaoYwpFz4wOF0IwDGI4ICF0IxFAAgtFA=")) From cfbc148a86da07530c3b320fa11cc105bbd8879d Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:37:42 -0400 Subject: [PATCH 04/13] Create metadata.json --- apps/bblobface/metadata.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 apps/bblobface/metadata.json diff --git a/apps/bblobface/metadata.json b/apps/bblobface/metadata.json new file mode 100644 index 0000000000..0d50a2424d --- /dev/null +++ b/apps/bblobface/metadata.json @@ -0,0 +1,14 @@ +{ "id": "bblobface", + "name": "Bangle Blobs Clock", + "shortName":"BBClock", + "icon": "app.png", + "version": "1.00", + "description": "A fully featured watch face with a playable game on the side.", + "type": "clock", + "tags": "", + "supports" : ["BANGLEJS2"], + "storage": [ + {"name":"bblobface.app.js","url":"app.js"}, + {"name":"bblobface.img","url":"app-icon.js","evaluate":true} + ] +} From 8fd2a87342c4143b2e3be930bdfdf81402e40237 Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:38:27 -0400 Subject: [PATCH 05/13] Upload Image Uploaded the png for the icon. --- apps/bblobface/app.png | Bin 0 -> 691 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/bblobface/app.png diff --git a/apps/bblobface/app.png b/apps/bblobface/app.png new file mode 100644 index 0000000000000000000000000000000000000000..2201fa621ee4950521e77d8914e279dffb9d614f GIT binary patch literal 691 zcmV;k0!;mhP)C*2ppRI|6k@Fx>{5a)Y{%9H!mi;NC!rNmH;sRFh1Ik z3_immfIwXb%nT5+y|;S)Mv+`!#7#r}!M!~rer9oGBFu@Ax-zp)*049%n~@ceaC2~_;g%pjT|k?un0Z*WH@(nF_no1dZCEPDG2;=RNO8)AB z-N3#~o~TbAxNNvQ)K>srQmI-4U~smtk6l521XU2vDNz43Lq0(Su~h-neuaGYdj_#h z0ohmXE}atl6qr?P5L*<;eFJ;54?Lm3W`q=w84XvVp56BXF5z1U)LEzpcf1aE?4?pF z$hQitPLn}<0_Kzu}$hUqkp5IPv4Q|#N!yTFL`2{%5LMz9>hB=MiFkU3Tssi3R z`jDNoP*X;qK)M_2eg=lQ--`bLW^m)D(YF+!r68I<@DApJsGIF8Rj9<;Ec6QkNSK>O Ze*m1G3ni=?{K^0T002ovPDHLkV1h2JIyC?Q literal 0 HcmV?d00001 From d9718f4e57337111ba3ac430ca4d2997063df69a Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:45:07 -0400 Subject: [PATCH 06/13] Add tags to metadata.json --- apps/bblobface/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bblobface/metadata.json b/apps/bblobface/metadata.json index 0d50a2424d..ad822e15c9 100644 --- a/apps/bblobface/metadata.json +++ b/apps/bblobface/metadata.json @@ -5,7 +5,7 @@ "version": "1.00", "description": "A fully featured watch face with a playable game on the side.", "type": "clock", - "tags": "", + "tags": "clock", "game", "supports" : ["BANGLEJS2"], "storage": [ {"name":"bblobface.app.js","url":"app.js"}, From baf720c5bcfc54494db7421284969504099532b1 Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:47:00 -0400 Subject: [PATCH 07/13] Fix metadata.json Attempt to fix the metadata.json --- apps/bblobface/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bblobface/metadata.json b/apps/bblobface/metadata.json index ad822e15c9..c9e4acca64 100644 --- a/apps/bblobface/metadata.json +++ b/apps/bblobface/metadata.json @@ -5,7 +5,7 @@ "version": "1.00", "description": "A fully featured watch face with a playable game on the side.", "type": "clock", - "tags": "clock", "game", + "tags": ["clock", "game"], "supports" : ["BANGLEJS2"], "storage": [ {"name":"bblobface.app.js","url":"app.js"}, From 4b925b7fea4c33179745c68250db268f2576c5e1 Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:50:22 -0400 Subject: [PATCH 08/13] Actually fix metadata.json After trying multiple things, I think this will fix the tags. --- apps/bblobface/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bblobface/metadata.json b/apps/bblobface/metadata.json index c9e4acca64..51b5b81f53 100644 --- a/apps/bblobface/metadata.json +++ b/apps/bblobface/metadata.json @@ -5,7 +5,7 @@ "version": "1.00", "description": "A fully featured watch face with a playable game on the side.", "type": "clock", - "tags": ["clock", "game"], + "tags": "clock, game", "supports" : ["BANGLEJS2"], "storage": [ {"name":"bblobface.app.js","url":"app.js"}, From e881ab3f52042855bc885451d89e9dc29baa7aff Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 13:05:54 -0400 Subject: [PATCH 09/13] Screenshots Uploaded a few screenshots for the README. --- apps/bblobface/screenshot1.png | Bin 0 -> 3797 bytes apps/bblobface/screenshot2.png | Bin 0 -> 4808 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/bblobface/screenshot1.png create mode 100644 apps/bblobface/screenshot2.png diff --git a/apps/bblobface/screenshot1.png b/apps/bblobface/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..91650c07a62a25d0c8ff75aeba9a2dbe0d72af18 GIT binary patch literal 3797 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 literal 0 HcmV?d00001 diff --git a/apps/bblobface/screenshot2.png b/apps/bblobface/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..64644965f7cfab5d4c278b85863c7ae8ba943434 GIT binary patch literal 4808 zcmV;(5;yIMP)Px{f=NU{RCr$PUE6}JC=8tW|Bs&C29W>>2_$OllYW^?qau`Ls1)$~^Yiof_w)1f z`}yUepFi<=WeYrom*%>Ee?Nb}zZu0({(NN*Mx`IeO(Nc>pQOOSJ6qss+@$LV1HThI zUTXdHo7)8g|NZ^_{Qmy_#Lt(t!!c&seV9srZy)c8fdjlR1Mf*XdF)g_e>o=YKDkU& z@Fc9J=-)?77*Fu~ITjpVm_Haen1BDxH$w6p)b#)^fP*L;82A8h0&DmAfO-J2CkEbq zjl^-!wm=1DX5N;K+q(52ZU8(1Z#fGDu`33CwhQ9wyDd;uh|lpEjQp80@Nz*2;PgAf zyeJcw@2;z}}7h~wi#Jw0j zPO5(Dz=e5d>EsT?Er8d&6v4nw0PyB&^g6J>%8{eG1;#bhckutEybztiz&p_KbBwD@+?fJ|ApEpdSvaly zo}%}o5vfJhU|FKQg&6nKTTzpy1+@KV>V-%(8{Y}J!c=N-25!lS6pUg68}DoZS1a>S zCJeM`Ap^q#)c=u_XrJJBcKP?z+SS@4y2s>Xd8@%&}`fs4IQL#KOVAF9-3%>q<9kqfKLA%%lv%h$b!5J({6H zyc?xV|2-NDHw=6RrpGTc4Hz}Q-zL!?{9-)MZ@W|6sms6bd?8g<)6G{Ffa@!B-2tJ2JxrEu#aSA z#&1LTqp@#!1E4YRjV-<8X5#8~0}}^;+fE1uKHB4x7Z(|#1t2bSuDGH*-v@wes|5q^ zIQlu%0mnaAbm#j3a4_)M0$YxL4s`)wu7%9Le>#(zuJ0xWju65OSa+W2sZ1(5C+^N0 z|6J>h419MRdA?pSFpPmU5?bly8&n9-fO?{Cy9}HM?Ri@I&Y;^J17}7)7KRg=;hPQ% z@ZOH!T?X!@^quZL-{7+t7y?R@s-2yOoKv-OR{`GJ!F#^+n7!d(#S(B4;nPG#900~?`s*0DXWkFv zN>m8%ZnOaK2;i?|V2q(f4D8$s5di)N7+9iUP%&^Yuwo?j(4k+&z_Zvm82BNC-Ei5j ziGgR?JFFdZY+SQ2?_ppX6`?}NpBSj+xKJUa8N7np5=y*fPFy51zB~rjGH{aU!i^@U zFb5@9VqjSwGvAbyk%t)>)|t2}&sLix=Y`k;@eP?c2Y7K=1!)WnGjGKQO#PIk<4HfT zlu0FChz7vNAK^xGiNmc*xntly({^qxfNUeM3}AvK?^qkn&efLp^QAuhj_O;eSUAY; zz7{Up6_qmZ{uSo2ce^^}QTA~^aCSbQoIM%$S6)W~r>28dzTyhp*$O-b+*bqH?!I)e zT47+_l?V`fnw5Np8z*?Bp?m@RZwjffxLe$K=v#u{MZG_NWu=vSkk!)L7$H{X0sWR4 zZ1=g&$EA6KW@^Sdc;SO+&BS*1C3{%7Qp}u(vnMYt=Vx6A4R|Z>HgP-G1Jw83s^iS%nOFs0&^(wYd-wiQkGWc*eR?O5jU*kymme~5Vg+zkQOh;fG+mpI%^fUhulcn+ zW-2dbR_Xe~QU=axQocjla{UuJc4U2mcSDCE0+lP_+;gDE-B$znH4NN?l0wKFycNvl z_+Vf;!v_P`(NV+v90TK^q^OAs8|wf2S86b@48$G*{1OK4!S|^)zW3~0J{mzB3@ih0 z28v~DZx9HNn0wWX0f_Bh+JnFzW7&(TO ze_z57N;s=bOvT$!na^b~snyOi5MBrj*)AEFV$xNH7B2aCkM*eobB?s^zn?HLf3ek^ z?OiIw4tU`pvbf0hzyjlQX^0~Ox4Zfr8G%QcxYdF649p5aokPo72Zn4Qg9Q>Xr&lzb zhO&Joa)7ydMjd#seW=_p@GAJ)@?4C3UnXuPY@qHr1I8j_wYQ1MC|B8;oh;mODV*`g zz%+zyRfr0VE4&Z^;29O!JWzeeb(PA%ofn-Ghu=QOuyPgRYByQ{_#Oa%Ap>(DzQ+$7 z0KNynMHP8T47@t*;LBg-MhgJn1K?LNFb~JQ5}`uK+AUOwb7RkDL7#;fSk}-hrLJ@iJb;y4MEGCb)Z z%qP1z6+!zw&cKI%Al=-#Gu?5k)Za);^y}poKo<~S?M4ePMCnM|jNmDuxn0oj`$*v{2vRH z+?Q_GI?#aFW^J@R@U}OWImM+T-UsaFZ${Zf7!v;s88k;`s3xuli`g+ku$B z;Jk#bt4&**18@rPLMHw^P0)1u2qRC|g+Lg%(Sa9L2y`5Fj$-W=?l9<|G=SBx-PzHm zwoG3D{)B{D2Gt(#CKG45@=O4j26_o2w2wj>uefJm?Oh6vZ~VX!LQGmr7yrUH!iw@R zje~=Mui2?H7&sVMz@0WlLWPjDV;vr8;_`n_g^;wZqRik%(@1GRzqQhnt#sGWf!isv zrfLPZKCl9xqC*Ea+75^#6E|(^+Qwjz0i1=Rjykpi9@5F~yb#j6F(?;a2zrQ=zoA@Y z;e|N$XKxG)yVT6J1SMg-o0dVf$CC`)&tI#l$Z;~~FxM@karn&q z!1)~f0EmyT?My+Mq(N;j!`m`w9!qzeTQ3AOqK~tPZytcgW-&KjhyXDCe7bbU zId!9H08BAA)-!`2H~{=A0J~=3?Dfo{0Axc*^E**@=jO=SX%4V3!Qct)?SkV944t02k@3jQH30ha33ZY+?0KA!g50)!nr! zg7$cnfqTZq07;cuQZM>h$thylRU<&7?ihlu)Lp&R$E=;5>A({3VGNDM$r2e2GH@e1 zErU2RaZ|qR_9ZFpzD^cMJ9~1YNdOG>;PN{zkF{DbT87&9{$z;sXiWO1T;m-(b-MFr zDBC%_5J&o$N*H)^ZCTaFYOOYniwv@Y=DxHstoC?UUWhS_&@r$V*H#U$!D5B77Yn|4 zAy|xWXH7G!b`Azc7G{cz`Ul#)lC3Ul6!<;yy(eVy= zAuCz$)VT#-OcmJxFJ%8R9cb^NY%7#xMvv}Jv1E~do z+f1BY!v=uqccCSK-LH*CnR#IIa2vhw3CUc-(hnQ}z6ZcAy$}^lxe+iw@GOC`8V6tD zMhgJn17Md7%$aZMXnnL=E`#?XH(CJr9ss*zU@qpJnS55k+sjruX{Sm&p+ZQ&s~vAR zb)(IUI-JdN2f(2N3t9~(GeQR*SA>VNl2@E&n!y|FwwnDagSixiFG@X;iJK3W@!f?i z+F7gPYL5>u#JL_t*-~KCNL#au%*24j;bv~M@Iq83_OdPn#vmG(RKxOLx;B~zSDThW zwa0%o1Di44u|Hdu6(@tF!=7Bc6n)8WV{(^X2*I$zw8&L4@RorFbAN4YF8Hsx+Mx2I zWz^N<2QS2I26CCuN&SQxaq&;g276bj5L@7_N?fuElpWCe2Tc0(LJ;dD!VBj5S*aOb z-DnVeJy^L8>}M@=>qJ<)(acO_U>8d6o~iFMaLw#!>!QIB!~A1AbyDEtKsm;K<8oBJ zSZ3*kFf?23V)s0*f>?Vh!!_Rw8p!QFaoR9p74%nlAq@J*i=1q3IM+k!0s8CV$g_zIk465BL=>B z?i`hg5vu#G}p+b;PX^MZd*64G$dQJ+nijhMHmN0qfz|)MM zH!sAV=#Q+~wX>jJWa6ez6l7lP4f;ezF1!#WayfDi_)0f6J7b0y;)2yI3j?p_psmYe zkG`4P3Yc-Q>rm#KF(Cudj-F|1_BmP0${h!6l|*esGw3z0KWiMUp0D*nJe1oWhhj!+ zh=q$RHEq8^H+=o)5%2N(nGD-XnRYYD3m8?pKU^v2je)m}I1#&U#jfje4Kmhnu|DvT zWLTBPtjZ6s)}4i88W4Ni(eiksXz$C)MP{@HomKy<&hz*8_cwE&sZM_EbR;_ej%t9( zz@gtx^;*NS_j7u_^-s9{+Gum;m4bIvd}NF+VqmHgT)J5LL?v-50Q@=tC+$KICa!{5iknnU z%D~(cA_e)Zas~twK3)bb!N8z_f`KL6Vi?;SJmHoA-eq9UOH*}fK^WnNfkTC$pN1p; zJ-rB$=LRWL!MnQh5i(L1su0|pTT6m&V&D`9Yd{=2usE5qXPByLeHu<4lMr@d;ICw0 zRWc(oabob+*K?+fHSH41#I30i+yHHrv0X9n0OAy6P5K6;@xw(nwo?unF7!eO^9NE; zO3O75ftMHmVz>Mrw*SOJwfqzp1 zqgl>sXCN0b@M~gVser;Ud->iK1BVKMYF~A&wwJomq@b+>Oo9GeGJsxUU=?_Q!V`OB z&~Wjf19M=OGOs%Z4le{hVDo0?NeV}JA?oYGAX6G%2=+Nx)qbfH%3kwQRY6*=XJ|Ju za4;~7Ja=}=T?XbdaZ6!@n;1Cklyd}si658)@9ID<7?^-f%*bGeTdBZK3~UNwHw?U^ z{| Date: Sun, 27 Aug 2023 13:57:51 -0400 Subject: [PATCH 10/13] Create README.md --- apps/bblobface/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 apps/bblobface/README.md diff --git a/apps/bblobface/README.md b/apps/bblobface/README.md new file mode 100644 index 0000000000..4c32221f60 --- /dev/null +++ b/apps/bblobface/README.md @@ -0,0 +1,34 @@ +# Bangle Blobs Clock +What if every time you checked the time, you could play a turn of a turn-based puzzle game? +You check the time dozens, maybe hundreds of times per day, and Bangle Blobs Clock wants to add a splash of fun to each of these moments! +Bangle Blobs Clock is a fully featured watch face with a turn-based puzzle game right next to the clock. + +![](screenshot1.png) +![](screenshot2.png) + +## Clock Features +- Hour and minute +- Seconds (only while the screen is unlocked to save power) +- Month, day, and day of week +- Battery percentage. Blue while charging, red when low, green otherwise. +- Respects your 24-hour/12-hour time setting in Locale +- Press the pause button to access your Widgets +- Supports Fast Loading + +## The Game +This is a turn-based puzzle game based on Puyo Puyo, an addictive puzzle game franchise by SEGA. +Blobs arrive in pairs that you can move, rotate, and place. When at least four Blobs of the same color touch, they pop, causing Blobs above them to fall. +If this causes another pop, it's called a chain! Build a massive chain reaction of popping Blobs! +- Drag left and right to move the pair +- Tap the left or right half of the screen to rotate the pair +- Swipe down to place the pair + +## More Info +If you're confused about the functionality of the clock or want a better explanation of how to play the game, I wrote up a user manual here: https://docs.google.com/document/d/1watPzChawBu4iM0lXypreejs3wvf2_8C-x5V2MWJQBc/edit?usp=sharing + +## Credits +- I'm Pasta Rhythm, computer scientist and aspiring game developer. +- ![nxdefiant, who made a Tetris game.](https://github.com/espruino/BangleApps/tree/master/apps/tetris) Bangle Blobs is my first Bangle app and my first time using JavaScript, so this was a daunting project. This Tetris game served as a great example that helped me get started. +- ![gfwilliams for Anton Clock](https://github.com/espruino/BangleApps/tree/master/apps/antonclk) and ![Targor for Kanagawa Clock.](https://github.com/espruino/BangleApps/tree/master/apps/kanagsec) These were good examples for how to make a watch face for the Bangle.js 2. +- Thanks to Gordon Williams and to everyone who contributes to Espruino and the Bangle.js 2 projects! +- SEGA, owners of the Puyo Puyo franchise that Bangle Blobs is based on. Please check out official Puyo Puyo games! From 639b26b7b3f3b9f65d23498f36e606a03fa77cfd Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 14:01:48 -0400 Subject: [PATCH 11/13] Edited README Fixed some formatting issues with the README --- apps/bblobface/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/bblobface/README.md b/apps/bblobface/README.md index 4c32221f60..7eab8221dc 100644 --- a/apps/bblobface/README.md +++ b/apps/bblobface/README.md @@ -28,7 +28,7 @@ If you're confused about the functionality of the clock or want a better explana ## Credits - I'm Pasta Rhythm, computer scientist and aspiring game developer. -- ![nxdefiant, who made a Tetris game.](https://github.com/espruino/BangleApps/tree/master/apps/tetris) Bangle Blobs is my first Bangle app and my first time using JavaScript, so this was a daunting project. This Tetris game served as a great example that helped me get started. -- ![gfwilliams for Anton Clock](https://github.com/espruino/BangleApps/tree/master/apps/antonclk) and ![Targor for Kanagawa Clock.](https://github.com/espruino/BangleApps/tree/master/apps/kanagsec) These were good examples for how to make a watch face for the Bangle.js 2. +- [nxdefiant, who made a Tetris game.](https://github.com/espruino/BangleApps/tree/master/apps/tetris) Bangle Blobs is my first Bangle app and my first time using JavaScript, so this was a daunting project. This Tetris game served as a great example that helped me get started. +- [gfwilliams for Anton Clock](https://github.com/espruino/BangleApps/tree/master/apps/antonclk) and [Targor for Kanagawa Clock.](https://github.com/espruino/BangleApps/tree/master/apps/kanagsec) These were good examples for how to make a watch face for the Bangle.js 2. - Thanks to Gordon Williams and to everyone who contributes to Espruino and the Bangle.js 2 projects! - SEGA, owners of the Puyo Puyo franchise that Bangle Blobs is based on. Please check out official Puyo Puyo games! From a46751a3731c226a05053d5a30c679448760440b Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 14:04:48 -0400 Subject: [PATCH 12/13] Add README to metadata --- apps/bblobface/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/bblobface/metadata.json b/apps/bblobface/metadata.json index 51b5b81f53..6af247c913 100644 --- a/apps/bblobface/metadata.json +++ b/apps/bblobface/metadata.json @@ -4,6 +4,7 @@ "icon": "app.png", "version": "1.00", "description": "A fully featured watch face with a playable game on the side.", + "readme":"README.md", "type": "clock", "tags": "clock, game", "supports" : ["BANGLEJS2"], From aeca14baa08977d8f2fa467d015d7efe3fe29fb1 Mon Sep 17 00:00:00 2001 From: PastaRhythm <83084413+PastaRhythm@users.noreply.github.com> Date: Sun, 27 Aug 2023 16:34:27 -0400 Subject: [PATCH 13/13] Update README.md Made a quick change to the credits to avoid confusion and make it more readable. --- apps/bblobface/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/bblobface/README.md b/apps/bblobface/README.md index 7eab8221dc..54e07e9f85 100644 --- a/apps/bblobface/README.md +++ b/apps/bblobface/README.md @@ -26,9 +26,10 @@ If this causes another pop, it's called a chain! Build a massive chain reaction ## More Info If you're confused about the functionality of the clock or want a better explanation of how to play the game, I wrote up a user manual here: https://docs.google.com/document/d/1watPzChawBu4iM0lXypreejs3wvf2_8C-x5V2MWJQBc/edit?usp=sharing -## Credits -- I'm Pasta Rhythm, computer scientist and aspiring game developer. +## Special Thanks +I'm Pasta Rhythm, computer scientist and aspiring game developer. I would like to say thank you to the people who inspired me while I was making this app: - [nxdefiant, who made a Tetris game.](https://github.com/espruino/BangleApps/tree/master/apps/tetris) Bangle Blobs is my first Bangle app and my first time using JavaScript, so this was a daunting project. This Tetris game served as a great example that helped me get started. - [gfwilliams for Anton Clock](https://github.com/espruino/BangleApps/tree/master/apps/antonclk) and [Targor for Kanagawa Clock.](https://github.com/espruino/BangleApps/tree/master/apps/kanagsec) These were good examples for how to make a watch face for the Bangle.js 2. - Thanks to Gordon Williams and to everyone who contributes to Espruino and the Bangle.js 2 projects! - SEGA, owners of the Puyo Puyo franchise that Bangle Blobs is based on. Please check out official Puyo Puyo games! +- Compile, the original creators of Puyo Puyo. The company went bankrupt long ago, but the people who worked for them continue to make games.