User prompt
agrega un boton para tutorial de instrucciones, agrega otro boton para apagar o prender la musica ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
agrega en total 10 arboles para lo mismo, el murcielago y el cubo flotante no deberan aparecer tan seguido
User prompt
agrega en total 10 casas y que no se sobrecargue es para tenervariedad
User prompt
agregaremos mas variedad de casas pon unas 10 casas pero no sobrecargues el fondo es solo para que tenga mejor visual
User prompt
quita las montañas porque queda muy cargado intenta que el fondo no quede sobrecargado
User prompt
el murcielago debe colicionar incluso uando sube y baja debe respetar su colision con el personaje
User prompt
NINGUN ELEMENTO DEL JUEGO DEBE PASAR ENCIMA DEL PERSONAJE PRINCIPAL
User prompt
los elementos decorativos del fondo deberan estar por detras de mi personaje tambien
User prompt
quisiera que pongamos elementos de fondo, como hicimos con las nubes pero a la altura del piso, como casas, montañas, etc
User prompt
la abeja no debe moverse tanto de arriba a abajo, el cubo tiene que estar un poco mas alto para que el personaje pase por ddebajo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
el murcielago debe volar mas rapido y verse mas en zic zac su animacion el cubo debe tener colision pero posicionarse mas alto ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
el vuelo de las abejas debe ser variado para algunas tener que saltarlas pero que no puedan dañar al personaje a la altura del piso, el cubo flotante debera estar mas alto, apenas sobre la cabeza del personaje principal, el murcielago debe volar mas en zic zac acercarse mas al suelo y volver a su posicion original ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
el aircube debe poder pasar por arriba de mi personaje, el murcielago quiero quen o sea tan animado que no cambie su proporcion de cuerpo y debera tener un ataque diferente, el vuela en zic zac de arriba a abajo constantemente ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
elimina el crystalspike y dale una nueva imagen al aircube,
User prompt
no quiero que cambie de tamaño el muercielago solo debera estar volando ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
se ve fea la animacion del muercielago hazla mas suave y el personaje del murcielago un poco mas grande respectando sus colisiones, respetando que no sea exagerado y pueda esquivarse ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
la abeja deve venir con su vuelo normal sin saltar tanto, solo apenas para que tenga una animacion dinamica, el nuevo obstaculo del suelo debe poder pasar por debajo sera un cubo en el aire ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
los dos ultimos nuevos personajes deberan tener su propia imagne y presentar un desafio nuevo, el volador puede bajar hasta el piso y subir a su posicion, tambien las abejas deberan variar la altura en la que vienen volando, pero siempre tiene que dar lugar a que el personaje principal pueda pasar, y las abejas nunca pueden tocar al personaje cuando este estatico en el piso ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
o sea las nubes seran 3 imagenes diferentes que puedes ir variando ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
vamos a agregar 3 nubes diferentes para que tengan mas viariacion, deberan notarse mas las cercanas con las lejanas, ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
repara las nubes ya que ahora es una imagen y por alguna razon se ve rara, deberan cambian el tamaño manteniendo la proporcion, deberan ser ubes aisladas no encimadas, que den la sensacion de avanzar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
todas las nubes deben tener la misma forma solo que algunas van mas detras y lento y las mas cercanas mas rapido ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
algunas nubes pasan por delante del logo
User prompt
repara el salto dejalo como estaba el salto normal con un solo click y el doble salto, agrega nuebes que pasaran volando, solo cuando es de dia, unas nubes volando mas grandes pasaran mas rapido y otras mas pequeñas pasaran mas lenta, com odecorando el cielo, o sea no deben tener animacion mas que ir pasando ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
las nubes deben tener la misma silueta solo que mas grandes o pequeñas, recupera el salto original y el doblee salto, porque me funciona mal el nuevo parametro
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AirCube = Container.expand(function () {
var self = Container.call(this);
// Create floating cube obstacle
var cubeGraphics = self.attachAsset('airCube', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.speed = 0;
self.passed = false;
self.floatOffset = Math.random() * Math.PI * 2;
self.baseY = 0; // Will be set when spawned
self.update = function () {
self.x -= self.speed;
// Gentle floating animation
self.y = self.baseY + Math.sin(LK.ticks * 0.04 + self.floatOffset) * 8;
// Subtle rotation
cubeGraphics.rotation = Math.sin(LK.ticks * 0.03) * 0.1;
};
return self;
});
var BackgroundElement = Container.expand(function () {
var self = Container.call(this);
// Create different types of background elements
var elementTypes = ['house1', 'house2', 'mountain1', 'mountain2', 'tree'];
var elementType = elementTypes[Math.floor(Math.random() * elementTypes.length)];
// Create depth-based layering for background elements
var isBackground = Math.random() < 0.5; // 50% chance to be background (far)
// Determine element size, alpha, and speed based on depth
var elementScale;
var alpha;
var speed;
if (isBackground) {
// Far background elements - smaller, slower, more transparent
elementScale = 0.4 + Math.random() * 0.3; // 0.4 to 0.7
alpha = 0.4 + Math.random() * 0.3; // 0.4 to 0.7
speed = 0.8 + Math.random() * 0.7; // 0.8 to 1.5
} else {
// Near background elements - larger, faster, more opaque
elementScale = 0.8 + Math.random() * 0.4; // 0.8 to 1.2
alpha = 0.6 + Math.random() * 0.3; // 0.6 to 0.9
speed = 1.5 + Math.random() * 1.0; // 1.5 to 2.5
}
// Create background element graphics
var elementGraphics = self.attachAsset(elementType, {
anchorX: 0.5,
anchorY: 1.0,
// Anchor at bottom for ground placement
scaleX: elementScale,
scaleY: elementScale,
alpha: alpha
});
// Apply slight tint variation for more natural look
var tintVariations = [0xffffff, 0xf8f8ff, 0xf0f8ff, 0xe6e6fa];
elementGraphics.tint = tintVariations[Math.floor(Math.random() * tintVariations.length)];
self.speed = speed;
self.elementType = elementType;
self.elementScale = elementScale;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Choose cloud type (0, 1, or 2)
var cloudType = Math.floor(Math.random() * 3);
// Create depth-based layering for clouds
var isBackground = Math.random() < 0.4; // 40% chance to be background (far)
var isMidground = !isBackground && Math.random() < 0.6; // 60% of remaining are midground
// Determine cloud size, alpha, and speed based on depth
var cloudScale;
var alpha;
var speed;
if (isBackground) {
// Far clouds - smallest, slowest, most transparent
cloudScale = 0.3 + Math.random() * 0.2; // 0.3 to 0.5
alpha = 0.3 + Math.random() * 0.2; // 0.3 to 0.5
speed = 0.5 + Math.random() * 0.5; // 0.5 to 1.0
} else if (isMidground) {
// Mid clouds - medium size, speed, and alpha
cloudScale = 0.6 + Math.random() * 0.3; // 0.6 to 0.9
alpha = 0.5 + Math.random() * 0.2; // 0.5 to 0.7
speed = 1.2 + Math.random() * 0.6; // 1.2 to 1.8
} else {
// Near clouds - largest, fastest, most opaque
cloudScale = 1.0 + Math.random() * 0.4; // 1.0 to 1.4
alpha = 0.7 + Math.random() * 0.2; // 0.7 to 0.9
speed = 2.0 + Math.random() * 1.0; // 2.0 to 3.0
}
// Choose cloud asset based on type
var cloudAssetId;
if (cloudType === 0) {
cloudAssetId = 'cloud1';
} else if (cloudType === 1) {
cloudAssetId = 'cloud2';
} else {
cloudAssetId = 'cloud3';
}
// Create single cloud image with proper scaling
var cloudGraphics = self.attachAsset(cloudAssetId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cloudScale,
scaleY: cloudScale,
alpha: alpha
});
// Apply slight tint variation for more natural look
var tintVariations = [0xffffff, 0xf8f8ff, 0xf0f8ff, 0xfafaff];
cloudGraphics.tint = tintVariations[Math.floor(Math.random() * tintVariations.length)];
self.speed = speed;
self.cloudScale = cloudScale;
self.cloudType = cloudType;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var Fluffball = Container.expand(function () {
var self = Container.call(this);
var fluffballGraphics = self.attachAsset('fluffball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.isJumping = false;
self.isDucking = false;
self.groundY = 0;
self.jumpPower = -35;
self.gravity = 0.8;
self.duckScale = 0.6;
self.normalScale = 1.0;
self.canDoubleJump = false;
self.hasDoubleJumped = false;
self.blinkTimer = 0;
self.isBlinking = false;
self.nextBlinkTime = 180; // Blink every 3 seconds (180 ticks at 60fps)
self.jump = function () {
if (!self.isJumping) {
self.velocityY = self.jumpPower;
self.isJumping = true;
self.canDoubleJump = true;
self.hasDoubleJumped = false;
LK.getSound('jump').play();
// Rotate backward during jump
tween(fluffballGraphics, {
rotation: -0.5
}, {
duration: 200,
easing: tween.easeOut
});
} else if (self.canDoubleJump && !self.hasDoubleJumped) {
// Double jump
self.velocityY = self.jumpPower * 0.8; // Slightly weaker second jump
self.hasDoubleJumped = true;
self.canDoubleJump = false;
LK.getSound('jump').play();
// Extra rotation for double jump
tween(fluffballGraphics, {
rotation: -0.8
}, {
duration: 150,
easing: tween.easeOut
});
}
};
self.startDuck = function () {
if (!self.isJumping) {
self.isDucking = true;
tween(fluffballGraphics, {
scaleY: self.duckScale
}, {
duration: 100
});
}
};
self.stopDuck = function () {
self.isDucking = false;
tween(fluffballGraphics, {
scaleY: self.normalScale
}, {
duration: 100
});
};
self.update = function () {
if (self.isJumping) {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Rotate forward when falling (positive velocity)
if (self.velocityY > 5) {
tween(fluffballGraphics, {
rotation: 0.3
}, {
duration: 150,
easing: tween.easeIn
});
}
if (self.y >= self.groundY) {
self.y = self.groundY;
self.velocityY = 0;
self.isJumping = false;
self.canDoubleJump = false;
self.hasDoubleJumped = false;
// Return to original rotation when landing
tween(fluffballGraphics, {
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
}
}
// Blinking animation
self.blinkTimer++;
if (self.blinkTimer >= self.nextBlinkTime && !self.isBlinking) {
self.isBlinking = true;
self.blinkTimer = 0;
self.nextBlinkTime = 180; // Reset timer for next blink (3 seconds)
// Remove current graphics and add blinking graphics
self.removeChild(fluffballGraphics);
fluffballGraphics = self.attachAsset('fluffballBlink', {
anchorX: 0.5,
anchorY: 0.5
});
// Switch back after blink duration
LK.setTimeout(function () {
if (self.isBlinking) {
// Remove blinking graphics and restore normal graphics
self.removeChild(fluffballGraphics);
fluffballGraphics = self.attachAsset('fluffball', {
anchorX: 0.5,
anchorY: 0.5
});
self.isBlinking = false;
}
}, 250); // Blink duration of 250ms (0.25 seconds)
}
// Bounce animation
if (!self.isJumping && LK.ticks % 30 == 0) {
tween(fluffballGraphics, {
scaleY: 1.1
}, {
duration: 150,
easing: tween.easeOut
});
tween(fluffballGraphics, {
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
};
return self;
});
var GummyBee = Container.expand(function () {
var self = Container.call(this);
var beeGraphics = self.attachAsset('gummyBee', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.passed = false;
self.bobOffset = Math.random() * Math.PI * 2;
self.baseY = 0; // Will be set when spawned
self.verticalRange = 25 + Math.random() * 30; // Reduced vertical movement range
self.verticalSpeed = 0.08 + Math.random() * 0.05; // Variable vertical speed
self.lastY = 0;
self.update = function () {
self.x -= self.speed;
// Initialize lastY if not set
if (self.lastY === undefined) self.lastY = self.y;
// Varied flight pattern - some bees fly high (requiring jumps), others fly low (safe at ground)
var verticalOffset = Math.sin(LK.ticks * self.verticalSpeed + self.bobOffset) * self.verticalRange;
self.y = self.baseY + verticalOffset;
// Wing rotation animation
beeGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.2;
// Scale animation for wing flapping
beeGraphics.scaleY = 1.0 + Math.sin(LK.ticks * 0.3) * 0.1;
// Update lastY
self.lastY = self.y;
};
return self;
});
var JellyObstacle = Container.expand(function () {
var self = Container.call(this);
var jellyGraphics = self.attachAsset('jellyObstacle', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = 0;
self.passed = false;
self.update = function () {
self.x -= self.speed;
// Wobble animation
jellyGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.1;
jellyGraphics.scaleY = 1 + Math.cos(LK.ticks * 0.08) * 0.05;
};
return self;
});
var ShadowBat = Container.expand(function () {
var self = Container.call(this);
var batGraphics = self.attachAsset('shadowBat', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.passed = false;
self.zigzagDirection = 1; // 1 for up, -1 for down
self.zigzagSpeed = 6; // Increased vertical movement speed for faster zigzag
self.zigzagRange = 150; // How far up/down to move
self.startY = 0; // Starting Y position
self.lastY = 0;
self.update = function () {
self.x -= self.speed;
// Initialize lastY if not set
if (self.lastY === undefined) self.lastY = self.y;
// Initialize startY if not set
if (self.startY === 0) self.startY = self.y;
// Enhanced zigzag movement - goes much closer to ground with faster movement
self.y += self.zigzagDirection * self.zigzagSpeed;
// Calculate ground proximity - bat can get within 120px of ground
var maxGroundApproach = self.groundY - 120;
// Change direction when reaching limits - goes closer to ground now
if (self.y <= self.startY - self.zigzagRange) {
self.zigzagDirection = 1; // Change to downward
} else if (self.y >= maxGroundApproach) {
self.zigzagDirection = -1; // Change to upward - return to original position
}
// More pronounced wing animation for faster zigzag effect
batGraphics.rotation = Math.sin(LK.ticks * 0.4) * 0.15; // More visible rotation for zigzag effect
// Update lastY
self.lastY = self.y;
};
return self;
});
var SparkleGem = Container.expand(function () {
var self = Container.call(this);
var gemGraphics = self.attachAsset('sparkleGem', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.collected = false;
self.update = function () {
self.x -= self.speed;
// Sparkle animation
gemGraphics.rotation += 0.1;
gemGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.2) * 0.3;
gemGraphics.scaleY = 1 + Math.cos(LK.ticks * 0.2) * 0.3;
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.twinkleSpeed = 0.02 + Math.random() * 0.03;
self.twinkleOffset = Math.random() * Math.PI * 2;
self.minAlpha = 0.3;
self.maxAlpha = 1.0;
self.minScale = 0.3;
self.maxScale = 1.5;
self.scaleSpeed = 0.01 + Math.random() * 0.02;
self.scaleOffset = Math.random() * Math.PI * 2;
self.disappearTimer = Math.random() * 600 + 300; // Random time between 5-15 seconds
self.isDisappearing = false;
self.disappearDuration = 0;
self.reappearDelay = 0;
self.update = function () {
// Create twinkling effect with random timing
var twinkle = Math.sin(LK.ticks * self.twinkleSpeed + self.twinkleOffset);
starGraphics.alpha = self.minAlpha + (self.maxAlpha - self.minAlpha) * (twinkle + 1) / 2;
// Dynamic scale changes
var scaleVariation = Math.sin(LK.ticks * self.scaleSpeed + self.scaleOffset);
var targetScale = self.minScale + (self.maxScale - self.minScale) * (scaleVariation + 1) / 2;
starGraphics.scaleX = targetScale;
starGraphics.scaleY = targetScale;
// Disappear and reappear cycle
self.disappearTimer--;
if (self.disappearTimer <= 0 && !self.isDisappearing) {
self.isDisappearing = true;
self.disappearDuration = Math.random() * 120 + 60; // Disappear for 1-3 seconds
self.reappearDelay = Math.random() * 300 + 180; // Reappear after 3-8 seconds
// Fade out
tween(starGraphics, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500 + Math.random() * 1000,
easing: tween.easeOut
});
}
if (self.isDisappearing) {
self.disappearDuration--;
if (self.disappearDuration <= 0) {
self.reappearDelay--;
if (self.reappearDelay <= 0) {
// Reset star state and fade back in
self.isDisappearing = false;
self.disappearTimer = Math.random() * 900 + 600; // Next disappear cycle
// Fade in with new random properties
self.twinkleSpeed = 0.02 + Math.random() * 0.03;
self.scaleSpeed = 0.01 + Math.random() * 0.02;
tween(starGraphics, {
alpha: self.maxAlpha,
scaleX: 1,
scaleY: 1
}, {
duration: 800 + Math.random() * 1200,
easing: tween.easeIn
});
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Game variables
var gameSpeed = 6;
var speedIncrement = 0.002;
var maxSpeed = 12;
var isGameRunning = true;
var perfectPassBonus = 10;
var gemValue = 5;
// Background variables
var currentTheme = 'day';
var isTransitioning = false;
var stars = [];
var starsContainer;
// Background setup
var dayBg = game.addChild(LK.getAsset('dayBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
var nightBg = game.addChild(LK.getAsset('nightBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 0
}));
// Ground setup
var groundY = 2732 - 500;
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY
}));
// Underground brown rectangle
var underground = game.addChild(LK.getAsset('underground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY + 200
}));
// Create stars container for night theme
starsContainer = game.addChild(new Container());
starsContainer.alpha = 0;
// Generate twinkling stars
for (var i = 0; i < 150; i++) {
var star = starsContainer.addChild(new Star());
star.x = Math.random() * 2048;
star.y = Math.random() * (2732 * 0.6); // Stars only in upper 60% of screen
stars.push(star);
}
// Player setup
var fluffball = game.addChild(new Fluffball());
fluffball.scaleX = 1.2;
fluffball.scaleY = 1.2;
fluffball.x = 300;
fluffball.y = groundY - 80;
fluffball.groundY = groundY - 80;
// Arrays for game objects
var jellyObstacles = [];
var gummyBees = [];
var sparkleGems = [];
var shadowBats = [];
var airCubes = [];
var clouds = [];
var backgroundElements = [];
// Create clouds container for day theme
var cloudsContainer = game.addChild(new Container());
// Create background elements container (behind character)
var backgroundElementsContainer = game.addChild(new Container());
// Timers for spawning
var obstacleSpawnTimer = 0;
var gemSpawnTimer = 0;
// Input tracking
var isHolding = false;
var lastClickTime = 0;
var doubleClickDelay = 300; // Maximum time between clicks for double click (ms)
// Score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
font: "'Arial Black', 'Helvetica', sans-serif"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 100;
// Speed display
var speedTxt = new Text2('SPEED: 1x', {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
speedTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(speedTxt);
speedTxt.x = -50;
speedTxt.y = 50;
// Functions
function spawnJellyObstacle() {
var obstacle = game.addChild(new JellyObstacle());
obstacle.scaleX = 1.3;
obstacle.scaleY = 1.3;
obstacle.x = 2048 + 100;
obstacle.y = groundY;
obstacle.speed = gameSpeed;
jellyObstacles.push(obstacle);
}
function spawnGummyBee() {
var bee = game.addChild(new GummyBee());
bee.scaleX = 1.3;
bee.scaleY = 1.3;
bee.x = 2048 + 100;
// Create varied flight patterns - some high (requiring jumps), some low (safe at ground)
var flightType = Math.random();
if (flightType < 0.4) {
// High flying bees that require jumping (40% chance)
var baseHeight = groundY - 250 - Math.random() * 150;
bee.verticalRange = 15 + Math.random() * 20; // Much smaller range for high flyers
} else {
// Low flying bees that are safe when character is on ground (60% chance)
var baseHeight = groundY - 150 - Math.random() * 100;
bee.verticalRange = 20 + Math.random() * 30; // Reduced range for low flyers
}
bee.y = baseHeight;
bee.baseY = baseHeight;
bee.speed = gameSpeed;
gummyBees.push(bee);
}
function spawnSparkleGem() {
var gem = game.addChild(new SparkleGem());
gem.scaleX = 1.2;
gem.scaleY = 1.2;
gem.x = 2048 + 100;
gem.y = groundY - 150 - Math.random() * 350;
gem.speed = gameSpeed;
sparkleGems.push(gem);
}
function spawnShadowBat() {
var bat = game.addChild(new ShadowBat());
bat.x = 2048 + 100;
bat.y = groundY - 350 - Math.random() * 200;
bat.speed = gameSpeed;
bat.groundY = groundY; // Set ground reference for diving
bat.zigzagRange = 200 + Math.random() * 100; // Increased range for more dramatic movement
bat.zigzagSpeed = 4 + Math.random() * 2; // Slightly faster zigzag
shadowBats.push(bat);
}
function spawnAirCube() {
var cube = game.addChild(new AirCube());
cube.x = 2048 + 100;
cube.y = groundY - 280; // Much higher position for character to pass underneath
cube.baseY = groundY - 280;
cube.speed = gameSpeed;
airCubes.push(cube);
}
function spawnCloud() {
var cloud = cloudsContainer.addChild(new Cloud());
cloud.x = 2048 + 200;
cloud.y = 200 + Math.random() * 800; // Clouds in upper portion of sky
clouds.push(cloud);
}
function spawnBackgroundElement() {
var element = backgroundElementsContainer.addChild(new BackgroundElement());
element.x = 2048 + 300;
element.y = groundY; // Position at ground level
backgroundElements.push(element);
}
function transitionBackground(newTheme) {
if (isTransitioning || currentTheme === newTheme) return;
isTransitioning = true;
if (newTheme === 'night') {
// Transition to night
tween(dayBg, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeInOut
});
tween(nightBg, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeInOut
});
// Show twinkling stars during night
tween(starsContainer, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
currentTheme = 'night';
isTransitioning = false;
}
});
// Hide clouds during night
tween(cloudsContainer, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeInOut
});
} else {
// Transition to day
tween(nightBg, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeInOut
});
tween(dayBg, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeInOut
});
// Hide twinkling stars during day
tween(starsContainer, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
currentTheme = 'day';
isTransitioning = false;
}
});
// Show clouds during day
tween(cloudsContainer, {
alpha: 1
}, {
duration: 2000,
easing: tween.easeInOut
});
}
}
function checkCollisions() {
// Check jelly obstacles
for (var i = jellyObstacles.length - 1; i >= 0; i--) {
var obstacle = jellyObstacles[i];
// Initialize last intersection state if not set
if (obstacle.lastIntersecting === undefined) {
obstacle.lastIntersecting = false;
}
var currentIntersecting = fluffball.intersects(obstacle);
// Only trigger collision on the exact frame when intersection starts
if (!obstacle.lastIntersecting && currentIntersecting) {
// Game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Update last intersection state
obstacle.lastIntersecting = currentIntersecting;
// Perfect pass bonus
if (!obstacle.passed && obstacle.x < fluffball.x - 50) {
obstacle.passed = true;
LK.setScore(LK.getScore() + perfectPassBonus);
// Animate score text
tween(scoreTxt, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
}
// Remove off-screen obstacles
if (obstacle.x < -100) {
obstacle.destroy();
jellyObstacles.splice(i, 1);
}
}
// Check gummy bees
for (var i = gummyBees.length - 1; i >= 0; i--) {
var bee = gummyBees[i];
var canCollide = true;
// If fluffball is on ground, prevent collision with bees flying too high
if (!fluffball.isJumping) {
// Character collision area when on ground - extends from feet to head
var fluffballTop = fluffball.y - 80; // Top of character
var fluffballBottom = fluffball.y + 80; // Bottom of character
// Only collide if bee is within the character's ground-level collision zone
if (bee.y < fluffballTop - 20) {
// Bee is too high above character when on ground - no collision
canCollide = false;
}
}
// Initialize last intersection state if not set
if (bee.lastIntersecting === undefined) {
bee.lastIntersecting = false;
}
var currentIntersecting = fluffball.intersects(bee) && canCollide;
// Only trigger collision on the exact frame when intersection starts
if (!bee.lastIntersecting && currentIntersecting) {
// Game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Update last intersection state
bee.lastIntersecting = currentIntersecting;
// Perfect pass bonus
if (!bee.passed && bee.x < fluffball.x - 50) {
bee.passed = true;
LK.setScore(LK.getScore() + perfectPassBonus);
// Animate score text
tween(scoreTxt, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
}
// Remove off-screen bees
if (bee.x < -100) {
bee.destroy();
gummyBees.splice(i, 1);
}
}
// Check sparkle gems
for (var i = sparkleGems.length - 1; i >= 0; i--) {
var gem = sparkleGems[i];
// Initialize last intersection state if not set
if (gem.lastIntersecting === undefined) {
gem.lastIntersecting = false;
}
var currentIntersecting = fluffball.intersects(gem) && !gem.collected;
// Only trigger collection on the exact frame when intersection starts
if (!gem.lastIntersecting && currentIntersecting) {
gem.collected = true;
LK.setScore(LK.getScore() + gemValue);
LK.getSound('collect').play();
LK.effects.flashObject(gem, 0xffffff, 200);
// Animate score text
tween(scoreTxt, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Remove gem with tween
tween(gem, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 200,
onFinish: function onFinish() {
gem.destroy();
}
});
sparkleGems.splice(i, 1);
} else if (gem.x < -100) {
gem.destroy();
sparkleGems.splice(i, 1);
}
// Update last intersection state
gem.lastIntersecting = currentIntersecting;
}
// Check shadow bats
for (var i = shadowBats.length - 1; i >= 0; i--) {
var bat = shadowBats[i];
var canCollide = true;
// If fluffball is on ground, only allow collision with lower part (not head)
if (!fluffball.isJumping) {
// Character head is roughly in the upper 40% of the sprite
var fluffballHeadTop = fluffball.y - 64; // Half of fluffball height (160/2 = 80, head is upper 80% so 64px)
var fluffballBodyBottom = fluffball.y + 32; // Lower part of character
// Only collide if bat is hitting the lower part of character, not the head
if (bat.y < fluffballHeadTop + 32) {
// Add small buffer for head protection
canCollide = false;
}
}
// Initialize last intersection state if not set
if (bat.lastIntersecting === undefined) {
bat.lastIntersecting = false;
}
var currentIntersecting = fluffball.intersects(bat) && canCollide;
// Only trigger collision on the exact frame when intersection starts
if (!bat.lastIntersecting && currentIntersecting) {
// Game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Update last intersection state
bat.lastIntersecting = currentIntersecting;
// Perfect pass bonus
if (!bat.passed && bat.x < fluffball.x - 50) {
bat.passed = true;
LK.setScore(LK.getScore() + perfectPassBonus);
// Animate score text
tween(scoreTxt, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
}
// Remove off-screen bats
if (bat.x < -100) {
bat.destroy();
shadowBats.splice(i, 1);
}
}
// Check air cubes - with collision detection enabled
for (var i = airCubes.length - 1; i >= 0; i--) {
var cube = airCubes[i];
// Initialize last intersection state if not set
if (cube.lastIntersecting === undefined) {
cube.lastIntersecting = false;
}
var currentIntersecting = fluffball.intersects(cube);
// Only trigger collision on the exact frame when intersection starts
if (!cube.lastIntersecting && currentIntersecting) {
// Game over
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return;
}
// Update last intersection state
cube.lastIntersecting = currentIntersecting;
// Perfect pass bonus
if (!cube.passed && cube.x < fluffball.x - 50) {
cube.passed = true;
LK.setScore(LK.getScore() + perfectPassBonus);
// Animate score text
tween(scoreTxt, {
tint: 0xFF0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
tint: 0xFFFFFF,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
}
// Remove off-screen cubes
if (cube.x < -100) {
cube.destroy();
airCubes.splice(i, 1);
}
}
}
// Input handlers
game.down = function (x, y, obj) {
if (isGameRunning) {
var currentTime = Date.now();
var timeSinceLastClick = currentTime - lastClickTime;
// Check for double click
if (timeSinceLastClick < doubleClickDelay) {
// Double click detected - trigger double jump immediately
fluffball.jump();
} else {
// Single click - trigger jump immediately
fluffball.jump();
}
lastClickTime = currentTime;
isHolding = true;
// Start ducking after a short delay if still holding
LK.setTimeout(function () {
if (isHolding) {
fluffball.startDuck();
}
}, 200);
}
};
game.up = function (x, y, obj) {
isHolding = false;
fluffball.stopDuck();
};
// Main game loop
game.update = function () {
if (!isGameRunning) return;
// Increase speed gradually
if (gameSpeed < maxSpeed) {
gameSpeed += speedIncrement;
}
// Update speed display
var speedMultiplier = Math.floor(gameSpeed / 6 * 10) / 10;
speedTxt.setText('SPEED: ' + speedMultiplier + 'x');
// Update score display
scoreTxt.setText(LK.getScore().toString());
// Spawn obstacles with increased spacing
obstacleSpawnTimer++;
if (obstacleSpawnTimer > 160 - gameSpeed * 4) {
obstacleSpawnTimer = 0;
var randomValue = Math.random();
if (randomValue < 0.35) {
spawnJellyObstacle();
} else if (randomValue < 0.65) {
spawnGummyBee();
} else if (randomValue < 0.85) {
spawnShadowBat();
} else {
spawnAirCube();
}
}
// Spawn gems with increased spacing
gemSpawnTimer++;
if (gemSpawnTimer > 220) {
gemSpawnTimer = 0;
if (Math.random() < 0.4) {
spawnSparkleGem();
}
}
// Update all objects speeds
for (var i = 0; i < jellyObstacles.length; i++) {
jellyObstacles[i].speed = gameSpeed;
}
for (var i = 0; i < gummyBees.length; i++) {
gummyBees[i].speed = gameSpeed;
}
for (var i = 0; i < sparkleGems.length; i++) {
sparkleGems[i].speed = gameSpeed;
}
for (var i = 0; i < shadowBats.length; i++) {
shadowBats[i].speed = gameSpeed;
}
for (var i = 0; i < airCubes.length; i++) {
airCubes[i].speed = gameSpeed;
}
// Spawn clouds only during day theme
if (currentTheme === 'day' && Math.random() < 0.005) {
// Low spawn rate for decoration
spawnCloud();
}
// Spawn background elements at ground level
if (Math.random() < 0.008) {
// Spawn rate for ground-level scenery
spawnBackgroundElement();
}
// Update and manage clouds
for (var i = clouds.length - 1; i >= 0; i--) {
var cloud = clouds[i];
if (cloud.x < -300) {
// Remove off-screen clouds
cloud.destroy();
clouds.splice(i, 1);
}
}
// Update and manage background elements
for (var i = backgroundElements.length - 1; i >= 0; i--) {
var element = backgroundElements[i];
if (element.x < -400) {
// Remove off-screen background elements
element.destroy();
backgroundElements.splice(i, 1);
}
}
// Check collisions
checkCollisions();
// Background transition based on score every 100 points
var score = LK.getScore();
var scoreThreshold = Math.floor(score / 100);
if (scoreThreshold % 2 === 1) {
// Odd hundreds (100, 300, 500...) = night
transitionBackground('night');
} else {
// Even hundreds (0, 200, 400...) = day
transitionBackground('day');
}
};
// Game logo setup
var gameLogo = game.addChild(LK.getAsset('gameLogo', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 800,
alpha: 0.7,
scaleX: 0.6,
scaleY: 0.6
}));
// Move clouds container after logo so some clouds can pass in front of it
game.removeChild(cloudsContainer);
game.addChild(cloudsContainer);
// Start breathing animation for logo
function startLogoBreathing() {
tween(gameLogo, {
scaleX: 1.02,
scaleY: 1.02
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(gameLogo, {
scaleX: 0.98,
scaleY: 0.98
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
startLogoBreathing(); // Loop the animation
}
});
}
});
}
// Start the breathing animation
startLogoBreathing();
// Start background music
LK.playMusic('backgroundMusic');
; ===================================================================
--- original.js
+++ change.js
@@ -506,8 +506,10 @@
var clouds = [];
var backgroundElements = [];
// Create clouds container for day theme
var cloudsContainer = game.addChild(new Container());
+// Create background elements container (behind character)
+var backgroundElementsContainer = game.addChild(new Container());
// Timers for spawning
var obstacleSpawnTimer = 0;
var gemSpawnTimer = 0;
// Input tracking
@@ -600,9 +602,9 @@
cloud.y = 200 + Math.random() * 800; // Clouds in upper portion of sky
clouds.push(cloud);
}
function spawnBackgroundElement() {
- var element = game.addChild(new BackgroundElement());
+ var element = backgroundElementsContainer.addChild(new BackgroundElement());
element.x = 2048 + 300;
element.y = groundY; // Position at ground level
backgroundElements.push(element);
}
Chibi style, incredibly cute, perfectly round, puffy creature. **It has no visible legs or limbs, appearing as a soft, adorable ball with a friendly, expressive face (big, innocent eyes and a small smile).** Implied motion is a gentle bounce or glide. Predominant color: light pink with subtle fluffy texture. Minimalist, clean lines, vibrant colors. Solid light blue background. Mobile game character asset, running/gliding animation frame.. In-Game asset. 2d. High contrast. No shadows
ojos cerrados
Kawaii, cute, pink logo for 'Fluffball's Endless Adventure'. The design should feature a whimsical, bubbly, and rounded font for the text, with soft, sweet aesthetics and subtle playful elements integrated into the typography itself (e.g., tiny sparkles, soft gradients, or a slight bouncy feel to the letters). No character or drawing should be included, only the stylized text.. In-Game asset. 2d. High contrast. No shadows
nube blanca sin bordes minimalista, silueta unica y original. In-Game asset. 2d. High contrast. No shadows
circulo blanco sin bordes. In-Game asset. 2d. High contrast. No shadows
kawaii shadown bat de lado. In-Game asset. 2d. High contrast. No shadows
pink cute rec tangle kawaii. In-Game asset. 2d. High contrast. No shadows
a single simple kawaii tree without outlines and no face, for a non-distracting game background. In-Game asset. 2d. High contrast. No shadows
a single simple kawaii house without outlines and no face, for a non-distracting game background. In-Game asset. 2d. High contrast. No shadows
a single simple kawaii house without outlines and no face, for a non-distracting game background. In-Game asset. 2d. High contrast. No shadows
a single simple kawaii house without outlines and no face, for a non-distracting game background. In-Game asset. 2d. High contrast. No shadows