User prompt
Diver, return to where I shot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The diver was born where I shot, let him return ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Let the fish I shoot die
User prompt
let the background be blue
User prompt
When a monster or enemy hits a player, it takes 1 life and the player has 3 lives.
User prompt
can you make the background in the sea
User prompt
little monsters follow me ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bullets should be removed from the screen
User prompt
Let the monster escape from me, let the monsters wander all over the screen. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Shoot the monster, let it grow bigger as you shoot, and let the monster explode at the end of the level, and let there be creatures walking around the screen. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'ReferenceError: pacman is not defined' in or related to this line: 'enemy.targetX = pacman.x;' Line Number: 111
User prompt
Let the Octopus monster move and have monsters come out of its arms. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: e._webGL is undefined' in or related to this line: 'self.y = newY;' Line Number: 62
User prompt
Please fix the bug: 'TypeError: e._webGL is undefined' in or related to this line: 'self.y = newY;' Line Number: 60
User prompt
Please fix the bug: 'TypeError: e._webGL is undefined' in or related to this line: 'pacman.y = y;' Line Number: 232
User prompt
Please fix the bug: 'TypeError: e._webGL is undefined' in or related to this line: 'self.y = newY;' Line Number: 50
User prompt
When the line is completed, only the completed area will be visible ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
let it be level 2
User prompt
let the line be a straight line
User prompt
When Pacman leaves the line behind and completes the line, the background image will be visible as long as it is completed, there will be a monster wandering around, when the level is completed, the background image will wait for 10 seconds as a reward, there will be 10 levels. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When Pacman leaves a line behind and completes the line, the background image will appear, there will be an octopus monster walking around, when the level is completed, the background image will wait for 10 seconds as a reward, and there will be 10 levels. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Pacman Arena: Monster Escape
Initial prompt
Can you make a 2D game where the main character Pacman, a monster in the middle, creatures coming out from around her, moves around the background with the arrow keys and shows the entire background image after completing the level of the game?
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('collectible', {
anchorX: 0.5,
anchorY: 0.5
});
// Random bubble size
var size = 0.3 + Math.random() * 0.7;
bubbleGraphics.scaleX = size;
bubbleGraphics.scaleY = size;
// Random bubble speed
self.speed = 1 + Math.random() * 2;
// Side drift
self.drift = (Math.random() - 0.5) * 0.5;
self.update = function () {
// Move upward
self.y -= self.speed;
// Add slight horizontal drift
self.x += self.drift;
// Remove if off screen
if (self.y < -50) {
var bubbleIndex = bubbles.indexOf(self);
if (bubbleIndex !== -1) {
bubbles.splice(bubbleIndex, 1);
}
self.destroy();
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.targetX = 0;
self.targetY = 0;
self.lastIntersecting = false;
self.returningToSpawn = false;
self.update = function () {
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// When reached target, destroy bullet instead of returning
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
}
// Check intersection with central monster
var currentIntersecting = self.intersects(centralMonster);
if (!self.lastIntersecting && currentIntersecting) {
// Hit the monster
monsterHits++;
centralMonster.grow();
// Award 100 points for each hit on the monster
playerScore += 100;
scoreText.setText('Score: ' + playerScore);
// Play monster hit sound
LK.getSound('monsterhit').play();
// Check if monster should explode after 10 hits
if (monsterHits >= hitsToWin) {
centralMonster.explode();
}
// Remove from bullets array
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
}
self.lastIntersecting = currentIntersecting;
// Check intersection with enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (self.intersects(enemy)) {
// Hit an enemy - destroy both bullet and enemy
// Award 50 points for killing fish
playerScore += 50;
scoreText.setText('Score: ' + playerScore);
// Play monster hit sound
LK.getSound('monsterhit').play();
enemy.destroy();
enemies.splice(i, 1);
// Remove bullet from bullets array
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
break; // Exit loop since bullet is destroyed
}
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
// Remove from bullets array
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
}
};
return self;
});
var CentralMonster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('centralMonster', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.spawnTimer = 0;
self.spawnInterval = 120; // Spawn every 2 seconds at 60fps
self.armPositions = [{
x: -250,
y: -200
},
// Top left arm
{
x: 250,
y: -200
},
// Top right arm
{
x: -300,
y: 0
},
// Left arm
{
x: 300,
y: 0
},
// Right arm
{
x: -250,
y: 200
},
// Bottom left arm
{
x: 250,
y: 200
} // Bottom right arm
];
self.startMovement = function () {
// Create continuous floating movement
self.animateMovement();
};
self.animateMovement = function () {
// Escape from Pacman - move away from him
var dx = self.x - pacman.x;
var dy = self.y - pacman.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If too close to Pacman, move away
if (distance < 400) {
// Normalize direction and move away
dx = dx / distance;
dy = dy / distance;
} else {
// Random movement when far enough
dx = (Math.random() - 0.5) * 2;
dy = (Math.random() - 0.5) * 2;
}
// Calculate new position (escape direction)
var newX = self.x + dx * (200 + Math.random() * 200);
var newY = self.y + dy * (200 + Math.random() * 200);
// Keep within screen bounds
newX = Math.max(200, Math.min(1848, newX));
newY = Math.max(200, Math.min(2532, newY));
tween(self, {
x: newX,
y: newY
}, {
duration: 1500 + Math.random() * 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.animateMovement(); // Continue movement
}
});
// Add rotation animation
tween(self, {
rotation: self.rotation + (Math.random() - 0.5) * 0.5
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeInOut
});
};
self.update = function () {
self.spawnTimer++;
// Spawn enemies from arms
if (self.spawnTimer >= self.spawnInterval) {
self.spawnTimer = 0;
self.spawnEnemy();
}
};
self.spawnEnemy = function () {
// Pick random arm position
var armIndex = Math.floor(Math.random() * self.armPositions.length);
var armPos = self.armPositions[armIndex];
// Create enemy at arm position (relative to monster)
var enemy = new Enemy();
enemy.x = self.x + armPos.x;
enemy.y = self.y + armPos.y;
// Store spawn position for reference
enemy.spawnX = enemy.x;
enemy.spawnY = enemy.y;
// Use level-specific follow chance
enemy.shouldFollowPlayer = Math.random() < currentLevelFollowChance;
// Set level-specific enemy speed
enemy.speed = currentLevelEnemySpeed;
// Enemy will follow Pacman automatically in its update method
enemies.push(enemy);
game.addChild(enemy);
// Add spawn effect
enemy.alpha = 0;
tween(enemy, {
alpha: 1,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 500,
easing: tween.easeOut
});
};
self.grow = function () {
// Calculate scaling factor that decreases with each hit
// Start with 0.1 scale increment and reduce by 0.002 per hit
var scaleIncrement = Math.max(0.01, 0.1 - monsterHits * 0.002);
var newScale = monsterGraphics.scaleX + scaleIncrement;
tween(monsterGraphics, {
scaleX: newScale,
scaleY: newScale
}, {
duration: 300,
easing: tween.easeOut
});
// Flash effect when hit
tween(monsterGraphics, {
tint: 0xff0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(monsterGraphics, {
tint: 0xffffff
}, {
duration: 100
});
}
});
};
self.explode = function () {
// Stop all movement
tween.stop(self);
// Check if player is close enough to be killed by explosion
var dx = pacman.x - self.x;
var dy = pacman.y - self.y;
var explosionDistance = Math.sqrt(dx * dx + dy * dy);
var explosionRadius = 600; // Lethal explosion radius
// Kill player if within explosion radius
if (explosionDistance <= explosionRadius) {
playerLives--;
// Update lives display by hiding icons
if (livesIcons[playerLives]) {
livesIcons[playerLives].visible = false;
}
// Flash effect on hit
LK.effects.flashScreen(0xff0000, 300);
// End game when lives reach 0
if (playerLives <= 0) {
LK.showGameOver();
return;
}
}
// Destroy all enemies when monster dies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.destroy();
enemies.splice(i, 1);
}
// Create dramatic death sequence with multiple effects
// First: Rapid growth and red tint
tween(monsterGraphics, {
scaleX: monsterGraphics.scaleX * 1.8,
scaleY: monsterGraphics.scaleY * 1.8,
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second: Violent shaking effect
var originalX = self.x;
var originalY = self.y;
var shakeCount = 0;
var maxShakes = 10;
function shake() {
if (shakeCount < maxShakes) {
tween(self, {
x: originalX + (Math.random() - 0.5) * 60,
y: originalY + (Math.random() - 0.5) * 60
}, {
duration: 50,
onFinish: function onFinish() {
shakeCount++;
shake();
}
});
} else {
// Third: Spin and shrink rapidly
tween(self, {
rotation: self.rotation + Math.PI * 4,
x: originalX,
y: originalY
}, {
duration: 800,
easing: tween.easeIn
});
tween(monsterGraphics, {
scaleX: 0,
scaleY: 0,
alpha: 0,
tint: 0xffffff
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
// Flash screen multiple times
LK.effects.flashScreen(0xffffff, 200);
LK.setTimeout(function () {
LK.effects.flashScreen(0xff0000, 200);
}, 250);
LK.setTimeout(function () {
LK.effects.flashScreen(0xffffff, 500);
}, 500);
// Show game won instead of resetting
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
});
}
}
shake();
}
});
};
return self;
});
// Create central monster
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.speed = 2;
self.targetX = 0;
self.targetY = 0;
self.lastX = 0;
self.lastY = 0;
self.directionChangeTimer = 0;
self.directionChangeInterval = 60 + Math.random() * 60; // Random direction changes
self.isChangingDirection = false;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Check if this enemy should follow the player
if (self.shouldFollowPlayer) {
// Follow player behavior - move towards Pacman
var dx = pacman.x - self.x;
var dy = pacman.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Move towards Pacman
var direction = Math.min(1, self.speed / distance);
self.x += dx * direction;
self.y += dy * direction;
}
} else {
// Random movement behavior
// Direction change timer
self.directionChangeTimer++;
if (self.directionChangeTimer >= self.directionChangeInterval && !self.isChangingDirection) {
self.directionChangeTimer = 0;
self.directionChangeInterval = 60 + Math.random() * 60;
self.isChangingDirection = true;
// Simple left/right movement only
var swimmingDirection = Math.random() > 0.5 ? 1 : -1; // Left or right
var swimDistance = 200 + Math.random() * 300; // Random swim distance
var tempTargetX = self.x + swimmingDirection * swimDistance;
// Keep within bounds
tempTargetX = Math.max(100, Math.min(1948, tempTargetX));
// Smooth horizontal movement only
tween(self, {
x: tempTargetX
}, {
duration: 1000 + Math.random() * 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isChangingDirection = false;
}
});
}
// Move towards Pacman horizontally only when not changing direction
if (!self.isChangingDirection) {
var dx = pacman.x - self.x;
var distance = Math.abs(dx);
if (distance > 0) {
// Move horizontally towards Pacman
var direction = dx > 0 ? 1 : -1;
self.x += direction * self.speed;
}
}
}
// Keep enemies within screen bounds instead of destroying them
if (self.x < 100) self.x = 100;
if (self.x > 1948) self.x = 1948;
if (self.y < 100) self.y = 100;
if (self.y > 2632) self.y = 2632;
};
return self;
});
var Pacman = Container.expand(function () {
var self = Container.call(this);
var pacmanGraphics = self.attachAsset('pacman', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.targetX = 0;
self.targetY = 0;
self.returningToSpawn = false;
self.update = function () {
// Move towards target position
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// When reached target, start returning to spawn after a delay
if (!self.returningToSpawn) {
self.returningToSpawn = true;
LK.setTimeout(function () {
tween(self, {
x: spawnX,
y: spawnY
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.returningToSpawn = false;
}
});
}, 1000);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0066cc
});
/****
* Game Code
****/
// Add sea background
var seaBackground = game.addChild(LK.getAsset('seaBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create Pacman character
var pacman = game.addChild(new Pacman());
pacman.x = 200;
pacman.y = 200;
// Create central monster
var centralMonster = game.addChild(new CentralMonster());
centralMonster.x = 1024;
centralMonster.y = 1366;
// Array to track enemies
var enemies = [];
// Array to track bullets
var bullets = [];
// Array to track bubbles
var bubbles = [];
// Bubble spawn timer
var bubbleSpawnTimer = 0;
// Track monster hits
var monsterHits = 0;
var hitsToWin = 50;
// Remove level tracking - make game continuous
// Player lives
var playerLives = 3;
// Player score
var playerScore = 0;
// Extra life tracking
var nextExtraLifeScore = 2500;
// Current level enemy settings
var currentLevelEnemySpeed = 2.0;
var currentLevelFollowChance = 0.5;
// Game timer removed
// Store spawn position - start from top-left corner
var spawnX = 200;
var spawnY = 200;
// Touch controls for Pacman movement and shooting
game.down = function (x, y, obj) {
pacman.targetX = x;
pacman.targetY = y;
// Calculate angle from Pacman to target and rotate Pacman
var dx = x - pacman.x;
var dy = y - pacman.y;
var angle = Math.atan2(dy, dx);
// Rotate Pacman to face the firing direction
tween(pacman, {
rotation: angle
}, {
duration: 200,
easing: tween.easeOut
});
// Create bullet towards touch position
var bullet = new Bullet();
bullet.x = pacman.x;
bullet.y = pacman.y;
bullet.targetX = x;
bullet.targetY = y;
bullets.push(bullet);
game.addChild(bullet);
// Play bubble sound effect
LK.getSound('bubble').play();
};
game.move = function (x, y, obj) {
pacman.targetX = x;
pacman.targetY = y;
};
// Game update loop
game.update = function () {
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.parent) {
// Bullet is still active
} else {
// Bullet was destroyed, remove from array
bullets.splice(i, 1);
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (enemy.parent) {
// Check collision with player
if (enemy.intersects(pacman)) {
// Player hit by enemy
playerLives--;
// Update lives display by hiding icons
if (livesIcons[playerLives]) {
livesIcons[playerLives].visible = false;
}
// Flash effect on hit
LK.effects.flashScreen(0xff0000, 300);
// End game when lives reach 0
if (playerLives <= 0) {
LK.showGameOver();
return;
}
// Remove enemy that hit player
enemy.destroy();
enemies.splice(j, 1);
continue;
}
} else {
// Enemy was destroyed, remove from array
enemies.splice(j, 1);
}
}
// Check collision with central monster
if (centralMonster.intersects(pacman)) {
// Player hit by central monster
playerLives--;
// Update lives display by hiding icons
if (livesIcons[playerLives]) {
livesIcons[playerLives].visible = false;
}
// Flash effect on hit
LK.effects.flashScreen(0xff0000, 300);
// End game when lives reach 0
if (playerLives <= 0) {
LK.showGameOver();
return;
}
// Push player away from monster
var dx = pacman.x - centralMonster.x;
var dy = pacman.y - centralMonster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
pacman.x += dx / distance * 100;
pacman.y += dy / distance * 100;
}
}
// Timer system removed
// Spawn bubbles
bubbleSpawnTimer++;
if (bubbleSpawnTimer >= 15) {
// Spawn every 15 frames (4 times per second)
bubbleSpawnTimer = 0;
// Create new bubble at random position at bottom
var bubble = new Bubble();
bubble.x = Math.random() * 2048;
bubble.y = 2732 + 50; // Start below screen
bubbles.push(bubble);
game.addChild(bubble);
// Add floating animation with tween
tween(bubble, {
alpha: 0.7,
scaleX: bubble.scaleX * 1.2,
scaleY: bubble.scaleY * 1.2
}, {
duration: 2000 + Math.random() * 3000,
easing: tween.easeInOut
});
}
// Check for extra life at 2500 points
if (playerScore >= nextExtraLifeScore) {
playerLives++;
nextExtraLifeScore += 2500; // Next extra life at 5000, 7500, etc.
// Add new life icon if we have room
if (livesIcons.length < playerLives) {
var newLifeIcon = LK.getAsset('pacman', {
anchorX: 0,
anchorY: 1,
scaleX: 0.3,
scaleY: 0.3,
x: 50 + livesIcons.length * 80,
y: -50
});
livesIcons.push(newLifeIcon);
LK.gui.bottomLeft.addChild(newLifeIcon);
}
// Make sure all current life icons are visible
for (var l = 0; l < Math.min(livesIcons.length, playerLives); l++) {
livesIcons[l].visible = true;
}
// Flash screen green for extra life
LK.effects.flashScreen(0x00ff00, 500);
}
// Update bubbles
for (var k = bubbles.length - 1; k >= 0; k--) {
var bubble = bubbles[k];
if (!bubble.parent) {
// Bubble was destroyed, remove from array
bubbles.splice(k, 1);
}
}
};
// Create lives display in bottom left corner with player image icons only
var livesIcons = [];
for (var i = 0; i < playerLives; i++) {
var livesIcon = LK.getAsset('pacman', {
anchorX: 0,
anchorY: 1,
scaleX: 0.3,
scaleY: 0.3,
x: 50 + i * 80,
y: -50
});
livesIcons.push(livesIcon);
LK.gui.bottomLeft.addChild(livesIcon);
}
// Create score display
var scoreText = new Text2('Score: ' + playerScore, {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
scoreText.x = -50;
scoreText.y = 50;
LK.gui.topRight.addChild(scoreText);
// Timer display removed
// Level display removed - continuous gameplay
// Continuous gameplay - no level progression
// Continuous gameplay - no level progression function needed
// Initialize continuous gameplay settings
currentLevelEnemySpeed = 2.0;
currentLevelFollowChance = 0.5;
centralMonster.spawnInterval = 100;
hitsToWin = 50;
// Start monster movement
centralMonster.startMovement();
// Play the uploaded diver music
LK.playMusic('diver'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('collectible', {
anchorX: 0.5,
anchorY: 0.5
});
// Random bubble size
var size = 0.3 + Math.random() * 0.7;
bubbleGraphics.scaleX = size;
bubbleGraphics.scaleY = size;
// Random bubble speed
self.speed = 1 + Math.random() * 2;
// Side drift
self.drift = (Math.random() - 0.5) * 0.5;
self.update = function () {
// Move upward
self.y -= self.speed;
// Add slight horizontal drift
self.x += self.drift;
// Remove if off screen
if (self.y < -50) {
var bubbleIndex = bubbles.indexOf(self);
if (bubbleIndex !== -1) {
bubbles.splice(bubbleIndex, 1);
}
self.destroy();
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.targetX = 0;
self.targetY = 0;
self.lastIntersecting = false;
self.returningToSpawn = false;
self.update = function () {
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// When reached target, destroy bullet instead of returning
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
}
// Check intersection with central monster
var currentIntersecting = self.intersects(centralMonster);
if (!self.lastIntersecting && currentIntersecting) {
// Hit the monster
monsterHits++;
centralMonster.grow();
// Award 100 points for each hit on the monster
playerScore += 100;
scoreText.setText('Score: ' + playerScore);
// Play monster hit sound
LK.getSound('monsterhit').play();
// Check if monster should explode after 10 hits
if (monsterHits >= hitsToWin) {
centralMonster.explode();
}
// Remove from bullets array
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
}
self.lastIntersecting = currentIntersecting;
// Check intersection with enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (self.intersects(enemy)) {
// Hit an enemy - destroy both bullet and enemy
// Award 50 points for killing fish
playerScore += 50;
scoreText.setText('Score: ' + playerScore);
// Play monster hit sound
LK.getSound('monsterhit').play();
enemy.destroy();
enemies.splice(i, 1);
// Remove bullet from bullets array
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
break; // Exit loop since bullet is destroyed
}
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
// Remove from bullets array
var bulletIndex = bullets.indexOf(self);
if (bulletIndex !== -1) {
bullets.splice(bulletIndex, 1);
}
self.destroy();
}
};
return self;
});
var CentralMonster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('centralMonster', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.spawnTimer = 0;
self.spawnInterval = 120; // Spawn every 2 seconds at 60fps
self.armPositions = [{
x: -250,
y: -200
},
// Top left arm
{
x: 250,
y: -200
},
// Top right arm
{
x: -300,
y: 0
},
// Left arm
{
x: 300,
y: 0
},
// Right arm
{
x: -250,
y: 200
},
// Bottom left arm
{
x: 250,
y: 200
} // Bottom right arm
];
self.startMovement = function () {
// Create continuous floating movement
self.animateMovement();
};
self.animateMovement = function () {
// Escape from Pacman - move away from him
var dx = self.x - pacman.x;
var dy = self.y - pacman.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If too close to Pacman, move away
if (distance < 400) {
// Normalize direction and move away
dx = dx / distance;
dy = dy / distance;
} else {
// Random movement when far enough
dx = (Math.random() - 0.5) * 2;
dy = (Math.random() - 0.5) * 2;
}
// Calculate new position (escape direction)
var newX = self.x + dx * (200 + Math.random() * 200);
var newY = self.y + dy * (200 + Math.random() * 200);
// Keep within screen bounds
newX = Math.max(200, Math.min(1848, newX));
newY = Math.max(200, Math.min(2532, newY));
tween(self, {
x: newX,
y: newY
}, {
duration: 1500 + Math.random() * 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.animateMovement(); // Continue movement
}
});
// Add rotation animation
tween(self, {
rotation: self.rotation + (Math.random() - 0.5) * 0.5
}, {
duration: 1500 + Math.random() * 1000,
easing: tween.easeInOut
});
};
self.update = function () {
self.spawnTimer++;
// Spawn enemies from arms
if (self.spawnTimer >= self.spawnInterval) {
self.spawnTimer = 0;
self.spawnEnemy();
}
};
self.spawnEnemy = function () {
// Pick random arm position
var armIndex = Math.floor(Math.random() * self.armPositions.length);
var armPos = self.armPositions[armIndex];
// Create enemy at arm position (relative to monster)
var enemy = new Enemy();
enemy.x = self.x + armPos.x;
enemy.y = self.y + armPos.y;
// Store spawn position for reference
enemy.spawnX = enemy.x;
enemy.spawnY = enemy.y;
// Use level-specific follow chance
enemy.shouldFollowPlayer = Math.random() < currentLevelFollowChance;
// Set level-specific enemy speed
enemy.speed = currentLevelEnemySpeed;
// Enemy will follow Pacman automatically in its update method
enemies.push(enemy);
game.addChild(enemy);
// Add spawn effect
enemy.alpha = 0;
tween(enemy, {
alpha: 1,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 500,
easing: tween.easeOut
});
};
self.grow = function () {
// Calculate scaling factor that decreases with each hit
// Start with 0.1 scale increment and reduce by 0.002 per hit
var scaleIncrement = Math.max(0.01, 0.1 - monsterHits * 0.002);
var newScale = monsterGraphics.scaleX + scaleIncrement;
tween(monsterGraphics, {
scaleX: newScale,
scaleY: newScale
}, {
duration: 300,
easing: tween.easeOut
});
// Flash effect when hit
tween(monsterGraphics, {
tint: 0xff0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(monsterGraphics, {
tint: 0xffffff
}, {
duration: 100
});
}
});
};
self.explode = function () {
// Stop all movement
tween.stop(self);
// Check if player is close enough to be killed by explosion
var dx = pacman.x - self.x;
var dy = pacman.y - self.y;
var explosionDistance = Math.sqrt(dx * dx + dy * dy);
var explosionRadius = 600; // Lethal explosion radius
// Kill player if within explosion radius
if (explosionDistance <= explosionRadius) {
playerLives--;
// Update lives display by hiding icons
if (livesIcons[playerLives]) {
livesIcons[playerLives].visible = false;
}
// Flash effect on hit
LK.effects.flashScreen(0xff0000, 300);
// End game when lives reach 0
if (playerLives <= 0) {
LK.showGameOver();
return;
}
}
// Destroy all enemies when monster dies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.destroy();
enemies.splice(i, 1);
}
// Create dramatic death sequence with multiple effects
// First: Rapid growth and red tint
tween(monsterGraphics, {
scaleX: monsterGraphics.scaleX * 1.8,
scaleY: monsterGraphics.scaleY * 1.8,
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second: Violent shaking effect
var originalX = self.x;
var originalY = self.y;
var shakeCount = 0;
var maxShakes = 10;
function shake() {
if (shakeCount < maxShakes) {
tween(self, {
x: originalX + (Math.random() - 0.5) * 60,
y: originalY + (Math.random() - 0.5) * 60
}, {
duration: 50,
onFinish: function onFinish() {
shakeCount++;
shake();
}
});
} else {
// Third: Spin and shrink rapidly
tween(self, {
rotation: self.rotation + Math.PI * 4,
x: originalX,
y: originalY
}, {
duration: 800,
easing: tween.easeIn
});
tween(monsterGraphics, {
scaleX: 0,
scaleY: 0,
alpha: 0,
tint: 0xffffff
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
// Flash screen multiple times
LK.effects.flashScreen(0xffffff, 200);
LK.setTimeout(function () {
LK.effects.flashScreen(0xff0000, 200);
}, 250);
LK.setTimeout(function () {
LK.effects.flashScreen(0xffffff, 500);
}, 500);
// Show game won instead of resetting
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
});
}
}
shake();
}
});
};
return self;
});
// Create central monster
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.speed = 2;
self.targetX = 0;
self.targetY = 0;
self.lastX = 0;
self.lastY = 0;
self.directionChangeTimer = 0;
self.directionChangeInterval = 60 + Math.random() * 60; // Random direction changes
self.isChangingDirection = false;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Check if this enemy should follow the player
if (self.shouldFollowPlayer) {
// Follow player behavior - move towards Pacman
var dx = pacman.x - self.x;
var dy = pacman.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Move towards Pacman
var direction = Math.min(1, self.speed / distance);
self.x += dx * direction;
self.y += dy * direction;
}
} else {
// Random movement behavior
// Direction change timer
self.directionChangeTimer++;
if (self.directionChangeTimer >= self.directionChangeInterval && !self.isChangingDirection) {
self.directionChangeTimer = 0;
self.directionChangeInterval = 60 + Math.random() * 60;
self.isChangingDirection = true;
// Simple left/right movement only
var swimmingDirection = Math.random() > 0.5 ? 1 : -1; // Left or right
var swimDistance = 200 + Math.random() * 300; // Random swim distance
var tempTargetX = self.x + swimmingDirection * swimDistance;
// Keep within bounds
tempTargetX = Math.max(100, Math.min(1948, tempTargetX));
// Smooth horizontal movement only
tween(self, {
x: tempTargetX
}, {
duration: 1000 + Math.random() * 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isChangingDirection = false;
}
});
}
// Move towards Pacman horizontally only when not changing direction
if (!self.isChangingDirection) {
var dx = pacman.x - self.x;
var distance = Math.abs(dx);
if (distance > 0) {
// Move horizontally towards Pacman
var direction = dx > 0 ? 1 : -1;
self.x += direction * self.speed;
}
}
}
// Keep enemies within screen bounds instead of destroying them
if (self.x < 100) self.x = 100;
if (self.x > 1948) self.x = 1948;
if (self.y < 100) self.y = 100;
if (self.y > 2632) self.y = 2632;
};
return self;
});
var Pacman = Container.expand(function () {
var self = Container.call(this);
var pacmanGraphics = self.attachAsset('pacman', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.targetX = 0;
self.targetY = 0;
self.returningToSpawn = false;
self.update = function () {
// Move towards target position
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// When reached target, start returning to spawn after a delay
if (!self.returningToSpawn) {
self.returningToSpawn = true;
LK.setTimeout(function () {
tween(self, {
x: spawnX,
y: spawnY
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.returningToSpawn = false;
}
});
}, 1000);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0066cc
});
/****
* Game Code
****/
// Add sea background
var seaBackground = game.addChild(LK.getAsset('seaBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create Pacman character
var pacman = game.addChild(new Pacman());
pacman.x = 200;
pacman.y = 200;
// Create central monster
var centralMonster = game.addChild(new CentralMonster());
centralMonster.x = 1024;
centralMonster.y = 1366;
// Array to track enemies
var enemies = [];
// Array to track bullets
var bullets = [];
// Array to track bubbles
var bubbles = [];
// Bubble spawn timer
var bubbleSpawnTimer = 0;
// Track monster hits
var monsterHits = 0;
var hitsToWin = 50;
// Remove level tracking - make game continuous
// Player lives
var playerLives = 3;
// Player score
var playerScore = 0;
// Extra life tracking
var nextExtraLifeScore = 2500;
// Current level enemy settings
var currentLevelEnemySpeed = 2.0;
var currentLevelFollowChance = 0.5;
// Game timer removed
// Store spawn position - start from top-left corner
var spawnX = 200;
var spawnY = 200;
// Touch controls for Pacman movement and shooting
game.down = function (x, y, obj) {
pacman.targetX = x;
pacman.targetY = y;
// Calculate angle from Pacman to target and rotate Pacman
var dx = x - pacman.x;
var dy = y - pacman.y;
var angle = Math.atan2(dy, dx);
// Rotate Pacman to face the firing direction
tween(pacman, {
rotation: angle
}, {
duration: 200,
easing: tween.easeOut
});
// Create bullet towards touch position
var bullet = new Bullet();
bullet.x = pacman.x;
bullet.y = pacman.y;
bullet.targetX = x;
bullet.targetY = y;
bullets.push(bullet);
game.addChild(bullet);
// Play bubble sound effect
LK.getSound('bubble').play();
};
game.move = function (x, y, obj) {
pacman.targetX = x;
pacman.targetY = y;
};
// Game update loop
game.update = function () {
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.parent) {
// Bullet is still active
} else {
// Bullet was destroyed, remove from array
bullets.splice(i, 1);
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (enemy.parent) {
// Check collision with player
if (enemy.intersects(pacman)) {
// Player hit by enemy
playerLives--;
// Update lives display by hiding icons
if (livesIcons[playerLives]) {
livesIcons[playerLives].visible = false;
}
// Flash effect on hit
LK.effects.flashScreen(0xff0000, 300);
// End game when lives reach 0
if (playerLives <= 0) {
LK.showGameOver();
return;
}
// Remove enemy that hit player
enemy.destroy();
enemies.splice(j, 1);
continue;
}
} else {
// Enemy was destroyed, remove from array
enemies.splice(j, 1);
}
}
// Check collision with central monster
if (centralMonster.intersects(pacman)) {
// Player hit by central monster
playerLives--;
// Update lives display by hiding icons
if (livesIcons[playerLives]) {
livesIcons[playerLives].visible = false;
}
// Flash effect on hit
LK.effects.flashScreen(0xff0000, 300);
// End game when lives reach 0
if (playerLives <= 0) {
LK.showGameOver();
return;
}
// Push player away from monster
var dx = pacman.x - centralMonster.x;
var dy = pacman.y - centralMonster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
pacman.x += dx / distance * 100;
pacman.y += dy / distance * 100;
}
}
// Timer system removed
// Spawn bubbles
bubbleSpawnTimer++;
if (bubbleSpawnTimer >= 15) {
// Spawn every 15 frames (4 times per second)
bubbleSpawnTimer = 0;
// Create new bubble at random position at bottom
var bubble = new Bubble();
bubble.x = Math.random() * 2048;
bubble.y = 2732 + 50; // Start below screen
bubbles.push(bubble);
game.addChild(bubble);
// Add floating animation with tween
tween(bubble, {
alpha: 0.7,
scaleX: bubble.scaleX * 1.2,
scaleY: bubble.scaleY * 1.2
}, {
duration: 2000 + Math.random() * 3000,
easing: tween.easeInOut
});
}
// Check for extra life at 2500 points
if (playerScore >= nextExtraLifeScore) {
playerLives++;
nextExtraLifeScore += 2500; // Next extra life at 5000, 7500, etc.
// Add new life icon if we have room
if (livesIcons.length < playerLives) {
var newLifeIcon = LK.getAsset('pacman', {
anchorX: 0,
anchorY: 1,
scaleX: 0.3,
scaleY: 0.3,
x: 50 + livesIcons.length * 80,
y: -50
});
livesIcons.push(newLifeIcon);
LK.gui.bottomLeft.addChild(newLifeIcon);
}
// Make sure all current life icons are visible
for (var l = 0; l < Math.min(livesIcons.length, playerLives); l++) {
livesIcons[l].visible = true;
}
// Flash screen green for extra life
LK.effects.flashScreen(0x00ff00, 500);
}
// Update bubbles
for (var k = bubbles.length - 1; k >= 0; k--) {
var bubble = bubbles[k];
if (!bubble.parent) {
// Bubble was destroyed, remove from array
bubbles.splice(k, 1);
}
}
};
// Create lives display in bottom left corner with player image icons only
var livesIcons = [];
for (var i = 0; i < playerLives; i++) {
var livesIcon = LK.getAsset('pacman', {
anchorX: 0,
anchorY: 1,
scaleX: 0.3,
scaleY: 0.3,
x: 50 + i * 80,
y: -50
});
livesIcons.push(livesIcon);
LK.gui.bottomLeft.addChild(livesIcon);
}
// Create score display
var scoreText = new Text2('Score: ' + playerScore, {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
scoreText.x = -50;
scoreText.y = 50;
LK.gui.topRight.addChild(scoreText);
// Timer display removed
// Level display removed - continuous gameplay
// Continuous gameplay - no level progression
// Continuous gameplay - no level progression function needed
// Initialize continuous gameplay settings
currentLevelEnemySpeed = 2.0;
currentLevelFollowChance = 0.5;
centralMonster.spawnInterval = 100;
hitsToWin = 50;
// Start monster movement
centralMonster.startMovement();
// Play the uploaded diver music
LK.playMusic('diver');