Merge branch 'master' into menuwheel

master
Gordon Williams 2021-12-06 08:46:41 +00:00 committed by GitHub
commit 45757fc882
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1414 additions and 55 deletions

View File

@ -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",
@ -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",
@ -4692,6 +4732,34 @@
"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 }
]
}
]

View File

@ -1 +1,2 @@
1.00: Release (2021/12/01)
1.01: Grey font when timer is frozen (2021/12/04)

View File

@ -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);

View File

@ -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

View File

@ -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();

12
apps/flow/README.md Normal file
View File

@ -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
![](screenshot1.png)
![](screenshot2.png)
![](screenshot3.png)

1
apps/flow/app-icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEw4X/AwX48EHgEC1WgCQkVqoDBBfuqBQcBqoLagEqGAguBqALaGAOoAoQuEBbEAKgIMBBQNUBbgMCyoKHBbBVBBYIKGBbEBtNVrQLfOgNaT4gLagp0CPQOABbcBFwNAgEKBgILbitVqAFClWq0ALZFwTDFGAQLZFwYwDBfg"))

220
apps/flow/app.js Normal file
View File

@ -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);

BIN
apps/flow/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

BIN
apps/flow/screenshot1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

BIN
apps/flow/screenshot2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
apps/flow/screenshot3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,3 @@
0.01: New App!
0.02: using TS and rollup to bundle
0.03: bug fixes and support bangle 1

View File

@ -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.

View File

@ -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 ![](<name>.png)
## 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>

File diff suppressed because one or more lines are too long

View File

@ -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)}();

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -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"
}
}

View File

@ -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(),
]
};

View File

@ -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);

View File

@ -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]
};
};

View File

@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "es2015",
"noImplicitAny": false,
"target": "es2015"
},
"include": [
"src"
]
}

View File

@ -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

View File

@ -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];

25
apps/launch/settings.js Normal file
View File

@ -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);
});

View File

@ -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)

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

@ -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(),

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

1
apps/snek/snek-icon.js Normal file
View File

@ -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=="))

469
apps/snek/snek.js Normal file
View File

@ -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();

BIN
apps/snek/snek.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1 @@
0.1: First release.

View File

@ -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();
});
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

2
core

@ -1 +1 @@
Subproject commit 23854083e0c3f83c649073a2d85e8079efc471d3
Subproject commit 59f80bb52a38da12cb272f9106cb3951b49dab2e