User prompt
kulenin yıkılma ihtimalide olsun çok yamuk ve dengesiz koyuldunğunda kule yıkılabilir ve ilk 50 puan verdikten sonra üstüne düzgün gelomesse 10 puan vermen lazım sen 50 puan verdin. ip ve kule hala yavaş sallanmakta onu hızlandırman ve eşit bi şekilde sallanması gerekli ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kuleler düzgün dizilmedikçe kulelerde sallansın 5 kule yamuk dizildiğinde sallanmaya başlasın eğer 5 ten sonra devam ederse yani kule tam düzgün dizilirse sallanma yavaşlasın ve kule tam düzgün hizalı dizildiğinde puanı 50 verilir tam olmassa puan 10 olur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
çok güzel şimdi ipin ve kulanin sallanması aynı şekilde olsun yani ip sağa giderken kule sola gitmesin ve her kule dikilişinde işler biraz daha zorlaştır ki oyunun zevki çıksın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kule nereye düşüyorsa zeminde oraya duracak en sola yerleşmeyecek ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
boylu boyuna çekilen zeminde ilk bıraktığımız kulanin durması gerekiyor ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
sallanan ipte ortda olması lazım zemine çekilen çizgide durması gerekiyor binayı nasıl dikicez ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ayrıca tıklayıp bıraktığımız ipte tam ortda olması gerekiyot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ekranın en soluna geldi ortasına gelmesi lazın, en altta ki zemin boylu boyuna uzanması lazım ve ürünler üst üste dizilirken sprey sıkılıyormuş havası vermesi lazım ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bir halat yardımı ile sağa sola sakin bir hızda sallanmalı dokunduğunda hallattan kopup temele ilk şişe düşmeli ardından gelen şişeler ilk şişenin üstüne düşmesse bunu oyun biter ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
probşemi çözermisin
User prompt
tamam bunların hepsini yap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
farklı bir eklenti dene
User prompt
plugins problem ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
hala eklenti hatası verdi ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
eklenti hatası verdi
Code edit (1 edits merged)
Please save this source code
User prompt
Loris Perfume Tower - Stack & Balance
Initial prompt
We are developing a mobile-compatible "Stack & Balance" style game inspired by City Bloxx for Loris Perfume. The game concept revolves around the elegant and entertaining stacking of Loris Perfume bottles. Game Details: Players start by placing a perfume bottle flat on the ground. They then attempt to precisely stack falling perfume bottles onto the previous bottle. Each successful placement awards points and triggers a subtle perfume-spraying animation. The bottles alternate between upright and inverted positions as they fall, increasing the game's difficulty and enjoyment. As the stack grows taller, maintaining balance becomes increasingly challenging, with realistic swaying effects. If the stack collapses, the game ends, and the final score is displayed. At certain score milestones, players earn special discount codes, redeemable on the Loris Perfume online store. Visual Design: Perfume bottles should be stylish and attractive, inspired by actual Loris Perfume bottle designs. Backgrounds should feature pastel tones or subtle modern patterns aligned with the brand identity. The user interface should be minimalist, intuitive, and user-friendly. Sound and Animation: A gentle and pleasant spray sound should accompany the perfume-spraying animation. Soft and satisfying sound effects should be used as bottles fall and stack. Background music should be calming yet enjoyable. Overall Objective: To create positive user interaction with the Loris Perfume brand and enhance brand awareness through gameplay. To provide a fun, addictive, and visually appealing gaming experience.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var FallenBottle = Container.expand(function () {
var self = Container.call(this);
var bottleGraphics = self.attachAsset('perfumeBottleUpright', {
anchorX: 0.5,
anchorY: 1.0
});
self.placed = false;
self.fallSpeed = 8;
self.update = function () {
if (!self.placed) {
self.y += self.fallSpeed;
}
};
return self;
});
var SwingingBottle = Container.expand(function () {
var self = Container.call(this);
// Create rope
var rope = self.attachAsset('rope', {
anchorX: 0.5,
anchorY: 0
});
rope.y = -150;
// Create bottle
var bottleGraphics = self.attachAsset('perfumeBottleUpright', {
anchorX: 0.5,
anchorY: 0
});
bottleGraphics.y = 150;
// Rope physics properties
self.angle = 0;
self.angularVelocity = 0;
self.ropeLength = 300;
self.swingSpeed = 0.02;
self.gravity = 0.0005;
self.damping = 0.998;
self.maxSwingAngle = Math.PI / 4; // 45 degrees max swing
// State
self.isSwinging = true;
self.fallSpeed = 5;
self.placed = false;
self.update = function () {
if (self.isSwinging) {
// Simple pendulum physics
self.angularVelocity += -self.gravity * Math.sin(self.angle);
self.angularVelocity *= self.damping;
self.angle += self.angularVelocity;
// Limit swing angle
if (Math.abs(self.angle) > self.maxSwingAngle) {
self.angle = self.maxSwingAngle * Math.sign(self.angle);
self.angularVelocity *= -0.8;
}
// Apply swing position to both rope and bottle in same direction
var swingOffset = Math.sin(self.angle) * self.ropeLength;
bottleGraphics.x = swingOffset;
rope.x = swingOffset;
rope.rotation = self.angle;
} else if (!self.placed) {
// Falling
self.y += self.fallSpeed;
}
};
self.releaseFromRope = function () {
self.isSwinging = false;
// Remove rope visual
if (rope.parent) {
rope.parent.removeChild(rope);
}
};
return self;
});
var Tower = Container.expand(function () {
var self = Container.call(this);
self.bottles = [];
self.baseHeight = 0;
self.swayAngle = 0;
self.swayVelocity = 0;
self.isSwaying = false;
self.swayIntensity = 0;
self.lastAlignment = 0;
// Add base platform
self.addBase = function () {
var base = self.attachAsset('bottleBase', {
anchorX: 0.5,
anchorY: 1.0
});
base.y = gameHeight - 50; // Position closer to bottom
base.x = 0; // Center the base
self.baseHeight = base.y;
};
self.addBottle = function (bottle) {
// Position bottle on top of stack
if (self.bottles.length === 0) {
// First bottle lands directly on the base
bottle.y = self.baseHeight;
} else {
// Stack subsequent bottles
bottle.y = self.baseHeight - self.bottles.length * 200;
}
// Keep bottle at its current x position (where it landed)
bottle.placed = true;
self.bottles.push(bottle);
};
self.getStackHeight = function () {
// First bottle lands directly on the base
if (self.bottles.length === 0) {
return self.baseHeight;
}
// Subsequent bottles stack on top
return self.baseHeight - self.bottles.length * 200;
};
self.checkValidPlacement = function (bottle) {
// Check if bottle lands close enough to tower position
// Tolerance decreases with difficulty
var baseTolerance = 200;
var tolerance = Math.max(80, baseTolerance - (currentDifficulty - 1) * 30);
return Math.abs(bottle.x - self.x) <= tolerance;
};
self.calculateAlignment = function () {
if (self.bottles.length < 2) return 1; // Perfect alignment for less than 2 bottles
var totalDeviation = 0;
var centerX = self.x;
for (var i = 0; i < self.bottles.length; i++) {
totalDeviation += Math.abs(self.bottles[i].x - centerX);
}
var averageDeviation = totalDeviation / self.bottles.length;
var maxAllowedDeviation = 100; // Perfect alignment threshold
var alignment = Math.max(0, 1 - averageDeviation / maxAllowedDeviation);
return alignment;
};
self.updateSway = function () {
var alignment = self.calculateAlignment();
self.lastAlignment = alignment;
// Start swaying if we have 5+ bottles and alignment is poor
if (self.bottles.length >= 5) {
var swayThreshold = 0.7; // Start swaying when alignment drops below 70%
if (alignment < swayThreshold) {
self.isSwaying = true;
self.swayIntensity = Math.max(0.5, 1 - alignment); // More misalignment = more sway
} else {
// Good alignment reduces sway
self.swayIntensity *= 0.95;
if (self.swayIntensity < 0.1) {
self.isSwaying = false;
self.swayIntensity = 0;
}
}
}
if (self.isSwaying) {
// Apply sway physics
self.swayVelocity += Math.sin(LK.ticks * 0.05) * 0.0002 * self.swayIntensity;
self.swayVelocity *= 0.98; // Damping
self.swayAngle += self.swayVelocity;
self.swayAngle *= 0.99; // Angle damping
// Apply sway to tower position
var maxSway = 30 * self.swayIntensity;
self.x = gameWidth / 2 + Math.sin(self.swayAngle) * maxSway;
// Apply sway rotation to all bottles
for (var i = 0; i < self.bottles.length; i++) {
var bottle = self.bottles[i];
var swayRotation = Math.sin(self.swayAngle) * 0.05 * self.swayIntensity;
bottle.rotation = swayRotation;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF5F0E8
});
/****
* Game Code
****/
var gameWidth = 2048;
var gameHeight = 2732;
// Game state variables
var score = 0;
var gameActive = true;
var swingingBottle = null;
var fallingBottle = null;
var towersBuilt = 0;
var currentDifficulty = 1;
// Create tower
var tower = game.addChild(new Tower());
tower.x = gameWidth / 2;
tower.addBase();
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0x8B4513
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create instruction text
var instructionTxt = new Text2('Touch to release bottle', {
size: 60,
fill: 0xA0522D
});
instructionTxt.anchor.set(0.5, 0);
instructionTxt.y = 120;
LK.gui.top.addChild(instructionTxt);
// Spawn new swinging bottle
function spawnSwingingBottle() {
if (!gameActive || swingingBottle) {
return;
}
swingingBottle = new SwingingBottle();
swingingBottle.x = gameWidth / 2; // Center horizontally
swingingBottle.y = 150; // Position rope anchor point higher
// Apply difficulty scaling
var difficultyMultiplier = 1 + (currentDifficulty - 1) * 0.3;
swingingBottle.swingSpeed *= difficultyMultiplier;
swingingBottle.gravity *= difficultyMultiplier;
swingingBottle.maxSwingAngle = Math.min(Math.PI / 3, Math.PI / 4 * difficultyMultiplier);
// Add random initial swing with increased randomness based on difficulty
var randomness = 0.5 + (currentDifficulty - 1) * 0.2;
swingingBottle.angle = (Math.random() - 0.5) * randomness;
swingingBottle.angularVelocity = (Math.random() - 0.5) * 0.01 * difficultyMultiplier;
game.addChild(swingingBottle);
}
// Release bottle from rope
function releaseBottle() {
if (!swingingBottle || !gameActive) {
return;
}
// Create falling bottle at current swing position
fallingBottle = new FallenBottle();
// Get the actual world position of the swinging bottle
var swingOffset = Math.sin(swingingBottle.angle) * swingingBottle.ropeLength;
fallingBottle.x = swingingBottle.x + swingOffset;
fallingBottle.y = swingingBottle.y + 150; // Account for rope length
game.addChild(fallingBottle);
// Remove swinging bottle
swingingBottle.destroy();
swingingBottle = null;
LK.getSound('placeBottle').play();
}
// Check bottle landing
function checkBottleLanding() {
if (!fallingBottle || fallingBottle.placed) {
return;
}
var expectedLandingHeight = tower.getStackHeight();
// Check if bottle reached landing position
if (fallingBottle.y >= expectedLandingHeight) {
// Check if placement is valid
if (tower.checkValidPlacement(fallingBottle)) {
// Successful placement
tower.addBottle(fallingBottle);
// Create spray effect
var sprayEffect = game.addChild(LK.getAsset('sprayEffect', {
anchorX: 0.5,
anchorY: 0.5
}));
sprayEffect.x = fallingBottle.x;
sprayEffect.y = fallingBottle.y - 100;
sprayEffect.alpha = 0.8;
sprayEffect.scaleX = 0.5;
sprayEffect.scaleY = 0.5;
// Animate spray effect
tween(sprayEffect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
sprayEffect.destroy();
}
});
fallingBottle = null;
// Calculate score based on alignment
var alignment = tower.calculateAlignment();
var bottleScore = 10; // Base score
if (alignment >= 0.9) {
bottleScore = 50; // Perfect alignment bonus
}
score += bottleScore;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
// Check if tower is complete (every 5 bottles = 1 tower)
if (tower.bottles.length % 5 === 0) {
towersBuilt++;
currentDifficulty = Math.min(5, Math.floor(towersBuilt / 2) + 1); // Increase difficulty every 2 towers, max level 5
// Show tower completion effect with different colors based on alignment
var flashColor = alignment >= 0.9 ? 0xFFD700 : 0x90EE90; // Gold for perfect, green for good
LK.effects.flashScreen(flashColor, 500);
}
// Spawn next bottle after delay (shorter delay at higher difficulties)
var spawnDelay = Math.max(500, 1000 - (currentDifficulty - 1) * 100);
LK.setTimeout(function () {
spawnSwingingBottle();
}, spawnDelay);
} else {
// Missed placement - game over
gameActive = false;
LK.effects.flashScreen(0xFF6B6B, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
}
// Game input handling
game.down = function (x, y, obj) {
releaseBottle();
};
// Main game update loop
game.update = function () {
if (!gameActive) {
return;
}
// Update tower sway
tower.updateSway();
// Check bottle landing
checkBottleLanding();
// Check if falling bottle has gone off screen
if (fallingBottle && fallingBottle.y > gameHeight + 100) {
// Missed bottle - game over
gameActive = false;
LK.effects.flashScreen(0xFF6B6B, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
};
// Start the game by spawning first swinging bottle
LK.setTimeout(function () {
spawnSwingingBottle();
}, 1000); ===================================================================
--- original.js
+++ change.js
@@ -80,8 +80,13 @@
var Tower = Container.expand(function () {
var self = Container.call(this);
self.bottles = [];
self.baseHeight = 0;
+ self.swayAngle = 0;
+ self.swayVelocity = 0;
+ self.isSwaying = false;
+ self.swayIntensity = 0;
+ self.lastAlignment = 0;
// Add base platform
self.addBase = function () {
var base = self.attachAsset('bottleBase', {
anchorX: 0.5,
@@ -118,8 +123,55 @@
var baseTolerance = 200;
var tolerance = Math.max(80, baseTolerance - (currentDifficulty - 1) * 30);
return Math.abs(bottle.x - self.x) <= tolerance;
};
+ self.calculateAlignment = function () {
+ if (self.bottles.length < 2) return 1; // Perfect alignment for less than 2 bottles
+ var totalDeviation = 0;
+ var centerX = self.x;
+ for (var i = 0; i < self.bottles.length; i++) {
+ totalDeviation += Math.abs(self.bottles[i].x - centerX);
+ }
+ var averageDeviation = totalDeviation / self.bottles.length;
+ var maxAllowedDeviation = 100; // Perfect alignment threshold
+ var alignment = Math.max(0, 1 - averageDeviation / maxAllowedDeviation);
+ return alignment;
+ };
+ self.updateSway = function () {
+ var alignment = self.calculateAlignment();
+ self.lastAlignment = alignment;
+ // Start swaying if we have 5+ bottles and alignment is poor
+ if (self.bottles.length >= 5) {
+ var swayThreshold = 0.7; // Start swaying when alignment drops below 70%
+ if (alignment < swayThreshold) {
+ self.isSwaying = true;
+ self.swayIntensity = Math.max(0.5, 1 - alignment); // More misalignment = more sway
+ } else {
+ // Good alignment reduces sway
+ self.swayIntensity *= 0.95;
+ if (self.swayIntensity < 0.1) {
+ self.isSwaying = false;
+ self.swayIntensity = 0;
+ }
+ }
+ }
+ if (self.isSwaying) {
+ // Apply sway physics
+ self.swayVelocity += Math.sin(LK.ticks * 0.05) * 0.0002 * self.swayIntensity;
+ self.swayVelocity *= 0.98; // Damping
+ self.swayAngle += self.swayVelocity;
+ self.swayAngle *= 0.99; // Angle damping
+ // Apply sway to tower position
+ var maxSway = 30 * self.swayIntensity;
+ self.x = gameWidth / 2 + Math.sin(self.swayAngle) * maxSway;
+ // Apply sway rotation to all bottles
+ for (var i = 0; i < self.bottles.length; i++) {
+ var bottle = self.bottles[i];
+ var swayRotation = Math.sin(self.swayAngle) * 0.05 * self.swayIntensity;
+ bottle.rotation = swayRotation;
+ }
+ }
+ };
return self;
});
/****
@@ -230,18 +282,24 @@
sprayEffect.destroy();
}
});
fallingBottle = null;
- // Update score
- score += 10;
+ // Calculate score based on alignment
+ var alignment = tower.calculateAlignment();
+ var bottleScore = 10; // Base score
+ if (alignment >= 0.9) {
+ bottleScore = 50; // Perfect alignment bonus
+ }
+ score += bottleScore;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
// Check if tower is complete (every 5 bottles = 1 tower)
if (tower.bottles.length % 5 === 0) {
towersBuilt++;
currentDifficulty = Math.min(5, Math.floor(towersBuilt / 2) + 1); // Increase difficulty every 2 towers, max level 5
- // Show tower completion effect
- LK.effects.flashScreen(0x90EE90, 500); // Green flash for tower completion
+ // Show tower completion effect with different colors based on alignment
+ var flashColor = alignment >= 0.9 ? 0xFFD700 : 0x90EE90; // Gold for perfect, green for good
+ LK.effects.flashScreen(flashColor, 500);
}
// Spawn next bottle after delay (shorter delay at higher difficulties)
var spawnDelay = Math.max(500, 1000 - (currentDifficulty - 1) * 100);
LK.setTimeout(function () {
@@ -265,8 +323,10 @@
game.update = function () {
if (!gameActive) {
return;
}
+ // Update tower sway
+ tower.updateSway();
// Check bottle landing
checkBottleLanding();
// Check if falling bottle has gone off screen
if (fallingBottle && fallingBottle.y > gameHeight + 100) {