mirror of https://github.com/espruino/BangleApps
commit
d62b175cf3
|
@ -0,0 +1 @@
|
|||
1.00: Initial release of Bangle Blobs Clock!
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+HGm56+5BQ4JBAJItXAAoMMCJQAPJ5pfhJApPQL65HHKIbTU2nXAAu0I5xQNBo4tC2gAFGIxHIL5oNGEoItGGIgwDL6oMGFxgwFL6oVFFxwwEL7YuPGARfVBYwvUL6YLGL84THL84KHL7YHCL6AeBFx+0JggAGLx4wQFwa3DAIwvHNJQwMFwhgIEQ7ILGAYxHBAQWJADUeFAIAEjwtnjwAFGMglBFowxEGA/XgrgICJouMGA4aBAIgvMB4ouOGAouGMZgNGFx4wCPQ5hMN44vTK44wLNo5fUcRwuHL67iOHAxfhFxYJBBooeBFx8ecRY4KBowwOFxDgHM5BtHGBguZfhIkBGI4ICFyILFAIxBHAAoOGXIgLHBowBGFo0FAAoxHFxhfPAoQAJCIguNGxRtGABYpDQB72LFxwwEcCJfJFx4wCL7gvTADYv/F/4APYoQuOaoYwpFz4wOF0IwDGI4ICF0IxFAAgtFA="))
|
|
@ -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();
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 691 B |
|
@ -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": "clock, game",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"bblobface.app.js","url":"app.js"},
|
||||
{"name":"bblobface.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue