Code edit (3 edits merged)
Please save this source code
Code edit (4 edits merged)
Please save this source code
User prompt
add something that shows what Barry you are selecting
User prompt
I'm saying like the berries from the menu are still bouncing when you're in the game making the bounce sound
User prompt
The berries are still bouncing while invisible
User prompt
Fix the bug where there are invisible berries bouncing
User prompt
Add a character to select with five different characters
User prompt
add a main menu
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Blueberry = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('blueberry', {
anchorX: 0.5,
anchorY: 0.5
});
self.baseSize = 80;
self.growthFactor = 1.0;
self.velocityX = 0;
self.velocityY = 0;
self.friction = 0.95;
self.bounceForce = 1.2;
self.lastBounced = false;
self.bounceCooldown = 0;
self.grow = function () {
self.growthFactor += 0.03;
graphics.scaleX = self.growthFactor;
graphics.scaleY = self.growthFactor;
};
self.getBounds = function () {
var radius = self.baseSize * self.growthFactor / 2;
return {
left: self.x - radius,
right: self.x + radius,
top: self.y - radius,
bottom: self.y + radius,
radius: radius
};
};
self.update = function () {
// Apply gravity only when not being dragged
if (dragNode !== self) {
self.velocityY += gravity;
}
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityX *= self.friction;
self.velocityY *= self.friction;
// Continuous rolling based on horizontal movement
if (Math.abs(self.velocityX) > 0.05) {
var rollDirection = self.velocityX > 0 ? 1 : -1;
graphics.rotation += rollDirection * Math.abs(self.velocityX) * 0.02;
}
var bounds = self.getBounds();
var bounced = false;
if (bounds.left <= 0) {
self.x = bounds.radius;
self.velocityX = Math.abs(self.velocityX) * self.bounceForce;
bounced = true;
// Add rolling animation when bouncing off left wall
if (Math.abs(self.velocityX) > 0.1) {
var rollSpeed = Math.abs(self.velocityX) * 0.1;
tween(graphics, {
rotation: graphics.rotation + Math.PI * 2
}, {
duration: 1000 / rollSpeed,
easing: tween.linear
});
}
}
if (bounds.right >= 2048) {
self.x = 2048 - bounds.radius;
self.velocityX = -Math.abs(self.velocityX) * self.bounceForce;
bounced = true;
// Add rolling animation when bouncing off right wall
if (Math.abs(self.velocityX) > 0.1) {
var rollSpeed = Math.abs(self.velocityX) * 0.2;
tween(graphics, {
rotation: graphics.rotation - Math.PI * 2
}, {
duration: 1000 / rollSpeed,
easing: tween.linear
});
}
}
if (bounds.top <= 0) {
self.y = bounds.radius;
self.velocityY = Math.abs(self.velocityY) * self.bounceForce;
bounced = true;
}
// Ground collision instead of bottom screen edge
if (bounds.bottom >= groundLevel) {
self.y = groundLevel - bounds.radius;
self.velocityY = -Math.abs(self.velocityY) * self.bounceForce;
bounced = true;
// Create dust particles when hitting ground with significant velocity
if (Math.abs(self.velocityY) > 3 || Math.abs(self.velocityX) > 3) {
for (var d = 0; d < 5; d++) {
createDustParticle(self.x, groundLevel);
}
}
// Stop trailing when landing
if (isTrailing && Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 2) {
isTrailing = false;
}
// Add rolling animation when hitting ground
if (Math.abs(self.velocityX) > 0.1) {
var rollDirection = self.velocityX > 0 ? 1 : -1;
var rollSpeed = Math.abs(self.velocityX) * 0.1;
tween(graphics, {
rotation: graphics.rotation + rollDirection * Math.PI * 2
}, {
duration: 1000 / rollSpeed,
easing: tween.linear
});
}
}
// Create trail particles when moving fast
if (isTrailing && (Math.abs(self.velocityX) > 1 || Math.abs(self.velocityY) > 1)) {
if (LK.ticks % 3 === 0) {
// Create particle every 3 frames
createTrailParticle(self.x, self.y);
}
}
// Update bounce cooldown
if (self.bounceCooldown > 0) {
self.bounceCooldown--;
}
// Only play bounce sound when transitioning from not bounced to bounced
// and cooldown has expired and there's significant velocity
if (bounced && !self.lastBounced && self.bounceCooldown === 0 && (Math.abs(self.velocityX) > 2 || Math.abs(self.velocityY) > 2)) {
LK.getSound('bounce').play();
self.bounceCooldown = 1; // 1 frames cooldown (~0.33 seconds at 60fps)
}
self.lastBounced = bounced;
};
return self;
});
var GoldenBerry = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('goldenBerry', {
anchorX: 0.5,
anchorY: 0.5
});
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.05;
self.startY = 0;
self.update = function () {
self.y = self.startY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 10;
};
return self;
});
var RedThorn = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('redThorn', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.rotation = Math.PI / 1;
self.pulseOffset = Math.random() * Math.PI * 2;
self.pulseSpeed = 0.08;
self.update = function () {
var pulse = 1 + Math.sin(LK.ticks * self.pulseSpeed + self.pulseOffset) * 0.1;
graphics.scaleX = pulse;
graphics.scaleY = pulse;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x9edbf3
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu', 'playing'
var menuContainer = game.addChild(new Container());
// Main menu setup
var titleText = new Text2('BLUEBERRY ADVENTURE!', {
size: 120,
fill: 0x4169E1
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
menuContainer.addChild(titleText);
var instructionText = new Text2('Help the hungry blueberry\neat golden berries!\n\nDrag and throw him around\nto collect food and avoid\nthe red thorns!', {
size: 80,
fill: 0x333333
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1000;
menuContainer.addChild(instructionText);
var startText = new Text2('TAP TO START', {
size: 100,
fill: 0xFF6B35
});
startText.anchor.set(0.5, 0.5);
startText.x = 1024;
startText.y = 1600;
menuContainer.addChild(startText);
// Blueberry setup (initially hidden)
var blueberry = game.addChild(new Blueberry());
blueberry.x = 1024;
blueberry.y = 1366;
blueberry.visible = false;
var goldenBerries = [];
var redThorns = [];
var dragNode = null;
var lastMouseX = 0;
var lastMouseY = 0;
var thornSpawnTimer = 0;
var berrySpawnTimer = 0;
var gravity = 0.8;
var groundLevel = 2632; // 100px from bottom of screen
var trailParticles = [];
var isTrailing = false;
function createTrailParticle(x, y) {
var particle = LK.getAsset('blueberry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.8
});
particle.x = x;
particle.y = y;
particle.life = 30; // frames to live
particle.maxLife = 30;
trailParticles.push(particle);
game.addChild(particle);
}
var dustParticles = [];
function createDustParticle(x, y) {
var particle = LK.getAsset('blueberry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
alpha: 0.6,
tint: 0xD2B48C
});
particle.x = x + (Math.random() - 0.5) * 60;
particle.y = y;
particle.velocityX = (Math.random() - 0.5) * 4;
particle.velocityY = -(Math.random() * 3 + 1);
particle.life = 40;
particle.maxLife = 40;
dustParticles.push(particle);
game.addChild(particle);
}
// Menu blueberry for decoration
var menuBlueberry = menuContainer.addChild(new Blueberry());
menuBlueberry.x = 1024;
menuBlueberry.y = 1300;
// Animate menu blueberry
tween(menuBlueberry, {
y: 1250
}, {
duration: 2000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
// Animate start text pulsing
tween(startText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.visible = false; // Initially hidden
function spawnGoldenBerry() {
var berry = new GoldenBerry();
var margin = 50;
berry.x = margin + Math.random() * (2048 - margin * 2);
berry.y = margin + Math.random() * (groundLevel - margin * 2);
berry.startY = berry.y;
var tooClose = true;
var attempts = 0;
while (tooClose && attempts < 20) {
tooClose = false;
var berryBounds = {
x: berry.x,
y: berry.y,
radius: 20
};
var blueberryBounds = blueberry.getBounds();
var dist = Math.sqrt(Math.pow(berry.x - blueberry.x, 2) + Math.pow(berry.y - blueberry.y, 2));
if (dist < blueberryBounds.radius + 100) {
berry.x = margin + Math.random() * (2048 - margin * 2);
berry.y = margin + Math.random() * (groundLevel - margin * 2);
berry.startY = berry.y;
tooClose = true;
}
// Check distance from all red thorns
for (var k = 0; k < redThorns.length; k++) {
var thornDist = Math.sqrt(Math.pow(berry.x - redThorns[k].x, 2) + Math.pow(berry.y - redThorns[k].y, 2));
if (thornDist < 120) {
berry.x = margin + Math.random() * (2048 - margin * 2);
berry.y = margin + Math.random() * (groundLevel - margin * 2);
berry.startY = berry.y;
tooClose = true;
break;
}
// Update trail particles
for (var t = trailParticles.length - 1; t >= 0; t--) {
var particle = trailParticles[t];
particle.life--;
// Fade out particle
particle.alpha = particle.life / particle.maxLife * 0.2;
particle.scaleX = particle.life / particle.maxLife * 0.1;
particle.scaleY = particle.life / particle.maxLife * 0.1;
// Remove dead particles
if (particle.life <= 0) {
particle.destroy();
trailParticles.splice(t, 1);
}
}
}
;
attempts++;
}
goldenBerries.push(berry);
game.addChild(berry);
}
function spawnRedThorn() {
var thorn = new RedThorn();
var margin = 50;
thorn.x = margin + Math.random() * (2048 - margin * 2);
thorn.y = margin + Math.random() * (groundLevel - margin * 2);
var tooClose = true;
var attempts = 0;
while (tooClose && attempts < 15) {
tooClose = false;
var blueberryBounds = blueberry.getBounds();
var dist = Math.sqrt(Math.pow(thorn.x - blueberry.x, 2) + Math.pow(thorn.y - blueberry.y, 2));
if (dist < blueberryBounds.radius + 200) {
thorn.x = margin + Math.random() * (2048 - margin * 2);
thorn.y = margin + Math.random() * (groundLevel - margin * 2);
tooClose = true;
}
attempts++;
}
redThorns.push(thorn);
game.addChild(thorn);
}
function handleMove(x, y, obj) {
if (dragNode) {
var deltaX = x - lastMouseX;
var deltaY = y - lastMouseY;
// Instead of teleporting, smoothly move towards target position
var targetX = x;
var targetY = y;
var currentX = dragNode.x;
var currentY = dragNode.y;
// Smooth interpolation towards target position
var lerpFactor = 0.15;
dragNode.x = currentX + (targetX - currentX) * lerpFactor;
dragNode.y = currentY + (targetY - currentY) * lerpFactor;
dragNode.velocityX = deltaX * 0.3;
dragNode.velocityY = deltaY * 0.3;
}
lastMouseX = x;
lastMouseY = y;
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (gameState === 'menu') {
startGame();
return;
}
dragNode = blueberry;
lastMouseX = x;
lastMouseY = y;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (dragNode) {
// Calculate throw velocity based on drag distance and speed
var throwMultiplier = 0.5;
var maxThrowSpeed = 15;
// Use the current velocity from dragging as throw velocity
var throwVelX = Math.max(-maxThrowSpeed, Math.min(maxThrowSpeed, dragNode.velocityX * throwMultiplier));
var throwVelY = Math.max(-maxThrowSpeed, Math.min(maxThrowSpeed, dragNode.velocityY * throwMultiplier));
// Apply the throw velocity to the blueberry
dragNode.velocityX = throwVelX;
dragNode.velocityY = throwVelY;
// Start trailing effect if there's significant velocity
if (Math.abs(throwVelX) > 2 || Math.abs(throwVelY) > 2) {
isTrailing = true;
}
// Add throwing effect - scale bounce animation
var blueberryGraphics = dragNode.children[0]; // Get the graphics child
var currentGrowthFactor = dragNode.growthFactor; // Store growth factor before clearing dragNode
if (blueberryGraphics) {
// Stop any existing scale tweens
tween.stop(blueberryGraphics, {
scaleX: true,
scaleY: true
});
// Create throwing effect with scale bounce
tween(blueberryGraphics, {
scaleX: currentGrowthFactor * 1.3,
scaleY: currentGrowthFactor * 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(blueberryGraphics, {
scaleX: currentGrowthFactor,
scaleY: currentGrowthFactor
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
}
dragNode = null;
};
// Create ground visual (initially hidden)
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
}));
ground.x = 0;
ground.y = groundLevel;
ground.visible = false;
// Game elements start hidden
function startGame() {
gameState = 'playing';
menuContainer.visible = false;
blueberry.visible = true;
ground.visible = true;
scoreTxt.visible = true;
// Spawn initial berries
spawnGoldenBerry();
spawnGoldenBerry();
spawnGoldenBerry();
}
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') {
return;
}
berrySpawnTimer++;
thornSpawnTimer++;
if (berrySpawnTimer > 150 && goldenBerries.length < 5) {
spawnGoldenBerry();
berrySpawnTimer = 0;
}
var thornSpawnRate = Math.max(360 - Math.floor(LK.getScore() * 3), 120);
if (thornSpawnTimer > thornSpawnRate) {
spawnRedThorn();
thornSpawnTimer = 0;
}
var blueberryBounds = blueberry.getBounds();
for (var i = goldenBerries.length - 1; i >= 0; i--) {
var berry = goldenBerries[i];
var dist = Math.sqrt(Math.pow(berry.x - blueberry.x, 2) + Math.pow(berry.y - blueberry.y, 2));
if (dist < blueberryBounds.radius + 20) {
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
blueberry.grow();
LK.getSound('collect').play();
LK.effects.flashObject(berry, 0xFFFFFF, 200);
berry.destroy();
goldenBerries.splice(i, 1);
if (LK.getScore() >= 100) {
LK.showYouWin();
}
}
}
for (var j = 0; j < redThorns.length; j++) {
var thorn = redThorns[j];
var dist = Math.sqrt(Math.pow(thorn.x - blueberry.x, 2) + Math.pow(thorn.y - blueberry.y, 2));
if (dist < blueberryBounds.radius + 20) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
}
// Update dust particles
for (var d = dustParticles.length - 1; d >= 0; d--) {
var dustParticle = dustParticles[d];
dustParticle.x += dustParticle.velocityX;
dustParticle.y += dustParticle.velocityY;
dustParticle.velocityX *= 0.98;
dustParticle.velocityY += 0.1; // gravity
dustParticle.life--;
// Fade out dust particle
dustParticle.alpha = dustParticle.life / dustParticle.maxLife * 0.6;
dustParticle.scaleX = dustParticle.life / dustParticle.maxLife * 0.2;
dustParticle.scaleY = dustParticle.life / dustParticle.maxLife * 0.2;
// Remove dead dust particles
if (dustParticle.life <= 0) {
dustParticle.destroy();
dustParticles.splice(d, 1);
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -174,11 +174,41 @@
/****
* Game Code
****/
+// Game state management
+var gameState = 'menu'; // 'menu', 'playing'
+var menuContainer = game.addChild(new Container());
+// Main menu setup
+var titleText = new Text2('BLUEBERRY ADVENTURE!', {
+ size: 120,
+ fill: 0x4169E1
+});
+titleText.anchor.set(0.5, 0.5);
+titleText.x = 1024;
+titleText.y = 600;
+menuContainer.addChild(titleText);
+var instructionText = new Text2('Help the hungry blueberry\neat golden berries!\n\nDrag and throw him around\nto collect food and avoid\nthe red thorns!', {
+ size: 80,
+ fill: 0x333333
+});
+instructionText.anchor.set(0.5, 0.5);
+instructionText.x = 1024;
+instructionText.y = 1000;
+menuContainer.addChild(instructionText);
+var startText = new Text2('TAP TO START', {
+ size: 100,
+ fill: 0xFF6B35
+});
+startText.anchor.set(0.5, 0.5);
+startText.x = 1024;
+startText.y = 1600;
+menuContainer.addChild(startText);
+// Blueberry setup (initially hidden)
var blueberry = game.addChild(new Blueberry());
blueberry.x = 1024;
blueberry.y = 1366;
+blueberry.visible = false;
var goldenBerries = [];
var redThorns = [];
var dragNode = null;
var lastMouseX = 0;
@@ -192,10 +222,10 @@
function createTrailParticle(x, y) {
var particle = LK.getAsset('blueberry', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 0.3,
- scaleY: 0.3,
+ scaleX: 0.5,
+ scaleY: 0.5,
alpha: 0.8
});
particle.x = x;
particle.y = y;
@@ -222,14 +252,38 @@
particle.maxLife = 40;
dustParticles.push(particle);
game.addChild(particle);
}
+// Menu blueberry for decoration
+var menuBlueberry = menuContainer.addChild(new Blueberry());
+menuBlueberry.x = 1024;
+menuBlueberry.y = 1300;
+// Animate menu blueberry
+tween(menuBlueberry, {
+ y: 1250
+}, {
+ duration: 2000,
+ easing: tween.easeInOut,
+ repeat: -1,
+ yoyo: true
+});
+// Animate start text pulsing
+tween(startText, {
+ scaleX: 1.1,
+ scaleY: 1.1
+}, {
+ duration: 1000,
+ easing: tween.easeInOut,
+ repeat: -1,
+ yoyo: true
+});
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
+scoreTxt.visible = false; // Initially hidden
function spawnGoldenBerry() {
var berry = new GoldenBerry();
var margin = 50;
berry.x = margin + Math.random() * (2048 - margin * 2);
@@ -324,8 +378,12 @@
lastMouseY = y;
}
game.move = handleMove;
game.down = function (x, y, obj) {
+ if (gameState === 'menu') {
+ startGame();
+ return;
+ }
dragNode = blueberry;
lastMouseX = x;
lastMouseY = y;
handleMove(x, y, obj);
@@ -374,19 +432,33 @@
}
}
dragNode = null;
};
-// Create ground visual
+// Create ground visual (initially hidden)
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
}));
ground.x = 0;
ground.y = groundLevel;
-spawnGoldenBerry();
-spawnGoldenBerry();
-spawnGoldenBerry();
+ground.visible = false;
+// Game elements start hidden
+function startGame() {
+ gameState = 'playing';
+ menuContainer.visible = false;
+ blueberry.visible = true;
+ ground.visible = true;
+ scoreTxt.visible = true;
+ // Spawn initial berries
+ spawnGoldenBerry();
+ spawnGoldenBerry();
+ spawnGoldenBerry();
+}
game.update = function () {
+ // Only update game logic when playing
+ if (gameState !== 'playing') {
+ return;
+ }
berrySpawnTimer++;
thornSpawnTimer++;
if (berrySpawnTimer > 150 && goldenBerries.length < 5) {
spawnGoldenBerry();