mirror of https://github.com/espruino/BangleApps
First commit, app Mandel
parent
5023902fed
commit
bbb3bca5a2
14
apps.json
14
apps.json
|
@ -2238,7 +2238,6 @@
|
|||
{"name":"worldclock.img","url":"worldclock-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
|
||||
{ "id": "digiclock",
|
||||
"name": "Digital Clock Face",
|
||||
"shortName":"Digi Clock",
|
||||
|
@ -2264,5 +2263,18 @@
|
|||
{"name":"dsdrelay.app.js","url":"dsdrelay.app.js"},
|
||||
{"name":"dsdrelay.img","url":"dsdrelay-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "mandel",
|
||||
"name": "Mandelbrot",
|
||||
"shortName":"Mandel",
|
||||
"icon": "mandel.png",
|
||||
"version":"0.01",
|
||||
"description": "Draw a zoomable Mandelbrot set",
|
||||
"tags": "game",
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"mandel.app.js","url":"mandel.min.js"},
|
||||
{"name":"mandel.img","url":"mandel-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Mandel
|
||||
|
||||
Draw a colored rendition of the famous Mandelbrot set. Pushing button 2 activates zoom mode: the top and left edge of the zoom region can be moved up/down
|
||||
with buttons 1 and 3 and left/right by touching the screen left right. Pushing button 2 again allows movement of the bottom and right edge in the same manner.
|
||||
Pushing button 2 a third time renders the selected region full screen.
|
||||
|
||||
The code uses inlined C code for perfomance reasons. Full source is provided on github.
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkA/4A/AEGIACQX/C/4X3x4XX/AXV/4XsBoYYFC6IPFC5gWFGAgXSDAgXIXAYXGF5mPA4ICCF6QUGC5wWKI5YVKR5ovWL7CPZX6zvXC5KPMDBYXVFwgXOB4QWFC9GPC65pKC5aBLC/4X/C54A/ADo"))
|
|
@ -0,0 +1,192 @@
|
|||
|
||||
var aux = new Float32Array(8);
|
||||
var p_aux = E.getAddressOf(aux, true);
|
||||
aux[0] = -2;
|
||||
aux[1] = -1.5;
|
||||
aux[2] = 1;
|
||||
aux[3] = 1.5;
|
||||
|
||||
var buf_height = 40;
|
||||
|
||||
var frameX1=0, frameX2=239, frameY1=0, frameY2=239;
|
||||
var frameCorner = 0;
|
||||
|
||||
var imbuf = Graphics.createArrayBuffer(240, buf_height, 16);
|
||||
var imbufaddr = E.getAddressOf(imbuf.buffer, true);
|
||||
var mimg = {
|
||||
width :imbuf.getWidth(),
|
||||
height:imbuf.getHeight(),
|
||||
bpp :16,
|
||||
buffer:imbuf.buffer
|
||||
};
|
||||
|
||||
var c = E.compiledC(`
|
||||
// void mandel(int, int)
|
||||
union shortbytes {
|
||||
short s;
|
||||
char b[2];
|
||||
};
|
||||
void mandel(float *p, short *ib) {
|
||||
float mincx = p[0];
|
||||
float mincy = p[1];
|
||||
float maxcx = p[2];
|
||||
float maxcy = p[3];
|
||||
int minx = (int)p[4];
|
||||
int miny = (int)p[5];
|
||||
int maxx = (int)p[6];
|
||||
int maxy = (int)p[7];
|
||||
int pib = 0;
|
||||
for (int y=miny; y<maxy; ++y)
|
||||
for (int x=minx; x<maxx; ++x) {
|
||||
float cr = mincx+(maxcx-mincx)*x/240.0;
|
||||
float ci = mincy+(maxcy-mincy)*y/240.0;
|
||||
float zr=0, zi=0;
|
||||
char niter = 31;
|
||||
while (--niter && zr>-2 && zr<1 && zi>-1.5 && zi<1.5) {
|
||||
float nr = zr*zr-zi*zi + cr;
|
||||
zi = 2*zr*zi + ci;
|
||||
zr = nr;
|
||||
}
|
||||
union shortbytes c, d;
|
||||
c.s = niter | (niter << 7)&0x7ff | (niter<<13)&0xffff;
|
||||
d.b[0] = c.b[1];
|
||||
d.b[1] = c.b[0];
|
||||
ib[pib++] = d.s;
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function drawRectangle(x1, y1, x2, y2) {
|
||||
if (frameCorner==1) g.setColor(1, 0, 0);
|
||||
else g.setColor(1, 1, 1);
|
||||
g.drawLine(x1, y1, x2, y1).drawLine(x1, y1, x1, y2);
|
||||
if (frameCorner==2) g.setColor(1, 0, 0);
|
||||
else g.setColor(1, 1, 1);
|
||||
g.drawLine(x1, y2, x2, y2).drawLine(x2, y1, x2, y2);
|
||||
}
|
||||
|
||||
function restoreRow(y) {
|
||||
mimg.width = 240;
|
||||
mimg.height = 1;
|
||||
aux[4] = 0;
|
||||
aux[5] = y;
|
||||
aux[6] = 240;
|
||||
aux[7] = y+1;
|
||||
c.mandel(p_aux, imbufaddr);
|
||||
g.drawImage(mimg, 0, y);
|
||||
}
|
||||
|
||||
function restoreCol(x) {
|
||||
mimg.width = 1;
|
||||
mimg.height = 240;
|
||||
aux[4] = x;
|
||||
aux[5] = 0;
|
||||
aux[6] = x+1;
|
||||
aux[7] = 240;
|
||||
c.mandel(p_aux, imbufaddr);
|
||||
g.drawImage(mimg, x, 0);
|
||||
}
|
||||
|
||||
function moveUp() {
|
||||
restoreCol(frameX1);
|
||||
restoreCol(frameX2);
|
||||
if (frameCorner==1 && frameY1>3) {
|
||||
restoreRow(frameY1);
|
||||
frameY1 -= 4;
|
||||
}
|
||||
if (frameCorner==2 && frameY2>3) {
|
||||
restoreRow(frameY2);
|
||||
frameY2 -= 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
function moveDown() {
|
||||
restoreCol(frameX1);
|
||||
restoreCol(frameX2);
|
||||
if (frameCorner==1 && frameY1<235) {
|
||||
restoreRow(frameY1);
|
||||
frameY1 += 4;
|
||||
}
|
||||
if (frameCorner==2 && frameY2<235) {
|
||||
restoreRow(frameY2);
|
||||
frameY2 += 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
function moveRight() {
|
||||
restoreRow(frameY1);
|
||||
restoreRow(frameY2);
|
||||
if (frameCorner==1 && frameX1<235) {
|
||||
restoreCol(frameX1);
|
||||
frameX1 += 4;
|
||||
}
|
||||
if (frameCorner==2 && frameX2<235) {
|
||||
restoreCol(frameX2);
|
||||
frameX2 += 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
function moveLeft() {
|
||||
restoreRow(frameY1);
|
||||
restoreRow(frameY2);
|
||||
if (frameCorner==1 && frameX1>3) {
|
||||
restoreCol(frameX1);
|
||||
frameX1 -= 4;
|
||||
}
|
||||
if (frameCorner==2 && frameX2>3) {
|
||||
restoreCol(frameX2);
|
||||
frameX2 -= 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
|
||||
function toggleFrame() {
|
||||
if (frameCorner<2) {
|
||||
frameCorner++;
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
else {
|
||||
frameCorner = 0;
|
||||
var mincx = aux[0] + (aux[2]-aux[0])*frameX1/240.0;
|
||||
var maxcx = aux[0] + (aux[2]-aux[0])*frameX2/240.0;
|
||||
var mincy = aux[1] + (aux[3]-aux[1])*frameY1/240.0;
|
||||
var maxcy = aux[1] + (aux[3]-aux[1])*frameY2/240.0;
|
||||
aux[0] = mincx;
|
||||
aux[1] = mincy;
|
||||
aux[2] = maxcx;
|
||||
aux[3] = maxcy;
|
||||
drawIt();
|
||||
}
|
||||
}
|
||||
|
||||
setWatch(toggleFrame, BTN2, {repeat: true});
|
||||
setWatch(moveUp, BTN1, {repeat: true});
|
||||
setWatch(moveDown, BTN3, {repeat: true});
|
||||
Bangle.on('touch', function(button) {
|
||||
switch(button) {
|
||||
case 1: moveLeft(); break;
|
||||
case 2: moveRight(); break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function drawIt() {
|
||||
aux[4] = 0;
|
||||
aux[5] = 0;
|
||||
aux[6] = 240;
|
||||
aux[7] = buf_height;
|
||||
mimg.width = 240;
|
||||
mimg.height = buf_height;
|
||||
for (var y=0; y<240/buf_height; ++y) {
|
||||
c.mandel(p_aux, imbufaddr);
|
||||
aux[5] += buf_height;
|
||||
aux[7] += buf_height;
|
||||
g.drawImage(mimg, 0, y*buf_height);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(drawIt, 50);
|
|
@ -0,0 +1 @@
|
|||
{"id":"mandel","name":"Mandel","src":"mandel.app.js","icon":"mandel.img"}
|
|
@ -0,0 +1,163 @@
|
|||
|
||||
var aux = new Float32Array(8);
|
||||
var p_aux = E.getAddressOf(aux, true);
|
||||
aux[0] = -2;
|
||||
aux[1] = -1.5;
|
||||
aux[2] = 1;
|
||||
aux[3] = 1.5;
|
||||
|
||||
var buf_height = 40;
|
||||
|
||||
var frameX1=0, frameX2=239, frameY1=0, frameY2=239;
|
||||
var frameCorner = 0;
|
||||
|
||||
var imbuf = Graphics.createArrayBuffer(240, buf_height, 16);
|
||||
var imbufaddr = E.getAddressOf(imbuf.buffer, true);
|
||||
var mimg = {
|
||||
width :imbuf.getWidth(),
|
||||
height:imbuf.getHeight(),
|
||||
bpp :16,
|
||||
buffer:imbuf.buffer
|
||||
};
|
||||
|
||||
var c = (function(){
|
||||
var bin=atob("0O0EepDtAFrQ7QFK0O0COpDtAzqf7URK/e7nei3p8EMX7pBa0O0Fev3u53rF68V8F+6QStDtBnr97ud6ACMX7pCK0O0Hev3u53q47gAqF+6QmvfuABq/7ggaTEVi2gzrAwaeRgHrRgYqRvfuCCqu6wUDQkUTRETaB+4QKnPuxXq47sd6HyNn7od6B+4QSsfuhGq47sd6c+5kenbuhWpn7od6n+0iesfuhFrw7kd6de6kWgE7E/D/AxPQ9O7CevHuEPoO3fTu4Xrx7hD6CdW07sF68e4Q+gTdtO7ievHuEPoR1NgBwPMKAEPqQzMDQ8PzByBg8wcHY/MPJyb4EnABMrXnATSp5yfuR2rw7mUKp+6nanfup3rn7icKdu4merDuYHrG573o8IMAAHBDAAAAAA==");
|
||||
return {
|
||||
mandel:E.nativeCall(1, "void(int, int)", bin),
|
||||
};
|
||||
})();
|
||||
|
||||
function drawRectangle(x1, y1, x2, y2) {
|
||||
if (frameCorner==1) g.setColor(1, 0, 0);
|
||||
else g.setColor(1, 1, 1);
|
||||
g.drawLine(x1, y1, x2, y1).drawLine(x1, y1, x1, y2);
|
||||
if (frameCorner==2) g.setColor(1, 0, 0);
|
||||
else g.setColor(1, 1, 1);
|
||||
g.drawLine(x1, y2, x2, y2).drawLine(x2, y1, x2, y2);
|
||||
}
|
||||
|
||||
function restoreRow(y) {
|
||||
mimg.width = 240;
|
||||
mimg.height = 1;
|
||||
aux[4] = 0;
|
||||
aux[5] = y;
|
||||
aux[6] = 240;
|
||||
aux[7] = y+1;
|
||||
c.mandel(p_aux, imbufaddr);
|
||||
g.drawImage(mimg, 0, y);
|
||||
}
|
||||
|
||||
function restoreCol(x) {
|
||||
mimg.width = 1;
|
||||
mimg.height = 240;
|
||||
aux[4] = x;
|
||||
aux[5] = 0;
|
||||
aux[6] = x+1;
|
||||
aux[7] = 240;
|
||||
c.mandel(p_aux, imbufaddr);
|
||||
g.drawImage(mimg, x, 0);
|
||||
}
|
||||
|
||||
function moveUp() {
|
||||
restoreCol(frameX1);
|
||||
restoreCol(frameX2);
|
||||
if (frameCorner==1 && frameY1>3) {
|
||||
restoreRow(frameY1);
|
||||
frameY1 -= 4;
|
||||
}
|
||||
if (frameCorner==2 && frameY2>3) {
|
||||
restoreRow(frameY2);
|
||||
frameY2 -= 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
function moveDown() {
|
||||
restoreCol(frameX1);
|
||||
restoreCol(frameX2);
|
||||
if (frameCorner==1 && frameY1<235) {
|
||||
restoreRow(frameY1);
|
||||
frameY1 += 4;
|
||||
}
|
||||
if (frameCorner==2 && frameY2<235) {
|
||||
restoreRow(frameY2);
|
||||
frameY2 += 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
function moveRight() {
|
||||
restoreRow(frameY1);
|
||||
restoreRow(frameY2);
|
||||
if (frameCorner==1 && frameX1<235) {
|
||||
restoreCol(frameX1);
|
||||
frameX1 += 4;
|
||||
}
|
||||
if (frameCorner==2 && frameX2<235) {
|
||||
restoreCol(frameX2);
|
||||
frameX2 += 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
function moveLeft() {
|
||||
restoreRow(frameY1);
|
||||
restoreRow(frameY2);
|
||||
if (frameCorner==1 && frameX1>3) {
|
||||
restoreCol(frameX1);
|
||||
frameX1 -= 4;
|
||||
}
|
||||
if (frameCorner==2 && frameX2>3) {
|
||||
restoreCol(frameX2);
|
||||
frameX2 -= 4;
|
||||
}
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
|
||||
|
||||
function toggleFrame() {
|
||||
if (frameCorner<2) {
|
||||
frameCorner++;
|
||||
drawRectangle(frameX1, frameY1, frameX2, frameY2);
|
||||
}
|
||||
else {
|
||||
frameCorner = 0;
|
||||
var mincx = aux[0] + (aux[2]-aux[0])*frameX1/240.0;
|
||||
var maxcx = aux[0] + (aux[2]-aux[0])*frameX2/240.0;
|
||||
var mincy = aux[1] + (aux[3]-aux[1])*frameY1/240.0;
|
||||
var maxcy = aux[1] + (aux[3]-aux[1])*frameY2/240.0;
|
||||
aux[0] = mincx;
|
||||
aux[1] = mincy;
|
||||
aux[2] = maxcx;
|
||||
aux[3] = maxcy;
|
||||
drawIt();
|
||||
}
|
||||
}
|
||||
|
||||
setWatch(toggleFrame, BTN2, {repeat: true});
|
||||
setWatch(moveUp, BTN1, {repeat: true});
|
||||
setWatch(moveDown, BTN3, {repeat: true});
|
||||
Bangle.on('touch', function(button) {
|
||||
switch(button) {
|
||||
case 1: moveLeft(); break;
|
||||
case 2: moveRight(); break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function drawIt() {
|
||||
aux[4] = 0;
|
||||
aux[5] = 0;
|
||||
aux[6] = 240;
|
||||
aux[7] = buf_height;
|
||||
mimg.width = 240;
|
||||
mimg.height = buf_height;
|
||||
for (var y=0; y<240/buf_height; ++y) {
|
||||
c.mandel(p_aux, imbufaddr);
|
||||
aux[5] += buf_height;
|
||||
aux[7] += buf_height;
|
||||
g.drawImage(mimg, 0, y*buf_height);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(drawIt, 50);
|
Loading…
Reference in New Issue