User prompt
oyunda bazen siyah top çıkıyor. bunu istemiyorum. ancak oyuna bir kaç özel top ekleyelim. bunlardan birincisi beyaz top olsun. atıldığında tüm zinciri 2 saniye boyunca durdursun. ve sayım ekranda çıksın. siyah top ekleyelim. bu da atıldığında zincire değerse, yanındaki 5 topu yok etsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
toplar, rotanın sonuna doğru birbirine giriyor. bunu istemiyorum
User prompt
zincirin hızı oyun boyunca sadece normal,hızlı ve en hızlı tuşuna basınca değişsin.
User prompt
oyunun normal hızını biraz daha yavaş yapalım. hızlı olan kısmını da yavaşlatalım. en hızlı modu da yavaşlatalım
User prompt
arka plan dinamik uzay görüntüsü olsun. arka plandaki renkli kareleri istemiyorum. 10 saniyede bir arka planda yıldız kaysın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
daha gerçekçi uzay olsun.
User prompt
oyunun arka planı uzay olsun.
User prompt
normal speed can be decrease
User prompt
The score system should be 1x for normal, 1.5x for fast and 2x for very fast. The points received will flash on the screen during the reading period. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
the normal game speed can be faster
User prompt
normal, fast and very fast speed increase
User prompt
The acceleration button works, but let's modify it. There are 3 levels of speed in the game: normal, fast and very fast. And let these work on a single button. If I press it once, it's fast. If I press it again, it's very fast. If I press it again, it goes back to normal.
User prompt
First, if I put 3 balls of the same color together, they should disappear. Then, when the gap between them is closed, the balls of the same color should touch each other and then disappear. Yes, these things happened, but what I wanted was the disappearance animation in order. First, when the balls of the same color come together, there will be an explosion effect, then when the gap closes, the balls of the same color that come together will disappear. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
First, if I put 3 balls of the same color together, they should disappear. Then, when the gap between them is closed, the balls of the same color should touch each other and then disappear.
User prompt
Yes, it disappears when you hit balls of the same color. However, when the gap in the chain is closed and the same colors appear side by side in front and behind, the balls should disappear. this happened. However, the balls should disappear when they touch each other.
User prompt
Yes, it disappears when you hit balls of the same color. However, when the gap in the chain is closed and the same colors appear side by side in front and behind, the balls should disappear.
User prompt
when i press the accelerate nothing happen. chain will not faster
User prompt
Add a clickable button to the game. When you press this button, the chain accelerates. Press again and it will return to its previous speed.
User prompt
the balls overlapping when comes near tyhe hole
User prompt
The balls are still overlapping each other as they move towards the hole.
User prompt
the hole position shoulde be near the shooter
User prompt
The route should not contact the shooter
User prompt
The route does not currently go to the hole. let's fix this. The end of the route must end at the hole. but there should be a longer route
User prompt
The route may be slightly longer. but the balls are still intertwined. In this case, there should be equal space between them and the balls should touch each other but not be intertwined.
User prompt
the route follows a single path towards the hole in a swirling pattern
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Ball = Container.expand(function (color) { var self = Container.call(this); self.color = color; self.ballColors = ['red', 'blue', 'green', 'yellow', 'purple', 'orange']; self.isSpecial = false; self.specialType = null; // 'explosive', 'freeze', 'rapid', 'white_freeze', 'black_destroyer' var ballGraphics = self.attachAsset('ball_' + color, { anchorX: 0.5, anchorY: 0.5 }); // Check for special ball types based on color if (color === 'white') { self.isSpecial = true; self.specialType = 'white_freeze'; ballGraphics.alpha = 0.9; ballGraphics.scaleX = 1.15; ballGraphics.scaleY = 1.15; // Add pulsing effect for white balls var _pulseEffect = function pulseEffect() { tween(ballGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1.15, scaleY: 1.15 }, { duration: 600, easing: tween.easeInOut, onFinish: _pulseEffect }); } }); }; _pulseEffect(); } else if (color === 'black') { self.isSpecial = true; self.specialType = 'black_destroyer'; ballGraphics.alpha = 0.9; ballGraphics.scaleX = 1.15; ballGraphics.scaleY = 1.15; ballGraphics.tint = 0x444444; // Slightly gray tint for visibility // Add pulsing effect for black balls var _pulseEffect = function pulseEffect() { tween(ballGraphics, { scaleX: 1.3, scaleY: 1.3, tint: 0x666666 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1.15, scaleY: 1.15, tint: 0x444444 }, { duration: 600, easing: tween.easeInOut, onFinish: _pulseEffect }); } }); }; _pulseEffect(); } else { // 5% chance for special balls on regular colors if (Math.random() < 0.05) { // Start pulsing animation var _pulseEffect = function pulseEffect() { tween(ballGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1.15, scaleY: 1.15 }, { duration: 600, easing: tween.easeInOut, onFinish: _pulseEffect }); } }); }; self.isSpecial = true; var specials = ['explosive', 'freeze', 'rapid']; self.specialType = specials[Math.floor(Math.random() * specials.length)]; ballGraphics.alpha = 0.9; // Add glow effect for special balls ballGraphics.scaleX = 1.15; ballGraphics.scaleY = 1.15; // Add pulsing effect if (self.specialType === 'explosive') { ballGraphics.tint = 0xFF4500; } else if (self.specialType === 'freeze') { ballGraphics.tint = 0x00FFFF; } else if (self.specialType === 'rapid') { ballGraphics.tint = 0xFFFF00; } _pulseEffect(); } } self.trackPosition = 0; self.trackX = 0; self.trackY = 0; self.isMoving = false; return self; }); var ChainBall = Ball.expand(function (color) { var self = Ball.call(this, color); self.chainIndex = 0; self.targetX = 0; self.targetY = 0; self.update = function () { if (self.isMoving) { // Smooth movement towards target position var dx = self.targetX - self.x; var dy = self.targetY - self.y; self.x += dx * 0.3; self.y += dy * 0.3; if (Math.abs(dx) < 1 && Math.abs(dy) < 1) { self.isMoving = false; self.x = self.targetX; self.y = self.targetY; } } }; return self; }); var Shooter = Container.expand(function () { var self = Container.call(this); var shooterGraphics = self.attachAsset('shooter', { anchorX: 0.5, anchorY: 0.5 }); // Add cannon barrel var barrel = self.attachAsset('track', { anchorX: 0, anchorY: 0.5, scaleX: 4, scaleY: 1.5, x: 0, y: 0 }); barrel.tint = 0x333333; self.angle = 0; self.currentBall = null; self.nextBall = null; self.rapidFire = false; self.rapidFireTimer = 0; self.shootCooldown = 0; self.loadBall = function () { if (self.currentBall) { self.currentBall.destroy(); } self.currentBall = self.nextBall; if (self.currentBall) { self.currentBall.x = 0; self.currentBall.y = -40; self.addChild(self.currentBall); // Add glowing effect to current ball tween(self.currentBall, { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, easing: tween.easeInOut }); // Start pulsing and shining animation animateShooterBall(); } // Generate next ball var colors = ['red', 'blue', 'green', 'yellow', 'purple']; var randomValue = Math.random(); var randomColor; if (randomValue < 0.05) { randomColor = 'white'; // 5% chance for white ball } else if (randomValue < 0.1) { randomColor = 'black'; // 5% chance for black ball } else { randomColor = colors[Math.floor(Math.random() * colors.length)]; } self.nextBall = new Ball(randomColor); }; self.aimAt = function (x, y) { var dx = x - self.x; var dy = y - self.y; self.angle = Math.atan2(dy, dx); self.rotation = self.angle; }; self.shoot = function () { if (self.shootCooldown > 0 || !self.currentBall) return null; var ball = self.currentBall; self.removeChild(ball); // Set ball velocity var speed = 8; ball.vx = Math.cos(self.angle) * speed; ball.vy = Math.sin(self.angle) * speed; ball.x = self.x; ball.y = self.y; self.loadBall(); // Set cooldown self.shootCooldown = self.rapidFire ? 10 : 20; LK.getSound('shoot').play(); return ball; }; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.rapidFire) { self.rapidFireTimer--; if (self.rapidFireTimer <= 0) { self.rapidFire = false; // Remove glow effect tween.stop(self, { tint: true }); self.tint = 0xFFFFFF; } else { // Maintain glow effect if (self.tint === 0xFFFFFF) { tween(self, { tint: 0xFFFF88 }, { duration: 200, easing: tween.easeInOut }); } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0a0a1a }); /**** * Game Code ****/ // Create dynamic space background with shooting stars function createSpaceBackground() { // Create complex starfield with realistic star colors and sizes (no colored squares) var starColors = [0xFFFFFF, 0xFFE4B5, 0xFFB347, 0x87CEEB, 0xF0F8FF, 0xFFF8DC]; var starSizes = [0.5, 0.8, 1.2, 1.8, 2.5, 3.2]; for (var layer = 0; layer < 5; layer++) { var numStars = layer === 0 ? 200 : layer === 1 ? 150 : layer === 2 ? 100 : layer === 3 ? 60 : 30; var baseAlpha = layer === 0 ? 0.2 : layer === 1 ? 0.4 : layer === 2 ? 0.6 : layer === 3 ? 0.8 : 1.0; for (var i = 0; i < numStars; i++) { var starSize = starSizes[Math.floor(Math.random() * starSizes.length)]; var star = game.addChild(LK.getAsset('track', { anchorX: 0.5, anchorY: 0.5, scaleX: starSize * 0.1, scaleY: starSize * 0.1 })); star.x = Math.random() * 2048; star.y = Math.random() * 2732; star.alpha = baseAlpha + Math.random() * 0.3; star.tint = starColors[Math.floor(Math.random() * starColors.length)]; // Add realistic twinkling based on star size and distance if (layer >= 2 && Math.random() < 0.4) { var twinkleDelay = Math.random() * 3000; LK.setTimeout(function () { var _twinkleEffect = function twinkleEffect() { if (star && star.parent) { tween(star, { alpha: star.alpha * 0.2 }, { duration: 1000 + Math.random() * 800, easing: tween.easeInOut, onFinish: function onFinish() { if (star && star.parent) { tween(star, { alpha: baseAlpha + Math.random() * 0.3 }, { duration: 1000 + Math.random() * 800, easing: tween.easeInOut, onFinish: _twinkleEffect }); } } }); } }; _twinkleEffect(); }, twinkleDelay); } } } // Create animated cosmic dust clouds with ellipse shapes only for (var i = 0; i < 12; i++) { var dust = game.addChild(LK.getAsset('hole', { anchorX: 0.5, anchorY: 0.5, scaleX: 2 + Math.random() * 3, scaleY: 1 + Math.random() * 2 })); dust.x = Math.random() * 2048; dust.y = Math.random() * 2732; dust.alpha = 0.03 + Math.random() * 0.05; dust.rotation = Math.random() * Math.PI * 2; // Realistic dust cloud colors var dustColors = [0x4B0082, 0x800080, 0x8B008B, 0x9400D3, 0x1E90FF, 0x00CED1, 0x483D8B]; dust.tint = dustColors[Math.floor(Math.random() * dustColors.length)]; // Add slow rotation animation var rotationSpeed = (Math.random() - 0.5) * 0.001; var dustRotation = dust.rotation; var _dustRotate = function dustRotate() { if (dust && dust.parent) { dustRotation += rotationSpeed; dust.rotation = dustRotation; LK.setTimeout(_dustRotate, 50); } }; _dustRotate(); } // Add some brighter nebula formations with ellipse shapes for (var i = 0; i < 6; i++) { var nebula = game.addChild(LK.getAsset('hole', { anchorX: 0.5, anchorY: 0.5, scaleX: 4 + Math.random() * 5, scaleY: 3 + Math.random() * 4 })); nebula.x = Math.random() * 2048; nebula.y = Math.random() * 2732; nebula.alpha = 0.08 + Math.random() * 0.12; nebula.rotation = Math.random() * Math.PI * 2; // More vibrant nebula colors var nebulaColors = [0xFF1493, 0x00FA9A, 0xFF4500, 0x9370DB, 0x00CED1, 0xFF69B4]; nebula.tint = nebulaColors[Math.floor(Math.random() * nebulaColors.length)]; // Add gentle pulsing effect var pulseDelay = Math.random() * 4000; LK.setTimeout(function () { var _nebulaEffect = function nebulaEffect() { if (nebula && nebula.parent) { tween(nebula, { alpha: nebula.alpha * 0.5, scaleX: nebula.scaleX * 1.1, scaleY: nebula.scaleY * 1.1 }, { duration: 2000 + Math.random() * 1000, easing: tween.easeInOut, onFinish: function onFinish() { if (nebula && nebula.parent) { tween(nebula, { alpha: 0.08 + Math.random() * 0.12, scaleX: 4 + Math.random() * 5, scaleY: 3 + Math.random() * 4 }, { duration: 2000 + Math.random() * 1000, easing: tween.easeInOut, onFinish: _nebulaEffect }); } } }); } }; _nebulaEffect(); }, pulseDelay); } } // Initialize space background createSpaceBackground(); // Create shooting star function function createShootingStar() { var shootingStar = game.addChild(LK.getAsset('track', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.1 })); // Random starting position from top or sides var startSide = Math.floor(Math.random() * 3); // 0 = top, 1 = left, 2 = right if (startSide === 0) { shootingStar.x = Math.random() * 2048; shootingStar.y = -50; } else if (startSide === 1) { shootingStar.x = -50; shootingStar.y = Math.random() * 1500; } else { shootingStar.x = 2098; shootingStar.y = Math.random() * 1500; } // Set shooting star properties shootingStar.alpha = 0.8; shootingStar.tint = 0xFFFFFF; shootingStar.rotation = Math.random() * Math.PI * 2; // Create trail effect with multiple small stars var trailStars = []; for (var i = 0; i < 5; i++) { var trailStar = game.addChild(LK.getAsset('track', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1 - i * 0.015, scaleY: 0.05 - i * 0.008 })); trailStar.x = shootingStar.x; trailStar.y = shootingStar.y; trailStar.alpha = 0.6 - i * 0.1; trailStar.tint = 0xFFFFFF; trailStar.rotation = shootingStar.rotation; trailStars.push(trailStar); } // Calculate movement direction var targetX = Math.random() * 2048; var targetY = 2732 + 200; var deltaX = targetX - shootingStar.x; var deltaY = targetY - shootingStar.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); var speed = 15 + Math.random() * 10; var vx = deltaX / distance * speed; var vy = deltaY / distance * speed; // Animate shooting star var _moveShootingStar = function moveShootingStar() { if (shootingStar && shootingStar.parent) { shootingStar.x += vx; shootingStar.y += vy; // Update trail positions for (var i = trailStars.length - 1; i > 0; i--) { if (trailStars[i] && trailStars[i].parent) { trailStars[i].x = trailStars[i - 1].x; trailStars[i].y = trailStars[i - 1].y; } } if (trailStars[0] && trailStars[0].parent) { trailStars[0].x = shootingStar.x; trailStars[0].y = shootingStar.y; } // Check if off screen if (shootingStar.x < -100 || shootingStar.x > 2148 || shootingStar.y > 2832) { shootingStar.destroy(); for (var i = 0; i < trailStars.length; i++) { if (trailStars[i] && trailStars[i].parent) { trailStars[i].destroy(); } } return; } LK.setTimeout(_moveShootingStar, 16); } }; _moveShootingStar(); } // Start shooting star timer (every 10 seconds) var shootingStarTimer = LK.setInterval(createShootingStar, 10000); // Game variables var chain = []; var flyingBalls = []; var shooter; var trackPoints = []; var chainSpeed = 0.0003; // Further decreased normal chain speed var normalChainSpeed = 0.0003; // Store normal speed var fastChainSpeed = 0.002; // Fast chain speed - slower than before var veryFastChainSpeed = 0.006; // Very fast chain speed - slower than before var speedLevel = 0; // 0 = normal, 1 = fast, 2 = very fast var chainFrozen = false; var freezeTimer = 0; var freezeCountdownDisplay = null; var level = 1; var gameWon = false; var gameLost = false; // Score multiplier system var scoreMultipliers = [1.0, 1.5, 2.0]; // normal, fast, very fast var pointsDisplays = []; // Array to track active point displays // Create vortex track path function createTrackPath() { trackPoints = []; var centerX = 1024; var centerY = 1366; var holeX = 1024; var holeY = 1200; // Hole position - closer to shooter var segments = 1500; // Longer track for better gameplay // Create single swirling path towards the hole - starts from outside and spirals inward in one continuous motion for (var i = 0; i < segments; i++) { var progress = i / segments; // Single spiral angle - creates one continuous swirl towards center var spiralAngle = progress * Math.PI * 6; // 3 full rotations for longer swirling path // Radius decreases linearly for smooth inward movement var baseRadius = 1000 * (1 - progress); // Linear decrease for steady approach to center // Add gentle wave motion for swirling effect var waveMotion = Math.sin(progress * Math.PI * 12) * (60 * (1 - progress)); // Gentle swirling motion var currentRadius = baseRadius + waveMotion; // Ensure minimum radius for playability at center currentRadius = Math.max(currentRadius, 40); // Calculate position on spiral path - interpolate towards hole position var spiralX = centerX + Math.cos(spiralAngle) * currentRadius; var spiralY = centerY + Math.sin(spiralAngle) * currentRadius; // Gradually move towards hole position in final segment var holeProgress = Math.max(0, (progress - 0.9) / 0.1); // Last 10% of track moves to hole var x = spiralX + (holeX - spiralX) * holeProgress; var y = spiralY + (holeY - spiralY) * holeProgress; // Ensure the path stays within screen bounds with padding x = Math.max(150, Math.min(1898, x)); y = Math.max(300, Math.min(2600, y)); trackPoints.push({ x: x, y: y }); } // Create visual track markers with vortex effect for (var i = 0; i < trackPoints.length; i += 6) { var trackMarker = game.addChild(LK.getAsset('track', { anchorX: 0.5, anchorY: 0.5 })); trackMarker.x = trackPoints[i].x; trackMarker.y = trackPoints[i].y; trackMarker.alpha = 0.3 + i / trackPoints.length * 0.3; // Fade in towards center // Scale markers smaller as they approach center for vortex effect var scaleProgress = i / trackPoints.length; trackMarker.scaleX = 0.5 + (1 - scaleProgress) * 0.5; trackMarker.scaleY = 0.5 + (1 - scaleProgress) * 0.5; } } // Create hole at end of track var hole = game.addChild(LK.getAsset('hole', { anchorX: 0.5, anchorY: 0.5 })); // Create shooter shooter = game.addChild(new Shooter()); shooter.x = 1024; // Center of screen horizontally (2048/2 = 1024) shooter.y = 1366; // Position near the center hole // Initialize first balls shooter.loadBall(); shooter.loadBall(); // Create initial chain function createChain() { chain = []; var chainLength = 15 + level * 5; var colors = ['red', 'blue', 'green', 'yellow', 'purple']; var ballSpacing = 50; // Space between balls - balls touch each other var trackSpacing = 5.0; // Increased track position spacing to prevent overlap // Ensure better color distribution by cycling through colors for (var i = 0; i < chainLength; i++) { // Use a mix of sequential and random distribution var colorIndex; if (i % 8 < 5) { // First 5 of every 8 balls use sequential colors colorIndex = i % colors.length; } else { // Last 3 of every 8 balls use random colors colorIndex = Math.floor(Math.random() * colors.length); } var color = colors[colorIndex]; var ball = game.addChild(new ChainBall(color)); ball.chainIndex = i; // Initialize track position with consistent spacing for vortex ball.trackPosition = i * 7.0; // Use consistent spacing to prevent overlap // Position ball immediately on track positionBallOnTrack(ball, ball.trackPosition); chain.push(ball); } } // Position ball on track function positionBallOnTrack(ball, trackPosition) { if (trackPosition >= trackPoints.length || trackPoints.length === 0) { if (trackPoints.length > 0) { ball.x = trackPoints[trackPoints.length - 1].x; ball.y = trackPoints[trackPoints.length - 1].y; } else { ball.x = 1024; ball.y = 1366; } return; } var pointIndex = Math.floor(Math.max(0, trackPosition)); var nextIndex = Math.min(pointIndex + 1, trackPoints.length - 1); var t = trackPosition - pointIndex; var point1 = trackPoints[pointIndex]; var point2 = trackPoints[nextIndex]; // Add safety check for undefined points if (!point1 || !point2) { ball.x = 1024; ball.y = 1366; ball.isMoving = false; return; } // Calculate position with anti-overlap adjustment near the hole var baseX = point1.x + (point2.x - point1.x) * t; var baseY = point1.y + (point2.y - point1.y) * t; // Apply spacing adjustment to prevent overlap near hole var progressToHole = trackPosition / trackPoints.length; if (progressToHole > 0.8) { // Near the hole (last 20% of track) // Add slight offset based on ball's chain position to prevent stacking var offsetAngle = ball.chainIndex * 0.3; // Small angular offset per ball var offsetRadius = 15 * (progressToHole - 0.8) * 5; // Increase offset near hole baseX += Math.cos(offsetAngle) * offsetRadius; baseY += Math.sin(offsetAngle) * offsetRadius; } ball.targetX = baseX; ball.targetY = baseY; ball.isMoving = true; } // Update chain positions function updateChain() { if (chainFrozen) { freezeTimer--; // Update freeze countdown display if (freezeCountdownDisplay) { var secondsLeft = Math.ceil(freezeTimer / 60); freezeCountdownDisplay.setText('FROZEN: ' + secondsLeft); } if (freezeTimer <= 0) { chainFrozen = false; // Remove countdown display if (freezeCountdownDisplay) { freezeCountdownDisplay.destroy(); freezeCountdownDisplay = null; } // Remove ice tint from all chain balls for (var i = 0; i < chain.length; i++) { var chainBall = chain[i]; tween(chainBall, { tint: 0xFFFFFF }, { duration: 300 }); } } return; } // Move all balls forward and maintain equal spacing for vortex var trackSpacing = 7.0; // Increased spacing to prevent overlap, especially near hole for (var i = 0; i < chain.length; i++) { var ball = chain[i]; // Move chain forward in vortex pattern ball.trackPosition += chainSpeed; // Check if reached hole (vortex center) if (ball.trackPosition >= trackPoints.length - 1) { gameLost = true; LK.showGameOver(); return; } } // Maintain equal spacing between balls for vortex movement for (var i = 0; i < chain.length; i++) { var ball = chain[i]; // Ensure proper spacing from previous ball if (i > 0) { var previousBall = chain[i - 1]; var expectedPosition = previousBall.trackPosition + trackSpacing; // Enforce minimum spacing to prevent overlap ball.trackPosition = Math.max(ball.trackPosition, expectedPosition); } positionBallOnTrack(ball, ball.trackPosition); } } // Check for matches function checkMatches() { var matches = []; var currentColor = null; var currentMatch = []; // First, ensure all balls are positioned correctly on the track for (var i = 0; i < chain.length; i++) { var ball = chain[i]; positionBallOnTrack(ball, ball.trackPosition); } // Check for consecutive balls of the same color for (var i = 0; i < chain.length; i++) { var ball = chain[i]; if (ball.color === currentColor) { currentMatch.push(ball); } else { if (currentMatch.length >= 3) { matches.push(currentMatch.slice()); } currentColor = ball.color; currentMatch = [ball]; } } // Check last group if (currentMatch.length >= 3) { matches.push(currentMatch.slice()); } // Remove matches for (var m = 0; m < matches.length; m++) { var match = matches[m]; var baseScore = match.length * 10; var multiplier = scoreMultipliers[speedLevel]; var score = Math.floor(baseScore * multiplier); // Calculate display position (center of the match) var displayX = 0; var displayY = 0; for (var b = 0; b < match.length; b++) { displayX += match[b].x; displayY += match[b].y; } displayX /= match.length; displayY /= match.length; // Display flashing points displayPoints(score, displayX, displayY); // Check for special balls for (var b = 0; b < match.length; b++) { var ball = match[b]; if (ball.isSpecial) { handleSpecialBall(ball); } } // Store the first index of the match to know where the gap starts var firstMatchIndex = chain.indexOf(match[0]); var trackSpacing = 7.0; // Increased spacing to prevent overlap var gapSize = match.length * trackSpacing; // Calculate gap size based on track spacing // Remove matched balls for (var b = 0; b < match.length; b++) { var ball = match[b]; var index = chain.indexOf(ball); if (index > -1) { chain.splice(index, 1); ball.destroy(); } } // Close the gap by moving all balls after the removed section forward for (var i = firstMatchIndex; i < chain.length; i++) { var ball = chain[i]; // Move the ball's track position forward to close the gap ball.trackPosition -= gapSize; } // Re-space all balls to maintain equal intervals after gap closing for (var i = 1; i < chain.length; i++) { var previousBall = chain[i - 1]; var currentBall = chain[i]; var expectedPosition = previousBall.trackPosition + trackSpacing; // Enforce minimum spacing to prevent overlap currentBall.trackPosition = Math.max(currentBall.trackPosition, expectedPosition); // Position the ball immediately to detect matches faster positionBallOnTrack(currentBall, currentBall.trackPosition); // Animate the ball to its new position smoothly tween(currentBall, { x: currentBall.targetX, y: currentBall.targetY }, { duration: 200, // Faster animation for quicker match detection easing: tween.easeOut }); } LK.setScore(LK.getScore() + score); LK.getSound('match').play(); // Pull chain back slightly when balls are removed chainSpeed = Math.max(0.5, chainSpeed - 0.1); } // Always check for new matches after gap closure, regardless of previous matches // This ensures balls disappear when they touch each other after gap closure if (matches.length > 0) { // After removing matches and closing gaps, check for new matches that may have formed // Use a timeout to allow animations to settle before checking LK.setTimeout(function () { checkMatches(); }, 50); // Reduced timeout for faster response } else { // Even if no matches were found initially, check again after any repositioning // This handles cases where balls of the same color touch after repositioning var hasRepositioned = false; for (var i = 1; i < chain.length; i++) { var prevBall = chain[i - 1]; var currBall = chain[i]; if (prevBall.color === currBall.color) { // Check if these balls are close enough to be considered touching var distance = Math.sqrt(Math.pow(currBall.x - prevBall.x, 2) + Math.pow(currBall.y - prevBall.y, 2)); if (distance < 60) { // Balls are touching hasRepositioned = true; break; } } } if (hasRepositioned) { LK.setTimeout(function () { checkMatches(); }, 50); } } // Check win condition if (chain.length === 0) { gameWon = true; level++; LK.showYouWin(); } } // Display flashing points function displayPoints(points, x, y) { var pointsText = new Text2('+' + points, { size: 80, fill: 0xFFFF00 }); pointsText.anchor.set(0.5, 0.5); pointsText.x = x; pointsText.y = y; pointsText.alpha = 1.0; pointsText.scaleX = 0.5; pointsText.scaleY = 0.5; game.addChild(pointsText); pointsDisplays.push(pointsText); // Animate the points display tween(pointsText, { scaleX: 1.2, scaleY: 1.2, y: y - 100 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { tween(pointsText, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { pointsText.destroy(); var index = pointsDisplays.indexOf(pointsText); if (index > -1) { pointsDisplays.splice(index, 1); } } }); } }); } // Handle special ball effects function handleSpecialBall(ball) { if (ball.specialType === 'explosive') { var _shakeEffect = function shakeEffect() { if (shakeTimer < shakeDuration) { game.x = originalX + (Math.random() - 0.5) * shakeIntensity; game.y = originalY + (Math.random() - 0.5) * shakeIntensity; shakeTimer += 16; LK.setTimeout(_shakeEffect, 16); } else { game.x = originalX; game.y = originalY; } }; // Remove nearby balls var explosionRadius = 3; var ballIndex = chain.indexOf(ball); var toRemove = []; for (var i = Math.max(0, ballIndex - explosionRadius); i < Math.min(chain.length, ballIndex + explosionRadius + 1); i++) { if (chain[i] !== ball) { toRemove.push(chain[i]); } } for (var i = 0; i < toRemove.length; i++) { var index = chain.indexOf(toRemove[i]); if (index > -1) { chain.splice(index, 1); toRemove[i].destroy(); } } LK.effects.flashScreen(0xff8000, 300); // Add screen shake effect var originalX = game.x; var originalY = game.y; var shakeIntensity = 10; var shakeDuration = 300; var shakeTimer = 0; _shakeEffect(); } else if (ball.specialType === 'freeze') { chainFrozen = true; freezeTimer = 180; // 3 seconds at 60fps LK.effects.flashScreen(0x00ffff, 500); // Add ice tint to all chain balls for (var i = 0; i < chain.length; i++) { var chainBall = chain[i]; tween(chainBall, { tint: 0x88DDFF }, { duration: 300 }); } } else if (ball.specialType === 'rapid') { shooter.rapidFire = true; shooter.rapidFireTimer = 300; // 5 seconds at 60fps LK.effects.flashScreen(0xffff00, 200); } else if (ball.specialType === 'white_freeze') { chainFrozen = true; freezeTimer = 120; // 2 seconds at 60fps LK.effects.flashScreen(0xffffff, 500); // Create freeze countdown display if (freezeCountdownDisplay) { freezeCountdownDisplay.destroy(); } freezeCountdownDisplay = new Text2('FROZEN: 2', { size: 80, fill: 0x00FFFF }); freezeCountdownDisplay.anchor.set(0.5, 0.5); LK.gui.center.addChild(freezeCountdownDisplay); // Add ice tint to all chain balls for (var i = 0; i < chain.length; i++) { var chainBall = chain[i]; tween(chainBall, { tint: 0x88DDFF }, { duration: 300 }); } } else if (ball.specialType === 'black_destroyer') { // Remove 5 nearby balls (2 on each side + the black ball itself) var explosionRadius = 2; var ballIndex = chain.indexOf(ball); var toRemove = []; for (var i = Math.max(0, ballIndex - explosionRadius); i < Math.min(chain.length, ballIndex + explosionRadius + 1); i++) { toRemove.push(chain[i]); } for (var i = 0; i < toRemove.length; i++) { var index = chain.indexOf(toRemove[i]); if (index > -1) { chain.splice(index, 1); toRemove[i].destroy(); } } LK.effects.flashScreen(0x444444, 400); // Add screen shake effect var originalX = game.x; var originalY = game.y; var shakeIntensity = 8; var shakeDuration = 400; var shakeTimer = 0; var _shakeEffect = function shakeEffect() { if (shakeTimer < shakeDuration) { game.x = originalX + (Math.random() - 0.5) * shakeIntensity; game.y = originalY + (Math.random() - 0.5) * shakeIntensity; shakeTimer += 16; LK.setTimeout(_shakeEffect, 16); } else { game.x = originalX; game.y = originalY; } }; _shakeEffect(); } LK.getSound('powerup').play(); } // Insert ball into chain function insertBallIntoChain(ball, insertIndex) { var chainBall = new ChainBall(ball.color); chainBall.isSpecial = ball.isSpecial; chainBall.specialType = ball.specialType; chainBall.x = ball.x; chainBall.y = ball.y; chainBall.scaleX = 0.1; chainBall.scaleY = 0.1; game.addChild(chainBall); // Animate ball insertion tween(chainBall, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); chain.splice(insertIndex, 0, chainBall); // Update chain indices for (var i = 0; i < chain.length; i++) { chain[i].chainIndex = i; } checkMatches(); } // Initialize game createTrackPath(); createChain(); // Position hole at the end of the track - near the shooter hole.x = 1024; hole.y = 1200; // Position hole closer to shooter // Add pulsing and shining animation to shooter ball function animateShooterBall() { if (shooter.currentBall) { // Pulsing effect tween(shooter.currentBall, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(shooter.currentBall, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: animateShooterBall }); } }); // Shining effect with alpha animation tween(shooter.currentBall, { alpha: 0.7 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { tween(shooter.currentBall, { alpha: 1.0 }, { duration: 600, easing: tween.easeInOut }); } }); } } // Score display var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Level display var levelTxt = new Text2('Level: 1', { size: 50, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); levelTxt.x = 120; levelTxt.y = 20; LK.gui.top.addChild(levelTxt); // Next ball preview var nextBallTxt = new Text2('Next:', { size: 40, fill: 0xFFFFFF }); nextBallTxt.anchor.set(1, 0); LK.gui.topRight.addChild(nextBallTxt); // Create accelerate button var accelerateBtn = new Text2('NORMAL', { size: 50, fill: 0xFFFFFF }); accelerateBtn.anchor.set(1, 1); accelerateBtn.x = -20; accelerateBtn.y = -20; LK.gui.bottomRight.addChild(accelerateBtn); // Button press handler accelerateBtn.down = function (x, y, obj) { speedLevel = (speedLevel + 1) % 3; // Cycle through 0, 1, 2 if (speedLevel === 0) { accelerateBtn.setText('NORMAL'); accelerateBtn.fill = 0xFFFFFF; } else if (speedLevel === 1) { accelerateBtn.setText('FAST'); accelerateBtn.fill = 0xFFFF00; } else { accelerateBtn.setText('VERY FAST'); accelerateBtn.fill = 0xFF4444; } }; // Game input game.down = function (x, y, obj) { shooter.aimAt(x, y); var ball = shooter.shoot(); if (ball) { flyingBalls.push(ball); game.addChild(ball); } }; // Main game loop game.update = function () { if (gameWon || gameLost) return; // Update chain updateChain(); // Update flying balls for (var i = flyingBalls.length - 1; i >= 0; i--) { var ball = flyingBalls[i]; ball.x += ball.vx; ball.y += ball.vy; // Check collision with chain var inserted = false; var collisionIndex = -1; for (var j = 0; j < chain.length; j++) { var chainBall = chain[j]; if (ball.intersects(chainBall)) { collisionIndex = j; break; } } // If collision detected, insert at collision position if (collisionIndex !== -1) { // Insert after the collided ball var insertIndex = collisionIndex + 1; var trackSpacing = 7.0; // Increased spacing to prevent overlap // Adjust track positions for all balls after insertion point for (var k = insertIndex; k < chain.length; k++) { chain[k].trackPosition += trackSpacing; // Move balls back to make space } insertBallIntoChain(ball, insertIndex); // Set the inserted ball's track position with proper spacing if (insertIndex < chain.length) { chain[insertIndex].trackPosition = chain[collisionIndex].trackPosition + trackSpacing; positionBallOnTrack(chain[insertIndex], chain[insertIndex].trackPosition); } // Re-space all balls after insertion to maintain equal intervals for (var k = insertIndex + 1; k < chain.length; k++) { var expectedPosition = chain[k - 1].trackPosition + trackSpacing; // Enforce minimum spacing to prevent overlap chain[k].trackPosition = Math.max(chain[k].trackPosition, expectedPosition); } ball.destroy(); flyingBalls.splice(i, 1); inserted = true; } // Remove if off screen if (!inserted && (ball.x < -100 || ball.x > 2148 || ball.y < -100 || ball.y > 2832)) { ball.destroy(); flyingBalls.splice(i, 1); } } // Update shooter shooter.update(); // Update UI scoreTxt.setText('Score: ' + LK.getScore()); levelTxt.setText('Level: ' + level); // Show next ball preview if (shooter.nextBall) { if (shooter.nextBall.parent) { shooter.nextBall.parent.removeChild(shooter.nextBall); } shooter.nextBall.x = -50; shooter.nextBall.y = 60; shooter.nextBall.scaleX = 0.8; shooter.nextBall.scaleY = 0.8; LK.gui.topRight.addChild(shooter.nextBall); } // Increase chain speed over time (slower increase) normalChainSpeed += 0.00003; // Update other speeds to maintain ratios fastChainSpeed = normalChainSpeed * 6.67; // Maintain same ratio as before veryFastChainSpeed = normalChainSpeed * 20; // Maintain same ratio as before if (speedLevel === 0) { chainSpeed = normalChainSpeed; } else if (speedLevel === 1) { chainSpeed = fastChainSpeed; } else { chainSpeed = veryFastChainSpeed; } };
===================================================================
--- original.js
+++ change.js
@@ -10,16 +10,21 @@
var self = Container.call(this);
self.color = color;
self.ballColors = ['red', 'blue', 'green', 'yellow', 'purple', 'orange'];
self.isSpecial = false;
- self.specialType = null; // 'explosive', 'freeze', 'rapid'
+ self.specialType = null; // 'explosive', 'freeze', 'rapid', 'white_freeze', 'black_destroyer'
var ballGraphics = self.attachAsset('ball_' + color, {
anchorX: 0.5,
anchorY: 0.5
});
- // 5% chance for special balls
- if (Math.random() < 0.05) {
- // Start pulsing animation
+ // Check for special ball types based on color
+ if (color === 'white') {
+ self.isSpecial = true;
+ self.specialType = 'white_freeze';
+ ballGraphics.alpha = 0.9;
+ ballGraphics.scaleX = 1.15;
+ ballGraphics.scaleY = 1.15;
+ // Add pulsing effect for white balls
var _pulseEffect = function pulseEffect() {
tween(ballGraphics, {
scaleX: 1.3,
scaleY: 1.3
@@ -37,24 +42,79 @@
});
}
});
};
+ _pulseEffect();
+ } else if (color === 'black') {
self.isSpecial = true;
- var specials = ['explosive', 'freeze', 'rapid'];
- self.specialType = specials[Math.floor(Math.random() * specials.length)];
+ self.specialType = 'black_destroyer';
ballGraphics.alpha = 0.9;
- // Add glow effect for special balls
ballGraphics.scaleX = 1.15;
ballGraphics.scaleY = 1.15;
- // Add pulsing effect
- if (self.specialType === 'explosive') {
- ballGraphics.tint = 0xFF4500;
- } else if (self.specialType === 'freeze') {
- ballGraphics.tint = 0x00FFFF;
- } else if (self.specialType === 'rapid') {
- ballGraphics.tint = 0xFFFF00;
- }
+ ballGraphics.tint = 0x444444; // Slightly gray tint for visibility
+ // Add pulsing effect for black balls
+ var _pulseEffect = function pulseEffect() {
+ tween(ballGraphics, {
+ scaleX: 1.3,
+ scaleY: 1.3,
+ tint: 0x666666
+ }, {
+ duration: 600,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(ballGraphics, {
+ scaleX: 1.15,
+ scaleY: 1.15,
+ tint: 0x444444
+ }, {
+ duration: 600,
+ easing: tween.easeInOut,
+ onFinish: _pulseEffect
+ });
+ }
+ });
+ };
_pulseEffect();
+ } else {
+ // 5% chance for special balls on regular colors
+ if (Math.random() < 0.05) {
+ // Start pulsing animation
+ var _pulseEffect = function pulseEffect() {
+ tween(ballGraphics, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 600,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(ballGraphics, {
+ scaleX: 1.15,
+ scaleY: 1.15
+ }, {
+ duration: 600,
+ easing: tween.easeInOut,
+ onFinish: _pulseEffect
+ });
+ }
+ });
+ };
+ self.isSpecial = true;
+ var specials = ['explosive', 'freeze', 'rapid'];
+ self.specialType = specials[Math.floor(Math.random() * specials.length)];
+ ballGraphics.alpha = 0.9;
+ // Add glow effect for special balls
+ ballGraphics.scaleX = 1.15;
+ ballGraphics.scaleY = 1.15;
+ // Add pulsing effect
+ if (self.specialType === 'explosive') {
+ ballGraphics.tint = 0xFF4500;
+ } else if (self.specialType === 'freeze') {
+ ballGraphics.tint = 0x00FFFF;
+ } else if (self.specialType === 'rapid') {
+ ballGraphics.tint = 0xFFFF00;
+ }
+ _pulseEffect();
+ }
}
self.trackPosition = 0;
self.trackX = 0;
self.trackY = 0;
@@ -125,9 +185,17 @@
animateShooterBall();
}
// Generate next ball
var colors = ['red', 'blue', 'green', 'yellow', 'purple'];
- var randomColor = colors[Math.floor(Math.random() * colors.length)];
+ var randomValue = Math.random();
+ var randomColor;
+ if (randomValue < 0.05) {
+ randomColor = 'white'; // 5% chance for white ball
+ } else if (randomValue < 0.1) {
+ randomColor = 'black'; // 5% chance for black ball
+ } else {
+ randomColor = colors[Math.floor(Math.random() * colors.length)];
+ }
self.nextBall = new Ball(randomColor);
};
self.aimAt = function (x, y) {
var dx = x - self.x;
@@ -409,8 +477,9 @@
var veryFastChainSpeed = 0.006; // Very fast chain speed - slower than before
var speedLevel = 0; // 0 = normal, 1 = fast, 2 = very fast
var chainFrozen = false;
var freezeTimer = 0;
+var freezeCountdownDisplay = null;
var level = 1;
var gameWon = false;
var gameLost = false;
// Score multiplier system
@@ -483,9 +552,9 @@
chain = [];
var chainLength = 15 + level * 5;
var colors = ['red', 'blue', 'green', 'yellow', 'purple'];
var ballSpacing = 50; // Space between balls - balls touch each other
- var trackSpacing = 10.0; // Increased track position spacing to prevent overlap
+ var trackSpacing = 5.0; // Increased track position spacing to prevent overlap
// Ensure better color distribution by cycling through colors
for (var i = 0; i < chainLength; i++) {
// Use a mix of sequential and random distribution
var colorIndex;
@@ -499,9 +568,9 @@
var color = colors[colorIndex];
var ball = game.addChild(new ChainBall(color));
ball.chainIndex = i;
// Initialize track position with consistent spacing for vortex
- ball.trackPosition = i * 10.0; // Use consistent spacing to prevent overlap
+ ball.trackPosition = i * 7.0; // Use consistent spacing to prevent overlap
// Position ball immediately on track
positionBallOnTrack(ball, ball.trackPosition);
chain.push(ball);
}
@@ -550,10 +619,20 @@
// Update chain positions
function updateChain() {
if (chainFrozen) {
freezeTimer--;
+ // Update freeze countdown display
+ if (freezeCountdownDisplay) {
+ var secondsLeft = Math.ceil(freezeTimer / 60);
+ freezeCountdownDisplay.setText('FROZEN: ' + secondsLeft);
+ }
if (freezeTimer <= 0) {
chainFrozen = false;
+ // Remove countdown display
+ if (freezeCountdownDisplay) {
+ freezeCountdownDisplay.destroy();
+ freezeCountdownDisplay = null;
+ }
// Remove ice tint from all chain balls
for (var i = 0; i < chain.length; i++) {
var chainBall = chain[i];
tween(chainBall, {
@@ -565,9 +644,9 @@
}
return;
}
// Move all balls forward and maintain equal spacing for vortex
- var trackSpacing = 10.0; // Increased spacing significantly to prevent overlap
+ var trackSpacing = 7.0; // Increased spacing to prevent overlap, especially near hole
for (var i = 0; i < chain.length; i++) {
var ball = chain[i];
// Move chain forward in vortex pattern
ball.trackPosition += chainSpeed;
@@ -577,10 +656,10 @@
LK.showGameOver();
return;
}
}
- // Maintain equal spacing between balls for vortex movement - start from the back
- for (var i = chain.length - 1; i >= 0; i--) {
+ // Maintain equal spacing between balls for vortex movement
+ for (var i = 0; i < chain.length; i++) {
var ball = chain[i];
// Ensure proper spacing from previous ball
if (i > 0) {
var previousBall = chain[i - 1];
@@ -643,9 +722,9 @@
}
}
// Store the first index of the match to know where the gap starts
var firstMatchIndex = chain.indexOf(match[0]);
- var trackSpacing = 10.0; // Increased spacing to prevent overlap
+ var trackSpacing = 7.0; // Increased spacing to prevent overlap
var gapSize = match.length * trackSpacing; // Calculate gap size based on track spacing
// Remove matched balls
for (var b = 0; b < match.length; b++) {
var ball = match[b];
@@ -818,8 +897,65 @@
} else if (ball.specialType === 'rapid') {
shooter.rapidFire = true;
shooter.rapidFireTimer = 300; // 5 seconds at 60fps
LK.effects.flashScreen(0xffff00, 200);
+ } else if (ball.specialType === 'white_freeze') {
+ chainFrozen = true;
+ freezeTimer = 120; // 2 seconds at 60fps
+ LK.effects.flashScreen(0xffffff, 500);
+ // Create freeze countdown display
+ if (freezeCountdownDisplay) {
+ freezeCountdownDisplay.destroy();
+ }
+ freezeCountdownDisplay = new Text2('FROZEN: 2', {
+ size: 80,
+ fill: 0x00FFFF
+ });
+ freezeCountdownDisplay.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(freezeCountdownDisplay);
+ // Add ice tint to all chain balls
+ for (var i = 0; i < chain.length; i++) {
+ var chainBall = chain[i];
+ tween(chainBall, {
+ tint: 0x88DDFF
+ }, {
+ duration: 300
+ });
+ }
+ } else if (ball.specialType === 'black_destroyer') {
+ // Remove 5 nearby balls (2 on each side + the black ball itself)
+ var explosionRadius = 2;
+ var ballIndex = chain.indexOf(ball);
+ var toRemove = [];
+ for (var i = Math.max(0, ballIndex - explosionRadius); i < Math.min(chain.length, ballIndex + explosionRadius + 1); i++) {
+ toRemove.push(chain[i]);
+ }
+ for (var i = 0; i < toRemove.length; i++) {
+ var index = chain.indexOf(toRemove[i]);
+ if (index > -1) {
+ chain.splice(index, 1);
+ toRemove[i].destroy();
+ }
+ }
+ LK.effects.flashScreen(0x444444, 400);
+ // Add screen shake effect
+ var originalX = game.x;
+ var originalY = game.y;
+ var shakeIntensity = 8;
+ var shakeDuration = 400;
+ var shakeTimer = 0;
+ var _shakeEffect = function shakeEffect() {
+ if (shakeTimer < shakeDuration) {
+ game.x = originalX + (Math.random() - 0.5) * shakeIntensity;
+ game.y = originalY + (Math.random() - 0.5) * shakeIntensity;
+ shakeTimer += 16;
+ LK.setTimeout(_shakeEffect, 16);
+ } else {
+ game.x = originalX;
+ game.y = originalY;
+ }
+ };
+ _shakeEffect();
}
LK.getSound('powerup').play();
}
// Insert ball into chain
@@ -969,9 +1105,9 @@
// If collision detected, insert at collision position
if (collisionIndex !== -1) {
// Insert after the collided ball
var insertIndex = collisionIndex + 1;
- var trackSpacing = 10.0; // Increased spacing to prevent overlap
+ var trackSpacing = 7.0; // Increased spacing to prevent overlap
// Adjust track positions for all balls after insertion point
for (var k = insertIndex; k < chain.length; k++) {
chain[k].trackPosition += trackSpacing; // Move balls back to make space
}
@@ -1012,9 +1148,13 @@
shooter.nextBall.scaleX = 0.8;
shooter.nextBall.scaleY = 0.8;
LK.gui.topRight.addChild(shooter.nextBall);
}
- // Set chain speed based on current speed level (no automatic progression)
+ // Increase chain speed over time (slower increase)
+ normalChainSpeed += 0.00003;
+ // Update other speeds to maintain ratios
+ fastChainSpeed = normalChainSpeed * 6.67; // Maintain same ratio as before
+ veryFastChainSpeed = normalChainSpeed * 20; // Maintain same ratio as before
if (speedLevel === 0) {
chainSpeed = normalChainSpeed;
} else if (speedLevel === 1) {
chainSpeed = fastChainSpeed;
8 ball billard with fire. In-Game asset. 2d. High contrast. No shadows
green neon ball. In-Game asset. 2d. High contrast. No shadows
blach hole gif. In-Game asset. 2d. High contrast. No shadows
space shooter cannon. In-Game asset. 2d. High contrast. No shadows
fire effect. In-Game asset. 2d. High contrast. No shadows
space track point. In-Game asset. 2d. High contrast. No shadows
aim . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
ice. In-Game asset. 2d. High contrast. No shadows
flying superman
laser beam. In-Game asset. 2d. High contrast. No shadows
green goblin. In-Game asset. 2d. High contrast. No shadows
rocket. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
shoot
Sound effect
match
Sound effect
powerup
Sound effect
Gameplay
Music
gameover
Sound effect
frozen
Sound effect
celebration
Sound effect
white_shoot
Sound effect
fire_flying
Sound effect
superman_flying
Sound effect
superman_laser
Sound effect
villain_flying
Sound effect
villain_laser
Sound effect