Add gameover and overall layout

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-28 23:54:52 +09:00
parent 9939aab976
commit acead592b7
4 changed files with 126 additions and 38 deletions

View File

@@ -1,19 +1,44 @@
<script>
import { initializeGame, updateGame, getScore } from './game/game.js';
import {
initializeGame,
updateGame,
getScore,
isGameOver,
resetGame
} from './game/game.js';
let game;
let score = $state(0);
let highScore = $state(0);
let state = $state('start'); // start | playing | gameover
window.setup = () => {
createCanvas(400, 800).parent(game);
initializeGame();
noLoop();
};
window.draw = () => {
updateGame();
score = getScore();
score = Math.floor(getScore());
if (isGameOver()) {
state = 'gameover';
if (score > highScore) {
highScore = score;
}
noLoop();
}
};
function playGame() {
resetGame();
score = 0;
state = 'playing';
loop();
}
$effect(() => {
new p5();
});
@@ -24,11 +49,23 @@
<div class="layout">
<aside class="scoreboard">
<h2>Score</h2>
<p>{score}</p>
<h2>High Score</h2>
<p>{highScore}</p>
</aside>
<div class="game-wrapper" bind:this={game}></div>
<div class="game-wrapper">
<div bind:this={game}></div>
{#if state !== 'playing'}
<div class="overlay">
<div class="overlay-card">
<h2>{state === 'gameover' ? 'Game over!' : 'Start new game'}</h2>
{#if state !== "start"} <p>Score: {score}</p> {/if }
<button onclick={playGame}>Play</button>
</div>
</div>
{/if}
</div>
<aside class="right-panel"></aside>
</div>
@@ -74,11 +111,47 @@
}
.game-wrapper {
position: relative;
width: 400px;
height: 800px;
border-radius: 18px;
overflow: hidden;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}
.overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.overlay-card {
background: rgba(255, 255, 255, 0.94);
color: #111;
padding: 28px;
border-radius: 18px;
min-width: 220px;
}
.overlay-card h2 {
margin-top: 0;
}
.overlay-card button {
font-size: 18px;
font-weight: bold;
padding: 10px 28px;
border: none;
border-radius: 999px;
cursor: pointer;
background: #2b2d42;
color: white;
}
.right-panel {
width: 220px;
}

View File

@@ -5,7 +5,8 @@ export const GAME_COLORS = {
movingPlat: '#4cc9f0',
springPlat: '#80ed99',
oneTimePlat: '#e76f51',
startingPlat: '#f4a261' };
startingPlat: '#f4a261'
};
export const PLATFORMS_GAP = 80;
export const PLATFORM_WIDHT = 70;
@@ -17,5 +18,3 @@ export const PLAT_TYPE = {
SPRING: 'spring',
ONE_TIME: 'one-time'
};

View File

@@ -1,48 +1,43 @@
import { updatePlayerPosition } from './gameUtils.js';
import { initPlatforms, moveWorld} from './platforms.js';
import { updatePlayerPosition, createPlayer } from './gameUtils.js';
import { initPlatforms, moveWorld } from './platforms.js';
import { GAME_COLORS, PLATFORMS_GAP } from './constants.js';
// Game state
let player;
let platforms;
let pendingWorldMove = 0;
let gameOver = false;
export function getScore() {
return (player?.elevation ?? 0);
return (player?.elevation ?? 0) / PLATFORMS_GAP * 10;
}
function createPlayer() {
player = new Sprite();
player.x = width / 2;
player.y = 700;
player.scale = 0.20;
player.img = "assets/nubzuki.png";
player.rotationLock = true;
player.w = 20;
player.h = 20;
player.offset.y = 25;
player.bounciness = 0;
player.elevation = 0;
return player;
export function isGameOver() {
return gameOver;
}
export function resetGame() {
allSprites.remove();
pendingWorldMove = 0;
gameOver = false;
export function initializeGame() {
//world.debug = true; //TODO remove
//allSprites.debug = true; //TODO remove
world.gravity.y = 10;
platforms = initPlatforms();
player = createPlayer();
}
export function initializeGame() {
world.gravity.y = 10;
resetGame();
}
export function updateGame() {
clear();
background(GAME_COLORS.background);
if (gameOver) {
return;
}
pendingWorldMove += updatePlayerPosition(player, platforms);
@@ -53,13 +48,15 @@ export function updateGame() {
player.y += move;
player.bounciness = 0;
}
player.rotation = player.vel.x * 1.5;
if (player.y > height) {
gameOver = true;
}
// UI
fill(0);
textSize(24);
textSize(40);
textAlign(RIGHT);
text(`${Math.floor(player.elevation)}`, width - 20, 30);
text(getScore(), width - 20, 50);
}

View File

@@ -1,5 +1,24 @@
import { PLAT_TYPE } from './constants.js';
export function createPlayer() {
const player = new Sprite();
player.x = width / 2;
player.y = 700;
player.scale = 0.20;
player.img = "assets/nubzuki.png";
player.rotationLock = true;
player.w = 20;
player.h = 20;
player.offset.y = 25;
player.bounciness = 0;
player.elevation = 0;
return player;
}
function handleJump(player, platform) {