diff --git a/apps/multidice/ChangeLog b/apps/multidice/ChangeLog new file mode 100644 index 000000000..cb0cce2aa --- /dev/null +++ b/apps/multidice/ChangeLog @@ -0,0 +1,32 @@ +0.90: got most of the features done, lacking some polish and real-hardware testing +1.00: overhauled the whole app, made some margins larger to be easier to tap on +1.01: fixed bug that caused rolled dice on the right of screen to be writ off-screen +1.02: added vibration when dice is rolled +1.03: vibration caused the accelerometer to never stop +1.04: decreased vibration strength +1.05: toggled the acceleration handler to prevent infinite buzz loop +1.06: increased vibration again +1.07: IDK how to use promises properly +1.08: still trying to fix the lack of vibrations +1.09: hopefully now it's fixed? +1.10: not having web bluetooth to debug is a PAIN +1.11: decreased vibration time, decreased accel requirement +1.12: issue with app calling roll function too many times at startup +1.13: added a delay after the buzzer stops to prevent multi-rolling +1.14: made the delay needlessly long to see if it even does anything +1.15: moved accel & vibration commands to the accelHandler function +1.16: enabled button usage & temporarily disabled acceleration +1.17: made changes to when accelHandler gets overwritten, temporarily disabled button usage +1.18: decided to keep around the button even while testing, disabled all safety round the accelHandler self-triggering +1.19: added longer delay before resetting accelHandler +1.20: removed all traces of accel b/c I've given up +1.21: added a drawWidgets command to see if I have the padding right +1.22: ok the buzzing *might* work now +1.23: forgot to resolve the promise +1.24: fixed dumb errors +1.25: god I hope this works +1.26: trying to add timeout after it's done buzzing... again +1.27: OH GOD IT FINALLY WORKS +1.28: increased vibration strength, added some comments, & some QOL +1.29: changed image +1.30: changed image, again diff --git a/apps/multidice/README.md b/apps/multidice/README.md new file mode 100644 index 000000000..72a2d8af5 --- /dev/null +++ b/apps/multidice/README.md @@ -0,0 +1,20 @@ +# multiple dice roller + +roll anywhere from 1-8 dice at the same time. + +## Usage + +![startup.png](startup.png) +On the menu screen: tap on the dice to change what variant is selected, & shake/or press BTN to roll the dice +![single_rolled.png](single_rolled.png) +On the dice screen: tap anywhere on the screen to go back to the menu, or shake/or press BTN to roll the dice + +## Features + +roll anywhere from 1-8 dice (d4, d6, d8, d10, d12, d20, & d percentile). You can select multiple different dice at the same time +![many_selected.png](many_selected.png) +![many_rolled.png](many_rolled.png) + +## Controls + +App uses touchscreen to cycle through different dice, and accelerometer/BTN to roll them diff --git a/apps/multidice/app-icon.js b/apps/multidice/app-icon.js new file mode 100644 index 000000000..88feb83cd --- /dev/null +++ b/apps/multidice/app-icon.js @@ -0,0 +1 @@ +atob("MDABAAAAA8AAAAAAB+AAf//+DDAAwAACGBgAwAADMAwAwAADYAYAgAAAwYMAgAABg+GAgAADBiDAgDwGBiBggH4MAmAwgMMYA8AYgIEwAAAMgIFg8AeGgIHBkAyDgMNBGAjDgH5BGAjDgDxh8A+DgAAwYAMGgAAYAYAMgAAMA+AYwAAGBiAwwAADBiBgwAADgmDAf//+w8Gwf///4AM8wAADMAYEzwADGA3En4ABDBvkmYABBjIkmYABI+IkH4ABPAPkjwABHAHEgDwBAHAEAH4BAPgEgGYBAIgEgGYBAIgEgH4BAPgEgDwBAHAEgADxHAHEgAH5PgPkgAGZIgIkgAGZIgIkgAH5PgPkwADzHAHEwAADAAAEcAAPwAAcP//8///w") diff --git a/apps/multidice/app.js b/apps/multidice/app.js new file mode 100644 index 000000000..53f67e21e --- /dev/null +++ b/apps/multidice/app.js @@ -0,0 +1,185 @@ +var menu = true; // default to have the selection menu open +const DICE_ARRAY = [0, 4, 6, 8, 10, 12, 20, 100]; // 0 means nothing selected +const SELECTION_ARRAY = [6, 0, 0, 0, 0, 0, 0, 0]; // default to selecting a single d20 + +// function to draw the selection menu +function drawMenu() { + + stringArr = new Array ("", "", "", "", "", "", "", ""); + for (i = 0; i < 8; i++) { + + if (SELECTION_ARRAY [i] != 0) { + + stringArr [i] = "" + DICE_ARRAY [SELECTION_ARRAY [i]]; + } else { + + stringArr [i] = " . "; // more clearly defines where the user can tap + } + } + + g.clear(); + g.setFont ("Vector", 40); + + // " ".slice(-3) left-pads all numbers with spaces + g.drawString ((" " + stringArr [0]).slice (-3), 5, 10); + g.drawString ((" " + stringArr [1]).slice (-3), 5, 50); + g.drawString ((" " + stringArr [2]).slice (-3), 5, 90); + g.drawString ((" " + stringArr [3]).slice (-3), 5, 130); + g.drawString ((" " + stringArr [4]).slice (-3), 96, 10); + g.drawString ((" " + stringArr [5]).slice (-3), 96, 50); + g.drawString ((" " + stringArr [6]).slice (-3), 96, 90); + g.drawString ((" " + stringArr [7]).slice (-3), 96, 130); +} + +// function to change what dice is selected in the menu +function touchHandler (button, xy) { + + if (! menu) { // if menu isn't open, open it & return + + menu = true; + drawMenu(); + return; + } + + if (xy.x <= 87) { // left + + if (xy.y <= 43) { // first + + selection = 0; + } else if (xy.y <= 87) { // second + + selection = 1; + } else if (xy.y <= 131) { // third + + selection = 2; + } else { // fourth + + selection = 3; + } + } else { // right + + if (xy.y <= 43) { // first + + selection = 4; + } else if (xy.y <= 87) { // second + + selection = 5; + } else if (xy.y <= 131) { // third + + selection = 6; + } else { // fourth + + selection = 7; + } + } + + if (SELECTION_ARRAY [selection] == SELECTION_ARRAY.length - 1) { // if last dice is selected, go back to first + + SELECTION_ARRAY [selection] = 0; + } else { + + SELECTION_ARRAY [selection] += 1; + } + + drawMenu(); +} + +function accelHandler (xyz) { + + if (xyz.diff >= 0.3) { + + menu = false; + mutex (rollDice).catch (() => { + + return; // not necessary, but prevents spamming the logs + }); + } +} + +// returns a resolved promise if no other mutex call is active, all further ones return a rejected one +let lock = false; +function mutex (functionRef) { + + if (lock) { + + return Promise.reject (new Error ("mutex is busy")); + } + + lock = true; + return new Promise ((resolve, reject) => { + + functionRef().then ((result) => { + + lock = false; + resolve (result); + }).catch ((error) => { + + lock = false; + reject (error); + }); + }); +} + +// function to roll all selected dice, and display them +function rollDice() { + + resultsArr = new Uint8Array (8); + for (i = 0; i < 8; i++) { + + if (SELECTION_ARRAY [i] != 0) { + + resultsArr [i] = random (DICE_ARRAY [SELECTION_ARRAY [i]]); + } + } + + g.clear(); + g.setFont ("Vector", 40); + + for (i = 0; i < 4; i++) { + + if (SELECTION_ARRAY [i] != 0) { + + g.drawString ((" " + resultsArr [i]).slice (-3), 5, 10 + 40 * i); + } + } + + for (i = 4; i < 8; i++) { + + if (SELECTION_ARRAY [i] != 0) { + + g.drawString ((" " + resultsArr [i]).slice (-3), 96, 10 + 40 * (i - 4)); + } + } + + return vibrate(); +} + +// triggers the vibration, then pauses before returning +function vibrate() { + + return new Promise ((resolve, reject) => { + + return Bangle.buzz (50, 1).then ((value) => { + + setTimeout (() => { + + resolve (value); + }, 200); + }); + }); +} + +// returns a integer [1, max] +function random (max) { + + return Math.round (Math.random() * (max - 1) + 1); +} + +drawMenu(); +Bangle.on ('touch', touchHandler); +Bangle.on ('accel', accelHandler); +setWatch (function() { + + menu = false; + mutex (rollDice); +}, BTN, {repeat: true, edge: "falling", debounce: 10}); diff --git a/apps/multidice/app.png b/apps/multidice/app.png new file mode 100644 index 000000000..75ee0514a Binary files /dev/null and b/apps/multidice/app.png differ diff --git a/apps/multidice/many_rolled.png b/apps/multidice/many_rolled.png new file mode 100644 index 000000000..4cf34e9c7 Binary files /dev/null and b/apps/multidice/many_rolled.png differ diff --git a/apps/multidice/many_selected.png b/apps/multidice/many_selected.png new file mode 100644 index 000000000..137e2c363 Binary files /dev/null and b/apps/multidice/many_selected.png differ diff --git a/apps/multidice/metadata.json b/apps/multidice/metadata.json new file mode 100644 index 000000000..304c789e4 --- /dev/null +++ b/apps/multidice/metadata.json @@ -0,0 +1,15 @@ +{ "id": "multidice", + "name": "multiple dice roller", + "shortName":"multidice", + "version":"1.30", + "description": "roll anywhere from 1-8 dice at the same time", + "icon": "app.png", + "tags": "tool,game", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"multidice.app.js","url":"app.js"}, + {"name":"multidice.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/multidice/single_rolled.png b/apps/multidice/single_rolled.png new file mode 100644 index 000000000..3ce67ab74 Binary files /dev/null and b/apps/multidice/single_rolled.png differ diff --git a/apps/multidice/startup.png b/apps/multidice/startup.png new file mode 100644 index 000000000..587281e5c Binary files /dev/null and b/apps/multidice/startup.png differ diff --git a/core b/core index 0d02ff376..893c2dbbe 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 0d02ff3763783d166ff84906af038420736aabfc +Subproject commit 893c2dbbe5a93fbb80d035a695663b4f4cca8875