1
0
Fork 0

Merge pull request #1838 from berkenbu/master

New App: Falcon 9 lander
master
Gordon Williams 2022-05-17 13:34:46 +01:00 committed by GitHub
commit da78061311
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 200 additions and 0 deletions

1
apps/f9lander/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: New App!

33
apps/f9lander/README.md Normal file
View File

@ -0,0 +1,33 @@
# F9 Lander
Land a Falcon 9 booster on a drone ship.
## Game play
Attempt to land your Falcon 9 booster on a drone ship before running out of fuel.
A successful landing requires:
* setting down on the ship
* the booster has to be mostly vertical
* the landing speed cannot be too high
## Controls
The angle of the booster is controlled by tilting the watch side-to-side. The
throttle level is controlled by tilting the watch forward and back:
* screen horizontal (face up) means no throttle
* screen vertical corresponds to full throttle
The fuel burn rate is proportional to the throttle level.
## Creators
Liam Kl. B.
Marko Kl. B.
## Screenshots
![](f9lander_screenshot1.png)
![](f9lander_screenshot2.png)
![](f9lander_screenshot3.png)

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwcA/4AD/P8yVJkgCCye27dt2wRE//kCIuSuwRIBwgCCpwRQpIRRnYRQkmdCIvPCJICBEZ4RG/IRP/15CJ/z5IRPz4RM/gQB/n+BxICCn/z/P/BxQCDz7mIAX4Cq31/CJ+ebpiYE/IR/CNP/5IROnn//4jP5DFQ5sJCKAjPk3oCMMk4QRQAX4Ckn7jBAA/5CK8nCJPJNHA"))

150
apps/f9lander/app.js Normal file
View File

@ -0,0 +1,150 @@
const falcon9 = Graphics.createImage(`
xxxxx
xxxxx xxxxx
x x
x x
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxxxxxx
xx xxxxx xx
xx xx`);
const droneShip = Graphics.createImage(`
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
`);
const droneX = Math.floor(Math.random()*(g.getWidth()-droneShip.width-40) + 20)
const cloudOffs = Math.floor(Math.random()*g.getWidth()/2);
const oceanHeight = g.getHeight()*0.1;
const targetY = g.getHeight()-oceanHeight-falcon9.height/2;
var booster = { x : g.getWidth()/4 + Math.random()*g.getWidth()/2,
y : 20,
vx : 0,
vy : 0,
mass : 100,
fuel : 100 };
var exploded = false;
var nExplosions = 0;
var landed = false;
const gravity = 4;
const dt = 0.1;
const fuelBurnRate = 20*(176/g.getHeight());
const maxV = 12;
function flameImageGen (throttle) {
var str = " xxx \n xxx \n";
str += "xxxxx\n".repeat(throttle);
str += " xxx \n x \n";
return Graphics.createImage(str);
}
function drawFalcon(x, y, throttle, angle) {
g.setColor(1, 1, 1).drawImage(falcon9, x, y, {rotate:angle});
if (throttle>0) {
var flameImg = flameImageGen(throttle);
var r = falcon9.height/2 + flameImg.height/2-1;
var xoffs = -Math.sin(angle)*r;
var yoffs = Math.cos(angle)*r;
if (Math.random()>0.7) g.setColor(1, 0.5, 0);
else g.setColor(1, 1, 0);
g.drawImage(flameImg, x+xoffs, y+yoffs, {rotate:angle});
}
}
function drawBG() {
g.setBgColor(0.2, 0.2, 1).clear();
g.setColor(0, 0, 1).fillRect(0, g.getHeight()-oceanHeight, g.getWidth()-1, g.getHeight()-1);
g.setColor(0.5, 0.5, 1).fillCircle(cloudOffs+34, 30, 15).fillCircle(cloudOffs+60, 35, 20).fillCircle(cloudOffs+75, 20, 10);
g.setColor(1, 1, 0).fillCircle(g.getWidth(), 0, 20);
g.setColor(1, 1, 1).drawImage(droneShip, droneX, g.getHeight()-oceanHeight-1);
}
function showFuel() {
g.setColor(0, 0, 0).setFont("4x6:2").setFontAlign(-1, -1, 0).drawString("Fuel: "+Math.abs(booster.fuel).toFixed(0), 4, 4);
}
function renderScreen(input) {
drawBG();
showFuel();
drawFalcon(booster.x, booster.y, Math.floor(input.throttle*12), input.angle);
}
function getInputs() {
var accel = Bangle.getAccel();
var a = Math.PI/2 + Math.atan2(accel.y, accel.x);
var t = (1+accel.z);
if (t > 1) t = 1;
if (t < 0) t = 0;
if (booster.fuel<=0) t = 0;
return {throttle: t, angle: a};
}
function epilogue(str) {
g.setFont("Vector", 24).setFontAlign(0, 0, 0).setColor(0, 0, 0).drawString(str, g.getWidth()/2, g.getHeight()/2).flip();
g.setFont("Vector", 16).drawString("<= again exit =>", g.getWidth()/2, g.getHeight()/2+20);
clearInterval(stepInterval);
Bangle.on("swipe", (d) => { if (d>0) load(); else load('f9lander.app.js'); });
}
function gameStep() {
if (exploded) {
if (nExplosions++ < 15) {
var r = Math.random()*25;
var x = Math.random()*30 - 15;
var y = Math.random()*30 - 15;
g.setColor(1, Math.random()*0.5+0.5, 0).fillCircle(booster.x+x, booster.y+y, r);
if (nExplosions==1) Bangle.buzz(600);
}
else epilogue("You crashed!");
}
else {
var input = getInputs();
if (booster.y >= targetY) {
// console.log(booster.x + " " + booster.y + " " + booster.vy + " " + droneX + " " + input.angle);
if (Math.abs(booster.x-droneX-droneShip.width/2)<droneShip.width/2 && Math.abs(input.angle)<Math.PI/8 && booster.vy<maxV) {
renderScreen({angle:0, throttle:0});
epilogue("You landed!");
}
else exploded = true;
}
else {
booster.x += booster.vx*dt;
booster.y += booster.vy*dt;
booster.vy += gravity*dt;
booster.fuel -= input.throttle*dt*fuelBurnRate;
booster.vy += -Math.cos(input.angle)*input.throttle*gravity*3*dt;
booster.vx += Math.sin(input.angle)*input.throttle*gravity*3*dt;
renderScreen(input);
}
}
}
var stepInterval;
Bangle.setLCDTimeout(0);
renderScreen({angle:0, throttle:0});
g.setFont("Vector", 24).setFontAlign(0, 0, 0).setColor(0, 0, 0).drawString("Swipe to start", g.getWidth()/2, g.getHeight()/2);
Bangle.on("swipe", () => {
stepInterval = setInterval(gameStep, Math.floor(1000*dt));
Bangle.removeListener("swipe");
});

BIN
apps/f9lander/f9lander.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,15 @@
{ "id": "f9lander",
"name": "Falcon9 Lander",
"shortName":"F9lander",
"version":"0.01",
"description": "Land a rocket booster",
"icon": "f9lander.png",
"screenshots" : [ { "url":"f9lander_screenshot1.png" }, { "url":"f9lander_screenshot2.png" }, { "url":"f9lander_screenshot3.png" }],
"readme": "README.md",
"tags": "game",
"supports" : ["BANGLEJS", "BANGLEJS2"],
"storage": [
{"name":"f9lander.app.js","url":"app.js"},
{"name":"f9lander.img","url":"app-icon.js","evaluate":true}
]
}