User prompt
black circle appear like blackhole slowly
User prompt
just move like spiral dont vibrate sprite ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix the vibration when ufo pulling into ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a black circle back to blackhole layer
User prompt
fix vibration when spiral tween and tween start at same position not right there ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
pull ufo with spiral shape and fix position at the center ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
wait game over screen 1 more second and change pull type like a spiral whirlpool ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix pull after fall ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
stop shake ufo after die
User prompt
dont shake ufo just pull spiral like into center of black hole
User prompt
shake very slowly ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
shake slowly and reduce time 2 to 1 second ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
wait game over screen 2 sec more and shake ufo in blackhole ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
delete when dying red dead effect
User prompt
black hole appear slowly and pull ufo slowly ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
blackhole layer is under the bird layer
User prompt
when dying move bird slowly to black hole and until wait play again screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when dying create blackhole image center of the screen
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'Cubic')' in or related to this line: 'tween.to(blackHole, {' Line Number: 492
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(blackHole, {' Line Number: 492
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'Cubic')' in or related to this line: 'tween.to(blackHole, {' Line Number: 492
User prompt
when dying open black hole asset on the screen center and bird pull into black hole effect
User prompt
change game name font size bigger x2
User prompt
move up game name 1000 px above tap to start text
User prompt
move up game name 800 px up
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bird class var Bird = Container.expand(function () { var self = Container.call(this); // Attach bird asset (ellipse, yellow) var birdAsset = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); // Physics properties self.velocityY = 0; self.gravity = 0.5; // Lower gravity per frame for slower fall self.flapStrength = -20; // Lower flap strength for gentler jump // Bird size for collision self.radius = birdAsset.width * 0.45; // Flap method self.flap = function () { self.velocityY = self.flapStrength; }; // Update method (called every tick) self.update = function () { // Only apply gravity and velocity if gameStarted is true if (typeof gameStarted !== "undefined" && gameStarted) { self.velocityY += self.gravity; self.y += self.velocityY; } // Clamp rotation for visual feedback (optional) var maxAngle = Math.PI / 4; var minAngle = -Math.PI / 6; var angle = self.velocityY / 40 * maxAngle; if (angle > maxAngle) { angle = maxAngle; } if (angle < minAngle) { angle = minAngle; } birdAsset.rotation = angle; }; return self; }); // PipePair class (top and bottom pipes as a pair) var PipePair = Container.expand(function () { var self = Container.call(this); // Pipe properties self.pipeWidth = 80; // Start very thin, will be set wider on spawn self.gapHeight = 520; // Will be randomized a bit self.speed = 12; // Speed at which pipes move left // Top pipe (cloud) self.topPipe = self.attachAsset('cloud', { anchorX: 0, anchorY: 1, width: self.pipeWidth, height: 300, // cloud height y: 0, x: 0 }); // Bottom pipe (mountain) self.bottomPipe = self.attachAsset('mountain', { anchorX: 0, anchorY: 0, width: self.pipeWidth, height: 600, // mountain height y: 0, x: 0 }); // Used to track if score was already given for this pipe self.passed = false; // Set pipes' vertical positions self.setGap = function (gapY, gapHeight) { self.gapHeight = gapHeight; // Top cloud: position at gapY, stretch to fill from top to gapY self.topPipe.y = gapY; self.topPipe.height = Math.max(1, gapY); // cloud height = gapY, min 1 self.topPipe.width = self.pipeWidth; // Bottom mountain: position at gapY+gapHeight, stretch to fill to bottom self.bottomPipe.y = gapY + gapHeight; self.bottomPipe.height = Math.max(1, 2732 - (gapY + gapHeight)); // mountain height self.bottomPipe.width = self.pipeWidth; }; // Update method self.update = function () { self.x -= self.speed; }; // Collision check with bird self.collidesWith = function (bird) { // Bird's bounding circle var bx = bird.x; var by = bird.y; var r = bird.radius; // Top pipe rectangle var topRect = { x: self.x, y: 0, w: self.pipeWidth, h: self.topPipe.y }; // Bottom pipe rectangle var bottomRect = { x: self.x, y: self.bottomPipe.y, w: self.pipeWidth, h: 2732 - self.bottomPipe.y }; // Helper: circle-rect collision function circleRectCollide(cx, cy, cr, rx, ry, rw, rh) { var closestX = Math.max(rx, Math.min(cx, rx + rw)); var closestY = Math.max(ry, Math.min(cy, ry + rh)); var dx = cx - closestX; var dy = cy - closestY; return dx * dx + dy * dy < cr * cr; } if (circleRectCollide(bx, by, r, topRect.x, topRect.y, topRect.w, topRect.h)) { return true; } if (circleRectCollide(bx, by, r, bottomRect.x, bottomRect.y, bottomRect.w, bottomRect.h)) { return true; } return false; }; // Has bird passed this pipe? (for scoring) self.isPassedBy = function (bird) { return !self.passed && self.x + self.pipeWidth < bird.x - bird.radius; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- No dynamic ground/upground height/width/distance here; handled in update below -- var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); game.addChild(background); // --- Cloud (top pipe) - white, wide, ellipse // Mountain (bottom pipe) - green, wide, triangle-like // --- Game Variables --- // Tween plugin for animations (not strictly needed for MVP, but included for future use) // --- Asset Initialization (shapes) --- var bird; var pipes = []; var pipeSpawnTimer = 0; var pipeInterval = 90; // Frames between pipes (1.5s at 60fps) var score = 0; var scoreTxt; var ground; var gameStarted = false; var gameOver = false; // --- Tap to Start Overlay --- var tapToStartTxt = new Text2('Tap to Start', { size: 140, fill: 0xffffff }); tapToStartTxt.anchor.set(0.5, 1); // anchor bottom center tapToStartTxt.x = 2048 / 2; // Move down so the layer sits on the ground, with a gap above ground var tapToStartGroundGap = 60; // distance above ground var tapToStartMaxY = 2732 - 920 - tapToStartGroundGap; // 120 is base ground height tapToStartTxt.y = tapToStartMaxY; tapToStartTxt.visible = false; // Add "How to play" instructions below the Tap to Start text var howToPlayTxt = new Text2('Tap to power up and guide your UFO through doors.\nAvoid galactic doors and see how far you can go!', { size: 70, fill: 0xffffff }); howToPlayTxt.anchor.set(0.5, 0); // anchor top center howToPlayTxt.x = 2048 / 2; howToPlayTxt.y = tapToStartTxt.y + 40; // 40px below tapToStartTxt // Remove from game if already added, then add to top if (tapToStartTxt.parent) { tapToStartTxt.parent.removeChild(tapToStartTxt); } game.addChild(tapToStartTxt); game.setChildIndex(tapToStartTxt, game.children.length - 1); // Always on top if (howToPlayTxt.parent) { howToPlayTxt.parent.removeChild(howToPlayTxt); } game.addChild(howToPlayTxt); game.setChildIndex(howToPlayTxt, game.children.length - 1); // --- GUI Score Display --- if (typeof scoreTxt !== "undefined" && scoreTxt && scoreTxt.parent) { scoreTxt.parent.removeChild(scoreTxt); scoreTxt.destroy(); } if (typeof scoreCircleBg !== "undefined" && scoreCircleBg && scoreCircleBg.parent) { scoreCircleBg.parent.removeChild(scoreCircleBg); scoreCircleBg.destroy(); } // Create a perfect circle background for the score and center it scoreCircleBg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: LK.gui.width / 2, y: 80 + 45, // 45 is half of 90 (score text size), so circle is centered behind text scaleX: 0.8, scaleY: 0.8 }); LK.gui.addChild(scoreCircleBg); scoreTxt = new Text2('0', { size: 90, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0.5); // Center score horizontally at the top, vertically centered in the circle scoreTxt.x = LK.gui.width / 2; scoreTxt.y = 80 + 45; LK.gui.addChild(scoreTxt); // Add game name text under the score in big font, but on overlay layer (with tapToStartTxt) var gameNameTxt = new Text2('Galactic Doors', { size: 220, fill: 0xffffff, font: "'Orbitron', 'Audiowide', 'Space Mono', 'GillSans-Bold', Impact, 'Arial Black', Tahoma" }); gameNameTxt.anchor.set(0.5, 0); // Place it under the score circle, with a gap, but on overlay gameNameTxt.x = 2048 / 2; gameNameTxt.y = tapToStartTxt.y - 1000; // 1000px above tapToStartTxt (visually grouped) gameNameTxt.visible = false; // Remove from game if already added, then add to top if (gameNameTxt.parent) { gameNameTxt.parent.removeChild(gameNameTxt); } game.addChild(gameNameTxt); game.setChildIndex(gameNameTxt, game.children.length - 1); // Move howToPlayTxt to overlay and hide initially howToPlayTxt.x = 2048 / 2; howToPlayTxt.y = tapToStartTxt.y + 40; howToPlayTxt.visible = false; if (howToPlayTxt.parent) { howToPlayTxt.parent.removeChild(howToPlayTxt); } game.addChild(howToPlayTxt); game.setChildIndex(howToPlayTxt, game.children.length - 1); // --- Ground (for collision) --- ground = LK.getAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: 2732 - 120 }); game.addChild(ground); // --- Mirrored ground at top (now called upground) --- var upground = LK.getAsset('ground', { anchorX: 0, anchorY: 1, x: 0, y: 0, scaleY: -1 }); game.addChild(upground); // --- Minimum ground width (never narrower than mountain/cloud asset) --- var minGroundWidth = 800; // same as mountain/cloud asset width var maxGroundWidth = 2048; // full width // --- Bird --- bird = new Bird(); game.addChild(bird); // Start position: horizontally 30% from left, vertically centered bird.x = 2048 * 0.3; bird.y = 2732 / 2; // --- Reset function --- function resetGame() { // Remove pipes for (var i = 0; i < pipes.length; i++) { pipes[i].destroy(); } pipes = []; // Ensure background is always at the back if (background && background.parent) { background.parent.setChildIndex(background, 0); } // Reset bird bird.x = 2048 * 0.3; bird.y = 2732 / 2; bird.velocityY = 0; // Reset score score = 0; scoreTxt.setText(score); // Reset timers pipeSpawnTimer = 0; gameStarted = false; gameOver = false; if (tapToStartTxt) { tapToStartTxt.visible = true; // Remove and re-add to ensure it's on top if (tapToStartTxt.parent) { tapToStartTxt.parent.removeChild(tapToStartTxt); } game.addChild(tapToStartTxt); game.setChildIndex(tapToStartTxt, game.children.length - 1); } if (gameNameTxt) { gameNameTxt.visible = true; if (gameNameTxt.parent) { gameNameTxt.parent.removeChild(gameNameTxt); } game.addChild(gameNameTxt); game.setChildIndex(gameNameTxt, game.children.length - 1); } if (howToPlayTxt) { howToPlayTxt.visible = true; if (howToPlayTxt.parent) { howToPlayTxt.parent.removeChild(howToPlayTxt); } game.addChild(howToPlayTxt); game.setChildIndex(howToPlayTxt, game.children.length - 1); } } // --- Start game on first tap --- game.down = function (x, y, obj) { if (gameOver) { return; } if (!gameStarted) { gameStarted = true; if (tapToStartTxt) { tapToStartTxt.visible = false; } if (gameNameTxt) { gameNameTxt.visible = false; } if (howToPlayTxt) { howToPlayTxt.visible = false; } bird.flap(); return; } bird.flap(); }; // --- Main update loop --- game.update = function () { if (gameOver) { return; } // Bird physics if (gameStarted) { bird.update(); } // Clamp bird to top of screen if (bird.y - bird.radius < 0) { bird.y = bird.radius; bird.velocityY = 0; } // Pipe spawning if (gameStarted) { pipeSpawnTimer++; if (pipeSpawnTimer >= pipeInterval) { pipeSpawnTimer = 0; // Mountain-like curve for gapY using a sine wave var minGapY = 350; var maxGapY = 2732 - 120 - 350 - 700; var t = (score + pipes.length) * 0.5; // t increases as more pipes spawn var amplitude = (maxGapY - minGapY) / 2; var centerY = minGapY + amplitude; var gapY = centerY + Math.sin(t) * amplitude; gapY = Math.max(minGapY, Math.min(maxGapY, gapY)); var gapHeight = 650 + Math.floor(Math.random() * 120); // 650-770 px (increased gap) // Calculate pipe width based on score: start thin, widen much more slowly var minPipeWidth = 80; var maxPipeWidth = 880; // Use a slower growth curve (e.g. score/120 instead of score/40) var pipeWidth = minPipeWidth + Math.floor((maxPipeWidth - minPipeWidth) * Math.min(1, score / 120)); // Clamp to max if (pipeWidth > maxPipeWidth) { pipeWidth = maxPipeWidth; } if (pipeWidth < minPipeWidth) { pipeWidth = minPipeWidth; } var pipePair = new PipePair(); pipePair.pipeWidth = pipeWidth; pipePair.topPipe.width = pipeWidth; pipePair.bottomPipe.width = pipeWidth; pipePair.x = 2048; pipePair.setGap(gapY, gapHeight); pipes.push(pipePair); game.addChild(pipePair); } } // Update pipes, check for collisions and scoring for (var i = pipes.length - 1; i >= 0; i--) { var pipe = pipes[i]; if (gameStarted) { pipe.update(); } // Remove pipes that are off screen if (pipe.x + pipe.pipeWidth < 0) { pipe.destroy(); pipes.splice(i, 1); continue; } // Collision if (gameStarted && pipe.collidesWith(bird)) { endGame(); return; } // Scoring if (gameStarted && pipe.isPassedBy(bird)) { score += 1; scoreTxt.setText(score); LK.getSound('score').play(); pipe.passed = true; } } // --- Move upground to upper edge and ground to lower edge, fixed positions --- if (ground && upground) { // Increase ground height as score increases, but clamp to a max (e.g. 600) var baseGroundHeight = 120; var maxGroundHeight = 600; // For every 5 points, increase by 12px (tune as needed) var groundHeight = baseGroundHeight + Math.floor(score / 5) * 12; if (groundHeight > maxGroundHeight) { groundHeight = maxGroundHeight; } // Always full width, always at x=0 ground.x = 0; upground.x = 0; ground.width = 2048; upground.width = 2048; ground.height = groundHeight; upground.height = groundHeight; // upground at very top edge upground.y = 0; // ground at very bottom edge ground.y = 2732 - groundHeight; } // Ground collision if (gameStarted && bird.y + bird.radius >= ground.y) { bird.y = ground.y - bird.radius; endGame(); return; } // Upground (top ground) collision if (gameStarted && bird.y - bird.radius <= upground.y + upground.height) { bird.y = upground.y + upground.height + bird.radius; endGame(); return; } }; // --- End game --- function endGame() { if (gameOver) { return; } gameOver = true; bird.velocityY = 0; // Stop bird movement after death // Show blackhole image at center of screen, under the bird layer var blackhole = LK.getAsset('blackhole', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); blackhole.alpha = 0; // Start invisible var birdIndex = game.children.indexOf(bird); if (birdIndex > -1) { game.addChildAt(blackhole, birdIndex); } else { game.addChild(blackhole); } // Removed red flash effect on death // Fade in blackhole slowly, then pull bird to center in a spiral, then wait 1s before game over tween(blackhole, { alpha: 1 }, { duration: 900, easing: tween.cubicInOut, onFinish: function onFinish() { // After blackhole is fully visible, spiral bird to center var spiralSteps = 60; // 1.2s at 60fps var spiralDuration = 1200; var startX = bird.x; var startY = bird.y; var endX = 2048 / 2; var endY = 2732 / 2; var startAngle = Math.atan2(startY - endY, startX - endX); var startRadius = Math.sqrt((startX - endX) * (startX - endX) + (startY - endY) * (startY - endY)); var spiralTick = 0; var _spiralTween = function spiralTween() { spiralTick++; var t = spiralTick / spiralSteps; // Spiral in: radius shrinks, angle increases var angle = startAngle + 2 * Math.PI * 2 * t; // 2 full turns var radius = startRadius * (1 - t); bird.x = endX + Math.cos(angle) * radius; bird.y = endY + Math.sin(angle) * radius; // Optionally, rotate bird for effect bird.rotation = angle + Math.PI / 2; if (spiralTick < spiralSteps) { LK.setTimeout(_spiralTween, spiralDuration / spiralSteps); } else { // Snap to center bird.x = endX; bird.y = endY; bird.rotation = 0; // Wait 1s before showing game over LK.setTimeout(function () { LK.showGameOver(); }, 1000); } }; _spiralTween(); } }); } // --- Reset on game over (handled by LK) --- LK.on('gameover', function () { resetGame(); }); // --- Initial reset --- resetGame(); // --- Pause Button --- // Place pause button at right, same vertical as scoreTxt var pauseBtn = new Text2('II', { size: 120, fill: 0xffffff }); pauseBtn.anchor.set(1, 0); // Place at top right, just below top edge (keep 80px from top for visibility) pauseBtn.x = 2048 - 60; // 60px from right edge pauseBtn.y = 80; LK.gui.addChild(pauseBtn); // Pause event (optional: you may want to hook this up to LK.pauseGame if available) // pauseBtn.down = function(x, y, obj) { // LK.pauseGame(); // };
===================================================================
--- original.js
+++ change.js
@@ -479,53 +479,49 @@
} else {
game.addChild(blackhole);
}
// Removed red flash effect on death
- // Fade in blackhole slowly, then spiral bird to center
+ // Fade in blackhole slowly, then pull bird to center in a spiral, then wait 1s before game over
tween(blackhole, {
alpha: 1
}, {
duration: 900,
easing: tween.cubicInOut,
onFinish: function onFinish() {
- // Spiral bird to center of blackhole
+ // After blackhole is fully visible, spiral bird to center
+ var spiralSteps = 60; // 1.2s at 60fps
var spiralDuration = 1200;
- var spiralStart = Date.now();
- var spiralStartX = bird.x;
- var spiralStartY = bird.y;
- var spiralEndX = 2048 / 2;
- var spiralEndY = 2732 / 2;
- var spiralRadius = Math.sqrt(Math.pow(spiralStartX - spiralEndX, 2) + Math.pow(spiralStartY - spiralEndY, 2));
- var spiralRotations = 2.5; // Number of spiral turns
- // We'll animate the spiral manually using LK.setInterval
- var spiralInterval = LK.setInterval(function () {
- var t = (Date.now() - spiralStart) / spiralDuration;
- if (t > 1) t = 1;
- // Ease in
- var easeT = tween.cubicInOut(t);
- // Spiral radius shrinks to 0
- var r = spiralRadius * (1 - easeT);
- // Angle increases
- var angle = spiralRotations * 2 * Math.PI * easeT;
- // Interpolate center
- var cx = spiralStartX + (spiralEndX - spiralStartX) * easeT;
- var cy = spiralStartY + (spiralEndY - spiralStartY) * easeT;
- // Bird position on spiral
- bird.x = cx + r * Math.cos(angle);
- bird.y = cy + r * Math.sin(angle);
+ var startX = bird.x;
+ var startY = bird.y;
+ var endX = 2048 / 2;
+ var endY = 2732 / 2;
+ var startAngle = Math.atan2(startY - endY, startX - endX);
+ var startRadius = Math.sqrt((startX - endX) * (startX - endX) + (startY - endY) * (startY - endY));
+ var spiralTick = 0;
+ var _spiralTween = function spiralTween() {
+ spiralTick++;
+ var t = spiralTick / spiralSteps;
+ // Spiral in: radius shrinks, angle increases
+ var angle = startAngle + 2 * Math.PI * 2 * t; // 2 full turns
+ var radius = startRadius * (1 - t);
+ bird.x = endX + Math.cos(angle) * radius;
+ bird.y = endY + Math.sin(angle) * radius;
// Optionally, rotate bird for effect
- if (bird.children && bird.children[0]) {
- bird.children[0].rotation += 0.15;
- }
- if (t >= 1) {
- LK.clearInterval(spiralInterval);
- bird.x = spiralEndX;
- bird.y = spiralEndY;
+ bird.rotation = angle + Math.PI / 2;
+ if (spiralTick < spiralSteps) {
+ LK.setTimeout(_spiralTween, spiralDuration / spiralSteps);
+ } else {
+ // Snap to center
+ bird.x = endX;
+ bird.y = endY;
+ bird.rotation = 0;
+ // Wait 1s before showing game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
- }, 1000 / 60); // 60fps
+ };
+ _spiralTween();
}
});
}
// --- Reset on game over (handled by LK) ---
galaxy theme background. In-Game asset. 2d. High contrast. No shadows
only black hole simple no background. In-Game asset. 2d. High contrast. No shadows
galactic portals looks like a black hole. In-Game asset. 2d. High contrast. No shadows
galactic portals looks like a long straight pillar . In-Game asset. 2d. High contrast. No shadows
create an ufo without legs only frizby shape. In-Game asset. 2d. High contrast. No shadows