Merge branch 'master' into master
114
apps.json
|
@ -29,6 +29,31 @@
|
|||
],
|
||||
"sortorder": -10
|
||||
},
|
||||
{
|
||||
"id": "hebrew_calendar",
|
||||
"name": "Hebrew Calendar",
|
||||
"shortName": "HebCal",
|
||||
"version": "0.03",
|
||||
"description": "lists the date according to the hebrew calendar",
|
||||
"icon": "app.png",
|
||||
"tags": "",
|
||||
"supports": [
|
||||
"BANGLEJS",
|
||||
"BANGLEJS2"
|
||||
],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{
|
||||
"name": "hebrew_calendar.app.js",
|
||||
"url": "app.js"
|
||||
},
|
||||
{
|
||||
"name": "hebrew_calendar.img",
|
||||
"url": "app-icon.js",
|
||||
"evaluate": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "messages",
|
||||
"name": "Messages",
|
||||
|
@ -104,7 +129,7 @@
|
|||
"id": "launch",
|
||||
"name": "Launcher",
|
||||
"shortName": "Launcher",
|
||||
"version": "0.09",
|
||||
"version": "0.10",
|
||||
"description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
|
||||
"icon": "app.png",
|
||||
"type": "launch",
|
||||
|
@ -112,8 +137,10 @@
|
|||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"launch.app.js","url":"app-bangle1.js","supports":["BANGLEJS"]},
|
||||
{"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]}
|
||||
{"name":"launch.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]},
|
||||
{"name":"launch.settings.js","url":"settings.js","supports":["BANGLEJS2"]}
|
||||
],
|
||||
"data": [{"name":"launch.json"}],
|
||||
"sortorder": -10
|
||||
},
|
||||
{
|
||||
|
@ -463,22 +490,22 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"id": "mandlebrotclock",
|
||||
"name": "Mandlebrot Clock",
|
||||
"id": "mandelbrotclock",
|
||||
"name": "Mandelbrot Clock",
|
||||
"version": "0.01",
|
||||
"description": "A mandlebrot set themed clock cool",
|
||||
"icon": "mandlebrotclock.png",
|
||||
"screenshots": [{ "url": "screenshot_mandlebrotclock.png" }],
|
||||
"description": "A mandelbrot set themed clock cool",
|
||||
"icon": "mandelbrotclock.png",
|
||||
"screenshots": [{ "url": "screenshot_mandelbrotclock.png" }],
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{ "name": "mandlebrotclock.app.js", "url": "mandlebrotclock.js" },
|
||||
{ "name": "mandelbrotclock.app.js", "url": "mandelbrotclock.js" },
|
||||
{
|
||||
"name": "mandlebrotclock.img",
|
||||
"url": "mandlebrotclock-icon.js",
|
||||
"name": "mandelbrotclock.img",
|
||||
"url": "mandelbrotclock-icon.js",
|
||||
"evaluate": true
|
||||
}
|
||||
]
|
||||
|
@ -2100,6 +2127,19 @@
|
|||
{"name":"snake.img","url":"snake-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "snek",
|
||||
"name": "The snek game",
|
||||
"shortName":"Snek",
|
||||
"version": "0.01",
|
||||
"description": "A snek game where you control a snek to eat all the apples!",
|
||||
"icon": "snek-icon.js",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"tags": "game,fun",
|
||||
"storage": [
|
||||
{"name":"snek.app.js","url":"snek.js"},
|
||||
{"name":"snek.img","url":"snek-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "calculator",
|
||||
"name": "Calculator",
|
||||
|
@ -4449,7 +4489,7 @@
|
|||
"shortName": "AuthWatch",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"version": "0.03",
|
||||
"version": "0.04",
|
||||
"description": "Google Authenticator compatible tool.",
|
||||
"tags": "tool",
|
||||
"interface": "interface.html",
|
||||
|
@ -4531,7 +4571,7 @@
|
|||
"shortName":"93 Dub",
|
||||
"icon": "93dub.png",
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"description": "Fan recreation of orviwan's 91 Dub app for the Pebble smartwatch. Uses assets from his 91-Dub-v2.0 repo",
|
||||
"tags": "clock",
|
||||
"type": "clock",
|
||||
|
@ -4591,9 +4631,9 @@
|
|||
},
|
||||
{
|
||||
"id":"a_speech_timer",
|
||||
"name":"A Speech Timer",
|
||||
"name":"Speech Timer",
|
||||
"icon": "app.png",
|
||||
"version":"1.00",
|
||||
"version":"1.01",
|
||||
"description": "A timer designed to help keeping your speeches and presentations to time.",
|
||||
"tags": "tool,timer",
|
||||
"readme":"README.md",
|
||||
|
@ -4691,6 +4731,52 @@
|
|||
"storage": [
|
||||
{"name":"weatherClock.app.js","url":"app.js"},
|
||||
{"name":"weatherClock.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "menuwheel",
|
||||
"name": "Wheel Menus",
|
||||
"version": "0.01",
|
||||
"description": "Replace Bangle.js 2's menus with a version that contains variable-size text and a back button",
|
||||
"readme": "README.md",
|
||||
"icon": "icon.png",
|
||||
"screenshots": [
|
||||
{"url":"screenshot_b1_dark.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_light.png"},
|
||||
{"url":"screenshot_b2_dark.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_light.png"}
|
||||
],
|
||||
"type": "boot",
|
||||
"tags": "system",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"menuwheel.boot.js","url":"boot.js"}
|
||||
]
|
||||
},
|
||||
{ "id": "widChargingStatus",
|
||||
"name": "Charging Status",
|
||||
"shortName":"ChargingStatus",
|
||||
"icon": "widget.png",
|
||||
"version":"0.1",
|
||||
"type": "widget",
|
||||
"description": "A simple widget that shows a yellow lightning icon to indicate whenever the watch is charging. This way one can see the charging status at a glance, no matter which battery widget is being used.",
|
||||
"tags": "widget",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"widChargingStatus.wid.js","url":"widget.js"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow",
|
||||
"name": "FLOW",
|
||||
"shortName": "FLOW",
|
||||
"version": "0.01",
|
||||
"description": "A game where you have to help a flow avoid white obstacles thing by tapping! This is a demake of an app which I forgot the name of. Press BTN(1) to restart. See if you can get to 2500 score!",
|
||||
"icon": "app.png",
|
||||
"tags": "game",
|
||||
"supports" : ["BANGLEJS", "BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name": "flow.app.js", "url": "app.js" },
|
||||
{"name": "flow.img", "url": "app-icon.js","evaluate": true }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: Initial version for upload
|
||||
0.02: DiscoMinotaur's adjustments (removed battery and adjusted spacing)
|
||||
0.03: Code style cleanup
|
||||
0.04: Set 00:00 to 12:00 for 12 hour time
|
||||
|
|
|
@ -9,3 +9,4 @@ Leer10
|
|||
Orviwan (original watchface and assets)
|
||||
Gordon Williams (Bangle.js, watchapps for reference code and documentation)
|
||||
DiscoMinotaur (adjustments)
|
||||
Ray Holder (minor 12 hour time rendering adjustment)
|
||||
|
|
|
@ -78,6 +78,9 @@ function draw(){
|
|||
} else {
|
||||
h = " " + h;
|
||||
}
|
||||
} else if (h === 0) {
|
||||
// display 12:00 instead of 00:00 for 12 hr mode
|
||||
h = "12";
|
||||
}
|
||||
|
||||
//draw separator
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
1.00: Release (2021/12/01)
|
||||
1.01: Grey font when timer is frozen (2021/12/04)
|
||||
|
|
|
@ -63,7 +63,7 @@ function countDown() {
|
|||
|
||||
Bangle.on('touch',(touchside, touchdata)=>{
|
||||
if (!islocked && istimeron && touchdata.y > (100+10)) {
|
||||
Bangle.buzz(40);
|
||||
Bangle.buzz(40);
|
||||
istimeron = false;
|
||||
clearInterval(timerinterval);
|
||||
} else if (touchdata.y > 24 && touchdata.y < (100-10)) {
|
||||
|
@ -134,20 +134,20 @@ function draw() {
|
|||
else if (current_value >= current_from) { g.setBgColor("#8F8"); }
|
||||
g.clearRect(0,24,176,176);
|
||||
|
||||
g.reset();
|
||||
g.setFontAlign(0, 0);
|
||||
|
||||
g.reset().setFontAlign(0, 0).setColor(istimeron ? "#000" : "#444");
|
||||
g.setFont("Michroma36").drawString(timeToString(current_value), 88, 62);
|
||||
|
||||
g.reset().setFontAlign(0, 0);
|
||||
|
||||
g.setFont("HaxorNarrow7x17");
|
||||
g.drawString(timeToString(current_from), 44, 62+26);
|
||||
g.drawString(timeToString(current_mid), 88, 62+26);
|
||||
g.drawString(timeToString(current_to), 132, 62+26);
|
||||
|
||||
|
||||
if (current_value >= current_from) { g.drawRect(44-1,62+26+9,44+1,62+26+9+1); }
|
||||
if (current_value >= current_mid) { g.drawRect(88-1,62+26+9,88+1,62+26+9+1); }
|
||||
if (current_value >= current_to) { g.drawRect(132-1,62+26+9,132+1,62+26+9+1); }
|
||||
|
||||
|
||||
if (showInstructions) {
|
||||
g.setFont("6x8").drawString("Tapping timer locks buttons", 88, 100+5);
|
||||
g.setFont("6x8").drawString("<= Swipe to change time =>", 88, 168);
|
||||
|
@ -159,7 +159,7 @@ function draw() {
|
|||
g.drawString(timeToString(newtimer_left_to), 44, 138+9);
|
||||
g.drawString(timeToString(newtimer_right_from), 132, 138-9);
|
||||
g.drawString(timeToString(newtimer_right_to), 132, 138+9);
|
||||
|
||||
|
||||
g.drawRect(0+8,138-24, 88-9+1, 138+22+1);
|
||||
g.drawRect(0+8,138-24, 88-9, 138+22);
|
||||
g.drawRect(88+8,138-24, 176-10+1, 138+22+1);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.04: Fix tapping at very bottom of list, exit on inactivity
|
||||
0.03: Add "Calculating" placeholder, update JSON save format
|
||||
0.02: Fix JSON save format
|
||||
0.01: First release
|
||||
|
|
|
@ -10,6 +10,8 @@ const calculating = "Calculating";
|
|||
const notokens = "No tokens";
|
||||
const notsupported = "Not supported";
|
||||
|
||||
// sample settings:
|
||||
// {tokens:[{"algorithm":"SHA1","digits":6,"period":30,"issuer":"","account":"","secret":"Bbb","label":"Aaa"}],misc:{}}
|
||||
var settings = require("Storage").readJSON("authentiwatch.json", true) || {tokens:[],misc:{}};
|
||||
if (settings.data ) tokens = settings.data ; /* v0.02 settings */
|
||||
if (settings.tokens) tokens = settings.tokens; /* v0.03+ settings */
|
||||
|
@ -146,14 +148,14 @@ function drawToken(id, r) {
|
|||
// counter - draw triangle as swipe hint
|
||||
let yc = (y1 + y2) / 2;
|
||||
g.fillPoly([0, yc, 10, yc - 10, 10, yc + 10, 0, yc]);
|
||||
adj = 5;
|
||||
adj = 10;
|
||||
}
|
||||
// digits just below label
|
||||
sz = 30;
|
||||
do {
|
||||
g.setFont("Vector", sz--);
|
||||
} while (g.stringWidth(state.otp) > (r.w - adj));
|
||||
g.drawString(state.otp, (x1 + x2) / 2 + adj, y1 + 16, false);
|
||||
g.drawString(state.otp, (x1 + adj + x2) / 2, y1 + 16, false);
|
||||
}
|
||||
// shaded lines top and bottom
|
||||
g.setColor(0.5, 0.5, 0.5);
|
||||
|
@ -163,6 +165,8 @@ function drawToken(id, r) {
|
|||
}
|
||||
|
||||
function draw() {
|
||||
var timerfn = exitApp;
|
||||
var timerdly = 10000;
|
||||
var d = new Date();
|
||||
if (state.curtoken != -1) {
|
||||
var t = tokens[state.curtoken];
|
||||
|
@ -203,17 +207,13 @@ function draw() {
|
|||
y += tokenentryheight;
|
||||
}
|
||||
if (drewcur) {
|
||||
// the current token has been drawn - draw it again in 1sec
|
||||
if (state.drawtimer) {
|
||||
clearTimeout(state.drawtimer);
|
||||
}
|
||||
var dly;
|
||||
// the current token has been drawn - schedule a redraw
|
||||
if (tokens[state.curtoken].period > 0) {
|
||||
dly = (state.otp == calculating) ? 1 : 1000;
|
||||
timerdly = (state.otp == calculating) ? 1 : 1000; // timed
|
||||
} else {
|
||||
dly = state.nexttime - d.getTime();
|
||||
timerdly = state.nexttime - d.getTime(); // counter
|
||||
}
|
||||
state.drawtimer = setTimeout(draw, dly);
|
||||
timerfn = draw;
|
||||
if (tokens[state.curtoken].period <= 0) {
|
||||
state.hide = 0;
|
||||
}
|
||||
|
@ -230,12 +230,16 @@ function draw() {
|
|||
g.setFontAlign(0, 0, 0);
|
||||
g.drawString(notokens, Bangle.appRect.x + Bangle.appRect.w / 2, Bangle.appRect.y + Bangle.appRect.h / 2, false);
|
||||
}
|
||||
if (state.drawtimer) {
|
||||
clearTimeout(state.drawtimer);
|
||||
}
|
||||
state.drawtimer = setTimeout(timerfn, timerdly);
|
||||
}
|
||||
|
||||
function onTouch(zone, e) {
|
||||
if (e) {
|
||||
var id = Math.floor((state.listy + (e.y - Bangle.appRect.y)) / tokenentryheight);
|
||||
if (id == state.curtoken || tokens.length == 0) {
|
||||
if (id == state.curtoken || tokens.length == 0 || id >= tokens.length) {
|
||||
id = -1;
|
||||
}
|
||||
if (state.curtoken != id) {
|
||||
|
@ -254,26 +258,20 @@ function onTouch(zone, e) {
|
|||
state.nextTime = 0;
|
||||
state.curtoken = id;
|
||||
state.hide = 2;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
draw();
|
||||
}
|
||||
|
||||
function onDrag(e) {
|
||||
if (e.x > g.getWidth() || e.y > g.getHeight()) return;
|
||||
if (e.dx == 0 && e.dy == 0) return;
|
||||
var newy = Math.min(state.listy - e.dy, tokens.length * tokenentryheight - Bangle.appRect.h);
|
||||
newy = Math.max(0, newy);
|
||||
if (newy != state.listy) {
|
||||
state.listy = newy;
|
||||
draw();
|
||||
}
|
||||
state.listy = Math.max(0, newy);
|
||||
draw();
|
||||
}
|
||||
|
||||
function onSwipe(e) {
|
||||
if (e == 1) {
|
||||
Bangle.showLauncher();
|
||||
}
|
||||
if (e == -1 && state.curtoken != -1 && tokens[state.curtoken].period <= 0) {
|
||||
tokens[state.curtoken].period--;
|
||||
let newsettings={tokens:tokens,misc:settings.misc};
|
||||
|
@ -281,8 +279,8 @@ function onSwipe(e) {
|
|||
state.nextTime = 0;
|
||||
state.otp = "";
|
||||
state.hide = 2;
|
||||
draw();
|
||||
}
|
||||
draw();
|
||||
}
|
||||
|
||||
function bangle1Btn(e) {
|
||||
|
@ -302,16 +300,22 @@ function bangle1Btn(e) {
|
|||
state.curtoken = -1;
|
||||
state.nextTime = 0;
|
||||
onTouch(0, fakee);
|
||||
} else {
|
||||
draw(); // resets idle timer
|
||||
}
|
||||
}
|
||||
|
||||
function exitApp() {
|
||||
Bangle.showLauncher();
|
||||
}
|
||||
|
||||
Bangle.on('touch', onTouch);
|
||||
Bangle.on('drag' , onDrag );
|
||||
Bangle.on('swipe', onSwipe);
|
||||
if (typeof BTN2 == 'number') {
|
||||
setWatch(function(){bangle1Btn(-1); }, BTN1, {edge:"rising", debounce:50, repeat:true});
|
||||
setWatch(function(){Bangle.showLauncher();}, BTN2, {edge:"rising", debounce:50, repeat:true});
|
||||
setWatch(function(){bangle1Btn( 1); }, BTN3, {edge:"rising", debounce:50, repeat:true});
|
||||
setWatch(function(){bangle1Btn(-1);}, BTN1, {edge:"rising", debounce:50, repeat:true});
|
||||
setWatch(function(){exitApp(); }, BTN2, {edge:"rising", debounce:50, repeat:true});
|
||||
setWatch(function(){bangle1Btn( 1);}, BTN3, {edge:"rising", debounce:50, repeat:true});
|
||||
}
|
||||
Bangle.loadWidgets();
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# FLOW
|
||||
|
||||
This is a game where you have to help a flow avoid white obstacles thing by tapping!
|
||||
This is a demake of an app which I forgot the name of.
|
||||
Press BTN(1) to restart.
|
||||
See if you can get to 2500 score!
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||

|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEw4X/AwX48EHgEC1WgCQkVqoDBBfuqBQcBqoLagEqGAguBqALaGAOoAoQuEBbEAKgIMBBQNUBbgMCyoKHBbBVBBYIKGBbEBtNVrQLfOgNaT4gLagp0CPQOABbcBFwNAgEKBgILbitVqAFClWq0ALZFwTDFGAQLZFwYwDBfg"))
|
|
@ -0,0 +1,220 @@
|
|||
const isB2 = process.env.HWVERSION === 2;
|
||||
|
||||
// Bangle.js 1 runs just too fast in direct mode??? (also no getPixel)
|
||||
if (!isB2) Bangle.setLCDMode("120x120");
|
||||
|
||||
const options = Bangle.getOptions();
|
||||
|
||||
options.lockTimeout = 0;
|
||||
options.lcdPowerTimeout = 0;
|
||||
|
||||
Bangle.setOptions(options);
|
||||
|
||||
g.reset();
|
||||
g.setBgColor(0, 0, 0);
|
||||
g.setColor(255, 255, 255);
|
||||
g.clear();
|
||||
const h = g.getHeight();
|
||||
|
||||
function trigToCoord(ret) {
|
||||
return ((ret + 1) * h) / 2;
|
||||
}
|
||||
|
||||
function trigToLen(ret) {
|
||||
return (ret * h) / 2;
|
||||
}
|
||||
|
||||
let i = 0.2;
|
||||
let speedCoef = 0.014;
|
||||
|
||||
let flowFile = require("Storage").readJSON("flow.json");
|
||||
|
||||
let highestI = (flowFile && flowFile.hiscore) || 0.1;
|
||||
|
||||
let colorA = [255, 255, 0];
|
||||
let colorB = [0, 255, 255];
|
||||
|
||||
let x = 0;
|
||||
let xt = 0;
|
||||
let safeMode = false;
|
||||
let lost = false;
|
||||
|
||||
function offsetRect(g, x, y, w) {
|
||||
g.fillRect(x, y, x + w, y + w);
|
||||
}
|
||||
|
||||
function getColor(num) {
|
||||
return [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1],
|
||||
[1, 1, 0],
|
||||
[0, 1, 1],
|
||||
[1, 0, 1],
|
||||
[0.5, 0.5, 1],
|
||||
[1, 0.5, 0],
|
||||
[0, 1, 0.5],
|
||||
[0.5, 0.5, 0.5],
|
||||
][num];
|
||||
}
|
||||
|
||||
function calculateColor(num) {
|
||||
colorA = getColor(Math.floor((num % 1) * 10));
|
||||
colorB = getColor(Math.floor((num % 10) - (num % 1)));
|
||||
}
|
||||
|
||||
calculateColor(highestI);
|
||||
|
||||
Bangle.on("touch", () => (safeMode = !safeMode));
|
||||
|
||||
function resetGame() {
|
||||
x = xt = 0;
|
||||
safeMode = lost = false;
|
||||
i = 0.2;
|
||||
speedCoef = 0.014;
|
||||
obstaclePeriod = 150;
|
||||
obstacleMode = 1;
|
||||
g.clear();
|
||||
shownScore = false;
|
||||
intervalId = setInterval(draw);
|
||||
}
|
||||
|
||||
function checkCollision() {
|
||||
lost = g.getPixel(trigToCoord(+x), (h * 2) / 3 - 4) !== 0;
|
||||
if (lost) {
|
||||
scoringI = i;
|
||||
speedCoef = Math.min(speedCoef, 0.02);
|
||||
g.setFont(isB2 ? "6x15" : "4x6", 3);
|
||||
g.setColor(colorA[0], colorA[1], colorA[2])
|
||||
.drawString(
|
||||
"Game over",
|
||||
trigToCoord(0) - g.stringWidth("Game over") / 2,
|
||||
trigToCoord(0)
|
||||
)
|
||||
.setColor(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function drawPlayer() {
|
||||
if (!safeMode) xt = Math.cos(i * Math.PI * 4) / 7.5;
|
||||
else xt = -Math.cos(i * Math.PI * 2) / 20 + 0.35;
|
||||
x = x * 0.8 + xt * 0.2;
|
||||
if (highestI > 250) calculateColor(i);
|
||||
g.setColor(colorA[0], colorA[1], colorA[2]);
|
||||
offsetRect(g, trigToCoord(+x), (h * 2) / 3, 3);
|
||||
g.setColor(colorB[0], colorB[1], colorB[2]);
|
||||
offsetRect(g, trigToCoord(-x), (h * 2) / 3, 3);
|
||||
}
|
||||
|
||||
let obstaclePeriod = 150;
|
||||
let obstacleMode = 1;
|
||||
|
||||
function drawObstracle() {
|
||||
g.setColor(1, 1, 1);
|
||||
switch (obstacleMode) {
|
||||
case 0:
|
||||
offsetRect(g, trigToCoord(-0.15), 0, trigToLen(0.3));
|
||||
break;
|
||||
case 1:
|
||||
offsetRect(g, trigToCoord(0.2), 0, trigToLen(0.2));
|
||||
offsetRect(g, trigToCoord(-0.4), 0, trigToLen(0.2));
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
obstaclePeriod--;
|
||||
if (obstaclePeriod <= 0) {
|
||||
// If we are off cooldown mode, pick a random actual mode
|
||||
if (obstacleMode === 2) {
|
||||
obstaclePeriod = Math.random() * 50 + 50;
|
||||
obstacleMode = Math.round(Math.random());
|
||||
} else if (Math.random() > 0.5) {
|
||||
// Give it a chance to repeat with no cooldown
|
||||
obstaclePeriod = 25 + 2.5 * speedCoef;
|
||||
obstacleMode = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let shownScore = false;
|
||||
let scoringI = 0;
|
||||
|
||||
function draw() {
|
||||
if (!lost) {
|
||||
drawPlayer();
|
||||
checkCollision();
|
||||
speedCoef *= 1.0005;
|
||||
drawObstracle();
|
||||
} else {
|
||||
speedCoef /= 1.05;
|
||||
if (speedCoef <= 0.005) {
|
||||
clearInterval(intervalId);
|
||||
i -= speedCoef;
|
||||
g.setFont(isB2 ? "6x15" : "4x6", 1);
|
||||
const str = "Hiscore: " + Math.round(highestI * 10);
|
||||
g.setColor(
|
||||
scoringI > highestI ? 0 : 255,
|
||||
0,
|
||||
scoringI > highestI ? 255 : 0
|
||||
)
|
||||
.drawString(
|
||||
str,
|
||||
trigToCoord(0) - g.stringWidth(str) / 2,
|
||||
trigToCoord(0)
|
||||
)
|
||||
.setColor(255, 255, 255);
|
||||
if (scoringI > highestI) {
|
||||
highestI = scoringI;
|
||||
require("Storage").writeJSON("flow.json", {
|
||||
hiscore: highestI,
|
||||
});
|
||||
calculateColor(highestI);
|
||||
}
|
||||
setTimeout(resetGame, 3000);
|
||||
} else if (speedCoef <= 0.01 && !shownScore) {
|
||||
shownScore = true;
|
||||
g.setFont(isB2 ? "6x15" : "4x6", 2);
|
||||
const str = "Score: " + Math.round(scoringI * 10);
|
||||
g.setColor(colorB[0], colorB[1], colorB[2])
|
||||
.drawString(
|
||||
str,
|
||||
trigToCoord(0) - g.stringWidth(str) / 2,
|
||||
trigToCoord(0)
|
||||
)
|
||||
.setColor(1, 1, 1);
|
||||
}
|
||||
}
|
||||
i += speedCoef;
|
||||
g.scroll(0, speedCoef * h);
|
||||
g.flip();
|
||||
}
|
||||
|
||||
let intervalId;
|
||||
|
||||
if (BTN.read()) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
color = getColor(i);
|
||||
g.setColor(color[0], color[1], color[2]);
|
||||
g.fillRect((i / 10) * h, 0, ((i + 1) / 10) * h, h);
|
||||
}
|
||||
g.setColor(0);
|
||||
g.setFont("Vector", 9);
|
||||
let str = "Welcome to the debug screen!";
|
||||
g.drawString(
|
||||
str,
|
||||
trigToCoord(0) - g.stringWidth(str) / 2,
|
||||
trigToCoord(0) - 9
|
||||
);
|
||||
str = "Don't hold BTN while opening to play!";
|
||||
g.drawString(str, trigToCoord(0) - g.stringWidth(str) / 2, trigToCoord(0));
|
||||
g.flip();
|
||||
setInterval(() => {
|
||||
g.scroll(0, 0.014 * h);
|
||||
i += 0.014;
|
||||
calculateColor(i);
|
||||
g.setColor(colorA[0], colorA[1], colorA[2]);
|
||||
g.fillRect(0, 0, trigToCoord(0), 0.014 * h);
|
||||
g.setColor(colorB[0], colorB[1], colorB[2]);
|
||||
g.fillRect(trigToCoord(0), 0, trigToCoord(1), 0.014 * h);
|
||||
}, 1000 / 30);
|
||||
} else intervalId = setInterval(draw, 1000 / 30);
|
After Width: | Height: | Size: 323 B |
After Width: | Height: | Size: 992 B |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: using TS and rollup to bundle
|
||||
0.03: bug fixes and support bangle 1
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-20 Ionică Bizău <bizauionica@gmail.com> (https://ionicabizau.net)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,26 @@
|
|||
# Hebrew Calendar
|
||||
|
||||
Displays the current hebrew calendar date
|
||||
Add screen shots (if possible) to the app folder and link then into this file with 
|
||||
|
||||
## Usage
|
||||
|
||||
Open the app, and it shows a menu with the date components
|
||||
|
||||
## Features
|
||||
|
||||
Shows the hebrew date, month, and year; alongside the gregorian date
|
||||
|
||||
## Controls
|
||||
|
||||
Name the buttons and what they are used for
|
||||
|
||||
## Requests
|
||||
|
||||
Michael Salaverry (github.com/barakplasma)
|
||||
|
||||
## Creator
|
||||
|
||||
Michael Salaverry
|
||||
with help from https://github.com/IonicaBizau/hebrew-date (MIT license)
|
||||
<div>Icons made by <a href="https://www.flaticon.com/authors/smashicons" title="Smashicons">Smashicons</a> from <a href="https://www.flaticon.com/" title="Flaticon">[www.flaticon.com](https://www.flaticon.com/premium-icon/calendar_3130060?term=jewish&page=1&position=10&page=1&position=10&related_id=3130060&origin=tag)</a></div>
|
|
@ -0,0 +1,17 @@
|
|||
!function(){"use strict";
|
||||
/*!
|
||||
* This script was taked from this page and ported to Node.js by Ionic Bizu
|
||||
* http://www.shamash.org/help/javadate.shtml
|
||||
*
|
||||
* This script was adapted from C sources written by
|
||||
* Scott E. Lee, which contain the following copyright notice:
|
||||
*
|
||||
* Copyright 1993-1995, Scott E. Lee, all rights reserved.
|
||||
* Permission granted to use, copy, modify, distribute and sell so long as
|
||||
* the above copyright and this permission statement are retained in all
|
||||
* copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
|
||||
*
|
||||
* Bill Hastings
|
||||
* RBI Software Systems
|
||||
* bhastings@rbi.com
|
||||
*/var t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};var i=new function(t,i,e,o,r,n,h,a,s,f,u,l,v,c){this[0]=t,this[1]=i,this[2]=e,this[3]=o,this[4]=r,this[5]=n,this[6]=h,this[7]=a,this[8]=s,this[9]=f,this[10]=u,this[11]=l,this[12]=v,this[13]=c}("Tishri","Heshvan","Kislev","Tevet","Shevat","AdarI","AdarII","Nisan","Iyyar","Sivan","Tammuz","Av","Elul"),e=new function(t,i,e,o,r,n,h,a,s,f,u,l,v,c,y,d,m,M,b){this[0]=t,this[1]=i,this[2]=e,this[3]=o,this[4]=r,this[5]=n,this[6]=h,this[7]=a,this[8]=s,this[9]=f,this[10]=u,this[11]=l,this[12]=v,this[13]=c,this[14]=y,this[15]=d,this[16]=m,this[17]=M,this[18]=b}(12,12,13,12,12,13,12,13,12,12,13,12,12,13,12,12,13,12,13);g.clear();let o=new Date,r=function(o){var r,n,h=0,a=0,s=0,f=0,u=0,l=0,v=0;function c(t){var i,o,r,n;for(f=Math.floor((t+310)/6940),r=void 0,n=void 0,r=31524,n=(r+=45971*f)>>16,n+=2744*f,o=Math.floor(n/25920),r=(n-=25920*o)<<16|65535&r,i=Math.floor(r/25920),l=o<<16|i,v=r-=25920*i;l<t-6940+310;)f++,v+=179876755,l+=Math.floor(v/25920),v%=25920;for(u=0;u<18&&!(l>t-74);u++)v+=765433*e[u],l+=Math.floor(v/25920),v%=25920}function y(t,i,e){var o=i,r=o%7;return(e>=19440||!(2==t||5==t||7==t||10==t||13==t||16==t||18==t)&&2==r&&e>=9924||(3==t||6==t||8==t||11==t||14==t||17==t||0==t)&&1==r&&e>=16789)&&(o++,7==++r&&(r=0)),3!=r&&5!=r&&0!=r||o++,o}var d=o;return"object"===(void 0===d?"undefined":t(d))&&(r=o.getMonth()+1,n=o.getDate(),d=o.getFullYear()),function(t){var i,o=0,r=0,n=t-347997;if(c(n),n>=(o=y(u,l,v))){if(s=19*f+u+1,n<o+59)return void(n<o+30?(h=1,a=n-o+1):(h=2,a=n-o-29));v+=765433*e[u],l+=Math.floor(v/25920),r=y((u+1)%19,l,v%=25920)}else{if(s=19*f+u,n>=o-177)return void(n>o-30?(h=13,a=n-o+30):n>o-60?(h=12,a=n-o+60):n>o-89?(h=11,a=n-o+89):n>o-119?(h=10,a=n-o+119):n>o-148?(h=9,a=n-o+148):(h=8,a=n-o+178));if(13==e[(s-1)%19]){if(h=7,(a=n-o+207)>0)return;if(h--,(a+=30)>0)return;h--,a+=30}else{if(h=6,(a=n-o+207)>0)return;h--,a+=30}if(a>0)return;if(h--,(a+=29)>0)return;r=o,c(l-365),o=y(u,l,v)}if(l=n-o-29,355==(i=r-o)||385==i){if(l<=30)return h=2,void(a=l);l-=30}else{if(l<=29)return h=2,void(a=l);l-=29}h=3,a=l}(function(t,i,e){var o=0,r=0,n=void 0;return o=t<0?t+4801:t+4800,i>2?r=i-3:(r=i+9,o--),n=Math.floor(146097*Math.floor(o/100)/4),n+=Math.floor(o%100*1461/4),n+=Math.floor((153*r+2)/5),n+=e-32045}(d,r,n)),{year:s,month:h,date:a,month_name:i[h-1]}}(o);var n={"":{title:"Hebrew Date"},cal:{value:require("locale").date(o,1),onchange:()=>{}},date:{value:r.date,onchange:()=>{}},month:{value:r.month_name,onchange:()=>{}},year:{value:r.year,onchange:()=>{}}};E.showMenu(n)}();
|
After Width: | Height: | Size: 32 KiB |
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "hebrew_calendar",
|
||||
"version": "0.0.3",
|
||||
"description": "Bangle.js app for seeing hebrew calendar",
|
||||
"main": "app.js",
|
||||
"types": "app.d.ts",
|
||||
"scripts": {
|
||||
"build": "rollup -c"
|
||||
},
|
||||
"author": {
|
||||
"name": "Michael Salaverry",
|
||||
"url": "https://github.com/barakplasma"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^4.1.1",
|
||||
"rollup": "^2.10.2",
|
||||
"rollup-plugin-terser": "^5.3.0",
|
||||
"terser": "^4.7.0",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "^3.9.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import typescript from '@rollup/plugin-typescript';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
export default {
|
||||
input: './src/app.ts',
|
||||
output: {
|
||||
dir: '.',
|
||||
format: 'iife',
|
||||
name: 'hebrew_calendar'
|
||||
},
|
||||
plugins: [
|
||||
typescript(),
|
||||
terser(),
|
||||
]
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
declare var Bangle: any;
|
||||
declare var g: any;
|
||||
declare var E: any;
|
||||
declare var require: any;
|
||||
|
||||
g.clear();
|
||||
|
||||
let now = new Date();
|
||||
import { hebrewDate } from "./hebrewDate";
|
||||
|
||||
let today = hebrewDate(now);
|
||||
|
||||
var mainmenu = {
|
||||
"" : {
|
||||
"title" : "Hebrew Date"
|
||||
},
|
||||
cal: {
|
||||
value: require('locale').date(now,1),
|
||||
onchange : () => {}
|
||||
},
|
||||
date: {
|
||||
value : today.date,
|
||||
onchange : () => {}
|
||||
},
|
||||
month: {
|
||||
value : today.month_name,
|
||||
onchange : () => {}
|
||||
},
|
||||
year: {
|
||||
value : today.year,
|
||||
onchange : () => {}
|
||||
}
|
||||
};
|
||||
E.showMenu(mainmenu);
|
|
@ -0,0 +1,358 @@
|
|||
/*!
|
||||
* This script was taked from this page and ported to Node.js by Ionic Bizu
|
||||
* http://www.shamash.org/help/javadate.shtml
|
||||
*
|
||||
* This script was adapted from C sources written by
|
||||
* Scott E. Lee, which contain the following copyright notice:
|
||||
*
|
||||
* Copyright 1993-1995, Scott E. Lee, all rights reserved.
|
||||
* Permission granted to use, copy, modify, distribute and sell so long as
|
||||
* the above copyright and this permission statement are retained in all
|
||||
* copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
|
||||
*
|
||||
* Bill Hastings
|
||||
* RBI Software Systems
|
||||
* bhastings@rbi.com
|
||||
*/
|
||||
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
var GREG_SDN_OFFSET = 32045,
|
||||
DAYS_PER_5_MONTHS = 153,
|
||||
DAYS_PER_4_YEARS = 1461,
|
||||
DAYS_PER_400_YEARS = 146097;
|
||||
|
||||
var HALAKIM_PER_HOUR = 1080,
|
||||
HALAKIM_PER_DAY = 25920,
|
||||
HALAKIM_PER_LUNAR_CYCLE = 29 * HALAKIM_PER_DAY + 13753,
|
||||
HALAKIM_PER_METONIC_CYCLE = HALAKIM_PER_LUNAR_CYCLE * (12 * 19 + 7);
|
||||
|
||||
var HEB_SDN_OFFSET = 347997,
|
||||
NEW_MOON_OF_CREATION = 31524,
|
||||
NOON = 18 * HALAKIM_PER_HOUR,
|
||||
AM3_11_20 = 9 * HALAKIM_PER_HOUR + 204,
|
||||
AM9_32_43 = 15 * HALAKIM_PER_HOUR + 589;
|
||||
|
||||
var SUN = 0,
|
||||
MON = 1,
|
||||
TUES = 2,
|
||||
WED = 3,
|
||||
THUR = 4,
|
||||
FRI = 5,
|
||||
SAT = 6;
|
||||
|
||||
function weekdayarr(d0, d1, d2, d3, d4, d5, d6) {
|
||||
this[0] = d0;
|
||||
this[1] = d1;
|
||||
this[2] = d2;
|
||||
this[3] = d3;
|
||||
this[4] = d4;
|
||||
this[5] = d5;
|
||||
this[6] = d6;
|
||||
}
|
||||
|
||||
function gregmontharr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11) {
|
||||
this[0] = m0;
|
||||
this[1] = m1;
|
||||
this[2] = m2;
|
||||
this[3] = m3;
|
||||
this[4] = m4;
|
||||
this[5] = m5;
|
||||
this[6] = m6;
|
||||
this[7] = m7;
|
||||
this[8] = m8;
|
||||
this[9] = m9;
|
||||
this[10] = m10;
|
||||
this[11] = m11;
|
||||
}
|
||||
|
||||
function hebrewmontharr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13?: any) {
|
||||
this[0] = m0;
|
||||
this[1] = m1;
|
||||
this[2] = m2;
|
||||
this[3] = m3;
|
||||
this[4] = m4;
|
||||
this[5] = m5;
|
||||
this[6] = m6;
|
||||
this[7] = m7;
|
||||
this[8] = m8;
|
||||
this[9] = m9;
|
||||
this[10] = m10;
|
||||
this[11] = m11;
|
||||
this[12] = m12;
|
||||
this[13] = m13;
|
||||
}
|
||||
|
||||
function monthsperyeararr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18) {
|
||||
this[0] = m0;
|
||||
this[1] = m1;
|
||||
this[2] = m2;
|
||||
this[3] = m3;
|
||||
this[4] = m4;
|
||||
this[5] = m5;
|
||||
this[6] = m6;
|
||||
this[7] = m7;
|
||||
this[8] = m8;
|
||||
this[9] = m9;
|
||||
this[10] = m10;
|
||||
this[11] = m11;
|
||||
this[12] = m12;
|
||||
this[13] = m13;
|
||||
this[14] = m14;
|
||||
this[15] = m15;
|
||||
this[16] = m16;
|
||||
this[17] = m17;
|
||||
this[18] = m18;
|
||||
}
|
||||
|
||||
var gWeekday = new weekdayarr("Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur"),
|
||||
gMonth = new gregmontharr("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"),
|
||||
hMonth = new hebrewmontharr("Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "AdarI", "AdarII", "Nisan", "Iyyar", "Sivan", "Tammuz", "Av", "Elul"),
|
||||
mpy = new monthsperyeararr(12, 12, 13, 12, 12, 13, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 13);
|
||||
|
||||
/**
|
||||
* hebrewDate
|
||||
* Convert the Gregorian dates into Hebrew calendar dates.
|
||||
*
|
||||
* @name hebrewDate
|
||||
* @function
|
||||
* @param {Date|Number} inputDate The date object (representing the Gregorian date) or the year.
|
||||
* @return {Object} An object containing:
|
||||
*
|
||||
* - `year`: The Hebrew year.
|
||||
* - `month`: The Hebrew month.
|
||||
* - `month_name`: The Hebrew month name.
|
||||
* - `date`: The Hebrew date.
|
||||
*/
|
||||
export const hebrewDate = function (inputDateOrYear: Date) {
|
||||
var inputMonth, inputDate;
|
||||
|
||||
var hebrewMonth = 0,
|
||||
hebrewDate = 0,
|
||||
hebrewYear = 0,
|
||||
metonicCycle = 0,
|
||||
metonicYear = 0,
|
||||
moladDay = 0,
|
||||
moladHalakim = 0;
|
||||
|
||||
function GregorianToSdn(inputYear, inputMonth, inputDay) {
|
||||
|
||||
var year = 0,
|
||||
month = 0,
|
||||
sdn = void 0;
|
||||
|
||||
// Make year a positive number
|
||||
if (inputYear < 0) {
|
||||
year = inputYear + 4801;
|
||||
} else {
|
||||
year = inputYear + 4800;
|
||||
}
|
||||
|
||||
// Adjust the start of the year
|
||||
if (inputMonth > 2) {
|
||||
month = inputMonth - 3;
|
||||
} else {
|
||||
month = inputMonth + 9;
|
||||
year--;
|
||||
}
|
||||
|
||||
sdn = Math.floor(Math.floor(year / 100) * DAYS_PER_400_YEARS / 4);
|
||||
sdn += Math.floor(year % 100 * DAYS_PER_4_YEARS / 4);
|
||||
sdn += Math.floor((month * DAYS_PER_5_MONTHS + 2) / 5);
|
||||
sdn += inputDay - GREG_SDN_OFFSET;
|
||||
|
||||
return sdn;
|
||||
}
|
||||
|
||||
function SdnToHebrew(sdn) {
|
||||
var tishri1 = 0,
|
||||
tishri1After = 0,
|
||||
yearLength = 0,
|
||||
inputDay = sdn - HEB_SDN_OFFSET;
|
||||
|
||||
FindTishriMolad(inputDay);
|
||||
tishri1 = Tishri1(metonicYear, moladDay, moladHalakim);
|
||||
|
||||
if (inputDay >= tishri1) {
|
||||
// It found Tishri 1 at the start of the year.
|
||||
hebrewYear = metonicCycle * 19 + metonicYear + 1;
|
||||
if (inputDay < tishri1 + 59) {
|
||||
if (inputDay < tishri1 + 30) {
|
||||
hebrewMonth = 1;
|
||||
hebrewDate = inputDay - tishri1 + 1;
|
||||
} else {
|
||||
hebrewMonth = 2;
|
||||
hebrewDate = inputDay - tishri1 - 29;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// We need the length of the year to figure this out,so find Tishri 1 of the next year.
|
||||
moladHalakim += HALAKIM_PER_LUNAR_CYCLE * mpy[metonicYear];
|
||||
moladDay += Math.floor(moladHalakim / HALAKIM_PER_DAY);
|
||||
moladHalakim = moladHalakim % HALAKIM_PER_DAY;
|
||||
tishri1After = Tishri1((metonicYear + 1) % 19, moladDay, moladHalakim);
|
||||
} else {
|
||||
// It found Tishri 1 at the end of the year.
|
||||
hebrewYear = metonicCycle * 19 + metonicYear;
|
||||
if (inputDay >= tishri1 - 177) {
|
||||
// It is one of the last 6 months of the year.
|
||||
if (inputDay > tishri1 - 30) {
|
||||
hebrewMonth = 13;
|
||||
hebrewDate = inputDay - tishri1 + 30;
|
||||
} else if (inputDay > tishri1 - 60) {
|
||||
hebrewMonth = 12;
|
||||
hebrewDate = inputDay - tishri1 + 60;
|
||||
} else if (inputDay > tishri1 - 89) {
|
||||
hebrewMonth = 11;
|
||||
hebrewDate = inputDay - tishri1 + 89;
|
||||
} else if (inputDay > tishri1 - 119) {
|
||||
hebrewMonth = 10;
|
||||
hebrewDate = inputDay - tishri1 + 119;
|
||||
} else if (inputDay > tishri1 - 148) {
|
||||
hebrewMonth = 9;
|
||||
hebrewDate = inputDay - tishri1 + 148;
|
||||
} else {
|
||||
hebrewMonth = 8;
|
||||
hebrewDate = inputDay - tishri1 + 178;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (mpy[(hebrewYear - 1) % 19] == 13) {
|
||||
hebrewMonth = 7;
|
||||
hebrewDate = inputDay - tishri1 + 207;
|
||||
if (hebrewDate > 0) return;
|
||||
hebrewMonth--;
|
||||
hebrewDate += 30;
|
||||
if (hebrewDate > 0) return;
|
||||
hebrewMonth--;
|
||||
hebrewDate += 30;
|
||||
} else {
|
||||
hebrewMonth = 6;
|
||||
hebrewDate = inputDay - tishri1 + 207;
|
||||
if (hebrewDate > 0) return;
|
||||
hebrewMonth--;
|
||||
hebrewDate += 30;
|
||||
}
|
||||
if (hebrewDate > 0) return;
|
||||
hebrewMonth--;
|
||||
hebrewDate += 29;
|
||||
if (hebrewDate > 0) return;
|
||||
// We need the length of the year to figure this out,so find Tishri 1 of this year.
|
||||
tishri1After = tishri1;
|
||||
FindTishriMolad(moladDay - 365);
|
||||
tishri1 = Tishri1(metonicYear, moladDay, moladHalakim);
|
||||
}
|
||||
}
|
||||
yearLength = tishri1After - tishri1;
|
||||
moladDay = inputDay - tishri1 - 29;
|
||||
if (yearLength == 355 || yearLength == 385) {
|
||||
// Heshvan has 30 days
|
||||
if (moladDay <= 30) {
|
||||
hebrewMonth = 2;
|
||||
hebrewDate = moladDay;
|
||||
return;
|
||||
}
|
||||
moladDay -= 30;
|
||||
} else {
|
||||
// Heshvan has 29 days
|
||||
if (moladDay <= 29) {
|
||||
hebrewMonth = 2;
|
||||
hebrewDate = moladDay;
|
||||
return;
|
||||
}
|
||||
moladDay -= 29;
|
||||
}
|
||||
// It has to be Kislev.
|
||||
hebrewMonth = 3;
|
||||
hebrewDate = moladDay;
|
||||
}
|
||||
|
||||
function FindTishriMolad(inputDay) {
|
||||
// Estimate the metonic cycle number. Note that this may be an under
|
||||
// estimate because there are 6939.6896 days in a metonic cycle not
|
||||
// 6940,but it will never be an over estimate. The loop below will
|
||||
// correct for any error in this estimate.
|
||||
metonicCycle = Math.floor((inputDay + 310) / 6940);
|
||||
// Calculate the time of the starting molad for this metonic cycle.
|
||||
MoladOfMetonicCycle();
|
||||
// If the above was an under estimate,increment the cycle number until
|
||||
// the correct one is found. For modern dates this loop is about 98.6%
|
||||
// likely to not execute,even once,because the above estimate is
|
||||
// really quite close.
|
||||
while (moladDay < inputDay - 6940 + 310) {
|
||||
metonicCycle++;
|
||||
moladHalakim += HALAKIM_PER_METONIC_CYCLE;
|
||||
moladDay += Math.floor(moladHalakim / HALAKIM_PER_DAY);
|
||||
moladHalakim = moladHalakim % HALAKIM_PER_DAY;
|
||||
}
|
||||
// Find the molad of Tishri closest to this date.
|
||||
for (metonicYear = 0; metonicYear < 18; metonicYear++) {
|
||||
if (moladDay > inputDay - 74) break;
|
||||
moladHalakim += HALAKIM_PER_LUNAR_CYCLE * mpy[metonicYear];
|
||||
moladDay += Math.floor(moladHalakim / HALAKIM_PER_DAY);
|
||||
moladHalakim = moladHalakim % HALAKIM_PER_DAY;
|
||||
}
|
||||
}
|
||||
|
||||
function MoladOfMetonicCycle() {
|
||||
var r1 = void 0,
|
||||
r2 = void 0,
|
||||
d1 = void 0,
|
||||
d2 = void 0;
|
||||
// Start with the time of the first molad after creation.
|
||||
r1 = NEW_MOON_OF_CREATION;
|
||||
// Calculate gMetonicCycle * HALAKIM_PER_METONIC_CYCLE. The upper 32
|
||||
// bits of the result will be in r2 and the lower 16 bits will be in r1.
|
||||
r1 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF);
|
||||
r2 = r1 >> 16;
|
||||
r2 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE >> 16 & 0xFFFF);
|
||||
// Calculate r2r1 / HALAKIM_PER_DAY. The remainder will be in r1,the
|
||||
// upper 16 bits of the quotient will be in d2 and the lower 16 bits
|
||||
// will be in d1.
|
||||
d2 = Math.floor(r2 / HALAKIM_PER_DAY);
|
||||
r2 -= d2 * HALAKIM_PER_DAY;
|
||||
r1 = r2 << 16 | r1 & 0xFFFF;
|
||||
d1 = Math.floor(r1 / HALAKIM_PER_DAY);
|
||||
r1 -= d1 * HALAKIM_PER_DAY;
|
||||
moladDay = d2 << 16 | d1;
|
||||
moladHalakim = r1;
|
||||
}
|
||||
|
||||
function Tishri1(metonicYear, moladDay, moladHalakim) {
|
||||
var tishri1 = moladDay,
|
||||
dow = tishri1 % 7,
|
||||
leapYear = metonicYear == 2 || metonicYear == 5 || metonicYear == 7 || metonicYear == 10 || metonicYear == 13 || metonicYear == 16 || metonicYear == 18,
|
||||
lastWasLeapYear = metonicYear == 3 || metonicYear == 6 || metonicYear == 8 || metonicYear == 11 || metonicYear == 14 || metonicYear == 17 || metonicYear == 0;
|
||||
|
||||
// Apply rules 2,3 and 4
|
||||
if (moladHalakim >= NOON || !leapYear && dow == TUES && moladHalakim >= AM3_11_20 || lastWasLeapYear && dow == MON && moladHalakim >= AM9_32_43) {
|
||||
tishri1++;
|
||||
dow++;
|
||||
if (dow == 7) dow = 0;
|
||||
}
|
||||
|
||||
// Apply rule 1 after the others because it can cause an additional delay of one day.
|
||||
if (dow == WED || dow == FRI || dow == SUN) {
|
||||
tishri1++;
|
||||
}
|
||||
|
||||
return tishri1;
|
||||
}
|
||||
|
||||
var inputYear: Date | number = inputDateOrYear;
|
||||
|
||||
if ((typeof inputYear === "undefined" ? "undefined" : _typeof(inputYear)) === "object") {
|
||||
inputMonth = inputDateOrYear.getMonth() + 1;
|
||||
inputDate = inputDateOrYear.getDate();
|
||||
inputYear = inputDateOrYear.getFullYear();
|
||||
}
|
||||
|
||||
SdnToHebrew(GregorianToSdn(inputYear, inputMonth, inputDate));
|
||||
|
||||
return {
|
||||
year: hebrewYear,
|
||||
month: hebrewMonth,
|
||||
date: hebrewDate,
|
||||
month_name: hMonth[hebrewMonth - 1]
|
||||
};
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "es2015",
|
||||
"noImplicitAny": false,
|
||||
"target": "es2015"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
|
@ -8,3 +8,4 @@
|
|||
0.08: Merge Bangle.js 1 and 2 launchers
|
||||
0.09: Bangle.js 2 - pressing the button goes back to clock (fix #971)
|
||||
After 10s of being locked, the launcher goes back to the clock screen
|
||||
0.10: added in selectable font in settings including scalable vector font
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
var s = require("Storage");
|
||||
let fonts = g.getFonts();
|
||||
var scaleval = 1;
|
||||
var vectorval = 20;
|
||||
var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
|
||||
let settings = require('Storage').readJSON("launch.json", true) || {};
|
||||
if ("vectorsize" in settings) {
|
||||
vectorval = parseInt(settings.vectorsize);
|
||||
}
|
||||
if ("font" in settings){
|
||||
if(settings.font == "Vector"){
|
||||
scaleval = vectorval/20;
|
||||
font = "Vector"+(vectorval).toString();
|
||||
}
|
||||
else{
|
||||
font = settings.font;
|
||||
scaleval = (font.split('x')[1])/20;
|
||||
}
|
||||
}
|
||||
var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type));
|
||||
apps.sort((a,b)=>{
|
||||
var n=(0|a.sortorder)-(0|b.sortorder);
|
||||
|
@ -11,8 +29,6 @@ apps.forEach(app=>{
|
|||
if (app.icon)
|
||||
app.icon = s.read(app.icon); // should just be a link to a memory area
|
||||
});
|
||||
// FIXME: not needed after 2v11
|
||||
var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
|
||||
// FIXME: check not needed after 2v11
|
||||
if (g.wrapString) {
|
||||
g.setFont(font);
|
||||
|
@ -22,9 +38,9 @@ if (g.wrapString) {
|
|||
function drawApp(i, r) {
|
||||
var app = apps[i];
|
||||
if (!app) return;
|
||||
g.clearRect(r.x,r.y,r.x+r.w-1, r.y+r.h-1);
|
||||
g.setFont(font).setFontAlign(-1,0).drawString(app.name,64,r.y+32);
|
||||
if (app.icon) try {g.drawImage(app.icon,8,r.y+8);} catch(e){}
|
||||
g.clearRect((r.x),(r.y),(r.x+r.w-1), (r.y+r.h-1));
|
||||
g.setFont(font).setFontAlign(-1,0).drawString(app.name,64*scaleval,r.y+(32*scaleval));
|
||||
if (app.icon) try {g.drawImage(app.icon,8*scaleval, r.y+(8*scaleval), {scale: scaleval});} catch(e){}
|
||||
}
|
||||
|
||||
g.clear();
|
||||
|
@ -32,7 +48,7 @@ Bangle.loadWidgets();
|
|||
Bangle.drawWidgets();
|
||||
|
||||
E.showScroller({
|
||||
h : 64, c : apps.length,
|
||||
h : 64*scaleval, c : apps.length,
|
||||
draw : drawApp,
|
||||
select : i => {
|
||||
var app = apps[i];
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// make sure to enclose the function in parentheses
|
||||
(function(back) {
|
||||
let settings = require('Storage').readJSON('launch.json',1)||{};
|
||||
let fonts = g.getFonts();
|
||||
function save(key, value) {
|
||||
settings[key] = value;
|
||||
require('Storage').write('launch.json',settings);
|
||||
}
|
||||
const appMenu = {
|
||||
'': {'title': 'Launcher Settings'},
|
||||
'< Back': back,
|
||||
'Font': {
|
||||
value: fonts.includes(settings.font)? fonts.indexOf(settings.font) : fonts.indexOf("12x20"),
|
||||
min:0, max:fonts.length-1, step:1,wrap:true,
|
||||
onchange: (m) => {save('font', fonts[m])},
|
||||
format: v => fonts[v]
|
||||
},
|
||||
'Vector font size': {
|
||||
value: settings.vectorsize || 10,
|
||||
min:10, max: 20,step:1,wrap:true,
|
||||
onchange: (m) => {save('vectorsize', m)}
|
||||
}
|
||||
};
|
||||
E.showMenu(appMenu);
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
# Mandlebrot Clock
|
||||
# Mandelbrot Clock
|
||||
|
||||
A simple clock themed on the mandlebrot set.
|
||||
A simple clock themed on the mandelbrot set.
|
||||
|
||||
Written by [James Milner](https://www.github.com/jameslmilner)
|
||||
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
@ -1,6 +1,6 @@
|
|||
// MIT License - James Milner 2021
|
||||
|
||||
const mandlebrotBmp = {
|
||||
const mandelbrotBmp = {
|
||||
width: 176,
|
||||
height: 176,
|
||||
bpp: 8,
|
||||
|
@ -13,7 +13,7 @@ const mandlebrotBmp = {
|
|||
};
|
||||
|
||||
function draw() {
|
||||
g.drawImage(mandlebrotBmp);
|
||||
g.drawImage(mandelbrotBmp);
|
||||
// work out how to display the current time
|
||||
const d = new Date();
|
||||
const h = d.getHours(),
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
@ -0,0 +1 @@
|
|||
0.01: New menu!
|
|
@ -0,0 +1,25 @@
|
|||
# Wheel Menu
|
||||
|
||||
Replace Bangle.js 2's menus with a version that contains variable-size text and a back button.
|
||||
|
||||
Bangle.js 1:
|
||||

|
||||

|
||||
|
||||
Bangle.js 2:
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
## Features
|
||||
|
||||
If the menu contains "Back" or "Exit", it is shown as a button instead.
|
||||
The menu wraps around, with a divider between the last and first items.
|
||||
|
||||
## Controls
|
||||
|
||||
Bangle.js 1: Use BTN1/BTN3 to scroll through items, BTN2 to open/edit the selected item.
|
||||
Bangle.js 2: Swipe up/down to scroll through items, tap/BTN to open/edit the selected item.
|
||||
|
||||
Press the back button (if present) to go back.
|
|
@ -0,0 +1,213 @@
|
|||
E.showMenu = function(items) {
|
||||
g.clearRect(Bangle.appRect); // clear screen if no menu supplied
|
||||
// clean up back button listener
|
||||
if (Bangle.backHandler) Bangle.removeListener('touch', Bangle.backHandler)
|
||||
delete Bangle.backHandler;
|
||||
if (!items) {
|
||||
Bangle.setUI();
|
||||
return;
|
||||
}
|
||||
|
||||
var B2 = process.env.HWVERSION===2,
|
||||
loc = require("locale"),
|
||||
menuItems = Object.keys(items),
|
||||
options = items[""];
|
||||
if (options) menuItems.splice(menuItems.indexOf(""),1);
|
||||
if (!(options instanceof Object)) options = {};
|
||||
|
||||
// show "< Back" item (or similar) as button instead (i.e. remove from the menu)
|
||||
var back,backLbl;
|
||||
for (var b of ['Back', 'Exit', 'Cancel']) {
|
||||
if (!items[b] && items['< '+b]) b = '< '+b;
|
||||
back = items[b];
|
||||
if (typeof back === "function") {
|
||||
backLbl = loc.translate(b);
|
||||
menuItems.splice(menuItems.indexOf(b),1);
|
||||
break;
|
||||
}
|
||||
else back = undefined;
|
||||
}
|
||||
// font sizes
|
||||
var small = B2?15:22,
|
||||
large = B2?30:45;
|
||||
if (options.selected === undefined) options.selected = 0;
|
||||
var ar = Bangle.appRect,
|
||||
x = ar.x,
|
||||
x2 = ar.x2,
|
||||
w = ar.w,
|
||||
y = ar.y,
|
||||
y2 = ar.y2;
|
||||
if (options.title) y += 22;
|
||||
var wrap = menuItems.length>3; // don't wrap if all items are always in view anyway
|
||||
|
||||
var vc=Math.round((y+y2)/2), // vertical center
|
||||
hc = Math.round((x+x2)/2), // horizontal center
|
||||
ih = large+small*2; // active item height
|
||||
|
||||
var getItem = idx => {
|
||||
// we wrap out-of-range indexes
|
||||
while (idx<0) idx+=menuItems.length;
|
||||
idx = idx%menuItems.length;
|
||||
var name = menuItems[idx];
|
||||
var item = items[name];
|
||||
var v;
|
||||
if ("object"== typeof item) {
|
||||
v = item.value;
|
||||
if (item.format) v = item.format(v);
|
||||
v = loc.translate(""+v);
|
||||
}
|
||||
return {lbl: loc.translate(name), v: v};
|
||||
};
|
||||
var l = {
|
||||
lastIdx : null, // we want a complete redraw on first run
|
||||
draw : function() {
|
||||
var idx = options.selected,
|
||||
edit = l.selectEdit;
|
||||
g.reset();
|
||||
|
||||
// don't highlight whole item when editing
|
||||
g.setColor(edit?g.theme.fg:g.theme.fgH)
|
||||
.setBgColor(edit?g.theme.bg:g.theme.bgH)
|
||||
.setFont('Vector', large);
|
||||
var item = getItem(idx),
|
||||
lw = g.stringWidth(item.lbl)+2;
|
||||
if (lw+2 >= w) { // label width doesn't fit at large size: scale it down
|
||||
g.setFont('Vector', Math.floor(large*ar.w/lw));
|
||||
}
|
||||
g.clearRect(x,vc-ih/2,x2,vc+ih/2)
|
||||
.setFontAlign(0,0,0).drawString(item.lbl,hc,vc);
|
||||
|
||||
if (item.v !== undefined) {
|
||||
g.setColor(g.theme.fgH).setBgColor(g.theme.bgH) // always highlighted: either as part of item, or while editing
|
||||
.setFontAlign(0,1,0)
|
||||
.setFont('Vector', small)
|
||||
.clearRect(x,vc+ih/2-small-2,x2,vc+ih/2)
|
||||
.drawString(item.v,hc,vc+ih/2-1);
|
||||
if (edit) {
|
||||
g.drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",x2-23,vc+ih/2-small+(B2?1:5),{scale:2});
|
||||
}
|
||||
}
|
||||
if (l.lastIdx !== idx) {
|
||||
// we scrolled: redraw all
|
||||
l.lastIdx=idx;
|
||||
g.reset();
|
||||
|
||||
if (options.title) {
|
||||
if (B2) g.setFont('12x20');
|
||||
else g.setFont('6x8',2);
|
||||
g.drawLine(x, y-2, x2, y-2)
|
||||
.setFontAlign(0,1,0)
|
||||
.drawString(options.title, (x+x2)/2, y-2);
|
||||
}
|
||||
|
||||
// clear prev/next items area
|
||||
g.clearRect(x,y,x2,vc-ih/2-1)
|
||||
.clearRect(x,vc+ih/2+1,x2,y2);
|
||||
|
||||
// get display label by index
|
||||
var lbl = idx => {
|
||||
var item = getItem(idx);
|
||||
if (item.v !== undefined) item.lbl+=': '+item.v;
|
||||
return item.lbl;
|
||||
}
|
||||
// previous two items
|
||||
g.setFontAlign(0, 1)
|
||||
if (wrap||idx>0) g.setFont('Vector', small).drawString(lbl(idx-1), hc, vc-ih/2-5);
|
||||
if (wrap||idx>1) g.setFont('Vector', small/2).drawString(lbl(idx-2), hc, vc-ih/2-small-10);
|
||||
// next two items
|
||||
g.setFontAlign(0, -1);
|
||||
if (wrap||idx<menuItems.length-1) g.setFont('Vector', small).drawString(lbl(idx+1), hc, vc+ih/2+5);
|
||||
if (wrap||idx<menuItems.length-2) g.setFont('Vector', small/2).drawString(lbl(idx+2), hc, vc+ih/2+small+10);
|
||||
|
||||
if (wrap) {
|
||||
// draw divider between first/last items
|
||||
var div = y => g.drawLine(x, y, x2, y);
|
||||
if (idx===0) div(vc-ih/2-1);
|
||||
if (idx===1) div(vc-ih/2-small-8);
|
||||
// if (s === 2) div(vc-ih/2-small*1.5-13);
|
||||
if (idx===menuItems.length-1) div(vc+ih/2+1);
|
||||
if (idx===menuItems.length-2) div(vc+ih/2+small+6);
|
||||
// if (s === 2) div(vc+ih/2+small*1.5+13);
|
||||
}
|
||||
|
||||
if (back) {
|
||||
g.setBgColor(g.theme.bg2)
|
||||
.setFont('Vector', small);
|
||||
var bw=g.stringWidth(backLbl);
|
||||
g.clearRect(x,y, x+bw+2, y+small+2);
|
||||
var bx1=x, by1=y, bx2=x+bw+2, by2=y+small+2;
|
||||
// g.drawRect(x,y, x+bw+2, y+small+2);
|
||||
var poly = [ // button outline
|
||||
bx1+2,by1,
|
||||
bx2-2,by1,
|
||||
bx2, by1+2,
|
||||
bx2, by2-2,
|
||||
bx2-2,by2,
|
||||
bx1+2,by2,
|
||||
bx1, by2-2,
|
||||
bx1, by1+2,
|
||||
]
|
||||
g.setColor(g.theme.bg2).fillPoly(poly, true)
|
||||
.setColor(g.theme.fg2).drawPoly(poly, true)
|
||||
.setFontAlign(-1,-1,0).drawString(backLbl, x+2,y+2);
|
||||
}
|
||||
}
|
||||
g.flip();
|
||||
},
|
||||
select : function() { // same as default menu
|
||||
var item = items[menuItems[options.selected]];
|
||||
if ("function" == typeof item) {l.lastIdx=null; item(l);} // force a redraw after callback
|
||||
else if ("object" == typeof item) {
|
||||
// if a number, go into 'edit mode'
|
||||
if ("number" == typeof item.value)
|
||||
l.selectEdit = l.selectEdit?undefined:item;
|
||||
else { // else just toggle bools
|
||||
if ("boolean" == typeof item.value) item.value=!item.value;
|
||||
if (item.onchange) {l.lastIdx=null; item.onchange(item.value);} // force a redraw after callback
|
||||
}
|
||||
l.draw();
|
||||
}
|
||||
},
|
||||
move : function(dir) {
|
||||
if (l.selectEdit) { // same as default menu
|
||||
var item = l.selectEdit;
|
||||
item.value -= (dir||1)*(item.step||1);
|
||||
if (item.min!==undefined && item.value<item.min) item.value = item.wrap ? item.max : item.min;
|
||||
if (item.max!==undefined && item.value>item.max) item.value = item.wrap ? item.min : item.max;
|
||||
if (item.onchange) {l.lastIdx=null; item.onchange(item.value);} // force a redraw after callback
|
||||
} else {
|
||||
if (B2) dir=-dir; // swipe vs button scrolling
|
||||
if (!wrap && (options.selected+dir<0 || options.selected+dir>=menuItems.length)) {
|
||||
return;
|
||||
}
|
||||
options.selected = (options.selected+dir+menuItems.length)%menuItems.length;
|
||||
}
|
||||
l.draw();
|
||||
}
|
||||
};
|
||||
l.draw();
|
||||
Bangle.setUI("updown",dir => {
|
||||
if (dir) l.move(dir);
|
||||
else l.select();
|
||||
});
|
||||
if (back) {
|
||||
// we have a back button: check touches before passing them to setUI's touchHandler
|
||||
if (B2) {
|
||||
Bangle.removeListener('touch', Bangle.touchHandler);
|
||||
Bangle.backHandler = (b, xy) => {
|
||||
// anywhere top-left (but above the active item) = back button
|
||||
if (xy.x<hc && xy.y<vc-ih/2) back();
|
||||
else Bangle.touchHandler(b, xy);
|
||||
}
|
||||
} else {
|
||||
// Bangle.js 1 has no touchHandler
|
||||
Bangle.backHandler = (b) => {
|
||||
// left side = back button
|
||||
if (b===1) back();
|
||||
}
|
||||
}
|
||||
// note: backHandler is cleaned up at the top of this file
|
||||
Bangle.on('touch', Bangle.backHandler);
|
||||
}
|
||||
return l;
|
||||
};
|
After Width: | Height: | Size: 880 B |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.5 KiB |
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("pFIwkB+MRAEH/EUIA7i93u9xEUIABEf4AC+93/4CBETpDBv//gEHEf6MB9wkB/8HSDl3vwjCAAfnErIjiEQYdBAAXuAoSNXEYIdDAAoj4j/3DpN3v6NWAA3/fDYjgRgIjLu9xESj2BAAN/SQwLBEe4XDdwghDBQQjSCgN+C5D9FEebTDEZJEWEQSDVEdZpDZYPnETYhDAAhpeEbzREI0rTbEdXuETb4Bvz1BAYIj/EYxrg9yQDv/3JoS9WEcoaGAAQtBOwYABEaSMBWoYeFJKgjjiIUD9ySEEjwAJFogj0SQgAFBQ4jRABcfXoQj/TowjCOgIkeEf7lHvz+CEb93Ef4jHR8Rr/fY4jCuIifAAQj/EIojbeohGeEcQhHfLRFDeoIicEcQbDv3uEYiNXIgnu87SgEcf/DKnxBJEf/4ACESf/EcYA=="))
|
|
@ -0,0 +1,469 @@
|
|||
function init() {
|
||||
this.titleScreen = true;
|
||||
this.min = 0;
|
||||
this.max = 160;
|
||||
this.step = 20;
|
||||
this.scoreMultiplier = 25;
|
||||
this.totalGrid = this.max / this.step;
|
||||
|
||||
if (g.theme.dark) {
|
||||
this.textColor = 1;
|
||||
} else {
|
||||
this.textColor = 0;
|
||||
}
|
||||
|
||||
this.getNewPosistion = () => {
|
||||
let newPos;
|
||||
while (!newPos) {
|
||||
// random bonus points for bad luck / lag
|
||||
if (currentPosition.length > 10) {
|
||||
this.score += 1;
|
||||
}
|
||||
const x = Math.floor(Math.random() * this.totalGrid + 1) * this.step;
|
||||
const y = Math.floor(Math.random() * this.totalGrid + 1) * this.step;
|
||||
const found = currentPosition.find(pos => {
|
||||
return pos.x === x && pos.y === y;
|
||||
});
|
||||
if (!found) {
|
||||
newPos = {x: x, y: y};
|
||||
}
|
||||
}
|
||||
return newPos;
|
||||
};
|
||||
|
||||
this.restart = () => {
|
||||
g.clear();
|
||||
this.titleScreen = false;
|
||||
this.score = 0;
|
||||
this.paused = false;
|
||||
this.currentPosition = [{x: 2 * step, y: 3 * step},{x: 1 * step, y: 3 * step}];
|
||||
this.death = false;
|
||||
this.gameSpeed = 200;
|
||||
this.directionSet = null;
|
||||
this.direction = 1;
|
||||
this.createApple();
|
||||
};
|
||||
|
||||
const game = () => {
|
||||
if (this.death && !this.paused) {
|
||||
g.clear();
|
||||
this.showDeathScreen();
|
||||
} else if (this.titleScreen && !this.paused) {
|
||||
this.showTitleScreen();
|
||||
} else if (!this.paused) {
|
||||
g.clear();
|
||||
this.drawApple();
|
||||
this.drawSnake();
|
||||
this.boundries();
|
||||
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
game();
|
||||
}, this.gameSpeed);
|
||||
};
|
||||
|
||||
this.increaseDifficulity = () => {
|
||||
if (gameSpeed > 59) {
|
||||
gameSpeed -= 10;
|
||||
}
|
||||
};
|
||||
|
||||
this.createApple = () => {
|
||||
this.applePosition = getNewPosistion();
|
||||
};
|
||||
|
||||
this.drawApple = () => {
|
||||
g.setColor(0, 1, 0);
|
||||
|
||||
g.drawImage(this.appleLeaf, this.applePosition.x - 15, this.applePosition.y - 10);
|
||||
g.setColor(1, 0, 0);
|
||||
|
||||
g.drawImage(this.apple, this.applePosition.x - 15, this.applePosition.y - 2);
|
||||
};
|
||||
|
||||
this.checkmax = (x) => {
|
||||
if (x > this.max) {
|
||||
return this.min;
|
||||
} else if (x < this.min) {
|
||||
return this.max;
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
this.movement = (lastItem) => {
|
||||
let newPosition;
|
||||
switch(this.direction) {
|
||||
case 3:
|
||||
newPosition = {
|
||||
x: checkmax(lastItem.x + this.step),
|
||||
y: lastItem.y
|
||||
};
|
||||
break;
|
||||
case 1:
|
||||
newPosition = {
|
||||
x: checkmax(lastItem.x - this.step),
|
||||
y: lastItem.y
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
newPosition = {
|
||||
x: lastItem.x,
|
||||
y: checkmax(lastItem.y + this.step)
|
||||
};
|
||||
break;
|
||||
case 0:
|
||||
newPosition = {
|
||||
x: lastItem.x,
|
||||
y: checkmax(lastItem.y - this.step)
|
||||
};
|
||||
break;
|
||||
}
|
||||
this.directionSet = false;
|
||||
this.checkDeath(newPosition);
|
||||
this.currentPosition.push(newPosition);
|
||||
|
||||
};
|
||||
|
||||
this.snakeHead = (props) => {
|
||||
switch (this.direction) {
|
||||
case 0:
|
||||
return [this.snakeUp, props.x - 9, props.y - 12];
|
||||
case 1:
|
||||
return [this.snakeLeft, props.x - 20, props.y - 10];
|
||||
case 3:
|
||||
return [this.snakeRight, props.x - 12, props.y - 12];
|
||||
case 2:
|
||||
return [this.snakeDown, props.x - 12, props.y - 7];
|
||||
default:
|
||||
return [this.snakeDown, props.x - 12, props.y - 7];
|
||||
}
|
||||
};
|
||||
|
||||
this.drawSnake = () => {
|
||||
const totalItems = this.currentPosition.length - 1;
|
||||
g.setColor(0, 1, 0);
|
||||
this.movement(this.currentPosition[totalItems]);
|
||||
this.currentPosition.forEach((props, index) => {
|
||||
if (index-1 === totalItems) {
|
||||
const head = this.snakeHead(props);
|
||||
|
||||
g.drawImage(head[0], head[1], head[2]);
|
||||
} else {
|
||||
g.fillCircle(props.x, props.y, 10);
|
||||
}
|
||||
});
|
||||
if (this.currentPosition[totalItems].x === this.applePosition.x && this.currentPosition[totalItems].y === this.applePosition.y) {
|
||||
this.createApple();
|
||||
this.increaseDifficulity();
|
||||
} else {
|
||||
this.currentPosition.shift();
|
||||
}
|
||||
};
|
||||
|
||||
this.checkDeath = (newPos) => {
|
||||
|
||||
const found = this.currentPosition.find((oldPos) => {
|
||||
return newPos.x === oldPos.x && newPos.y === oldPos.y;
|
||||
});
|
||||
if (found) {
|
||||
Bangle.buzz();
|
||||
g.clear();
|
||||
this.death = true;
|
||||
}
|
||||
};
|
||||
|
||||
this.boundries = () => {
|
||||
if (this.currentPosition.x >= this.maxPx) {
|
||||
this.currentPosition.x = this.maxPx;
|
||||
}
|
||||
else if (this.currentPosition.x < 10) {
|
||||
this.currentPosition.x = 10;
|
||||
}
|
||||
|
||||
if ( this.currentPosition.y >= this.maxPy) {
|
||||
this.currentPosition.y = this.maxPy;
|
||||
} else if (this.currentPosition.y < 10) {
|
||||
this.currentPosition.y = 10;
|
||||
}
|
||||
};
|
||||
|
||||
this.creatTopScrore = () => {
|
||||
require("Storage").writeJSON("snek_jd", {
|
||||
topScore: this.calculateScore()
|
||||
});
|
||||
};
|
||||
|
||||
this.calculateScore = () => {
|
||||
return currentPosition.length * this.scoreMultiplier + this.score;
|
||||
};
|
||||
|
||||
this.showDeathScreen = () => {
|
||||
this.paused = true;
|
||||
g.setFont('Vector', 25);
|
||||
g.setColor(1, 0, 0);
|
||||
g.drawString("GAME OVER",15, 50, "solid");
|
||||
g.setFont('Vector', 15);
|
||||
g.setColor(this.textColor, this.textColor, this.textColor);
|
||||
g.drawString("Score : " + this.calculateScore(), 50, 78, "solid");
|
||||
|
||||
let storage = require("Storage").readJSON("snek_jd");
|
||||
if (storage && storage.topScore) {
|
||||
if (storage.topScore < this.calculateScore()) {
|
||||
g.setColor(0, 1, 1);
|
||||
g.drawString("New top score!", 20, 95, "solid");
|
||||
g.setFont('Vector', 22);
|
||||
g.drawString(this.calculateScore(), 20, 115, "solid");
|
||||
|
||||
this.creatTopScrore();
|
||||
} else {
|
||||
g.setColor(this.textColor, this.textColor, this.textColor);
|
||||
g.drawString("Top score : " + storage.topScore, 20, 95, "solid");
|
||||
}
|
||||
} else {
|
||||
this.creatTopScrore();
|
||||
}
|
||||
g.setFont('Vector', 25);
|
||||
};
|
||||
|
||||
/* Events */
|
||||
Bangle.on('tap', (data) => {
|
||||
Bangle.setLCDPower(true);
|
||||
if (this.death) {
|
||||
this.showTitleScreen();
|
||||
} else if (this.titleScreen || this.paused) {
|
||||
this.restart();
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.on('accel', (xyz) => {
|
||||
if (Math.abs(xyz.x) > Math.abs(xyz.y)) {
|
||||
if (xyz.x < 0) {
|
||||
if (!this.directionSet && this.direction !== 1) {
|
||||
Bangle.setLCDPower(true);
|
||||
this.direction = 3;
|
||||
}
|
||||
} else {
|
||||
if (!this.directionSet && this.direction !== 3) {
|
||||
Bangle.setLCDPower(true);
|
||||
this.direction = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (xyz.y < 0) {
|
||||
if (!this.directionSet && this.direction !== 0) {
|
||||
Bangle.setLCDPower(true);
|
||||
this.direction = 2;
|
||||
}
|
||||
} else {
|
||||
if (!this.directionSet && this.direction !== 2) {
|
||||
Bangle.setLCDPower(true);
|
||||
this.direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.directionSet = true;
|
||||
});
|
||||
|
||||
this.showTitleScreen = () => {
|
||||
this.death = false;
|
||||
g.clear();
|
||||
g.setColor(0, 1, 0);
|
||||
g.setFont('Vector', 50);
|
||||
g.drawString("nek", 70, 15, "solid");
|
||||
g.drawImage(this.titleScreenImg, 20, 20);
|
||||
g.fillPoly([
|
||||
15, 66,
|
||||
152, 70,
|
||||
159, 79,
|
||||
21, 71 ]);
|
||||
g.setColor(this.textColor, this.textColor, this.textColor);
|
||||
g.setFont('Vector', 15);
|
||||
g.drawString("Tilt to turn", 20, 100, "solid");
|
||||
g.drawString("Tap to start", 20, 120, "solid");
|
||||
|
||||
g.setColor(0, 1, 0);
|
||||
|
||||
g.setFont('4x6', 3);
|
||||
g.drawString("Jason de Belle", 5, 145, "solid");
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* Graphics */
|
||||
this.snakeUp = Graphics.createImage(`
|
||||
XX XX
|
||||
xx xx
|
||||
xx xx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
xxxxxxxx
|
||||
xxxx xxxx
|
||||
xxxxxx xxxxxxx
|
||||
xxxxxxxxxxxxxxxx
|
||||
xxxxx xXXx xxxxx
|
||||
xxxxx XX xxxxx
|
||||
xxxxx XX xxxxx
|
||||
xxxxxx xxxx xxxxx
|
||||
xxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
`);
|
||||
this.snakeDown = Graphics.createImage(`
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
xxxxxx xxxx xxxxxx
|
||||
xxxxxx xxxx xxxxxx
|
||||
xxxx XX xxxxx
|
||||
xxxx XX xxxxx
|
||||
xxxx xXXx xxxx
|
||||
xxxx xXXx xxxx
|
||||
xXxxxxxxxxxxxx
|
||||
xXxxxxxxxxxxxx
|
||||
xxx xxx
|
||||
xxxx xxxx
|
||||
xxxx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
x x
|
||||
xx xx
|
||||
xx xx
|
||||
`);
|
||||
|
||||
this.snakeRight = Graphics.createImage(`
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xXxxxxxx xxxx
|
||||
xXxxxxxx xxxx
|
||||
xxxxxxxX xxx
|
||||
xxxxxxxX xxx xxxx
|
||||
xxxxxxxxxxXX xxxxxx xxxx
|
||||
xxxxxxxxxxXX xxxxxx xx
|
||||
xxxxxxxxxxXXxxxxx xxxxxxxx
|
||||
xxxxxxxxxxXXxxxxx xxxxxxxx
|
||||
xxxxxxxxxxxx xxxxx xx
|
||||
xxxxxxxxxxxx xxxxx xxx
|
||||
xxxxxxxx xx xxxx
|
||||
xxxxxxxx xx
|
||||
xxxxxxxx xxx
|
||||
xxxxxxxx xxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxx
|
||||
xxxxxxxxx
|
||||
`);
|
||||
this.snakeLeft = Graphics.createImage(`
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xXxxxxxxxxxxxx
|
||||
xX xxxxxxxxxx
|
||||
x xx xXxxxxxxxx
|
||||
xx xx xXxxxxxxxx
|
||||
xx xx xxxx xxXXxxxxxxxx
|
||||
xxxxxxx xxxxxXXxxxxxxxx
|
||||
xxxxxxx xxxxxXXxxxxxxxx
|
||||
xx xx xxxx xxXXxxxxxxxx
|
||||
xx xxx xxxxxxxxxx
|
||||
x xxx xxxxxxxxx
|
||||
xxxx xxxxxxxxx
|
||||
xxxx xxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxx
|
||||
xxxxxxxxx
|
||||
`);
|
||||
|
||||
this.apple = Graphics.createImage(`
|
||||
xxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxx
|
||||
`);
|
||||
|
||||
this.appleLeaf = Graphics.createImage(`
|
||||
xxxxxx
|
||||
xxxxxx
|
||||
xxxx
|
||||
XXxxxxxxxx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
xx
|
||||
`);
|
||||
|
||||
|
||||
this.titleScreenImg = Graphics.createImage(`
|
||||
sxxxxxxxs
|
||||
xxsxxx xxxxxs
|
||||
xxxxxxxxsxx xxxxsx
|
||||
xxxxxxxxxxxxxxxsxxs xxxxsxx
|
||||
xxxxxxxxxxxxxxxxxxxxxsxxxsssxxxxxxsxxxx
|
||||
xxxxxxxxxxxxxxxxxxxsxxxxsxxs xxsxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxsxx xxxsxx
|
||||
xxxxxxxxxxxxxxxxxxxxx sxxx ssxxsx
|
||||
xxxxxxxxxxxxxxx xxxxxxs
|
||||
xxxxxxxxxxxx ssss
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxxxx
|
||||
xxxxxxxxxx
|
||||
xxxxxxx
|
||||
xxx
|
||||
`);
|
||||
|
||||
game();
|
||||
}
|
||||
init();
|
After Width: | Height: | Size: 4.9 KiB |
|
@ -0,0 +1 @@
|
|||
0.1: First release.
|
|
@ -0,0 +1,31 @@
|
|||
(() => {
|
||||
const icon = require("heatshrink").decompress(atob("ikggMAiEAgYIBmEAg4EB+EAh0AgPggEeCAIEBnwQBAgP+gEP//x///j//8f//k///H//4BYOP/4lBv4bDvwEB4EAvAEBwEAuA7DCAI7BgAQBhEAA"));
|
||||
const iconWidth = 18;
|
||||
|
||||
function draw() {
|
||||
g.reset();
|
||||
if (Bangle.isCharging()) {
|
||||
g.setColor("#FD0");
|
||||
g.drawImage(icon, this.x + 1, this.y + 1, {
|
||||
scale: 0.6875
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
WIDGETS.chargingStatus = {
|
||||
area: 'tr',
|
||||
width: Bangle.isCharging() ? iconWidth : 0,
|
||||
draw: draw,
|
||||
};
|
||||
|
||||
Bangle.on('charging', (charging) => {
|
||||
if (charging) {
|
||||
Bangle.buzz();
|
||||
WIDGETS.chargingStatus.width = iconWidth;
|
||||
} else {
|
||||
WIDGETS.chargingStatus.width = 0;
|
||||
}
|
||||
Bangle.drawWidgets(); // re-layout widgets
|
||||
g.flip();
|
||||
});
|
||||
})();
|
After Width: | Height: | Size: 3.6 KiB |
2
core
|
@ -1 +1 @@
|
|||
Subproject commit 23854083e0c3f83c649073a2d85e8079efc471d3
|
||||
Subproject commit 59f80bb52a38da12cb272f9106cb3951b49dab2e
|