User prompt
slow it more the sound!
User prompt
Slow the sound more
User prompt
Slow the soundmovment for the player when dragging it
User prompt
add playermovment sound when dragging it.
User prompt
respawn 2 shadowspirit max in level1 if one removed another one can be respawned later, do 4 shadowspirit max for level2.
User prompt
the player is appearing behind showerareas when moved on it in level1!
User prompt
Name the spirit that i free from the top before they turn to dark spirit 'Bluespirit'
User prompt
not the pollutedspirit that i clean i meant the other spirit that player freed it before it turns to darkspirit if i free one remove one enemy.
User prompt
when free a blue spirit remove one enemy of shadowspirit
User prompt
make background02 visible again
User prompt
when level2 start don't let any enemies from recent level because they appeared behind background02 and the player get damage without seen them to avoid them!
User prompt
Hide background02
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var i = 0; i < showerAreas.length; i++) {' Line Number: 267
User prompt
make the pollutedspirit respawning on shower area only, calculate if one of it empty to respawn in it each 10 sec. for level2 place 4 Shower area.
User prompt
Add 2 showerarea on the sides of the middle of the screen with space between it 200px
User prompt
the player is behind background02 in level2! fix that!.
User prompt
make the first scene when game start 'level1' and add another separated level 'level2' with background02
User prompt
colecting riverspirt regenerate the health by 30% for the player.
User prompt
change directions of the shadow spirits from the middle of the screen too.
Code edit (1 edits merged)
Please save this source code
User prompt
Don't do brush sound for the riverspirit!
User prompt
Show it always after pollutedspirit assets on the screen
User prompt
Show brush after pollutedspirit assets on the screen
User prompt
Add brush asset to the game when player clean the pollutedspirits show the brush on them with animation left and right by small distance to look like its brushing them. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
There's no brush asset showing on the polluted spirits fix it! ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BlueSpirit = Container.expand(function () {
var self = Container.call(this);
var spiritGraphics = self.attachAsset('blueSpirit', {
anchorX: 0.5,
anchorY: 0.5
});
self.waitTime = 0;
self.maxWaitTime = 600; // 10 seconds at 60fps
self.isDark = false;
self.speed = 1;
self.update = function () {
self.waitTime++;
if (!self.isDark && self.waitTime >= self.maxWaitTime) {
self.turnDark();
}
if (self.isDark) {
self.y += self.speed;
}
};
self.turnDark = function () {
self.isDark = true;
spiritGraphics.tint = 0x2a0845;
tween(spiritGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500
});
};
return self;
});
var HealthBar = Container.expand(function () {
var self = Container.call(this);
// Background bar
self.bgBar = self.attachAsset('healthBarBg', {
anchorX: 0,
anchorY: 0.5
});
// Health bar
self.healthBar = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
self.maxWidth = 300;
self.updateHealth = function (healthPercent) {
self.healthBar.scaleX = healthPercent / 100;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.tokens = 0;
self.health = 100;
self.maxHealth = 100;
self.collectToken = function () {
self.tokens++;
};
self.deliverTokens = function () {
var delivered = self.tokens;
self.tokens = 0;
return delivered;
};
self.takeDamage = function () {
var damage = Math.random() * 7 + 3; // Random between 3-10
self.health -= damage;
self.health = Math.max(0, self.health); // Ensure health doesn't go below 0
LK.effects.flashObject(self, 0xff0000, 500);
return self.health <= 0;
};
return self;
});
var PollutedSpirit = Container.expand(function () {
var self = Container.call(this);
var pollutedGraphics = self.attachAsset('pollutedSpirit', {
anchorX: 0.5,
anchorY: 0.5
});
self.tokensNeeded = 3;
self.isCleansed = false;
self.cleanse = function () {
self.isCleansed = true;
tween(pollutedGraphics, {
tint: 0x98fb98
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var RiverSpirit = Container.expand(function () {
var self = Container.call(this);
var riverGraphics = self.attachAsset('riverSpirit', {
anchorX: 0.5,
anchorY: 0.5
});
self.bonusValue = 20;
self.speed = 0.5;
self.update = function () {
self.x += self.speed;
self.rotation += 0.01;
};
return self;
});
var ShadowSpirit = Container.expand(function () {
var self = Container.call(this);
var shadowGraphics = self.attachAsset('shadowSpirit', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.targetPlayer = null;
self.update = function () {
if (self.targetPlayer) {
var dx = self.targetPlayer.x - self.x;
var dy = self.targetPlayer.y - 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;
}
// Change direction based on position relative to screen middle
var screenMiddle = 1024;
if (self.x < screenMiddle) {
// Shadow is on left side, face right towards middle
self.scaleX = 1;
} else {
// Shadow is on right side, face left towards middle
self.scaleX = -1;
}
}
};
return self;
});
var Token = Container.expand(function () {
var self = Container.call(this);
var tokenGraphics = self.attachAsset('token', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
if (!self.collected) {
self.rotation += 0.02;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var gameStarted = false;
var introBackground = null;
var startButton = null;
var currentLevel = 'level1';
var gameBackground = null;
// Declare game variables in global scope
var player, tokens, blueSpirits, shadowSpirits, pollutedSpirits, riverSpirit;
var spawnTimer, spawnInterval, shadowSpawnTimer, shadowSpawnInterval;
var scoreTxt, tokenTxt, healthBar;
var brushSprite = null;
var showerAreas = [],
pollutedSpawnTimer,
pollutedSpawnInterval;
// Show intro screen
function showIntroScreen() {
introBackground = game.addChild(LK.getAsset('introbackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
startButton = game.addChild(LK.getAsset('startbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
}));
LK.playMusic('intromusic');
}
// Start the actual game
function startGame() {
gameStarted = true;
if (introBackground) {
introBackground.destroy();
introBackground = null;
}
if (startButton) {
startButton.destroy();
startButton = null;
}
LK.stopMusic();
LK.playMusic('bathhouse');
initializeGame();
}
// Spawn functions in global scope
function spawnToken() {
var token = new Token();
token.x = Math.random() * 1848 + 100;
token.y = Math.random() * 2332 + 300;
tokens.push(token);
game.addChild(token);
}
function spawnSpirit() {
var spirit = new BlueSpirit();
spirit.x = Math.random() * 1848 + 100;
spirit.y = 300;
blueSpirits.push(spirit);
game.addChild(spirit);
}
function spawnShadowSpirit() {
var shadow = new ShadowSpirit();
shadow.x = Math.random() * 1848 + 100;
shadow.y = Math.random() * 400 + 300;
shadow.targetPlayer = player;
shadowSpirits.push(shadow);
game.addChild(shadow);
}
function spawnPollutedSpirit() {
// Find an empty shower area
var emptyAreas = [];
for (var i = 0; i < showerAreas.length; i++) {
if (!showerAreas[i].occupied) {
emptyAreas.push(showerAreas[i]);
}
}
// Only spawn if there's an empty area
if (emptyAreas.length > 0) {
var selectedArea = emptyAreas[Math.floor(Math.random() * emptyAreas.length)];
var polluted = new PollutedSpirit();
polluted.x = selectedArea.x;
polluted.y = selectedArea.y;
polluted.assignedShowerArea = selectedArea;
selectedArea.occupied = true;
pollutedSpirits.push(polluted);
game.addChild(polluted);
// Move brush sprite to render on top of polluted spirits
if (brushSprite) {
game.removeChild(brushSprite);
game.addChild(brushSprite);
}
}
}
function spawnRiverSpirit() {
if (!riverSpirit) {
riverSpirit = new RiverSpirit();
riverSpirit.x = -100;
riverSpirit.y = Math.random() * 1000 + 1066;
game.addChild(riverSpirit);
}
}
function startLevel2() {
currentLevel = 'level2';
// Remove current background
if (gameBackground) {
gameBackground.destroy();
gameBackground = null;
}
// Clear all existing enemies from level1
for (var i = blueSpirits.length - 1; i >= 0; i--) {
blueSpirits[i].destroy();
}
blueSpirits = [];
for (var j = shadowSpirits.length - 1; j >= 0; j--) {
shadowSpirits[j].destroy();
}
shadowSpirits = [];
for (var k = pollutedSpirits.length - 1; k >= 0; k--) {
if (pollutedSpirits[k].assignedShowerArea) {
pollutedSpirits[k].assignedShowerArea.occupied = false;
}
pollutedSpirits[k].destroy();
}
pollutedSpirits = [];
if (riverSpirit) {
riverSpirit.destroy();
riverSpirit = null;
}
// Remove existing shower areas
for (var i = 0; i < showerAreas.length; i++) {
showerAreas[i].destroy();
}
showerAreas = [];
// Add level2 background
gameBackground = game.addChild(LK.getAsset('background02', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
visible: true
}));
// Add 4 shower areas for level2
var screenMiddle = 1024;
var spacing = 200;
var showerAreaWidth = 300;
var positions = [{
x: screenMiddle - spacing * 1.5 - showerAreaWidth,
y: 1200
}, {
x: screenMiddle - spacing / 2 - showerAreaWidth / 2,
y: 1200
}, {
x: screenMiddle + spacing / 2 + showerAreaWidth / 2,
y: 1200
}, {
x: screenMiddle + spacing * 1.5 + showerAreaWidth,
y: 1200
}];
for (var p = 0; p < positions.length; p++) {
var showerArea = game.addChild(LK.getAsset('Showerarea', {
anchorX: 0.5,
anchorY: 0.5,
x: positions[p].x,
y: positions[p].y
}));
showerArea.occupied = false;
showerAreas.push(showerArea);
}
// Move player to front to ensure it renders above the new background
game.removeChild(player);
game.addChild(player);
// Reset game state for new level
player.health = player.maxHealth;
healthBar.updateHealth(player.health);
spawnInterval = 120; // Make level2 slightly harder
shadowSpawnInterval = 240;
}
function initializeGame() {
game.setBackgroundColor(0x16213e);
currentLevel = 'level1';
// Add level1 game background
gameBackground = game.addChild(LK.getAsset('gamebackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
player = game.addChild(new Player());
player.x = 1024;
player.y = 2200;
tokens = [];
blueSpirits = [];
shadowSpirits = [];
pollutedSpirits = [];
riverSpirit = null;
spawnTimer = 0;
spawnInterval = 180; // 3 seconds initially
shadowSpawnTimer = 0;
shadowSpawnInterval = 300; // 5 seconds
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
tokenTxt = new Text2('Tokens: 0', {
size: 60,
fill: 0xFFD700
});
tokenTxt.anchor.set(1, 0);
tokenTxt.x = -20;
LK.gui.topRight.addChild(tokenTxt);
healthBar = new HealthBar();
healthBar.x = 20;
healthBar.y = 30;
LK.gui.topLeft.addChild(healthBar);
// Initial spawns
for (var i = 0; i < 5; i++) {
spawnToken();
}
spawnSpirit();
spawnPollutedSpirit();
// Initialize brush sprite (initially hidden)
brushSprite = LK.getAsset('brush', {
anchorX: 0.5,
anchorY: 0.5
});
brushSprite.visible = false;
game.addChild(brushSprite);
// Initialize shower area system
showerAreas = [];
pollutedSpawnTimer = 0;
pollutedSpawnInterval = 600; // 10 seconds at 60fps
// Add shower areas based on level
var screenMiddle = 1024;
var spacing = 200;
var showerAreaWidth = 300; // Based on asset width
if (currentLevel === 'level1') {
// Level 1: 2 shower areas
var leftShowerArea = game.addChild(LK.getAsset('Showerarea', {
anchorX: 0.5,
anchorY: 0.5,
x: screenMiddle - spacing / 2 - showerAreaWidth / 2,
y: 1366 // Middle of screen height
}));
leftShowerArea.occupied = false;
showerAreas.push(leftShowerArea);
var rightShowerArea = game.addChild(LK.getAsset('Showerarea', {
anchorX: 0.5,
anchorY: 0.5,
x: screenMiddle + spacing / 2 + showerAreaWidth / 2,
y: 1366 // Middle of screen height
}));
rightShowerArea.occupied = false;
showerAreas.push(rightShowerArea);
} else if (currentLevel === 'level2') {
// Level 2: 4 shower areas
var positions = [{
x: screenMiddle - spacing * 1.5 - showerAreaWidth,
y: 1200
}, {
x: screenMiddle - spacing / 2 - showerAreaWidth / 2,
y: 1200
}, {
x: screenMiddle + spacing / 2 + showerAreaWidth / 2,
y: 1200
}, {
x: screenMiddle + spacing * 1.5 + showerAreaWidth,
y: 1200
}];
for (var p = 0; p < positions.length; p++) {
var showerArea = game.addChild(LK.getAsset('Showerarea', {
anchorX: 0.5,
anchorY: 0.5,
x: positions[p].x,
y: positions[p].y
}));
showerArea.occupied = false;
showerAreas.push(showerArea);
}
}
// Move player to front to ensure it renders above shower areas
game.removeChild(player);
game.addChild(player);
}
var dragActive = false;
game.down = function (x, y, obj) {
if (!gameStarted && startButton) {
// Check if click is within start button bounds
var buttonLeft = startButton.x - startButton.width * startButton.anchor.x;
var buttonRight = startButton.x + startButton.width * (1 - startButton.anchor.x);
var buttonTop = startButton.y - startButton.height * startButton.anchor.y;
var buttonBottom = startButton.y + startButton.height * (1 - startButton.anchor.y);
if (x >= buttonLeft && x <= buttonRight && y >= buttonTop && y <= buttonBottom) {
startGame();
return;
}
}
if (gameStarted) {
dragActive = true;
}
};
game.up = function (x, y, obj) {
if (gameStarted) {
dragActive = false;
}
};
game.move = function (x, y, obj) {
if (gameStarted && dragActive && player) {
player.x = x;
player.y = y;
}
};
game.update = function () {
if (!gameStarted) {
return;
}
// Update spawn timers
spawnTimer++;
shadowSpawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnSpirit();
spawnTimer = 0;
// Increase difficulty
if (spawnInterval > 60) {
spawnInterval -= 2;
}
}
if (shadowSpawnTimer >= shadowSpawnInterval) {
spawnShadowSpirit();
shadowSpawnTimer = 0;
}
// Token spawning
if (LK.ticks % 120 === 0) {
spawnToken();
}
// Polluted spirit spawning every 10 seconds
pollutedSpawnTimer++;
if (pollutedSpawnTimer >= pollutedSpawnInterval) {
spawnPollutedSpirit();
pollutedSpawnTimer = 0;
}
// River spirit spawning
if (LK.getScore() > 0 && LK.getScore() % 50 === 0 && !riverSpirit) {
spawnRiverSpirit();
}
// Check token collection
for (var i = tokens.length - 1; i >= 0; i--) {
var token = tokens[i];
if (!token.collected && player.intersects(token)) {
token.collected = true;
player.collectToken();
tokenTxt.setText('Tokens: ' + player.tokens);
LK.getSound('collect').play();
token.destroy();
tokens.splice(i, 1);
}
}
// Check spirit interactions
for (var j = blueSpirits.length - 1; j >= 0; j--) {
var spirit = blueSpirits[j];
if (!spirit.isDark && player.intersects(spirit) && player.tokens > 0) {
player.tokens -= 1; // Only consume 1 token per spirit
LK.setScore(LK.getScore() + 5); // Award 5 points per spirit freed
scoreTxt.setText('Score: ' + LK.getScore());
tokenTxt.setText('Tokens: ' + player.tokens);
LK.getSound('deliver').play();
// Remove one shadow spirit when blue spirit is freed
if (shadowSpirits.length > 0) {
var shadowToRemove = shadowSpirits[0];
shadowToRemove.destroy();
shadowSpirits.splice(0, 1);
}
spirit.destroy();
blueSpirits.splice(j, 1);
}
if (spirit.isDark && spirit.y > 2932) {
spirit.destroy();
blueSpirits.splice(j, 1);
}
}
// Check shadow spirit collisions
for (var k = shadowSpirits.length - 1; k >= 0; k--) {
var shadow = shadowSpirits[k];
if (shadow.lastIntersecting === undefined) {
shadow.lastIntersecting = false;
}
var currentIntersecting = player.intersects(shadow);
if (!shadow.lastIntersecting && currentIntersecting) {
LK.getSound('damage').play();
var gameOver = player.takeDamage();
healthBar.updateHealth(player.health);
if (gameOver) {
LK.showGameOver();
}
shadow.destroy();
shadowSpirits.splice(k, 1);
continue;
}
shadow.lastIntersecting = currentIntersecting;
}
// Check polluted spirit cleansing
for (var l = pollutedSpirits.length - 1; l >= 0; l--) {
var polluted = pollutedSpirits[l];
if (!polluted.isCleansed && player.intersects(polluted) && player.tokens >= polluted.tokensNeeded) {
player.tokens -= polluted.tokensNeeded;
tokenTxt.setText('Tokens: ' + player.tokens);
LK.setScore(LK.getScore() + 15);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('cleanse').play();
// Show and animate brush
if (brushSprite) {
brushSprite.visible = true;
brushSprite.x = polluted.x;
brushSprite.y = polluted.y;
// Stop any existing brush animations
tween.stop(brushSprite);
// Animate brush left and right to simulate brushing
tween(brushSprite, {
x: polluted.x - 30
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(brushSprite, {
x: polluted.x + 30
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(brushSprite, {
x: polluted.x - 20
}, {
duration: 150,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(brushSprite, {
x: polluted.x + 20
}, {
duration: 150,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(brushSprite, {
x: polluted.x
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
brushSprite.visible = false;
}
});
}
});
}
});
}
});
}
});
}
// Free up the shower area
if (polluted.assignedShowerArea) {
polluted.assignedShowerArea.occupied = false;
}
polluted.cleanse();
pollutedSpirits.splice(l, 1);
}
}
// Check river spirit collection
if (riverSpirit) {
if (riverSpirit.lastIntersecting === undefined) {
riverSpirit.lastIntersecting = false;
}
var riverIntersecting = player.intersects(riverSpirit);
if (!riverSpirit.lastIntersecting && riverIntersecting) {
LK.setScore(LK.getScore() + riverSpirit.bonusValue);
scoreTxt.setText('Score: ' + LK.getScore());
// Regenerate health by 30%
player.health += player.maxHealth * 0.3;
player.health = Math.min(player.health, player.maxHealth); // Cap at max health
healthBar.updateHealth(player.health);
LK.effects.flashObject(player, 0x87ceeb, 1000); // Flash blue to indicate healing
riverSpirit.destroy();
riverSpirit = null;
} else if (riverSpirit && riverSpirit.x > 2200) {
riverSpirit.destroy();
riverSpirit = null;
}
if (riverSpirit) {
riverSpirit.lastIntersecting = riverIntersecting;
}
}
// Player direction based on position
var screenMiddle = 1024;
if (player.x < screenMiddle) {
// Player is on left side, face left (flip horizontally)
player.scaleX = -1;
} else {
// Player is on right side, face right (normal orientation)
player.scaleX = 1;
}
// Level progression
if (currentLevel === 'level1' && LK.getScore() >= 250) {
startLevel2();
}
// Win condition
if (currentLevel === 'level2' && LK.getScore() >= 500) {
LK.showYouWin();
}
};
// Show intro screen initially
showIntroScreen(); ===================================================================
--- original.js
+++ change.js
@@ -450,8 +450,11 @@
showerArea.occupied = false;
showerAreas.push(showerArea);
}
}
+ // Move player to front to ensure it renders above shower areas
+ game.removeChild(player);
+ game.addChild(player);
}
var dragActive = false;
game.down = function (x, y, obj) {
if (!gameStarted && startButton) {