/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var Dot = Container.expand(function () {
var self = Container.call(this);
var dotGraphics = self.attachAsset('dot', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
return self;
});
var Fruit = Container.expand(function () {
var self = Container.call(this);
var fruitGraphics = self.attachAsset('fruit', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 100;
// Create wobble animation
var _wobble = function wobble() {
tween(fruitGraphics, {
rotation: Math.PI / 16
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(fruitGraphics, {
rotation: -Math.PI / 16
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: _wobble
});
}
});
};
_wobble();
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.direction = null;
self.nextDirection = null;
self.move = function (direction) {
self.nextDirection = direction;
};
self.update = function () {
if (!self.direction && !self.nextDirection) {
return;
}
var nextX = self.x;
var nextY = self.y;
// Try to move in the next direction if available
if (self.nextDirection) {
if (self.nextDirection === 'up') {
nextY -= self.speed;
} else if (self.nextDirection === 'down') {
nextY += self.speed;
} else if (self.nextDirection === 'left') {
nextX -= self.speed;
} else if (self.nextDirection === 'right') {
nextX += self.speed;
}
// Check if valid move
if (!self.willCollideWithWall(nextX, nextY)) {
self.direction = self.nextDirection;
self.nextDirection = null;
} else {
// Revert to current position
nextX = self.x;
nextY = self.y;
}
}
// Continue in current direction
if (self.direction) {
if (self.direction === 'up') {
nextY -= self.speed;
} else if (self.direction === 'down') {
nextY += self.speed;
} else if (self.direction === 'left') {
nextX -= self.speed;
} else if (self.direction === 'right') {
nextX += self.speed;
}
// Check if valid move
if (!self.willCollideWithWall(nextX, nextY)) {
self.x = nextX;
self.y = nextY;
} else {
// Stop moving in this direction
self.direction = null;
}
}
};
self.willCollideWithWall = function (nextX, nextY) {
var playerHalfWidth = playerGraphics.width / 2;
var playerHalfHeight = playerGraphics.height / 2;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var wallHalfWidth = wall.getChildAt(0).width / 2;
var wallHalfHeight = wall.getChildAt(0).height / 2;
if (Math.abs(nextX - wall.x) < playerHalfWidth + wallHalfWidth && Math.abs(nextY - wall.y) < playerHalfHeight + wallHalfHeight) {
return true;
}
}
return false;
};
return self;
});
var PowerPellet = Container.expand(function () {
var self = Container.call(this);
var pelletGraphics = self.attachAsset('powerPellet', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 50;
// Create pulsing animation
var _pulse = function pulse() {
tween(pelletGraphics, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(pelletGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _pulse
});
}
});
};
_pulse();
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Define game variables
var player;
var dots = [];
var powerPellets = [];
var walls = [];
var fruits = [];
var currentLevel = storage.level || 1;
var timeLeft = 60;
var isGameActive = false;
var fruitTimer = null;
var gameWidth = 2048;
var gameHeight = 2732;
var tileSize = 60;
// Define gameTimer variable
var gameTimer = null;
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -scoreTxt.width - 20;
scoreTxt.y = 20;
var timeTxt = new Text2('Time: 60', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timeTxt);
timeTxt.y = 20;
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelTxt);
levelTxt.x = 120; // Avoid the top-left 100x100 area
levelTxt.y = 20;
var messageBox = new Container();
var messageBg = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
width: 1000,
height: 300,
tint: 0x000088
});
messageBg.alpha = 0.8;
messageBox.addChild(messageBg);
var messageTxt = new Text2('Level 1', {
size: 80,
fill: 0xFFFFFF
});
messageTxt.anchor.set(0.5, 0.5);
messageBox.addChild(messageTxt);
messageBox.visible = false;
messageBox.x = gameWidth / 2;
messageBox.y = gameHeight / 2;
game.addChild(messageBox);
// Level layouts - using a simple approach with 1 = wall, 0 = dot, 2 = power pellet, X = empty
// These are small levels for the MVP, could be expanded later
var levelLayouts = [
// Level 1 - Simple maze
["111111111111111111111", "100000000100000000001", "101111110101111110101", "101000010101000010101", "101010110101011010101", "101010110101011010101", "102010000000000010201", "101011111X11111010101", "101000001X10000010101", "101111101X10111110101", "100000100000100000001", "101111111111111111101", "100000000000000000001", "111111111111111111111"],
// Level 2 - More complex
["111111111111111111111", "100000100000100000001", "101110101110101111101", "101000100000100000101", "101011111111111010101", "101000000100000010101", "101011110101111010101", "102000010101000010201", "101111010101011111101", "101000000000000000101", "101011111X11111010101", "100010000X00001010001", "111110101X10101011111", "100000101X10101000001", "101111101X10101111101", "100000000000000000001", "111111111111111111111"],
// Level 3 - Even more complex
["111111111111111111111", "100000000100000000001", "101111110101111110101", "101000010101000010101", "101010110101011010101", "101010110101011010101", "102010000000000010201", "101010111X11101010101", "101010001X10001010101", "101011101X10111010101", "100000100000100000001", "101111111101111111101", "101000000000000000101", "101011111111111110101", "102010000000000010201", "101110101110101011101", "101000100000100010001", "101010111111101010101", "100010000000000010001", "111111111111111111111"]];
// Initialize the game level
function initLevel(level) {
// Clear the game board
clearLevel();
// Reset time and update UI
timeLeft = 60;
currentLevel = level;
isGameActive = true;
// Set level text
levelTxt.setText('Level: ' + level);
timeTxt.setText('Time: ' + timeLeft);
// Get the current level layout
var layout = levelLayouts[level - 1] || levelLayouts[0];
// Calculate starting position to center the maze
var mazeWidth = layout[0].length * tileSize;
var mazeHeight = layout.length * tileSize;
var startX = (gameWidth - mazeWidth) / 2 + tileSize / 2;
var startY = (gameHeight - mazeHeight) / 2 + tileSize / 2;
// Create the maze based on the layout
for (var y = 0; y < layout.length; y++) {
for (var x = 0; x < layout[y].length; x++) {
var posX = startX + x * tileSize;
var posY = startY + y * tileSize;
if (layout[y][x] === '1') {
// Wall
var wall = new Wall();
wall.x = posX;
wall.y = posY;
walls.push(wall);
game.addChild(wall);
} else if (layout[y][x] === '0') {
// Dot
var dot = new Dot();
dot.x = posX;
dot.y = posY;
dots.push(dot);
game.addChild(dot);
} else if (layout[y][x] === '2') {
// Power Pellet
var powerPellet = new PowerPellet();
powerPellet.x = posX;
powerPellet.y = posY;
powerPellets.push(powerPellet);
game.addChild(powerPellet);
}
// If it's the first empty space we find, place the player there
if (!player && (layout[y][x] === '0' || layout[y][x] === 'X')) {
player = new Player();
player.x = posX;
player.y = posY;
game.addChild(player);
}
}
}
// Show level message
showMessage('Level ' + level + '\nGet Ready!');
// Set up fruit spawn timer
fruitTimer = LK.setInterval(spawnFruit, 15000); // Spawn fruit every 15 seconds
// Start the game timer
gameTimer = LK.setInterval(updateTimer, 1000);
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.5,
duration: 1000
}
});
}
// Clear the current level
function clearLevel() {
// Clear all game timers
if (fruitTimer) {
LK.clearInterval(fruitTimer);
fruitTimer = null;
}
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Remove all game objects
if (player) {
player.destroy();
player = null;
}
for (var i = 0; i < dots.length; i++) {
dots[i].destroy();
}
dots = [];
for (var i = 0; i < powerPellets.length; i++) {
powerPellets[i].destroy();
}
powerPellets = [];
for (var i = 0; i < walls.length; i++) {
walls[i].destroy();
}
walls = [];
for (var i = 0; i < fruits.length; i++) {
fruits[i].destroy();
}
fruits = [];
}
// Update the game timer
function updateTimer() {
if (!isGameActive) {
return;
}
timeLeft--;
timeTxt.setText('Time: ' + timeLeft);
if (timeLeft <= 0) {
// Time's up!
endGame();
}
}
// Spawn a fruit at a random empty location
function spawnFruit() {
if (!isGameActive || fruits.length >= 3) {
return;
}
// Find all empty spots
var emptySpots = [];
var layout = levelLayouts[currentLevel - 1] || levelLayouts[0];
var mazeWidth = layout[0].length * tileSize;
var mazeHeight = layout.length * tileSize;
var startX = (gameWidth - mazeWidth) / 2 + tileSize / 2;
var startY = (gameHeight - mazeHeight) / 2 + tileSize / 2;
for (var y = 0; y < layout.length; y++) {
for (var x = 0; x < layout[y].length; x++) {
if (layout[y][x] === 'X') {
emptySpots.push({
x: startX + x * tileSize,
y: startY + y * tileSize
});
}
}
}
if (emptySpots.length > 0) {
var spot = emptySpots[Math.floor(Math.random() * emptySpots.length)];
var fruit = new Fruit();
fruit.x = spot.x;
fruit.y = spot.y;
fruits.push(fruit);
game.addChild(fruit);
}
}
// Show a message on screen
function showMessage(text) {
messageTxt.setText(text);
messageBox.visible = true;
// Hide the message after 2 seconds
LK.setTimeout(function () {
messageBox.visible = false;
}, 2000);
}
// End the current game
function endGame() {
isGameActive = false;
// Update high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Show game over
LK.showGameOver();
}
// Complete the current level
function completeLevel() {
isGameActive = false;
// Clear timers
if (fruitTimer) {
LK.clearInterval(fruitTimer);
fruitTimer = null;
}
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
// Calculate bonus points for remaining time
var timeBonus = timeLeft * 10;
LK.setScore(LK.getScore() + timeBonus);
scoreTxt.setText('Score: ' + LK.getScore());
// Show level complete message
showMessage('Level Complete!\nTime Bonus: ' + timeBonus);
// Play level complete sound
LK.getSound('levelComplete').play();
// Proceed to next level after a delay
LK.setTimeout(function () {
currentLevel++;
storage.level = currentLevel;
// Check if there are more levels
if (currentLevel <= levelLayouts.length) {
initLevel(currentLevel);
} else {
// Player beat all levels
showMessage('Congratulations!\nYou beat all levels!');
LK.setTimeout(function () {
LK.showYouWin();
}, 2000);
}
}, 3000);
}
// Handle touch input for movement
game.down = function (x, y) {
if (!player || !isGameActive) {
return;
}
// Calculate direction based on touch position relative to player
var dx = x - player.x;
var dy = y - player.y;
if (Math.abs(dx) > Math.abs(dy)) {
// Horizontal movement
if (dx > 0) {
player.move('right');
} else {
player.move('left');
}
} else {
// Vertical movement
if (dy > 0) {
player.move('down');
} else {
player.move('up');
}
}
};
// Main game update loop
game.update = function () {
if (!isGameActive) {
return;
}
// Update player
if (player) {
player.update();
// Check for dot collection
for (var i = dots.length - 1; i >= 0; i--) {
if (player.intersects(dots[i])) {
// Collect dot
LK.setScore(LK.getScore() + dots[i].value);
scoreTxt.setText('Score: ' + LK.getScore());
// Play sound
LK.getSound('eat').play();
// Remove dot
dots[i].destroy();
dots.splice(i, 1);
}
}
// Check for power pellet collection
for (var i = powerPellets.length - 1; i >= 0; i--) {
if (player.intersects(powerPellets[i])) {
// Collect power pellet
LK.setScore(LK.getScore() + powerPellets[i].value);
scoreTxt.setText('Score: ' + LK.getScore());
// Play sound
LK.getSound('powerUp').play();
// Add time bonus
timeLeft += 10;
timeTxt.setText('Time: ' + timeLeft);
// Flash effect to indicate power-up
LK.effects.flashScreen(0x00FFFF, 500);
// Remove power pellet
powerPellets[i].destroy();
powerPellets.splice(i, 1);
}
}
// Check if level is complete
if (dots.length === 0 && powerPellets.length === 0) {
completeLevel();
return;
}
// Check for fruit collection
for (var i = fruits.length - 1; i >= 0; i--) {
if (player.intersects(fruits[i])) {
// Collect fruit
LK.setScore(LK.getScore() + fruits[i].value);
scoreTxt.setText('Score: ' + LK.getScore());
// Play sound
LK.getSound('fruitCollect').play();
// Remove fruit
fruits[i].destroy();
fruits.splice(i, 1);
break; // Exit loop after collecting a fruit
}
}
}
};
// Initialize the first level
initLevel(currentLevel); ===================================================================
--- original.js
+++ change.js
@@ -107,11 +107,15 @@
}
}
};
self.willCollideWithWall = function (nextX, nextY) {
+ var playerHalfWidth = playerGraphics.width / 2;
+ var playerHalfHeight = playerGraphics.height / 2;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
- if (Math.abs(nextX - wall.x) < playerGraphics.width / 2 + wall.getChildAt(0).width / 2 && Math.abs(nextY - wall.y) < playerGraphics.height / 2 + wall.getChildAt(0).height / 2) {
+ var wallHalfWidth = wall.getChildAt(0).width / 2;
+ var wallHalfHeight = wall.getChildAt(0).height / 2;
+ if (Math.abs(nextX - wall.x) < playerHalfWidth + wallHalfWidth && Math.abs(nextY - wall.y) < playerHalfHeight + wallHalfHeight) {
return true;
}
}
return false;
@@ -476,13 +480,8 @@
LK.getSound('eat').play();
// Remove dot
dots[i].destroy();
dots.splice(i, 1);
- // Check if level is complete
- if (dots.length === 0 && powerPellets.length === 0) {
- completeLevel();
- return;
- }
}
}
// Check for power pellet collection
for (var i = powerPellets.length - 1; i >= 0; i--) {
@@ -499,15 +498,15 @@
LK.effects.flashScreen(0x00FFFF, 500);
// Remove power pellet
powerPellets[i].destroy();
powerPellets.splice(i, 1);
- // Check if level is complete
- if (dots.length === 0 && powerPellets.length === 0) {
- completeLevel();
- return;
- }
}
}
+ // Check if level is complete
+ if (dots.length === 0 && powerPellets.length === 0) {
+ completeLevel();
+ return;
+ }
// Check for fruit collection
for (var i = fruits.length - 1; i >= 0; i--) {
if (player.intersects(fruits[i])) {
// Collect fruit
@@ -517,8 +516,9 @@
LK.getSound('fruitCollect').play();
// Remove fruit
fruits[i].destroy();
fruits.splice(i, 1);
+ break; // Exit loop after collecting a fruit
}
}
}
};