diff --git a/app.py b/app.py index ac87c3f..e475d54 100644 --- a/app.py +++ b/app.py @@ -261,4 +261,9 @@ def pumpkin_memory(): def pumpkin_roll(): return render_template("pumpkin_roll.jinja2") +@app.route("/whack_a_pumpkin") +@login_required +def whack_a_pumpkin(): + return render_template("whack_a_pumpkin.jinja2") + app.run(host=os.getenv("HOST", "0.0.0.0"), port=int(os.getenv("PORT", 8080)), debug=os.getenv("DEBUG_MODE", False).lower() == "true") \ No newline at end of file diff --git a/static/graphics/whackapumpkin.png b/static/graphics/whackapumpkin.png new file mode 100644 index 0000000..5c3776c Binary files /dev/null and b/static/graphics/whackapumpkin.png differ diff --git a/static/js/game.js b/static/js/game.js index f74848b..ccedfa2 100644 --- a/static/js/game.js +++ b/static/js/game.js @@ -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); diff --git a/static/js/pumpkin_memory.js b/static/js/pumpkin_memory.js index 3b2d919..3be5b40 100644 --- a/static/js/pumpkin_memory.js +++ b/static/js/pumpkin_memory.js @@ -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]; } \ No newline at end of file diff --git a/static/js/pumpkin_roll.js b/static/js/pumpkin_roll.js index 78dcc8a..01b45bc 100644 --- a/static/js/pumpkin_roll.js +++ b/static/js/pumpkin_roll.js @@ -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]; } \ No newline at end of file diff --git a/static/js/whack_a_pumpkin.js b/static/js/whack_a_pumpkin.js new file mode 100644 index 0000000..5ba2392 --- /dev/null +++ b/static/js/whack_a_pumpkin.js @@ -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}`; + } + + }) + }); +} \ No newline at end of file diff --git a/templates/countdown.jinja2 b/templates/countdown.jinja2 index 26e0339..ff12604 100644 --- a/templates/countdown.jinja2 +++ b/templates/countdown.jinja2 @@ -13,6 +13,9 @@ + diff --git a/templates/gamebase.jinja2 b/templates/gamebase.jinja2 new file mode 100644 index 0000000..c00f68b --- /dev/null +++ b/templates/gamebase.jinja2 @@ -0,0 +1,34 @@ +{% extends "base.jinja2" %} + +{% block nav %} + +{% block gamenav %}{% endblock %} + + + +{% endblock %} + +{% block body %} +
+

WIP!!! Not part of this week!!

+
+ +
+
+ + +{% block game_js %}{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/templates/index.jinja2 b/templates/index.jinja2 index 137df96..b383cad 100644 --- a/templates/index.jinja2 +++ b/templates/index.jinja2 @@ -12,6 +12,9 @@ + diff --git a/templates/profile.jinja2 b/templates/profile.jinja2 index 9da213a..51fbdcc 100644 --- a/templates/profile.jinja2 +++ b/templates/profile.jinja2 @@ -12,6 +12,9 @@ + @@ -33,6 +36,7 @@ {% if logged_in_account %}

Logged in as: {{ username }}

Pumpkin Roll High Score: Loading...

+

Whack a Pumpkin High Score: Loading...

Pumpkin Memory (Easy) Best Time: Loading...

Pumpkin Memory (Medium) Best Time: Loading...

Pumpkin Memory (Hard) Best Time: Loading...

@@ -101,15 +105,22 @@ setup_pumpkin("current_pumpkin_canvas", "currentclearBtn", "currentlightBtn", "change_pattern_form", "current_pattern_field", {{ grid_size }}); setup_pumpkin("new_pumpkin_canvas", "newclearBtn", "newlightBtn", "change_pattern_form", "new_pattern_field", {{ grid_size }}); +function formatTime(time) { + return time !== "None" ? `${time}s` : time; +} + pumpkin_roll_highscore = localStorage.getItem("pumpkin_roll_highscore") || "None" +whackapumpkin_highscore = localStorage.getItem("whackapumpkin_highscore") || "None" memory_best_easy = localStorage.getItem("memory_best_easy") || "None" memory_best_medium = localStorage.getItem("memory_best_medium") || "None" memory_best_hard = localStorage.getItem("memory_best_hard") || "None" memory_best_extrahard = localStorage.getItem("memory_best_extrahard") || "None" -document.getElementById("pumpkin_roll_highscore").textContent = `Pumpkin Roll High Score: ${pumpkin_roll_highscore}` -document.getElementById("memory_best_easy").textContent = `Pumpkin Memory (Easy) Best Time: ${memory_best_easy}` -document.getElementById("memory_best_medium").textContent = `Pumpkin Memory (Medium) Best Time: ${memory_best_medium}` -document.getElementById("memory_best_hard").textContent = `Pumpkin Memory (Hard) Best Time: ${memory_best_hard}` -document.getElementById("memory_best_extrahard").textContent = `Pumpkin Memory (Extra Hard) Best Time: ${memory_best_extrahard}` + +document.getElementById("pumpkin_roll_highscore").textContent = `Pumpkin Roll High Score: ${formatTime(pumpkin_roll_highscore)}`; +document.getElementById("whackapumpkin_highscore").textContent = `Whack a Pumpkin High Score: ${formatTime(whackapumpkin_highscore)}`; +document.getElementById("memory_best_easy").textContent = `Pumpkin Memory (Easy) Best Time: ${formatTime(memory_best_easy)}`; +document.getElementById("memory_best_medium").textContent = `Pumpkin Memory (Medium) Best Time: ${formatTime(memory_best_medium)}`; +document.getElementById("memory_best_hard").textContent = `Pumpkin Memory (Hard) Best Time: ${formatTime(memory_best_hard)}`; +document.getElementById("memory_best_extrahard").textContent = `Pumpkin Memory (Extra Hard) Best Time: ${formatTime(memory_best_extrahard)}`; {% endblock body %} \ No newline at end of file diff --git a/templates/pumpkin_memory.jinja2 b/templates/pumpkin_memory.jinja2 index 42ec8fe..710bc5e 100644 --- a/templates/pumpkin_memory.jinja2 +++ b/templates/pumpkin_memory.jinja2 @@ -1,11 +1,6 @@ -{% extends "base.jinja2" %} +{% extends "gamebase.jinja2" %} -{% block title %}Pumpkin Memory{% endblock title %} - -{% block nav %} - +{% block gamenav %} @@ -13,30 +8,10 @@ Pumpkin Memory - - {% endblock %} -{% block body %} +{% block title %}Pumpkin Memory{% endblock title %} -
-

WIP!!! Not part of this week!!

-
- -
-
- - - - -{% endblock %} \ No newline at end of file +{% block game_js %}{% endblock %} \ No newline at end of file diff --git a/templates/pumpkin_roll.jinja2 b/templates/pumpkin_roll.jinja2 index 298f537..d5ac688 100644 --- a/templates/pumpkin_roll.jinja2 +++ b/templates/pumpkin_roll.jinja2 @@ -1,11 +1,6 @@ -{% extends "base.jinja2" %} +{% extends "gamebase.jinja2" %} -{% block title %}Pumpkin Roll{% endblock title %} - -{% block nav %} - +{% block gamenav %} @@ -13,29 +8,10 @@ Pumpkin Memory - - {% endblock %} -{% block body %} -
-

WIP!!! Not part of this week!!

-
- -
-
- - - - -{% endblock %} \ No newline at end of file +{% block title %}Pumpkin Roll{% endblock title %} + +{% block game_js %}{% endblock %} \ No newline at end of file diff --git a/templates/whack_a_pumpkin.jinja2 b/templates/whack_a_pumpkin.jinja2 new file mode 100644 index 0000000..330e933 --- /dev/null +++ b/templates/whack_a_pumpkin.jinja2 @@ -0,0 +1,17 @@ +{% extends "gamebase.jinja2" %} + +{% block gamenav %} + + + +{% endblock %} + +{% block title %}Whack a Pumpkin{% endblock title %} + +{% block game_js %}{% endblock %} \ No newline at end of file