From b84d0446a87f86ffc2c1f7eee5a695a3b863f19d Mon Sep 17 00:00:00 2001 From: Fabio Date: Tue, 14 Apr 2020 09:08:26 +0200 Subject: [PATCH] New game Snake! --- apps.json | 13 ++++ apps/snake/ChangeLog | 1 + apps/snake/README.md | 13 ++++ apps/snake/snake-icon.js | 1 + apps/snake/snake.js | 144 +++++++++++++++++++++++++++++++++++++++ apps/snake/snake.png | Bin 0 -> 2337 bytes 6 files changed, 172 insertions(+) create mode 100644 apps/snake/ChangeLog create mode 100644 apps/snake/README.md create mode 100644 apps/snake/snake-icon.js create mode 100644 apps/snake/snake.js create mode 100644 apps/snake/snake.png diff --git a/apps.json b/apps.json index 56a6b69d3..dc9d47c2c 100644 --- a/apps.json +++ b/apps.json @@ -1171,5 +1171,18 @@ {"name":"bledetect.app.js","url":"bledetect.js"}, {"name":"bledetect.img","url":"bledetect-icon.js","evaluate":true} ] + }, + { "id": "snake", + "name": "Snake", + "shortName":"Snake", + "icon": "snake.png", + "version":"0.01", + "description": "The classic snake game. Eat apples and don't bite your tail:", + "tags": "game,fun", + "readme": "README.md", + "storage": [ + {"name":"snake.app.js","url":"snake.js"}, + {"name":"snake.img","url":"snake-icon.js","evaluate":true} + ] } ] diff --git a/apps/snake/ChangeLog b/apps/snake/ChangeLog new file mode 100644 index 000000000..2286a7f70 --- /dev/null +++ b/apps/snake/ChangeLog @@ -0,0 +1 @@ +0.01: New App! \ No newline at end of file diff --git a/apps/snake/README.md b/apps/snake/README.md new file mode 100644 index 000000000..7860dbd88 --- /dev/null +++ b/apps/snake/README.md @@ -0,0 +1,13 @@ +# Snake + +![Screenshot](https://i.ibb.co/XzWrvPL/screenshot.png) + +The legentary classic game is now available on Bangle.js! +Eat apples and don't bite your tail. + +## Controls + +- UP: BTN1 +- DOWN: BTN3 +- LEFT: BTN4 +- RIGHT: BTN5 diff --git a/apps/snake/snake-icon.js b/apps/snake/snake-icon.js new file mode 100644 index 000000000..305061003 --- /dev/null +++ b/apps/snake/snake-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4A/ADE3m9hsIusrdhGIM3LtU3g0GAgQxlEwIqBmEAgEGF4QwkF4c3F4MxF4dbF8qLDrYHDre74IABF8QwBLoaPDF8wPKF96/jF/4v/F/4vrrc3AIQsnsIAKF94wiFxgv/R//+m4ABrYALBwIpYFwwAQLC4v/F7gXGF91hACovWFqwwUF4VbF7IwUFzSRVF1gwCF9wwZFyoA/AH4A/AH4A/AGg=")) \ No newline at end of file diff --git a/apps/snake/snake.js b/apps/snake/snake.js new file mode 100644 index 000000000..37b461596 --- /dev/null +++ b/apps/snake/snake.js @@ -0,0 +1,144 @@ +const H = g.getWidth(); +const W = g.getHeight(); +let running = true; +let score = 0; +let d; + +// game world +const gridSize = 40; +const tileSize = 6; +let nextX = 0; +let nextY = 0; + +// snake +const defaultTailSize = 3; +let tailSize = defaultTailSize; +const snakeTrail = []; +let snakeX = 10; +let snakeY = 10; + +// apple +let appleX = Math.floor(Math.random() * gridSize); +let appleY = Math.floor(Math.random() * gridSize); + +function gameStart() { + running = true; + score = 0; +} + +function gameStop() { + g.clear(); + g.setColor("#FFFFFF"); + g.setFont("6x8", 2); + g.drawString("GAME OVER!", W / 2, H / 2 - 20); + g.drawString("Tap to Restart", W / 2, H / 2 + 20); + running = false; + tailSize = defaultTailSize; +} + +function draw() { + if (!running) { + return; + } + + // move snake in next pos + snakeX += nextX; + snakeY += nextY; + + // snake over game world? + if (snakeX < 0) { + snakeX = gridSize - 1; + } + + if (snakeX > gridSize - 1) { + snakeX = 0; + } + + if (snakeY < 0) { + snakeY = gridSize - 1; + } + if (snakeY > gridSize - 1) { + snakeY = 0; + } + + //snake bite apple? + if (snakeX === appleX && snakeY === appleY) { + tailSize++; + score++; + + appleX = Math.floor(Math.random() * gridSize); + appleY = Math.floor(Math.random() * gridSize); + } + + //paint background + g.setColor("#000000"); + g.fillRect(0, 0, H, W); + + // paint snake + g.setColor("#008000"); + + for (let i = 0; i < snakeTrail.length; i++) { + g.fillRect(snakeTrail[i].x * tileSize, snakeTrail[i].y * tileSize, snakeTrail[i].x * tileSize + tileSize, snakeTrail[i].y * tileSize + tileSize); + + //snake bites it's tail? + if (snakeTrail[i].x === snakeX && snakeTrail[i].y === snakeY && tailSize > defaultTailSize) { + gameStop(); + } + } + + // paint apple + g.setColor("#FF0000"); + g.fillRect(appleX * tileSize, appleY * tileSize, appleX * tileSize + tileSize, appleY * tileSize + tileSize); + + // paint score + g.setColor("#FFFFFF"); + g.setFont("6x8"); + g.setFontAlign(0, 0); + g.drawString("Score:" + score, W / 2, 10); + + //set snake trail + snakeTrail.push({ x: snakeX, y: snakeY }); + while (snakeTrail.length > tailSize) { + snakeTrail.shift(); + } +} + +// input +setWatch(() => {// Up + if (d !== 'd') { + nextX = 0; + nextY = -1; + d = 'u'; + } +}, BTN1, { repeat: true }); +setWatch(() => {// Down + if (d !== 'u') { + nextX = 0; + nextY = 1; + d = 'd'; + } +}, BTN3, { repeat: true }); +setWatch(() => {// Left + if (d !== 'r') { + nextX = -1; + nextY = 0; + d = 'l'; + } +}, BTN4, { repeat: true }); +setWatch(() => {// Right + if (d !== 'l') { + nextX = 1; + nextY = 0; + d = 'r'; + } +}, BTN5, { repeat: true }); + +Bangle.on('touch', button => { + if (!running) { + gameStart(); + } +}); + +// render X times per second +var x = 5; +setInterval(draw, 1000 / x); \ No newline at end of file diff --git a/apps/snake/snake.png b/apps/snake/snake.png new file mode 100644 index 0000000000000000000000000000000000000000..04564a8f77dad377b2dd2dd0a50561ca582bc6fb GIT binary patch literal 2337 zcmaJ@dpuNWAD`rwUb~B2QaBxEcE)AKV1}6n;ml;b#$_m8DaOpfe3*-wgFzRhTq@Sa zOB-^J-dI`6t?W{5Yg1ApOBX4ds3;*~N2PuLcze%t&Ur4M@Avz={_&)Hd2Cl#(^o^G zQ0h!qh%KKjS3Xr``QJ}rK2<(#MCksAk0=z0;LFx_5a9FdK|d19k|lP5 z!}+f964)o+!gS*q7}hX{*o<-HdGRsYGn(2dO*1~2``k& zh8Ul0$#?c(ID&|&1VU_VEI!s6FOq~2h!hHCMZ?O z`#*)HzHwrhz=oxwXbD$dxKQI2Q(~%%1m++jiLXc$xtc|cVg#Su?C4Tgb_lNTfSaY)A~q$=TV)#@d-q zX4tNBArUuP01J^-F7IzH{fpd{RuG8gmLXWekAZm%iAVr^2${n<(toq4-4hpE|Ir2*+9Jsg;L68LQcN2!HIwE3J;{~ zEj=BInVkszDbI#qUW3_@u6xF}tpN}isj6-ci?>p%-uv#0~Qd2!is z*7siT5k{9y$1>8*DX6C9fx?};K6e(ikYzTKLdfA#R$Wa;(T`7M>f4G!T| zh1{1+b;43Hw_Fe}3YeOoda7!J+qF)m`DVflS-oho^W`wuC<%KZglNE%`hwU*l^=)5b&HH6?|!yCmjl4NoGp3Jrz zK3&=R|L*fBXnLjlBC2Pp4ysT*rLyLVl$N2S zcLqYoz03Q{AKebT@(8@K>v&?t&thaic^6IL(qrTM+1ncI-2@_x?T+j&Z7JP!Bdu$G z++4Hv3FzDvmQW9pG`!vBBCN1J)2AIvr#4r&Wj(@IXy}$`esi~!NoU!u2yX|Sp%0a`%MFS(NLxL2BkB#T__BFwmVICPxsE5 zZ=beodpv-J&SxswVk&lVH*kc=guZjDjZ|swM%CPS ztF#fSh)=E5bKIIa9saDNo*O_;F<3jQqaC31jCyvQt#Gd>vtZFK=sPC{=JoM>Kmlw` zvUtG=P3!X8?|;gH>b*cx8?v8oXT;~1ny0PV$W0x47l!yadQ65@o3;BZ#%S)z=Q=$= zPvoJKqABR4f#%#scQ~RNXL@sMdA5vnIQeXvPS3RSd~3==+9Cn-?e9lMA`ci}YQ&6p zjF%2OtBJ~O63WSr$wLJyTk2R?&pA5Qh^be8HlsH@{nmD9^h8NvVqj2Tss3Qg_w^gr zv1^pKh&?AM0LC3T|I78u*_*Cu|MO7wgS5+q9IU6*^Ok}UtLBEQad+eGAbe6^qo$o8 z)Lkz<4LkUii62JPZ#>wt{&``gs@Sk1_kBQLu9nBWxYQO2N24mWSLfX|o%%ak4R;n& zvM@iobzgMaegE9?y~?|O^BS?5@a~9@;^-%$TZnz7Y!Yb&TvS8FRdLpEsvaP*JALrMJqvYUZGj;WIy+%C0f9NL#dDXo@ z%*STaf8tK_FlOCXw4%b^#SBzj&Vxd#XgdczPTuVfCEtKZEvn0v2ADRqM{!a}`^