Merge branch 'isaacphi-master'

pull/1293/head
Gordon Williams 2022-01-13 13:52:47 +00:00
commit 9fc8d48852
7 changed files with 249 additions and 0 deletions

View File

@ -5643,5 +5643,22 @@
"storage": [
{"name":"widpb.wid.js","url":"widpb.wid.js"}
]
},
{
"id": "timeandlife",
"name": "Time and Life",
"shortName":"Time and Lfie",
"icon": "app.png",
"version":"0.1",
"description": "A simple watchface which displays the time when the screen is tapped and decays according to the rules of Conway's game of life.",
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS2"],
"allow_emulator":true,
"readme": "README.md",
"storage": [
{"name":"timeandlife.app.js","url":"app.js"},
{"name":"timeandlife.img","url":"app-icon.js","evaluate":true}
]
}
]

View File

@ -0,0 +1 @@
0.1: New app

View File

@ -0,0 +1,5 @@
# Time and Life
A simple watchface which displays the time when the screen is tapped and decays according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life).
![](screenshot.png)

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkB/4AGCY4PHC/4X/C/4X/C/4XvJ/4X/C/4X/C/4X3AH4A/AH4A/AH4A/"))

225
apps/timeandlife/app.js Normal file
View File

@ -0,0 +1,225 @@
// Globals
const X = 176,
Y = 176; // screen resolution of bangle 2
const STEP_TIMEOUT = 1000;
const PAUSE_TIME = 3000;
const ONE = [
[0, 1, 0],
[1, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[1, 1, 1],
];
const TWO = [
[0, 1, 0],
[1, 0, 1],
[0, 0, 1],
[0, 1, 0],
[1, 0, 0],
[1, 0, 0],
[1, 1, 1],
];
const THREE = [
[0, 1, 0],
[1, 0, 1],
[0, 0, 1],
[0, 1, 0],
[0, 0, 1],
[1, 0, 1],
[0, 1, 0],
];
const FOUR = [
[0, 0, 1],
[1, 0, 1],
[1, 0, 1],
[1, 1, 1],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1],
];
const FIVE = [
[1, 1, 1],
[1, 0, 0],
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 1],
[0, 1, 0],
];
const SIX = [
[0, 1, 0],
[1, 0, 1],
[1, 0, 0],
[1, 1, 0],
[1, 0, 1],
[1, 0, 1],
[0, 1, 0],
];
const SEVEN = [
[1, 1, 1],
[1, 0, 1],
[0, 0, 1],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
];
const EIGHT = [
[0, 1, 0],
[1, 0, 1],
[1, 0, 1],
[0, 1, 0],
[1, 0, 1],
[1, 0, 1],
[0, 1, 0],
];
const NINE = [
[0, 1, 0],
[1, 0, 1],
[1, 0, 1],
[0, 1, 1],
[0, 0, 1],
[1, 0, 1],
[0, 1, 0],
];
const ZERO = [
[0, 1, 0],
[1, 0, 1],
[1, 0, 1],
[1, 0, 1],
[1, 0, 1],
[1, 0, 1],
[0, 1, 0],
];
const NUMBERS = [ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE];
// Arraybuffers to store game state
// 484 8 bit integers that are either 1 or 0 form the 22 x 22 grid
let data = new Uint8Array(484);
let nextData = new Uint8Array(484);
let palette = new Uint16Array(256); // palette for rendering data
palette[0] = g.theme.bg;
palette[1] = g.theme.fg;
let lastPaused = new Date();
// Conway's game of life
// if < 2 neighbours, set off
// if 2 or 3 neighbours, set on
// if > 3 neighbours, set off
/*const updateStateC = E.compiledC(`
// void run(int, int)
void run(char* n, char* m){
// n is a pointer to the first byte in data, m is for nextdata
int count = 0;
for (int i=0;i<484;i++) {
// Add 8 neighbours, wrapping around
count =
*(n+(i+484-23)%484) +
*(n+(i+484-22)%484) +
*(n+(i+484-21)%484) +
*(n+(i+484-1)%484) +
*(n+(i+484+1)%484) +
*(n+(i+484+21)%484) +
*(n+(i+484+22)%484) +
*(n+(i+484+23)%484);
if (count < 2 || count > 3) {
*(m+i) = 0;
} else {
*(m+i) = 1;
}
}
}
`);*/
// precompiled - taken from file downloaded from Bangle.js storage after
// Web IDE upload
const updateStateC=function(a){return a=atob('ACLwtU/08nMBJxZGAvLNFQL1536V+/P0A/sUVJ778/UD+xXlAvLPHhD4BMBEXZ778/UD+xXlZERFXQLy4x4sRJ778/UD+xXlAvLlHkVdLESe+/P1A/sV5QLy+R5FXSxEnvvz9QP7FeUC9f1+RV0sRJ778/UD+xXlAvL7HkVdLESe+/P1A/sV5UVdLEQCPAIsNL88RjRGjFQBMrL18n+10fC9AAA='),{run:E.nativeCall(1,'void(int, int)',a)}}();
function draw() {
g.drawImage({
width:22, height:22, bpp: 8,
palette : palette, // ideally we'd just have BPP 1 and would render direct but it makes the code tricky
buffer : data.buffer,
},0,0,{scale:8});
}
const step = () => {
if (new Date() - lastPaused < PAUSE_TIME) {
return;
}
let startTime = new Date();
const dataAddr = E.getAddressOf(data, true);
const nextDataAddr = E.getAddressOf(nextData, true);
updateStateC.run(dataAddr, nextDataAddr);
draw();
data.set(nextData);
};
const setPixel = (i, j) => {
data[i * 22 + j] = 1;
nextData[i * 22 + j] = 1;
};
const setNum = (character, i, j) => {
const startJ = j;
character.forEach(row => {
j = startJ;
row.forEach(pixel => {
if (pixel) setPixel(i, j);
j++;
});
i++;
});
};
const setDots = () => {
setPixel(10, 10);
setPixel(12, 10);
};
const drawTime = () => {
lastPaused = new Date();
g.clear();
data.fill(0);
const d = new Date();
const hourTens = Math.floor(d.getHours() / 10);
const hourOnes = d.getHours() % 10;
const minuteTens = Math.floor(d.getMinutes() / 10);
const minuteOnes = d.getMinutes() % 10;
setNum(NUMBERS[hourTens], 8, 1);
setNum(NUMBERS[hourOnes], 8, 6);
setDots();
setNum(NUMBERS[minuteTens], 8, 13);
setNum(NUMBERS[minuteOnes], 8, 18);
draw();
};
const start = () => {
Bangle.setUI("clock"); // Show launcher when middle button pressed
g.clear();
Bangle.setLCDTimeout(20); // backlight/lock timeout in seconds
let stepInterval = setInterval(step, STEP_TIMEOUT);
// Handlers
Bangle.on('touch', drawTime);
// Sleep mode
Bangle.on('lock', isLocked => {
if (stepInterval) {
clearInterval(stepInterval);
}
stepInterval = undefined;
if (!isLocked) {
drawTime();
stepInterval = setInterval(step, STEP_TIMEOUT);
}
});
drawTime();
};
start();

BIN
apps/timeandlife/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB