Spaces:
Running
Running
Update game.html
Browse files
game.html
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
<!DOCTYPE html>
|
|
|
|
| 2 |
<!-- VERSION: DOUBLE-JUMP-FIX + POLISH-PASS-1 v11 -->
|
| 3 |
<!-- VERSION: FIXED-GREEN-PLATFORM-SPEED + FIXED-RUNTIME + FIXED-BOOK-PATTERN + INFINITE-STABLE-BOOKCASE + FULLSCREEN + TALL-AUTO-EXTENDING-WORLD + ALWAYS-VISIBLE-JUMP v8 -->
|
| 4 |
<html>
|
|
@@ -457,9 +458,9 @@ function init(){
|
|
| 457 |
score = 0;
|
| 458 |
landingCount = 0;
|
| 459 |
scoringStarted = false;
|
| 460 |
-
//
|
| 461 |
-
//
|
| 462 |
-
doubleJumpReady = ownsDoubleJump;
|
| 463 |
landingParticles = [];
|
| 464 |
gameOverAngle = 0;
|
| 465 |
}
|
|
@@ -506,7 +507,7 @@ function triggerGameOver(){
|
|
| 506 |
}
|
| 507 |
|
| 508 |
function attemptDoubleJump(){
|
| 509 |
-
if(state !== 'playing' || !ownsDoubleJump || !doubleJumpReady || !player) return false;
|
| 510 |
|
| 511 |
doubleJumpReady = false;
|
| 512 |
player.vy = BOUNCE_V;
|
|
@@ -530,14 +531,33 @@ function openCustomMinutesPurchase(){
|
|
| 530 |
}
|
| 531 |
|
| 532 |
function openMinutesPrompt(){
|
| 533 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 534 |
if(input === null) return;
|
|
|
|
| 535 |
let n = Math.floor(Number(input));
|
| 536 |
if(!isFinite(n) || n <= 0) return;
|
|
|
|
| 537 |
n = Math.min(n, minutesBank);
|
| 538 |
if(n <= 0) return;
|
|
|
|
| 539 |
minutesBank -= n;
|
| 540 |
timeLeftSeconds += n * 60;
|
|
|
|
| 541 |
saveGame();
|
| 542 |
playBeep(900, 0.15);
|
| 543 |
}
|
|
@@ -770,7 +790,7 @@ function update(){
|
|
| 770 |
if(coinsCollected >= DOUBLE_JUMP_COST){
|
| 771 |
coinsCollected -= DOUBLE_JUMP_COST;
|
| 772 |
ownsDoubleJump = true;
|
| 773 |
-
doubleJumpReady =
|
| 774 |
// Save ownership in two places so the upgrade cannot disappear if
|
| 775 |
// the rest of the JSON save is ever replaced or corrupted.
|
| 776 |
localStorage.setItem(DOUBLE_JUMP_OWNED_KEY, "true");
|
|
@@ -800,7 +820,7 @@ function update(){
|
|
| 800 |
pointerWasDown = mouse.pressed;
|
| 801 |
if(pauseClicked && hitRect(mouse.x, mouse.y, PAUSE_BTN)){ state = 'paused'; return; }
|
| 802 |
|
| 803 |
-
const minutesBtnVisible = ownsDoubleJump
|
| 804 |
if(pauseClicked && hitRect(mouse.x, mouse.y, JUMP_BTN)){ attemptDoubleJump(); }
|
| 805 |
if(pauseClicked && minutesBtnVisible && hitRect(mouse.x, mouse.y, MINUTES_BTN)){ openMinutesPrompt(); return; }
|
| 806 |
const jumpInputDown = keys[' '] || keys['w'] || keys['W'] || keys['ArrowUp'];
|
|
@@ -908,7 +928,7 @@ function update(){
|
|
| 908 |
wobble = 8;
|
| 909 |
spawnLandingParticles(player.x, platTop);
|
| 910 |
lastLandedY = platTop;
|
| 911 |
-
|
| 912 |
playBeep(500 + Math.random()*200, 0.1);
|
| 913 |
landingCount++;
|
| 914 |
if(landingCount === 2){ scoringStarted = true; baseline = player.y; }
|
|
@@ -1409,9 +1429,10 @@ function draw(){
|
|
| 1409 |
screen.drawText('BUY - ' + DOUBLE_JUMP_COST, DJ_BUY_BTN.x, DJ_BUY_BTN.y, 17, '#ffffff');
|
| 1410 |
}
|
| 1411 |
|
| 1412 |
-
//
|
| 1413 |
-
screen.drawText('MINUTES', -175, 55,
|
| 1414 |
screen.drawText('You have ' + minutesBank + ' minute' + (minutesBank===1?'':'s') + ' banked.', -175, 26, 14, '#666');
|
|
|
|
| 1415 |
MINUTE_PACKS.forEach((pack, i) => {
|
| 1416 |
const btn = MINUTE_PACK_BTNS[i];
|
| 1417 |
const afford = coinsCollected >= pack.cost;
|
|
@@ -1462,8 +1483,9 @@ function draw(){
|
|
| 1462 |
screen.drawRect(PAUSE_BTN.x-6, PAUSE_BTN.y, 5, 18, '#ffffff');
|
| 1463 |
screen.drawRect(PAUSE_BTN.x+6, PAUSE_BTN.y, 5, 18, '#ffffff');
|
| 1464 |
|
| 1465 |
-
// Always show the JUMP button.
|
| 1466 |
-
|
|
|
|
| 1467 |
? '#777777'
|
| 1468 |
: (doubleJumpReady ? '#ff9f3f' : '#b97842');
|
| 1469 |
|
|
@@ -1471,12 +1493,21 @@ function draw(){
|
|
| 1471 |
screen.drawCircle(JUMP_BTN.x, JUMP_BTN.y, 40, '#ffffff');
|
| 1472 |
screen.drawCircle(JUMP_BTN.x, JUMP_BTN.y, 34, jumpButtonColor);
|
| 1473 |
screen.drawText('JUMP', JUMP_BTN.x, JUMP_BTN.y+5, 15, '#ffffff');
|
| 1474 |
-
|
| 1475 |
-
|
| 1476 |
-
if(ownsDoubleJump &&
|
| 1477 |
-
|
| 1478 |
-
|
| 1479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1480 |
}
|
| 1481 |
if(timeLeftSeconds > 0){
|
| 1482 |
const totalSec = Math.ceil(timeLeftSeconds);
|
|
@@ -1535,7 +1566,10 @@ function loop(now){
|
|
| 1535 |
if(lastFrameTime === null) lastFrameTime = now;
|
| 1536 |
const dtSec = (now - lastFrameTime) / 1000;
|
| 1537 |
lastFrameTime = now;
|
| 1538 |
-
if(timeLeftSeconds > 0)
|
|
|
|
|
|
|
|
|
|
| 1539 |
update();
|
| 1540 |
draw();
|
| 1541 |
requestAnimationFrame(loop);
|
|
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
+
<!-- VERSION: DOUBLE-JUMP-MINUTES-ACTIVATION v12 -->
|
| 3 |
<!-- VERSION: DOUBLE-JUMP-FIX + POLISH-PASS-1 v11 -->
|
| 4 |
<!-- VERSION: FIXED-GREEN-PLATFORM-SPEED + FIXED-RUNTIME + FIXED-BOOK-PATTERN + INFINITE-STABLE-BOOKCASE + FULLSCREEN + TALL-AUTO-EXTENDING-WORLD + ALWAYS-VISIBLE-JUMP v8 -->
|
| 5 |
<html>
|
|
|
|
| 458 |
score = 0;
|
| 459 |
landingCount = 0;
|
| 460 |
scoringStarted = false;
|
| 461 |
+
// Buying Double Jump unlocks the feature, but it only works while
|
| 462 |
+
// Double Jump time is active. Use the on-screen button to choose minutes.
|
| 463 |
+
doubleJumpReady = ownsDoubleJump && timeLeftSeconds > 0;
|
| 464 |
landingParticles = [];
|
| 465 |
gameOverAngle = 0;
|
| 466 |
}
|
|
|
|
| 507 |
}
|
| 508 |
|
| 509 |
function attemptDoubleJump(){
|
| 510 |
+
if(state !== 'playing' || !ownsDoubleJump || timeLeftSeconds <= 0 || !doubleJumpReady || !player) return false;
|
| 511 |
|
| 512 |
doubleJumpReady = false;
|
| 513 |
player.vy = BOUNCE_V;
|
|
|
|
| 531 |
}
|
| 532 |
|
| 533 |
function openMinutesPrompt(){
|
| 534 |
+
if(!ownsDoubleJump){
|
| 535 |
+
playBeep(150, 0.2);
|
| 536 |
+
return;
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
if(minutesBank <= 0){
|
| 540 |
+
window.alert('You do not have any Double Jump minutes banked. Buy minutes in the Shop first.');
|
| 541 |
+
playBeep(150, 0.2);
|
| 542 |
+
return;
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
const input = window.prompt(
|
| 546 |
+
'How many minutes of Double Jump do you want to use? (' +
|
| 547 |
+
minutesBank + ' minute' + (minutesBank === 1 ? '' : 's') + ' banked)'
|
| 548 |
+
);
|
| 549 |
+
|
| 550 |
if(input === null) return;
|
| 551 |
+
|
| 552 |
let n = Math.floor(Number(input));
|
| 553 |
if(!isFinite(n) || n <= 0) return;
|
| 554 |
+
|
| 555 |
n = Math.min(n, minutesBank);
|
| 556 |
if(n <= 0) return;
|
| 557 |
+
|
| 558 |
minutesBank -= n;
|
| 559 |
timeLeftSeconds += n * 60;
|
| 560 |
+
doubleJumpReady = true;
|
| 561 |
saveGame();
|
| 562 |
playBeep(900, 0.15);
|
| 563 |
}
|
|
|
|
| 790 |
if(coinsCollected >= DOUBLE_JUMP_COST){
|
| 791 |
coinsCollected -= DOUBLE_JUMP_COST;
|
| 792 |
ownsDoubleJump = true;
|
| 793 |
+
doubleJumpReady = false;
|
| 794 |
// Save ownership in two places so the upgrade cannot disappear if
|
| 795 |
// the rest of the JSON save is ever replaced or corrupted.
|
| 796 |
localStorage.setItem(DOUBLE_JUMP_OWNED_KEY, "true");
|
|
|
|
| 820 |
pointerWasDown = mouse.pressed;
|
| 821 |
if(pauseClicked && hitRect(mouse.x, mouse.y, PAUSE_BTN)){ state = 'paused'; return; }
|
| 822 |
|
| 823 |
+
const minutesBtnVisible = ownsDoubleJump;
|
| 824 |
if(pauseClicked && hitRect(mouse.x, mouse.y, JUMP_BTN)){ attemptDoubleJump(); }
|
| 825 |
if(pauseClicked && minutesBtnVisible && hitRect(mouse.x, mouse.y, MINUTES_BTN)){ openMinutesPrompt(); return; }
|
| 826 |
const jumpInputDown = keys[' '] || keys['w'] || keys['W'] || keys['ArrowUp'];
|
|
|
|
| 928 |
wobble = 8;
|
| 929 |
spawnLandingParticles(player.x, platTop);
|
| 930 |
lastLandedY = platTop;
|
| 931 |
+
doubleJumpReady = ownsDoubleJump && timeLeftSeconds > 0;
|
| 932 |
playBeep(500 + Math.random()*200, 0.1);
|
| 933 |
landingCount++;
|
| 934 |
if(landingCount === 2){ scoringStarted = true; baseline = player.y; }
|
|
|
|
| 1429 |
screen.drawText('BUY - ' + DOUBLE_JUMP_COST, DJ_BUY_BTN.x, DJ_BUY_BTN.y, 17, '#ffffff');
|
| 1430 |
}
|
| 1431 |
|
| 1432 |
+
// Double Jump minutes
|
| 1433 |
+
screen.drawText('DOUBLE JUMP MINUTES', -175, 55, 22, '#333');
|
| 1434 |
screen.drawText('You have ' + minutesBank + ' minute' + (minutesBank===1?'':'s') + ' banked.', -175, 26, 14, '#666');
|
| 1435 |
+
screen.drawText('Use them with the purple button during the game.', -175, 5, 12, '#777');
|
| 1436 |
MINUTE_PACKS.forEach((pack, i) => {
|
| 1437 |
const btn = MINUTE_PACK_BTNS[i];
|
| 1438 |
const afford = coinsCollected >= pack.cost;
|
|
|
|
| 1483 |
screen.drawRect(PAUSE_BTN.x-6, PAUSE_BTN.y, 5, 18, '#ffffff');
|
| 1484 |
screen.drawRect(PAUSE_BTN.x+6, PAUSE_BTN.y, 5, 18, '#ffffff');
|
| 1485 |
|
| 1486 |
+
// Always show the JUMP button. Buying the upgrade unlocks it, but
|
| 1487 |
+
// Double Jump time must also be active before the jump can be used.
|
| 1488 |
+
const jumpButtonColor = !ownsDoubleJump || timeLeftSeconds <= 0
|
| 1489 |
? '#777777'
|
| 1490 |
: (doubleJumpReady ? '#ff9f3f' : '#b97842');
|
| 1491 |
|
|
|
|
| 1493 |
screen.drawCircle(JUMP_BTN.x, JUMP_BTN.y, 40, '#ffffff');
|
| 1494 |
screen.drawCircle(JUMP_BTN.x, JUMP_BTN.y, 34, jumpButtonColor);
|
| 1495 |
screen.drawText('JUMP', JUMP_BTN.x, JUMP_BTN.y+5, 15, '#ffffff');
|
| 1496 |
+
|
| 1497 |
+
let jumpStatus = 'LOCKED';
|
| 1498 |
+
if(ownsDoubleJump && timeLeftSeconds <= 0) jumpStatus = 'NO TIME';
|
| 1499 |
+
else if(ownsDoubleJump && doubleJumpReady) jumpStatus = 'READY';
|
| 1500 |
+
else if(ownsDoubleJump) jumpStatus = 'USED';
|
| 1501 |
+
screen.drawText(jumpStatus, JUMP_BTN.x, JUMP_BTN.y-14, 9, '#ffffff');
|
| 1502 |
+
|
| 1503 |
+
// This button is the way to activate Double Jump time. It is visible
|
| 1504 |
+
// on both desktop and mobile after the upgrade has been purchased.
|
| 1505 |
+
if(ownsDoubleJump){
|
| 1506 |
+
const useTimeColor = minutesBank > 0 ? '#8a5cff' : '#777777';
|
| 1507 |
+
screen.drawRect(MINUTES_BTN.x, MINUTES_BTN.y, MINUTES_BTN.w, MINUTES_BTN.h, useTimeColor);
|
| 1508 |
+
screen.drawText(timeLeftSeconds > 0 ? 'ADD TIME' : 'USE DOUBLE JUMP',
|
| 1509 |
+
MINUTES_BTN.x, MINUTES_BTN.y+12, timeLeftSeconds > 0 ? 15 : 13, '#ffffff');
|
| 1510 |
+
screen.drawText(minutesBank + ' min banked', MINUTES_BTN.x, MINUTES_BTN.y-13, 11, '#ffffff');
|
| 1511 |
}
|
| 1512 |
if(timeLeftSeconds > 0){
|
| 1513 |
const totalSec = Math.ceil(timeLeftSeconds);
|
|
|
|
| 1566 |
if(lastFrameTime === null) lastFrameTime = now;
|
| 1567 |
const dtSec = (now - lastFrameTime) / 1000;
|
| 1568 |
lastFrameTime = now;
|
| 1569 |
+
if(timeLeftSeconds > 0){
|
| 1570 |
+
timeLeftSeconds = Math.max(0, timeLeftSeconds - dtSec);
|
| 1571 |
+
if(timeLeftSeconds === 0) doubleJumpReady = false;
|
| 1572 |
+
}
|
| 1573 |
update();
|
| 1574 |
draw();
|
| 1575 |
requestAnimationFrame(loop);
|