From 9945f7aa4d4050447553cc2aad7d2ed3c55485b9 Mon Sep 17 00:00:00 2001 From: Burin-Zhargal Date: Tue, 21 Oct 2025 19:54:59 +0300 Subject: [PATCH] Snake ArcadeGame added: Issues: 1) Cannot to create new asset\sprite\gameobject properly 2) tried to create invisible "trigger" but failed to do. --- src/gameObjects/map_arcade/index.js | 3 + .../map_arcade/snake.gameObject.js | 28 +++ .../game_machine_14.interactions.js | 231 ++++++++++++++++++ src/interactions/map_arcade/index.js | 2 + 4 files changed, 264 insertions(+) create mode 100644 src/gameObjects/map_arcade/snake.gameObject.js create mode 100644 src/interactions/map_arcade/game_machine_14.interactions.js diff --git a/src/gameObjects/map_arcade/index.js b/src/gameObjects/map_arcade/index.js index bff73a9d..a5397368 100644 --- a/src/gameObjects/map_arcade/index.js +++ b/src/gameObjects/map_arcade/index.js @@ -2,10 +2,13 @@ import { jessie } from './jessie.gameObject'; import { npcsInArcadeMap } from './npcsOnmap'; +//import { snake } from './snake.gameObject'; + const gameObjects = [ npcsInArcadeMap, // Add more game objects here jessie, + //snake --snake gameobj ]; export default gameObjects; diff --git a/src/gameObjects/map_arcade/snake.gameObject.js b/src/gameObjects/map_arcade/snake.gameObject.js new file mode 100644 index 00000000..db514237 --- /dev/null +++ b/src/gameObjects/map_arcade/snake.gameObject.js @@ -0,0 +1,28 @@ +/* +import { scaleFactor } from '../../constants'; +///still cannot "spawn" my game object +export const snake = (k, map, spawnpoints) => { + k.loadSprite('snake', './assets/sprites/snakeArcade.png', { + sliceX: 10, + sliceY: 20, + }); + /*k.onDraw(() => { + k.drawSprite({ + sprite: k.loadSprite('snakeArcade', './assets/sprites/snakeArcade.png'), //Sorry, dart-style :->D + pos: k.vec2(100, 200), + }); +}); + + return k.make([ + k.sprite('snakeArcade'), + k.area({ + shape: new k.Rect(k.vec2(0), 117, 159), + }), + k.body({ isStatic: true }), + k.anchor('center'), + k.pos(map.pos.x + spawnpoints.player.x, map.pos.y + spawnpoints.player.y), + k.scale(scaleFactor + 0.5), + 'snake', + ]); +}; +*/ \ No newline at end of file diff --git a/src/interactions/map_arcade/game_machine_14.interactions.js b/src/interactions/map_arcade/game_machine_14.interactions.js new file mode 100644 index 00000000..83f7f045 --- /dev/null +++ b/src/interactions/map_arcade/game_machine_14.interactions.js @@ -0,0 +1,231 @@ +// 2025 Hacktoberfest PR by Burin-Zhargal Papaev +// New arcade game: Snake. +//Never able to invoke because struggle to add the new sprite gameobject properly. +/*import { displayDialogue } from '../../utils'; + +export const interactionWithGameMachine14 = (player, k, map) => { + k.onCollide('player', 'snake', () => { + showCustomPrompt( + 'Do you want to play Snake Videogame?', + ['Yes', 'No'], + (selectedOption) => { + if (selectedOption === 'Yes') { + displayDialogue({ + k, + player, + text: ['Starting Snake VideoGame... Good luck!'], + onDisplayEnd: () => { + startSnakeScene(k); + k.go('snake'); + }, + }); + } else { + displayDialogue({ + k, + player, + text: ['Maybe next time!'], + }); + } + } + ); + }); +}; + +function showCustomPrompt(message, options, callback) { + document.getElementById('prompt-message').textContent = message; + + const optionsContainer = document.getElementById('options-container'); + optionsContainer.innerHTML = ''; + + options.forEach((option) => { + const button = document.createElement('button'); + button.textContent = option; + button.classList.add('option-btn'); + button.setAttribute('tabindex', '0'); // Make the button focusable + + + button.onclick = function () { + callback(option); + closeCustomPrompt(); + }; + + + button.addEventListener('keydown', function (e) { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); // Prevent the default behavior + callback(option); + closeCustomPrompt(); + } + }); + + optionsContainer.appendChild(button); + }); + + + document.getElementById('custom-prompt').style.display = 'flex'; + + // Set focus on the first button + if (optionsContainer.children.length > 0) { + optionsContainer.children[0].focus(); + } +} + + +function closeCustomPrompt() { + // Hide the custom prompt + document.getElementById('custom-prompt').style.display = 'none'; +} + +export function startSnakeScene(k) { + const { add, rect, color, pos, area, anchor, outline, text, onKeyPress, loop, wait, rand, width, height, go } = k; + + k.scene('snake', () => { + // Config + const CELL = 16; + const GRID_W = Math.floor(width() / CELL); + const GRID_H = Math.floor(height() / CELL); + const SPEED = 0.12; // seconds per step + + // State + let dir = k.vec2(1, 0); + let nextDir = dir.clone(); + let snake = [k.vec2(Math.floor(GRID_W / 2), Math.floor(GRID_H / 2))]; + let grow = 0; + let score = 0; + let alive = true; + + // UI + const ui = add([ + text(`Score: 0`), + pos(8, 8), + anchor('topleft'), + color(255, 255, 255), + outline(2, k.rgb(0, 0, 0)), + { updateScore: (s) => (ui.text = `Score: ${s}`) }, + ]); + + // Helpers + const toPx = (v) => pos(v.x * CELL + CELL / 2, v.y * CELL + CELL / 2); + + // Renderers + function drawSnake() { + // Clear existing snake parts + for (const n of get('snake-part')) n.destroy(); + + // Redraw + snake.forEach((cell, i) => { + add([ + rect(CELL - 2, CELL - 2), + toPx(cell), + anchor('center'), + color(i === 0 ? k.rgb(0, 200, 0) : k.rgb(0, 150, 0)), + outline(2, k.rgb(0, 0, 0)), + 'snake-part', + ]); + }); + } + + // Food + let foodPos = null; + let foodObj = null; + function placeFood() { + // choose empty cell + while (true) { + const fx = Math.floor(rand(1, GRID_W - 1)); + const fy = Math.floor(rand(1, GRID_H - 1)); + const conflict = snake.some((s) => s.x === fx && s.y === fy); + if (!conflict) { + foodPos = k.vec2(fx, fy); + if (foodObj) foodObj.destroy(); + foodObj = add([ + rect(CELL - 2, CELL - 2), + toPx(foodPos), + anchor('center'), + color(220, 60, 60), + outline(2, k.rgb(0, 0, 0)), + 'food', + ]); + break; + } + } + } + + function gameOver() { + alive = false; + add([ + text(`Game Over\nScore: ${score}\n\nPress Enter to return`), + pos(width() / 2, height() / 2), + anchor('center'), + color(255, 255, 255), + outline(2, k.rgb(0, 0, 0)), + ]); + + const returnTo = 'game'; + k.onKeyPress('enter', () => go(returnTo)); + // Also auto-return after 3 seconds + wait(3, () => go(returnTo)); + } + + // Input + const dirs = { + left: k.vec2(-1, 0), + right: k.vec2(1, 0), + up: k.vec2(0, -1), + down: k.vec2(0, 1), + }; + for (const key in dirs) { + onKeyPress(key, () => { + const d = dirs[key]; + // Prevent 180° reverse + if (snake.length > 1 && d.x === -dir.x && d.y === -dir.y) return; + nextDir = d.clone(); + }); + } + + // Init + drawSnake(); + placeFood(); + + // Step loop + loop(SPEED, () => { + if (!alive) return; + + // advance direction chosen since last step + dir = nextDir.clone(); + + // compute new head + const head = snake[0]; + const newHead = k.vec2(head.x + dir.x, head.y + dir.y); + + // wall collision + if (newHead.x < 0 || newHead.y < 0 || newHead.x >= GRID_W || newHead.y >= GRID_H) { + gameOver(); + return; + } + + // self collision + if (snake.some((s, i) => i !== 0 && s.x === newHead.x && s.y === newHead.y)) { + gameOver(); + return; + } + + // move + snake.unshift(newHead); + if (grow > 0) { + grow--; + } else { + snake.pop(); + } + + // eat + if (foodPos && newHead.x === foodPos.x && newHead.y === foodPos.y) { + score += 1; + ui.updateScore(score); + grow += 1; + placeFood(); + } + + drawSnake(); + }); + }); +}*/ diff --git a/src/interactions/map_arcade/index.js b/src/interactions/map_arcade/index.js index 522fede3..d45ef207 100644 --- a/src/interactions/map_arcade/index.js +++ b/src/interactions/map_arcade/index.js @@ -16,6 +16,7 @@ import { interactionWithGameMachine9 } from './game_machine_9.interactions'; import { interactionWithGameMachine5 } from './game_machine_5.interactions'; import { interactionWithGameMachine7 } from './game_machine_7.interaction'; import { interactionWithGameMachine13 } from './game_machine_13.interactions'; +//import { interactionWithGameMachine14 } from './game_machine_14.interactions'; const interactions = [ enterMapCityInteraction, @@ -42,6 +43,7 @@ const interactions = [ interactionWithGameMachineCrawl, interactionWithGameMachine5, interactionWithGameMachine13, + //interactionWithGameMachine14, ]; export default interactions;