diff --git a/app.yaml b/app.yaml index 24df925..9b03e62 100644 --- a/app.yaml +++ b/app.yaml @@ -1,8 +1,16 @@ runtime: nodejs20 +env: standard + handlers: +# Serve all static files with url ending with a file extension +- url: /(.*\..+)$ + static_files: www/\1 + upload: www/(.*\..+)$ + static_dir: www/ # Catch all handler to index.html - url: /.* - static_files: www/* - upload: www/* + static_dir: www/ + static_files: www/index.html + upload: www/index.html service: default diff --git a/package.json b/package.json index 2d78786..16c8bb7 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "qGhast", "scripts": { - "build": "esbuild --bundle www/main.js --outfile=www/main.js --minify --allow-overwrite --servedir=www", + "build": "esbuild --bundle www/main.js --outfile=www/main.js --minify --allow-overwrite", "dev": "esbuild --bundle src/main.js --outfile=www/main.js --servedir=www", "bundle": "npm run build && mkdir -p dist && zip -r dist/game.zip www -x \"**/.DS_Store\"", - "start": "npm run build" + "start": "npm run dev" }, "dependencies": { "kaboom": "^3000.1.17", diff --git a/src/main.js b/src/main.js index 7b0de54..6fa2891 100644 --- a/src/main.js +++ b/src/main.js @@ -24,11 +24,13 @@ const ERROR_RATE = 0.1; const STABILIZER_INSERTION_RATE = 0.05; const WAIT_TIME = 2; const BLOCK_DIMENSION = 32 * 1.75; -const SPRITE_SCALE = 0.25; +const ENEMY_SCALE = 0.25; const PC_SCALE = 0.15; const DMG_THRESHOLD = 5; -const player = add([ +let player = undefined; + +player = add([ sprite("pc"), scale(PC_SCALE), pos(width() / 4 + BLOCK_DIMENSION +4, BLOCK_DIMENSION + 8), // place the player in top-right of the maze @@ -36,105 +38,125 @@ const player = add([ body(), // collide with blocks ]); +scene("gameover", (props) => { + add([ + text(props.txt, 32), + pos(width() / 2, height() / 2), + ]); + add([ + text(`Score: ${props.score}`, 32), + pos(width() / 2, height() / 2 + 32), + ]); +}); + player.xDamage = 0; player.zDamage = 0; let ticks = 0; -loop(1, () => { - if (!player.exists() || player.xDamage >= DMG_THRESHOLD || player.zDamage >= DMG_THRESHOLD) { - go("gameover", { score: 20 - player.xDamage + player.zDamage }); - } - // update opacity and color of the player based on damage - player.color = rgb(255, 255 - player.zDamage * 50, 255 - player.zDamage * 50); - player.opacity = 1 - (player.xDamage + player.xDamage) * 0.1; - // Decide whether to spawn an error - const poll = ticks++ > WAIT_TIME ? round(random() * (1 / ERROR_RATE)) : 0; - if (poll === 2) { - const zError = add([ - sprite("zError"), - scale(SPRITE_SCALE), - pos(rand(0, width()), rand(0, height())), - area(), - // anchor("center"), - state("move", ["idle", "attack", "move"]), - "zError", - ]); - // Run the callback once every time we enter "idle" state. - // Here we stay "idle" for 0.5 second, then enter "attack" state. - zError.onStateEnter("idle", async () => { - await wait(0.5); - zError.enterState("attack"); - }); - // When we enter "attack" state, we fire a bullet, - // and enter "move" state after 1 sec - zError.onStateEnter("attack", async () => { - // Don't do anything if player doesn't exist anymore - if (player.exists()) { - const dir = player.pos.sub(zError.pos).unit(); - add([ - pos(zError.pos), - move(dir, BULLET_SPEED), - rect(12, 12), - area(), - offscreen({ destroy: true }), - // anchor("center"), - color(RED), - "bullet", - ]); +let DEBUG = false; + +scene("main", () => { + loop(1, () => { + console.log("Player exists?", player.exists()); + if (!player.exists() || player.xDamage >= DMG_THRESHOLD || player.zDamage >= DMG_THRESHOLD || DEBUG) { + const props = { + txt: "Game Over!", + score: 20 - player.xDamage + player.zDamage, } - await wait(1); - zError.enterState("move"); - }); - zError.onStateEnter("move", async () => { - await wait(2); - zError.enterState("idle"); - }); - zError.onStateUpdate("move", () => { - if (!player.exists()) return; - const dir = player.pos.sub(zError.pos).unit(); - zError.move(dir.scale(ENEMY_SPEED)); - }); - } else if (poll === 1) { - const xError = add([ - sprite("xError"), - scale(SPRITE_SCALE), - pos(rand(0, width()), rand(0, height())), - area(), - // anchor("center"), - state("move", ["idle", "attack", "move", "lunge"]), - "zError", - ]); - xError.onStateEnter("move", async () => { - await wait(2); - xError.enterState("idle"); - }); - xError.onStateUpdate("move", () => { - if (!player.exists()) return; - const dir = player.pos.sub(xError.pos).unit(); - xError.move(dir.scale(ENEMY_SPEED)); - }); - xError.onStateEnter("idle", async () => { - await wait(0.5); - xError.enterState("attack"); - }); - xError.onStateEnter("lunge", async () => { - xError.lungePoints++; - if (xError.lungePoints > 10) { - xError.enterState("move"); - } else { + go("gameover", props); + } + // update opacity and color of the player based on damage + player.color = rgb(255, 255 - player.zDamage * 50, 255 - player.zDamage * 50); + player.opacity = 1 - (player.xDamage + player.xDamage) * 0.1; + // Decide whether to spawn an error + const poll = ticks++ > WAIT_TIME ? round(random() * (1 / ERROR_RATE)) : 0; + if (poll === 2) { + const zError = add([ + sprite("zError"), + scale(ENEMY_SCALE), + pos(rand(0, width()), rand(0, height())), + area(), + // anchor("center"), + state("move", ["idle", "attack", "move"]), + "zError", + ]); + // Run the callback once every time we enter "idle" state. + // Here we stay "idle" for 0.5 second, then enter "attack" state. + zError.onStateEnter("idle", async () => { + await wait(0.5); + zError.enterState("attack"); + }); + // When we enter "attack" state, we fire a bullet, + // and enter "move" state after 1 sec + zError.onStateEnter("attack", async () => { + // Don't do anything if player doesn't exist anymore + if (player.exists()) { + const dir = player.pos.sub(zError.pos).unit(); + add([ + pos(zError.pos), + move(dir, BULLET_SPEED), + rect(12, 12), + area(), + offscreen({ destroy: true }), + // anchor("center"), + color(RED), + "bullet", + ]); + } + await wait(1); + zError.enterState("move"); + }); + zError.onStateEnter("move", async () => { + await wait(2); + zError.enterState("idle"); + }); + zError.onStateUpdate("move", () => { + if (!player.exists()) return; + const dir = player.pos.sub(zError.pos).unit(); + zError.move(dir.scale(ENEMY_SPEED)); + }); + } else if (poll === 1) { + const xError = add([ + sprite("xError"), + scale(ENEMY_SCALE), + pos(rand(0, width()), rand(0, height())), + area(), + // anchor("center"), + state("move", ["idle", "attack", "move", "lunge"]), + "zError", + ]); + xError.onStateEnter("move", async () => { + await wait(2); + xError.enterState("idle"); + }); + xError.onStateUpdate("move", () => { + if (!player.exists()) return; const dir = player.pos.sub(xError.pos).unit(); - xError.move(dir.scale(ENEMY_SPEED * 20)); - await wait(0.01); + xError.move(dir.scale(ENEMY_SPEED)); + }); + xError.onStateEnter("idle", async () => { + await wait(0.5); + xError.enterState("attack"); + }); + xError.onStateEnter("lunge", async () => { + xError.lungePoints++; + if (xError.lungePoints > 10) { + xError.enterState("move"); + } else { + const dir = player.pos.sub(xError.pos).unit(); + xError.move(dir.scale(ENEMY_SPEED * 20)); + await wait(0.01); + xError.enterState("lunge"); + } + }); + xError.onStateEnter("attack", async () => { + await wait(1); + xError.lungePoints = 0; xError.enterState("lunge"); - } - }); - xError.onStateEnter("attack", async () => { - await wait(1); - xError.lungePoints = 0; - xError.enterState("lunge"); - }); - } + }); + } + }); }); player.onCollide("xError", () => { @@ -160,8 +182,12 @@ player.onCollide("z-stabilizer", (stabilizer) => { destroy(stabilizer); }); -player.onCollide("measure", (measure) => { - go("You win!"); +player.onCollide("measure", () => { + const props = { + txt: "You win!", + score: 20 - player.xDamage + player.zDamage, + } + go("gameover", props); }); // Register input handlers & movement @@ -303,7 +329,6 @@ const mazeTileSettings = { ], "M": () => [ rect(BLOCK_DIMENSION, BLOCK_DIMENSION), - //sprite("measure"), color(BLUE), area(), "measure", diff --git a/www/index.html b/www/index.html index bfca779..930c57e 100644 --- a/www/index.html +++ b/www/index.html @@ -7,6 +7,6 @@ - +