Add whack a pumpkin and best score, move games to game_info and setup_game, make a modular basegame template and build upon that, fix game settings not using the current game specific settings

This commit is contained in:
csd4ni3l
2025-11-02 21:23:09 +01:00
parent 7094603bd7
commit 0904eede95
13 changed files with 245 additions and 102 deletions

View File

@@ -66,15 +66,17 @@ function show_settings(category, GAME_TITLE, SETTINGS) {
}
function start_game() {
const [GAME_TITLE, SETTINGS] = game_info();
kaplay(
{
width: WIDTH,
height: HEIGHT,
canvas: document.getElementById("canvas"),
root: document.getElementById("game-container"),
crisp: !localStorage.getItem("Anti-Alasing"),
texFilter: (localStorage.getItem("Texture Filtering") || "nearest").toLowerCase(),
maxFPS: Number(localStorage.getItem("FPS Limit")),
crisp: !localStorage.getItem(`${GAME_TITLE} Anti-Aliasing`),
texFilter: (localStorage.getItem(`${GAME_TITLE} Texture Filtering`) || "nearest").toLowerCase(),
maxFPS: Number(localStorage.getItem(`${GAME_TITLE} FPS Limit`)),
font: "New Rocker",
background: "#e18888",
buttons: {
@@ -90,8 +92,8 @@ function start_game() {
}
);
const [GAME_TITLE, SETTINGS] = setup_game();
setup_game();
scene("settings", (setting_category) => {
let generated_button_lists = Object.entries(SETTINGS).map(([key, value]) => [key, color(127, 127, 127), color(0, 0, 0, 0), scene_lambda("settings", key)]);
generated_button_lists = [["Back", color(127, 127, 127), color(0, 0, 0, 0), scene_lambda("main_menu")]].concat(generated_button_lists);

View File

@@ -1,5 +1,4 @@
function setup_game() {
loadSprite("pumpkin", "/static/graphics/pumpkin.png");
function game_info() {
const SETTINGS = {
"Graphics": {
"Anti-Aliasing": {"type": "bool", "default": "true"},
@@ -13,6 +12,12 @@ function setup_game() {
"SFX Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
},
};
return ["Pumpkin Memory", SETTINGS];
}
function setup_game() {
loadSprite("pumpkin", "/static/graphics/pumpkin.png");
scene("game", (difficulty, pumpkin_array, revealed, found_pairs, start) => {
create_button(5, 5, 150, 75, "Back", color(127, 127, 127), color(0, 0, 0, 0), scene_lambda("main_menu"))
@@ -71,7 +76,7 @@ function setup_game() {
const best_time_display = (best_time == 99999) ? "None" : `${best_time}s`;
const elapsed = performance.now() - start;
const timer_label = create_label(520, 5, `Time spent: ${(elapsed / 1000).toFixed(1)}s Best Time: ${best_time_display}`);
const timer_label = create_label(400, 5, `Time spent: ${(elapsed / 1000).toFixed(1)}s Best Time: ${best_time_display}`);
const timer_interval_id = setInterval(() => {
const elapsed = performance.now() - start;
@@ -88,8 +93,9 @@ function setup_game() {
best_time = (elapsed / 1000).toFixed(1);
}
localStorage.setItem(`memory_best_${difficulty}`, best_time);
create_label(520, 320, `You win!\nTime took: ${(elapsed / 1000).toFixed(1)} s Best Time: ${best_time_display}`, 48);
const best_time_display = (best_time == 99999) ? "None" : `${best_time}s`;
create_label(520, 320, `You win!\nTime took: ${(elapsed / 1000).toFixed(1)} s\nBest Time: ${best_time_display}`, 48);
return;
}
@@ -102,7 +108,7 @@ function setup_game() {
const sprite = create_sprite(start_x + col * (pumpkin_size + space_between), start_y + row * (pumpkin_size + space_between), "pumpkin");
sprite.scale = 1;
tween(sprite.scale, 0, 0.2, (val) => sprite.scale = val).then(() => {
create_label(start_x + col * (pumpkin_size + space_between) + pumpkin_size / 2, start_y + row * (pumpkin_size + space_between) + pumpkin_size / 2, arr[i], 24);
create_label(start_x + col * (pumpkin_size + space_between) + pumpkin_size / 3, start_y + row * (pumpkin_size + space_between) + pumpkin_size / 2, arr[i], 24);
tween(sprite.scale, 1, 0.2, (val) => sprite.scale = val).then(() => {
wait(0.5, () => {
if (found_pair == null) {
@@ -140,6 +146,4 @@ function setup_game() {
["Extra Hard", color(127, 127, 127), color(0, 0, 0, 0), scene_lambda("game", "extrahard")]
], WIDTH / 2, HEIGHT / 8, HEIGHT / 50)
});
return ["Pumpkin Memory", SETTINGS];
}

View File

@@ -1,3 +1,24 @@
function game_info() {
const SETTINGS = {
"Graphics": {
"Anti-Aliasing": {"type": "bool", "default": "true"},
"Texture Filtering": {"type": "option", "options": ["Nearest", "Linear"], "default": "Linear"},
"FPS Limit": {"type": "slider", "min": 0, "max": 480, "default": 60},
},
"Sound": {
"Music": {"type": "bool", "default": "true"},
"SFX": {"type": "bool", "default": "true"},
"Music Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
"SFX Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
},
"Input": {
"Controller Enabled": {"type": "bool", "default": "true"}
}
};
return ["Pumpkin Roll", SETTINGS];
}
function spawn_enemy(enemy_type) {
let enemy_width;
let enemy_height;
@@ -38,39 +59,19 @@ function setup_game() {
loadSprite("tombstone", "/static/graphics/tombstone.png");
loadSprite("bird", "/static/graphics/bird.png");
const SETTINGS = {
"Graphics": {
"Anti-Aliasing": {"type": "bool", "default": "true"},
"Texture Filtering": {"type": "option", "options": ["Nearest", "Linear"], "default": "Linear"},
"FPS Limit": {"type": "slider", "min": 0, "max": 480, "default": 60},
},
"Sound": {
"Music": {"type": "bool", "default": "true"},
"SFX": {"type": "bool", "default": "true"},
"Music Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
"SFX Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
},
"Input": {
"Controller Enabled": {"type": "bool", "default": "true"}
}
};
const GRAVITY = 2500;
const JUMP_VELOCITY = -1200;
const GROUND_Y = 670;
scene("play", () => {
let score = 0;
let high_score = localStorage.getItem("pumpkin_roll_highscore");
let high_score = Number(localStorage.getItem("pumpkin_roll_highscore"));
let game_over = false;
let enemies = [];
let last_enemy_spawn = performance.now();
const score_label = create_label(480, 10, `Score: ${score} High Score: ${high_score}`);
if (high_score == null) {
high_score = 0;
}
let pumpkin_sprite = add([
sprite("pumpkin"),
pos(50, 670),
@@ -157,6 +158,4 @@ function setup_game() {
}
});
})
return ["Pumpkin Roll", SETTINGS];
}

View File

@@ -0,0 +1,114 @@
function game_info() {
const SETTINGS = {
"Graphics": {
"Anti-Aliasing": {"type": "bool", "default": "true"},
"Texture Filtering": {"type": "option", "options": ["Nearest", "Linear"], "default": "Linear"},
"FPS Limit": {"type": "slider", "min": 0, "max": 480, "default": 60},
},
"Sound": {
"Music": {"type": "bool", "default": "true"},
"SFX": {"type": "bool", "default": "true"},
"Music Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
"SFX Volume": {"type": "slider", "min": 0, "max": 100, "default": 50},
}
};
return ["Whack a Pumpkin", SETTINGS];
}
function spawn_pumpkin(pumpkin_spaces, used_slots) {
const free_slots = pumpkin_spaces.filter((_, i) => !used_slots.has(i));
const random_index = Math.floor(Math.random() * free_slots.length);
const [x, y] = free_slots[random_index];
const pumpkin_sprite = add([
sprite("pumpkin"),
pos(x, y),
area(),
"pumpkin"
])
setInterval(() => {
destroy(pumpkin_sprite);
}, 600);
return pumpkin_sprite;
}
function setup_game() {
loadSprite("bg", "/static/graphics/whackapumpkin.png");
loadSprite("pumpkin", "/static/graphics/pumpkin.png");
const pumpkin_spaces = [
[480, 12000],
[615, 12000],
[750, 12000],
[480, 420],
[615, 420],
[750, 420],
[480, 540],
[615, 540],
[750, 540],
];
scene("play", () => {
const pumpkins = [];
const used_slots = new Set();
const start = performance.now();
let game_over = false;
let score = 0;
let high_score = Number(localStorage.getItem("whackapumpkin_high_score"));
const bg = add([
sprite("bg"),
pos(420, 15),
scale(0.85)
]);
create_button(5, 5, 150, 75, "Back", color(127, 127, 127), color(0, 0, 0, 0), scene_lambda("main_menu"))
const info_label = create_label(525, 50, `Time left: 120s\nScore: ${score}\nHigh Score: ${high_score}`);
function spawn_pumpkins() {
pumpkins.push(spawn_pumpkin(pumpkin_spaces, used_slots));
if (!game_over) {
setTimeout(spawn_pumpkins, Math.random() * 1500);
}
}
setTimeout(spawn_pumpkins, Math.random() * 1500);
onClick("pumpkin", (pumpkin) => {
destroy(pumpkin);
score += 1;
if (score > high_score) {
high_score = score;
localStorage.setItem("whackapumpkin_high_score", high_score);
}
})
bg.onUpdate(() => {
const elapsed = performance.now() - start;
if ((elapsed / 1000) >= 120) {
create_label(520, 12020, `Game Over!\nScore: ${score}\nHigh Score: ${high_score}`, 48);
game_over = true;
for (const pumpkin of pumpkins) {
destroy(pumpkin);
}
destroy(bg);
destroy(info_label);
}
else {
info_label.text = `Time left: ${(120 - (elapsed / 1000)).toFixed(1)}s\nScore: ${score}\nHigh Score: ${high_score}`;
}
})
});
}