User prompt
create a restart from level 1 button
User prompt
the maze is bit going out of screen on the left
User prompt
let's make a hidden bonus score, that will start from 1000 and decrease with time, and the bonus will be added at the end of level, depends how fast is the player
User prompt
ok delete the level 3 and lets do only two level the winning will be at the end of level 2
User prompt
put it front of the door for block the path in level 3 , that wall will be destructible
User prompt
use the wall2 asset and put it somewher before the exit to block the path on level 3
User prompt
use the wall2 asset and put it somewher before the exit to block the path
User prompt
still out,
User prompt
the text of the starting screen going out of the screen
User prompt
also need to explain on startitng screen under level 1 level 2 find all the fire for allow Ari to get out
User prompt
also need to explain on startitng level 2 find all the fire for allow Ari to get out
User prompt
on level 2 need to collect all the fire of the level for can finish the level
User prompt
add the lever on the map of the level 2 and 3
User prompt
on level 3 need to collect all the fire of the level for can finish the level
User prompt
the door cannot be opened and level finished at level 2 and three without actionnate the button
User prompt
on the level 2 the door is locked let's add a lever for open it
User prompt
the maze should be bigger
User prompt
the wall have to be compact and have no space where the player can stuck
User prompt
the labyrinth should take more free space on the gamer screen and be bigger it's only using a little part of the screen
User prompt
the restart button after level 3 restart to level 1
User prompt
lets make only three level, the player will wiin at level 3
User prompt
level 2, we will add a button the door is locked need to press it for open door and can exit
User prompt
it's instruvtion so before starting the level pls
User prompt
add a message, level 1 : Help Ari to find the exit
User prompt
finish a level add +100 to the score
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var Button = Container.expand(function () { var self = Container.call(this); var buttonGraphic = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); self.onPress = null; self.update = function () { // Pulsating effect var pulseValue = Math.sin(LK.ticks / 15) * 0.1 + 0.9; buttonGraphic.scale.set(pulseValue, pulseValue); }; self.down = function (x, y, obj) { if (self.onPress) { self.onPress(); } }; return self; }); var DestructibleWall = Container.expand(function () { var self = Container.call(this); var wallGraphic = self.attachAsset('wall2', { anchorX: 0.5, anchorY: 0.5 }); self.visible = true; self.health = 3; // Set health for destructible wall self.update = function () { // Pulsating effect to indicate destructible nature var pulseValue = Math.sin(LK.ticks / 15) * 0.1 + 0.9; wallGraphic.scale.set(pulseValue, pulseValue); }; self.takeDamage = function () { self.health -= 1; if (self.health <= 0) { self.destroy(); } }; return self; }); var Exit = Container.expand(function () { var self = Container.call(this); var exitGraphic = self.attachAsset('exit', { anchorX: 0.5, anchorY: 0.5 }); self.visible = false; self.update = function () { // Pulsating effect var pulseValue = Math.sin(LK.ticks / 15) * 0.1 + 0.9; exitGraphic.scale.set(pulseValue, pulseValue); }; return self; }); var Fire = Container.expand(function () { var self = Container.call(this); var fireGraphic = self.attachAsset('fire', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Pulsating effect var pulseValue = Math.sin(LK.ticks / 20) * 0.2 + 0.8; fireGraphic.scale.set(pulseValue, pulseValue); }; return self; }); var Lever = Container.expand(function () { var self = Container.call(this); var leverGraphic = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); self.onActivate = null; self.update = function () { // Pulsating effect var pulseValue = Math.sin(LK.ticks / 15) * 0.1 + 0.9; leverGraphic.scale.set(pulseValue, pulseValue); }; self.down = function (x, y, obj) { if (self.onActivate) { self.onActivate(); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphic = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); var lightAura = self.attachAsset('light', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); // Initialize light level (100% to start) self.lightLevel = 100; self.maxLightLevel = 100; self.lightDrainRate = 0.000000001; // Update player position and light self.update = function () { // Update light radius based on light level var lightScale = self.lightLevel / self.maxLightLevel * 1.0; lightAura.scale.set(lightScale, lightScale); }; // Method to restore light self.restoreLight = function (amount) { self.lightLevel += amount; if (self.lightLevel > self.maxLightLevel) { self.lightLevel = self.maxLightLevel; } // Visual feedback for light restoration tween(lightAura, { alpha: 0.6 }, { duration: 300, onFinish: function onFinish() { tween(lightAura, { alpha: 0.3 }, { duration: 300 }); } }); }; return self; }); var RestartButton = Container.expand(function () { var self = Container.call(this); var buttonGraphic = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); self.onPress = function () { level = 1; // Reset to level 1 storage.level = level; // Update storage to reflect the reset level initializeLevel(); // Re-initialize the level }; self.update = function () { // Pulsating effect var pulseValue = Math.sin(LK.ticks / 15) * 0.1 + 0.9; buttonGraphic.scale.set(pulseValue, pulseValue); }; self.down = function (x, y, obj) { if (self.onPress) { self.onPress(); } }; return self; }); var Trap = Container.expand(function () { var self = Container.call(this); var trapGraphic = self.attachAsset('trap', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.visible = false; self.active = true; self.update = function () { // Simple pulsating effect when visible if (self.visible) { var pulseValue = Math.sin(LK.ticks / 10) * 0.1 + 0.9; trapGraphic.scale.set(pulseValue, pulseValue); } }; self.triggerTrap = function () { if (!self.active) { return; } self.active = false; // Visual feedback tween(trapGraphic, { alpha: 1 }, { duration: 200, onFinish: function onFinish() { tween(trapGraphic, { alpha: 0.3 }, { duration: 1000, onFinish: function onFinish() { self.active = true; trapGraphic.alpha = 0.7; } }); } }); }; return self; }); var Wall = Container.expand(function () { var self = Container.call(this); var wallGraphic = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); self.visible = false; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Decrease bonus score over time bonusScore -= bonusScoreDecreaseRate / 60; // Assuming 60 FPS, decrease score every frame if (bonusScore < 0) { bonusScore = 0; } // Ensure bonus score doesn't go negative // Update player and elements var scoreText; // Define scoreText in the global scope var level = storage.level || 1; var mazeWidth = 20; var mazeHeight = 15; var cellSize = 120; var lightDrainBase = 0.1; var lightDrainIncrease = 0.025; var mazeCenterX = 2048 / 2; var mazeCenterY = 2732 / 2; var mazeOffsetX = mazeCenterX - mazeWidth * cellSize / 2 + cellSize / 2; var mazeOffsetY = mazeCenterY - mazeHeight * cellSize / 2; var mazeVisible = false; // Game elements var player; var walls = []; var lightOrbs = []; var traps = []; var exit; var maze = []; var visitedCells = {}; // UI Elements var lightMeter; var levelText; var gameStarted = false; var bonusScore = 1000; // Initialize hidden bonus score var bonusScoreDecreaseRate = 1; // Rate at which the bonus score decreases per second var calibrationText; // Initialize maze grid function initializeMaze() { maze = []; visitedCells = {}; // Create a grid filled with walls for (var y = 0; y < mazeHeight; y++) { maze[y] = []; for (var x = 0; x < mazeWidth; x++) { maze[y][x] = 1; // 1 represents a wall } } // Generate maze using recursive backtracking generateMaze(1, 1); // Ensure the exit is always reachable by placing it at the end of a generated path var exitPlaced = false; while (!exitPlaced) { var exitX = Math.floor(Math.random() * (mazeWidth - 2)) + 1; var exitY = Math.floor(Math.random() * (mazeHeight - 2)) + 1; if (maze[exitY][exitX] === 0) { maze[exitY][exitX] = 2; // 2 represents exit exitPlaced = true; } } // Place light orbs (about 5% of open cells) var totalCells = Math.floor(mazeWidth * mazeHeight / 2); var orbCount = Math.max(3, Math.floor(totalCells * 0.05) + level - 1); for (var i = 0; i < orbCount; i++) { var orbPlaced = false; while (!orbPlaced) { var randomX = Math.floor(Math.random() * (mazeWidth - 2)) + 1; var randomY = Math.floor(Math.random() * (mazeHeight - 2)) + 1; // Ensure we're not placing on walls, exit, or starting position if (maze[randomY][randomX] === 0 && !(randomX === 1 && randomY === 1)) { maze[randomY][randomX] = 3; // 3 represents light orb orbPlaced = true; } } } } // Recursive backtracking maze generation function generateMaze(x, y) { maze[y][x] = 0; // 0 represents an open path // Randomize direction order var directions = [[0, -2], // Up [2, 0], // Right [0, 2], // Down [-2, 0] // Left ]; shuffleArray(directions); // Try each direction for (var i = 0; i < directions.length; i++) { var dx = directions[i][0]; var dy = directions[i][1]; var nx = x + dx; var ny = y + dy; // Check if the new position is valid if (nx > 0 && nx < mazeWidth - 1 && ny > 0 && ny < mazeHeight - 1 && maze[ny][nx] === 1) { // Carve path by setting the cell between current and new cell to 0 maze[y + dy / 2][x + dx / 2] = 0; generateMaze(nx, ny); } } } // Helper function to shuffle array function shuffleArray(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } return array; } // Create maze game objects function createMazeObjects() { // Clear previous objects for (var i = walls.length - 1; i >= 0; i--) { walls[i].destroy(); } walls = []; for (var i = lightOrbs.length - 1; i >= 0; i--) { lightOrbs[i].destroy(); } lightOrbs = []; if (exit) { exit.destroy(); exit = null; } // Create new maze objects for (var y = 0; y < mazeHeight; y++) { for (var x = 0; x < mazeWidth; x++) { var cellX = mazeOffsetX + x * cellSize + cellSize / 2; var cellY = mazeOffsetY + y * cellSize + cellSize / 2; if (maze[y][x] === 1) { // Wall var wall = new Wall(); wall.x = cellX; wall.y = cellY; game.addChild(wall); walls.push(wall); } else if (maze[y][x] === 2) { // Exit exit = new Exit(); exit.x = cellX; exit.y = cellY; game.addChild(exit); if (level === 2) { exit.visible = false; // Initially hide the exit in level 2 } } else if (maze[y][x] === 3) { // Light Orb var orb = new Fire(); orb.x = cellX; orb.y = cellY; game.addChild(orb); lightOrbs.push(orb); } else if (maze[y][x] === 4) { // Trap var trap = new Trap(); trap.x = cellX; trap.y = cellY; game.addChild(trap); traps.push(trap); } else if (maze[y][x] === 5 && (level === 2 || level === 3)) { var lever = new Lever(); lever.x = cellX; lever.y = cellY; game.addChild(lever); lever.onActivate = function () { exit.visible = true; // Unlock the exit when the lever is activated }; } } } // Create or position player at start if (!player) { player = new Player(); game.addChild(player); } player.x = mazeOffsetX + 1 * cellSize + cellSize / 2; player.y = mazeOffsetY + 1 * cellSize + cellSize / 2; player.lightLevel = player.maxLightLevel; } // Set up UI elements function setupUI() { // Removed light meter display from the UI // Level indicator (top center) levelText = new Text2('Level ' + level + ': Help Ari to find the exit', { size: 80, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); // Score display (top-right corner) scoreText = new Text2('Score: ' + LK.getScore(), { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); // Calibration/start text (center) calibrationText = new Text2('Level 1: Help Ari to find the exit\nLevel 2: Find all the fire to allow Ari to get out\nLook at screen to calibrate\nthen open mouth to start', { size: 60, // Adjusted size to fit within the screen fill: 0xFFFFFF }); calibrationText.anchor.set(0.5, 0.5); LK.gui.center.addChild(calibrationText); // Restart button (bottom-right corner) var restartButton = new RestartButton(); restartButton.x = 2048 - 100; // Position at bottom-right corner restartButton.y = 2732 - 100; LK.gui.bottomRight.addChild(restartButton); } // Update light visibility based on player position function updateVisibility() { // Calculate the visibility radius based on player's light level var visibilityRadius = player.lightLevel / player.maxLightLevel * 4 * cellSize; // Update walls visibility for (var i = 0; i < walls.length; i++) { var wall = walls[i]; var dx = wall.x - player.x; var dy = wall.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); // Show walls within the light radius wall.visible = distance <= visibilityRadius; } // Update light orbs visibility for (var i = 0; i < lightOrbs.length; i++) { var orb = lightOrbs[i]; var dx = orb.x - player.x; var dy = orb.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); // Light orbs are visible from further away (they emit light) orb.visible = distance <= visibilityRadius * 1.2; } // Update exit visibility if (exit) { var dx = exit.x - player.x; var dy = exit.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); exit.visible = distance <= visibilityRadius; } // Track visited cells for minimap effect (simple fog of war) var cellX = Math.floor((player.x - mazeOffsetX) / cellSize); var cellY = Math.floor((player.y - mazeOffsetY) / cellSize); var key = cellX + "," + cellY; visitedCells[key] = true; } // Check for collision with maze walls function checkWallCollision(newX, newY) { var playerRadius = 30; // Half the player's width for (var i = 0; i < walls.length; i++) { var wall = walls[i]; var wallHalfWidth = wall.width / 2; // Simple circle-rectangle collision var closestX = Math.max(wall.x - wallHalfWidth, Math.min(newX, wall.x + wallHalfWidth)); var closestY = Math.max(wall.y - wallHalfWidth, Math.min(newY, wall.y + wallHalfWidth)); var dx = newX - closestX; var dy = newY - closestY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerRadius) { return true; // Collision detected } } return false; // No collision } // Check for collision with game objects function checkObjectCollisions() { var playerRadius = 30; // Half the player's width // Check fire collectibles for (var i = lightOrbs.length - 1; i >= 0; i--) { var fire = lightOrbs[i]; var dx = player.x - fire.x; var dy = player.y - fire.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerRadius + 20) { // Collect fire LK.setScore(LK.getScore() + 10); // Increase score by 10 LK.getSound('pickupSound').play(); fire.destroy(); lightOrbs.splice(i, 1); // Update score display scoreText.setText('Score: ' + LK.getScore()); } } // Check exit if (exit) { var dx = player.x - exit.x; var dy = player.y - exit.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerRadius + 40) { // Check if exit is visible (unlocked) before allowing level completion if (exit.visible && level === 2 && lightOrbs.length === 0) { // Reach exit // Level completed LK.getSound('exitSound').play(); LK.setScore(LK.getScore() + 100 + Math.floor(bonusScore)); // Increase score by 100 plus remaining bonus score when level is completed scoreText.setText('Score: ' + LK.getScore()); // Update score display LK.showYouWin(); level = 1; // Reset to level 1 after winning storage.level = level; // Update storage to reflect the reset level } } } } // Initialize a level function initializeLevel() { initializeMaze(); createMazeObjects(); updateVisibility(); // Update UI levelText.setText('Level ' + level + (level === 2 ? ' (Final Level)' : '')); } // Start game function startGame() { gameStarted = true; calibrationText.visible = false; initializeLevel(); // Play background music LK.playMusic('bgMusic'); } // Set up the game setupUI(); // Game update loop game.update = function () { // When not started yet, wait for mouth open to start if (!gameStarted) { if (facekit.mouthOpen) { startGame(); } return; } // Update player and elements player.update(); // Update light orbs for (var i = 0; i < lightOrbs.length; i++) { lightOrbs[i].update(); } // Update exit if (exit) { exit.update(); } // Removed light percentage update from the game update loop // Player movement using face tracking if (facekit.noseTip) { // Calculate movement based on face position relative to center var centerX = 2048 / 2; var centerY = 2732 / 2; var deltaX = (facekit.noseTip.x - centerX) * 0.05; var deltaY = (facekit.noseTip.y - centerY) * 0.05; // Calculate new position var newX = player.x + deltaX; var newY = player.y + deltaY; // Check if new position is valid (not colliding with walls) if (!checkWallCollision(newX, player.y)) { player.x = newX; } if (!checkWallCollision(player.x, newY)) { player.y = newY; } } // Update visibility based on player position updateVisibility(); // Check for collisions with game objects checkObjectCollisions(); };
===================================================================
--- original.js
+++ change.js
@@ -136,8 +136,31 @@
});
};
return self;
});
+var RestartButton = Container.expand(function () {
+ var self = Container.call(this);
+ var buttonGraphic = self.attachAsset('button', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.onPress = function () {
+ level = 1; // Reset to level 1
+ storage.level = level; // Update storage to reflect the reset level
+ initializeLevel(); // Re-initialize the level
+ };
+ self.update = function () {
+ // Pulsating effect
+ var pulseValue = Math.sin(LK.ticks / 15) * 0.1 + 0.9;
+ buttonGraphic.scale.set(pulseValue, pulseValue);
+ };
+ self.down = function (x, y, obj) {
+ if (self.onPress) {
+ self.onPress();
+ }
+ };
+ return self;
+});
var Trap = Container.expand(function () {
var self = Container.call(this);
var trapGraphic = self.attachAsset('trap', {
anchorX: 0.5,
@@ -401,8 +424,13 @@
fill: 0xFFFFFF
});
calibrationText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(calibrationText);
+ // Restart button (bottom-right corner)
+ var restartButton = new RestartButton();
+ restartButton.x = 2048 - 100; // Position at bottom-right corner
+ restartButton.y = 2732 - 100;
+ LK.gui.bottomRight.addChild(restartButton);
}
// Update light visibility based on player position
function updateVisibility() {
// Calculate the visibility radius based on player's light level
Si tu souhaites créer un personnage tenant une torche pour ton jeu, voici quelques conseils pour le design : Design du personnage : Proportions simples : Garde le design du personnage simple et épuré, avec une silhouette facilement reconnaissable. Il pourrait être petit et mignon, dans un style cartoon. Torche : La torche devrait être grande par rapport à la taille du personnage, avec une flamme vive pour ajouter du dynamisme. Assure-toi que la flamme est visible et lumineuse, avec des dégradés de jaune et orange.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Les murs du labyrinthe sont massifs, faits de pierre vieillie et recouverts de lichens et de mousses qui ajoutent une touche d'humidité et d'abandon. Leur texture est rugueuse, avec des fissures profondes qui laissent deviner l’âge et l’histoire de ce lieu oublié. Couleur : La couleur des murs varie, mais elle est dominée par des tons sombres : gris foncé, marron, et parfois des touches d'ocre là où l'humidité a pris ses marques. Ils semblent presque absorbers la lumière de la torche du personnage, rendant l'atmosphère encore plus oppressante. De temps à autre, des éclats métalliques ou des traces de rouille peuvent se deviner sur les bords, suggérant des artefacts oubliés du passé. Forme et structure : Les murs ne sont pas droits. Ils sont souvent irréguliers, déformés, avec des angles aigus ou des corners inattendus qui surprennent le joueur et compliquent son déplacement. Certains murs peuvent même être en partie effondrés, créant des passages secrets ou des obstacles qu'i. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
La porte d'Exit est un portail mystérieux et imposant qui se distingue par son atmosphère énigmatique. Elle est située à la fin du labyrinthe, là où la lumière semble devenir plus intense et où le suspense atteint son apogée. Structure : La porte est massive, faite de pierres anciennes et usées par le temps, avec des gravures mystérieuses sur les côtés. Elle semble être une sorte de portail magique, ses bords ornés de runes qui brillent faiblement dans l'obscurité. Les gravures changent légèrement lorsque le joueur s'en approche, comme si elles réagissaient à la présence du héros. Couleurs et lumière : L'exit émet une lumière douce mais persistante, un halo qui contraste fortement avec l'obscurité du reste du labyrinthe. La lumière n'est pas chaude, mais plutôt froide, avec des tons de bleu pâle et d'argent. Cela donne à la porte une allure à la fois apaisante et étrange. De petites étincelles flottent autour de la porte, comme si une force invisible était à l'œuvre.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
fire cute cartoon 2d. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
lever cute cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Les murs du labyrinthe sont massifs, faits de pierre vieillie et recouverts de lichens et de mousses qui ajoutent une touche d'humidité et d'abandon. Leur texture est rugueuse, avec des fissures profondes qui laissent deviner l’âge et l’histoire de ce lieu oublié. Couleur : La couleur des murs varie, mais elle est dominée par des tons sombres : gris foncé, marron, et parfois des touches d'ocre là où l'humidité a pris ses marques. Ils semblent presque absorbers la lumière de la torche du personnage, rendant l'atmosphère encore plus oppressante. De temps à autre, des éclats métalliques ou des traces de rouille peuvent se deviner sur les bords, suggérant des artefacts oubliés du passé. celui ci sera en brique rouge Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows