User prompt
Notaladı hafif büyüt ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Notlar eger vurulmadıysa hedef bölgesini biraz geçtikten sonra kaybolsun
User prompt
Çok hafif aşagı
User prompt
Biraz aşagı
User prompt
Aşagıdaki 3 nesneyi ekrana görüncek şekilde biraz yukarı taşi
User prompt
Hedef alanı ve hedef alanı şeridini aşagı dogru biraz genişlet
User prompt
Alttaki 3 nesneye dokundugunda yıldırım animasyonu ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
3 nesnenin etrafında dönen parçaçık animasyonlarını kaldır
User prompt
Alttaki 3 nesnenin parçacık efekti animasyonlarını kaldır
User prompt
Nota parçacık efektini arttır
User prompt
Canları biraz aşagı konumlandır
User prompt
Lives için 5 sayı yerine 5 adet kalp görseli kullan
User prompt
Oyuncu için 5 can ekle
User prompt
Olmadı sıradaki müzigin çalması için oyuncunun 1. Müzik bitişinden sonra bir notu vurmasını bekleyin
User prompt
Müzik degiştirme başlangıçta oldugu gibi nota hedef alanda vuruldugunda başlayacak
User prompt
40 saniyede bir oyun müzigi degiştir
User prompt
Şarkı degişim süresini 1dk yap şarkı sesi azalarak kazybolsun yeni şarkı başlaması için oyuncunun notayı vurmasını bekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyun müzigi 3 tekrar yaptıktan sonra sıradaki şarkı için oyuncunun notayı vurmasını beklemeli
User prompt
Çok az nota düşme hızını arttır ve oyun boyunca aynı hıza sabitle
User prompt
Nota iniş hızını sabit bir hıza sabitle
User prompt
Çalışmıyor
User prompt
Oyun müzigi 3 tekrardan sonra degişir
User prompt
Oyunda müzik çalmaya başladıgında en fazla 3tekrar yapar bittikten sonra rastgele başka bir müzik nota tetiklenmesiyle çalmaya başlar
User prompt
Oyun müziklerinde 5 tekrardan sonra müzik degiştir
User prompt
Bir 3 oyun müzigi daha ekle
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Note = Container.expand(function (trackIndex, isPowerNote) { var self = Container.call(this); self.trackIndex = trackIndex; self.isPowerNote = isPowerNote || false; self.speed = 4; self.hasBeenTapped = false; self.lastY = 0; var noteGraphics = self.attachAsset(self.isPowerNote ? 'powerNote' : 'note', { anchorX: 0.5, anchorY: 0.5 }); if (self.isPowerNote) { noteGraphics.tint = 0xFFD93D; self.scale.set(1.2); } self.update = function () { if (self.lastY === undefined) self.lastY = self.y; if (self.lastInTargetZone === undefined) self.lastInTargetZone = false; // Check if note just entered target zone var targetY = 1600; // unifiedTargetZone.y var inTargetZone = Math.abs(self.y - targetY) <= 100; // Within target zone range // Additional check: ensure no other note is currently in target zone var otherNoteInZone = false; for (var k = 0; k < notes.length; k++) { var otherNote = notes[k]; if (otherNote !== self && !otherNote.hasBeenTapped && Math.abs(otherNote.y - targetY) <= 100) { otherNoteInZone = true; break; } } if (!self.lastInTargetZone && inTargetZone && !self.hasBeenTapped && !otherNoteInZone) { // Note just entered target zone and no other note is present - trigger explosion self.triggerExplosion(); } // Check if note just left target zone without being tapped (missed) if (self.lastInTargetZone && !inTargetZone && !self.hasBeenTapped) { // Note was missed - play miss sound LK.getSound('miss').play(); } self.lastY = self.y; self.lastInTargetZone = inTargetZone; self.y += self.speed; }; self.checkTiming = function () { var targetY = unifiedTargetZone.y; var distance = Math.abs(self.y - targetY); if (distance <= 30) { return 'perfect'; } else if (distance <= 60) { return 'good'; } return 'miss'; }; self.triggerExplosion = function () { if (self.hasBeenTapped) return; var timing = self.checkTiming(); if (timing !== 'miss') { self.hasBeenTapped = true; var points = 0; if (timing === 'perfect') { points = 1; LK.getSound('perfect').play(); createParticleEffect(self.x, self.y, self.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = 1; LK.getSound('tap').play(); createParticleEffect(self.x, self.y, 0x87CEEB); } updateScore(points); // Start background music on first successful hit if (!musicStarted) { currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)]; LK.playMusic(currentMusicTrack); musicStarted = true; } unifiedTargetZone.flash(); // Trigger explosion animation on corresponding bottom object var bottomObjects = [leftObject, centerObject, rightObject]; if (bottomObjects[self.trackIndex]) { var targetObject = bottomObjects[self.trackIndex]; // Flash the bottom object var originalAlpha = targetObject.alpha; tween(targetObject, { alpha: 1.0 }, { duration: 100, onFinish: function onFinish() { tween(targetObject, { alpha: originalAlpha }, { duration: 200 }); } }); // Scale pulse effect var originalScale = targetObject.scaleX; tween(targetObject, { scaleX: originalScale * 1.1, scaleY: originalScale * 1.1 }, { duration: 150, onFinish: function onFinish() { tween(targetObject, { scaleX: originalScale, scaleY: originalScale }, { duration: 150 }); } }); } // Explode the note tween(self, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.destroy(); for (var j = 0; j < notes.length; j++) { if (notes[j] === self) { notes.splice(j, 1); break; } } } }); } }; return self; }); var TargetZone = Container.expand(function (trackIndex) { var self = Container.call(this); self.trackIndex = trackIndex; var zoneGraphics = self.attachAsset('targetZone', { anchorX: 0.5, anchorY: 0.5 }); zoneGraphics.alpha = 0.9; self.flash = function () { zoneGraphics.alpha = 1.0; tween(zoneGraphics, { alpha: 0.9 }, { duration: 200 }); }; return self; }); var Track = Container.expand(function (trackIndex) { var self = Container.call(this); self.trackIndex = trackIndex; var trackGraphics = self.attachAsset('track', { anchorX: 0.5, anchorY: 0 }); trackGraphics.alpha = 0.1; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Game variables var notes = []; var tracks = []; var targetZones = []; var numTracks = 3; var trackWidth = 300; var gameWidth = 2048; var score = 0; var noteSpawnTimer = 0; var noteSpawnInterval = 120; var gameSpeed = 1; var difficultyTimer = 0; // Note queue system to prevent simultaneous target zone entry var noteQueue = []; var lastTargetZoneEntry = 0; var minTimeBetweenEntries = 80; // Further increased minimum frames between notes entering target zone // Vertical spacing system to prevent notes from overlapping var minVerticalSpacing = 250; // Increased minimum pixels between notes vertically // Bottom objects for explosion effects var leftObject, centerObject, rightObject; // Strip line references for sway effects var leftStripLine, centerStripLine, rightStripLine; // UI elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); scoreTxt.x = 120; // Position away from platform menu icon scoreTxt.y = 220; // Move even further down from top LK.gui.topLeft.addChild(scoreTxt); // Add background image var background = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); background.x = 0; background.y = 0; background.tint = 0x000000; game.addChild(background); // Initialize tracks and unified target zone var startX = (gameWidth - numTracks * trackWidth) / 2 + trackWidth / 2; for (var i = 0; i < numTracks; i++) { var track = new Track(i); track.x = startX + i * trackWidth; track.y = 0; tracks.push(track); game.addChild(track); } // Create single unified target zone covering all tracks var unifiedTargetZone = new TargetZone(0); unifiedTargetZone.x = gameWidth / 2; // Center of screen unifiedTargetZone.y = 1600; // Scale the target zone to cover all tracks unifiedTargetZone.scale.x = numTracks * trackWidth / 350; // Scale to cover all track widths targetZones.push(unifiedTargetZone); // Add unified background covering entire play area var unifiedBg = LK.getAsset('unifiedBackground', { anchorX: 0.5, anchorY: 0 }); unifiedBg.x = gameWidth / 2; // Center horizontally unifiedBg.y = 0; // Start from top of screen unifiedBg.width = gameWidth + 800; // Extend much further beyond screen width on both sides unifiedBg.height = 3500; // Extend further downward beyond screen height unifiedBg.alpha = 0.8; // Slightly transparent to show game elements clearly game.addChild(unifiedBg); // Re-add strip lines and unified target zone to foreground for (var i = 0; i < numTracks; i++) { // Add strip line for each track (moved to foreground) var stripLine = LK.getAsset('stripLine', { anchorX: 0.5, anchorY: 0 }); stripLine.x = startX + i * trackWidth; stripLine.y = 0; stripLine.alpha = 0.8; // Store original position for vibration reset stripLine.originalX = stripLine.x; game.addChild(stripLine); // Store references to strip lines if (i === 0) leftStripLine = stripLine;else if (i === 1) centerStripLine = stripLine;else if (i === 2) rightStripLine = stripLine; } // Add unified target zone to foreground game.addChild(unifiedTargetZone); // Create rounded border around unified target zone var borderThickness = 8; var targetZoneWidth = 350 * unifiedTargetZone.scale.x; var targetZoneHeight = 200; // Top border var topBorder = LK.getAsset('stripLine', { anchorX: 0.5, anchorY: 0.5 }); topBorder.width = targetZoneWidth - borderThickness; topBorder.height = borderThickness; topBorder.x = unifiedTargetZone.x; topBorder.y = unifiedTargetZone.y - targetZoneHeight / 2 - borderThickness / 2; topBorder.alpha = 1.0; game.addChild(topBorder); // Bottom border var bottomBorder = LK.getAsset('stripLine', { anchorX: 0.5, anchorY: 0.5 }); bottomBorder.width = targetZoneWidth - borderThickness; bottomBorder.height = borderThickness; bottomBorder.x = unifiedTargetZone.x; bottomBorder.y = unifiedTargetZone.y + targetZoneHeight / 2 + borderThickness / 2; bottomBorder.alpha = 1.0; game.addChild(bottomBorder); // Left border var leftBorder = LK.getAsset('stripLine', { anchorX: 0.5, anchorY: 0.5 }); leftBorder.width = borderThickness; leftBorder.height = targetZoneHeight - borderThickness; leftBorder.x = unifiedTargetZone.x - targetZoneWidth / 2 - borderThickness / 2; leftBorder.y = unifiedTargetZone.y; leftBorder.alpha = 1.0; game.addChild(leftBorder); // Right border var rightBorder = LK.getAsset('stripLine', { anchorX: 0.5, anchorY: 0.5 }); rightBorder.width = borderThickness; rightBorder.height = targetZoneHeight - borderThickness; rightBorder.x = unifiedTargetZone.x + targetZoneWidth / 2 + borderThickness / 2; rightBorder.y = unifiedTargetZone.y; rightBorder.alpha = 1.0; game.addChild(rightBorder); // Add rounded corners with ellipses // Top-left corner var topLeftCorner = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); topLeftCorner.x = unifiedTargetZone.x - targetZoneWidth / 2; topLeftCorner.y = unifiedTargetZone.y - targetZoneHeight / 2; topLeftCorner.alpha = 1.0; game.addChild(topLeftCorner); // Top-right corner var topRightCorner = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); topRightCorner.x = unifiedTargetZone.x + targetZoneWidth / 2; topRightCorner.y = unifiedTargetZone.y - targetZoneHeight / 2; topRightCorner.alpha = 1.0; game.addChild(topRightCorner); // Bottom-left corner var bottomLeftCorner = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); bottomLeftCorner.x = unifiedTargetZone.x - targetZoneWidth / 2; bottomLeftCorner.y = unifiedTargetZone.y + targetZoneHeight / 2; bottomLeftCorner.alpha = 1.0; game.addChild(bottomLeftCorner); // Bottom-right corner var bottomRightCorner = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); bottomRightCorner.x = unifiedTargetZone.x + targetZoneWidth / 2; bottomRightCorner.y = unifiedTargetZone.y + targetZoneHeight / 2; bottomRightCorner.alpha = 1.0; game.addChild(bottomRightCorner); // Helper functions function spawnNote() { var trackIndex = Math.floor(Math.random() * numTracks); var isPowerNote = Math.random() < 0.1; // Add to queue instead of spawning directly noteQueue.push({ trackIndex: trackIndex, isPowerNote: isPowerNote, readyTime: LK.ticks + Math.max(0, lastTargetZoneEntry + minTimeBetweenEntries - LK.ticks) }); } function processNoteQueue() { for (var i = noteQueue.length - 1; i >= 0; i--) { var queuedNote = noteQueue[i]; if (LK.ticks >= queuedNote.readyTime) { // Check if any note is currently in or approaching target zone var canSpawn = true; var targetY = 1600; var spawnY = -50; var targetZoneBuffer = 200; // Extended buffer zone around target for (var j = 0; j < notes.length; j++) { var existingNote = notes[j]; // Check if note is in extended target zone area (larger buffer for safety) if (Math.abs(existingNote.y - targetY) <= targetZoneBuffer) { canSpawn = false; break; } // Check if note will reach target zone soon (prediction based on speed) var timeToTarget = (targetY - existingNote.y) / existingNote.speed; if (timeToTarget > 0 && timeToTarget <= 50) { // Within 50 frames of reaching target canSpawn = false; break; } // Check vertical spacing collision - prevent notes from being too close vertically if (Math.abs(existingNote.y - spawnY) < minVerticalSpacing) { canSpawn = false; break; } } if (canSpawn) { // Spawn the note var note = new Note(queuedNote.trackIndex, queuedNote.isPowerNote); note.x = startX + queuedNote.trackIndex * trackWidth; note.y = spawnY; note.speed = 4 * gameSpeed; notes.push(note); game.addChild(note); lastTargetZoneEntry = LK.ticks; noteQueue.splice(i, 1); } else { // Delay this note by adding minimum time queuedNote.readyTime = LK.ticks + minTimeBetweenEntries; } } } } function updateScore(points) { score += points; scoreTxt.setText('Score: ' + score); LK.setScore(score); } function createParticleEffect(x, y, color) { // Create optimized particle effects var totalParticles = 40; // Reduced particle count for performance var primaryParticles = 20; var secondaryParticles = 12; var trailParticles = 8; // Primary burst particles - fast moving with enhanced visuals for (var i = 0; i < primaryParticles; i++) { var particle = LK.getAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); particle.x = x; particle.y = y; // Enhanced color with gradient-like effect var colorVariation = 0x202020 * Math.random(); particle.tint = (color || 0xFFD93D) + colorVariation; particle.alpha = 0.9 + Math.random() * 0.1; game.addChild(particle); // Calculate random direction and speed for each particle var angle = i / primaryParticles * Math.PI * 2 + (Math.random() - 0.5) * 1.8; var speed = 600 + Math.random() * 500; // Enhanced speed range var targetX = x + Math.cos(angle) * speed; var targetY = y + Math.sin(angle) * speed; // Enhanced particle scaling with better proportions particle.scaleX = 2.5 + Math.random() * 2.0; // Better balanced particle size particle.scaleY = particle.scaleX + (Math.random() - 0.5) * 0.5; // Slight asymmetry for organic feel // Animate particle flying outward with enhanced effects tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.05, // Smoother scale transition scaleY: 0.05, rotation: (Math.random() - 0.5) * Math.PI * 12 // Enhanced rotation }, { duration: 800 + Math.random() * 700, // Optimized duration for better visual flow easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Secondary slower particles for depth with improved visuals for (var i = 0; i < secondaryParticles; i++) { var particle = LK.getAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); particle.x = x + (Math.random() - 0.5) * 40; // Refined initial spread particle.y = y + (Math.random() - 0.5) * 40; // Enhanced secondary particle coloring var secondaryColor = color || 0xFFD93D; var brightness = 0.7 + Math.random() * 0.3; particle.tint = secondaryColor * brightness; particle.alpha = 0.75 + Math.random() * 0.25; game.addChild(particle); var angle = Math.random() * Math.PI * 2; var speed = 350 + Math.random() * 250; // Enhanced secondary particle speed var targetX = x + Math.cos(angle) * speed; var targetY = y + Math.sin(angle) * speed; // Enhanced secondary particle scaling particle.scaleX = 1.8 + Math.random() * 1.5; // Better proportioned secondary particles particle.scaleY = particle.scaleX * (0.8 + Math.random() * 0.4); // Varied proportions // Delayed animation for staggered effect with enhanced timing tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, // Smoother scale transition scaleY: 0.1, rotation: (Math.random() - 0.5) * Math.PI * 10 // Enhanced rotation }, { duration: 1000 + Math.random() * 800, // Refined duration easing: tween.easeInOut, onFinish: function onFinish() { particle.destroy(); } }); } // Enhanced trail particles that move upward for (var i = 0; i < trailParticles; i++) { var particle = LK.getAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); particle.x = x + (Math.random() - 0.5) * 60; // Enhanced initial spread particle.y = y; // Enhanced trail particle coloring with glow effect var trailColor = color || 0xFFD93D; var glowIntensity = 0.8 + Math.random() * 0.2; particle.tint = trailColor * glowIntensity; particle.alpha = 0.6 + Math.random() * 0.3; game.addChild(particle); // Enhanced trail particle scaling with better proportions particle.scaleX = 3.0 + Math.random() * 2.0; // Better balanced trail particles particle.scaleY = particle.scaleX * (0.6 + Math.random() * 0.8); // More varied shapes // Animate upward with enhanced gravity-like effect tween(particle, { x: particle.x + (Math.random() - 0.5) * 200, // Enhanced horizontal spread y: y - 350 - Math.random() * 250, // Enhanced upward movement alpha: 0, scaleX: 0.2, // Smoother scale transition scaleY: 0.2, rotation: (Math.random() - 0.5) * Math.PI * 8 // Enhanced rotation }, { duration: 1200 + Math.random() * 900, // Optimized duration easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } } function checkNoteInTrack(trackIndex) { for (var i = 0; i < notes.length; i++) { var note = notes[i]; if (note.trackIndex === trackIndex && !note.hasBeenTapped) { var timing = note.checkTiming(); if (timing !== 'miss') { note.hasBeenTapped = true; var points = 0; if (timing === 'perfect') { points = 1; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = 1; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); // Start background music on first successful hit if (!musicStarted) { currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)]; LK.playMusic(currentMusicTrack); musicStarted = true; } unifiedTargetZone.flash(); note.destroy(); notes.splice(i, 1); return true; } } } return false; } // Touch handlers game.down = function (x, y, obj) { for (var i = 0; i < numTracks; i++) { var trackX = startX + i * trackWidth; if (x >= trackX - trackWidth / 2 && x <= trackX + trackWidth / 2) { if (!checkNoteInTrack(i)) { LK.getSound('miss').play(); } break; } } }; // Main game loop game.update = function () { // Spawn notes noteSpawnTimer++; if (noteSpawnTimer >= noteSpawnInterval) { spawnNote(); noteSpawnTimer = 0; } // Process note queue to ensure no simultaneous target zone entries processNoteQueue(); // Update difficulty difficultyTimer++; if (difficultyTimer >= 1800) { // Every 30 seconds gameSpeed += 0.2; noteSpawnInterval = Math.max(20, noteSpawnInterval - 2); difficultyTimer = 0; } // Update notes for (var i = notes.length - 1; i >= 0; i--) { var note = notes[i]; // Check if note missed target zone - let it pass slightly further before removing if (!note.hasBeenTapped && note.lastY <= 1800 && note.y > 1800) { note.destroy(); notes.splice(i, 1); continue; } // Remove notes that are off screen if (note.y > 2800) { note.destroy(); notes.splice(i, 1); } } // Update orbital particles and clean up off-screen particles var allChildren = game.children.slice(); // Create a copy to avoid modification during iteration for (var i = allChildren.length - 1; i >= 0; i--) { var child = allChildren[i]; // Update orbital particles if (child && child.isOrbitalParticle && child.targetObject) { child.orbitAngle += child.orbitSpeed; child.orbitRadius *= child.spiralRate; // Orbital positioning with vertical oscillation var verticalOffset = Math.sin(child.orbitAngle * 3) * 10; child.x = child.targetObject.x + Math.cos(child.orbitAngle) * child.orbitRadius; child.y = child.targetObject.y + Math.sin(child.orbitAngle) * child.orbitRadius + verticalOffset; } // Check if this is a particle (has particle-like properties) if (child && child.x !== undefined && child.y !== undefined && child.width <= 10 && child.height <= 10) { // Remove particles that are far off-screen or destroyed if (child.x < -500 || child.x > 2548 || child.y < -500 || child.y > 3232 || child.destroyed) { if (child.destroy) { child.destroy(); } else { game.removeChild(child); } } } } // Create continuous particle effects around the three objects enhanceObjectVisuals(); // Win condition if (score >= 10000) { LK.showYouWin(); } }; // Add 3 objects at bottom of target zone (left, center, right) var targetBottomY = unifiedTargetZone.y + targetZoneHeight / 2 + 800; // Move objects much further down var objectSpacing = targetZoneWidth / 1.5; // Increased spacing for better separation between objects // Left object leftObject = LK.getAsset('leftObjectAsset', { anchorX: 0.5, anchorY: 0.5 }); leftObject.x = unifiedTargetZone.x - objectSpacing; leftObject.y = targetBottomY; // Scale up the left object leftObject.scaleX = 2.0; leftObject.scaleY = 2.0; // Animate color change for left object tween(leftObject, { tint: 0xFFD700 // Change to gold color }, { duration: 1500, easing: tween.easeInOut }); leftObject.alpha = 0.8; game.addChild(leftObject); // Center object centerObject = LK.getAsset('centerObjectAsset', { anchorX: 0.5, anchorY: 0.5 }); centerObject.x = unifiedTargetZone.x; centerObject.y = targetBottomY; // Scale up the center object centerObject.scaleX = 2.0; centerObject.scaleY = 2.0; // Animate color change for center object tween(centerObject, { tint: 0xFF1493 // Change to deep pink color }, { duration: 1500, easing: tween.easeInOut }); centerObject.alpha = 0.8; game.addChild(centerObject); // Right object rightObject = LK.getAsset('rightObjectAsset', { anchorX: 0.5, anchorY: 0.5 }); rightObject.x = unifiedTargetZone.x + objectSpacing; rightObject.y = targetBottomY; // Scale up the right object rightObject.scaleX = 2.0; rightObject.scaleY = 2.0; // Animate color change for right object tween(rightObject, { tint: 0x9370DB // Change to medium purple color }, { duration: 1500, easing: tween.easeInOut }); rightObject.alpha = 0.8; game.addChild(rightObject); // Objects are now properly sized - no extreme scaling needed // Move objects to topmost layer for better visibility game.removeChild(leftObject); game.addChild(leftObject); game.removeChild(centerObject); game.addChild(centerObject); game.removeChild(rightObject); game.addChild(rightObject); // Add touch handlers to the 3 bottom objects leftObject.down = function (x, y, obj) { // Create particle effect when touched createParticleEffect(leftObject.x, leftObject.y, 0xFFD700); // Add guitar string vibration effect to left track strip line if (leftStripLine) { // Use stored original position instead of current position var originalX = leftStripLine.originalX; var _vibrateString = function vibrateString() { if (vibrationCount >= maxVibrations) { // Reset to original position when vibration completes tween(leftStripLine, { x: originalX }, { duration: 100, easing: tween.easeOut }); return; } var amplitude = baseAmplitude * (1 - vibrationCount / maxVibrations); var direction = vibrationCount % 2 === 0 ? 1 : -1; tween(leftStripLine, { x: originalX + amplitude * direction }, { duration: 40, easing: tween.easeInOut, onFinish: function onFinish() { vibrationCount++; _vibrateString(); } }); }; // Guitar string effect - rapid horizontal vibrations that decay var vibrationCount = 0; var maxVibrations = 15; var baseAmplitude = 25; _vibrateString(); } // Check for notes in left track (track 0) within target zone for (var i = 0; i < notes.length; i++) { var note = notes[i]; if (note.trackIndex === 0 && !note.hasBeenTapped) { var timing = note.checkTiming(); if (timing !== 'miss') { // Explode the note note.hasBeenTapped = true; var points = 0; if (timing === 'perfect') { points = 1; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = 1; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); // Start background music on first successful hit if (!musicStarted) { currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)]; LK.playMusic(currentMusicTrack); musicStarted = true; } unifiedTargetZone.flash(); // Scale animation for explosion effect tween(note, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 200, onFinish: function onFinish() { note.destroy(); for (var j = 0; j < notes.length; j++) { if (notes[j] === note) { notes.splice(j, 1); break; } } } }); break; } } } }; centerObject.down = function (x, y, obj) { // Create particle effect when touched createParticleEffect(centerObject.x, centerObject.y, 0xFF1493); // Add guitar string vibration effect to center track strip line if (centerStripLine) { // Use stored original position instead of current position var originalX = centerStripLine.originalX; var _vibrateString2 = function vibrateString() { if (vibrationCount >= maxVibrations) { // Reset to original position when vibration completes tween(centerStripLine, { x: originalX }, { duration: 100, easing: tween.easeOut }); return; } var amplitude = baseAmplitude * (1 - vibrationCount / maxVibrations); var direction = vibrationCount % 2 === 0 ? 1 : -1; tween(centerStripLine, { x: originalX + amplitude * direction }, { duration: 40, easing: tween.easeInOut, onFinish: function onFinish() { vibrationCount++; _vibrateString2(); } }); }; // Guitar string effect - rapid horizontal vibrations that decay var vibrationCount = 0; var maxVibrations = 15; var baseAmplitude = 25; _vibrateString2(); } // Check for notes in center track (track 1) within target zone for (var i = 0; i < notes.length; i++) { var note = notes[i]; if (note.trackIndex === 1 && !note.hasBeenTapped) { var timing = note.checkTiming(); if (timing !== 'miss') { // Explode the note note.hasBeenTapped = true; var points = 0; if (timing === 'perfect') { points = 1; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = 1; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); // Start background music on first successful hit if (!musicStarted) { currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)]; LK.playMusic(currentMusicTrack); musicStarted = true; } unifiedTargetZone.flash(); // Scale animation for explosion effect tween(note, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 200, onFinish: function onFinish() { note.destroy(); for (var j = 0; j < notes.length; j++) { if (notes[j] === note) { notes.splice(j, 1); break; } } } }); break; } } } }; rightObject.down = function (x, y, obj) { // Create particle effect when touched createParticleEffect(rightObject.x, rightObject.y, 0x9370DB); // Add guitar string vibration effect to right track strip line if (rightStripLine) { // Use stored original position instead of current position var originalX = rightStripLine.originalX; var _vibrateString3 = function vibrateString() { if (vibrationCount >= maxVibrations) { // Reset to original position when vibration completes tween(rightStripLine, { x: originalX }, { duration: 100, easing: tween.easeOut }); return; } var amplitude = baseAmplitude * (1 - vibrationCount / maxVibrations); var direction = vibrationCount % 2 === 0 ? 1 : -1; tween(rightStripLine, { x: originalX + amplitude * direction }, { duration: 40, easing: tween.easeInOut, onFinish: function onFinish() { vibrationCount++; _vibrateString3(); } }); }; // Guitar string effect - rapid horizontal vibrations that decay var vibrationCount = 0; var maxVibrations = 15; var baseAmplitude = 25; _vibrateString3(); } // Check for notes in right track (track 2) within target zone for (var i = 0; i < notes.length; i++) { var note = notes[i]; if (note.trackIndex === 2 && !note.hasBeenTapped) { var timing = note.checkTiming(); if (timing !== 'miss') { // Explode the note note.hasBeenTapped = true; var points = 0; if (timing === 'perfect') { points = 1; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = 1; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); // Start background music on first successful hit if (!musicStarted) { currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)]; LK.playMusic(currentMusicTrack); musicStarted = true; } unifiedTargetZone.flash(); // Scale animation for explosion effect tween(note, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 200, onFinish: function onFinish() { note.destroy(); for (var j = 0; j < notes.length; j++) { if (notes[j] === note) { notes.splice(j, 1); break; } } } }); break; } } } }; // Music will start when first note is hit var musicStarted = false; var musicTracks = ['bgmusic', 'bgmusic2', 'bgmusic3', 'bgmusic4', 'bgmusic5']; var currentMusicTrack = null; // Add continuous particle effects around the three bottom objects function createContinuousParticleEffect(targetObject, color) { var particle = LK.getAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); // Enhanced positioning with better distribution var angle = Math.random() * Math.PI * 2; var radius = 100 + Math.random() * 120; // Enhanced radius range var startX = targetObject.x + Math.cos(angle) * radius; var startY = targetObject.y + Math.sin(angle) * radius; particle.x = startX; particle.y = startY; // Enhanced color with subtle variations var colorVariation = 0x151515 * (Math.random() - 0.5); particle.tint = color + colorVariation; particle.alpha = 0.6 + Math.random() * 0.4; // Enhanced alpha range // Enhanced particle scaling with better proportions particle.scaleX = 1.2 + Math.random() * 1.8; // Better balanced continuous particles particle.scaleY = particle.scaleX * (0.8 + Math.random() * 0.4); // Varied shapes for organic feel game.addChild(particle); // Enhanced orbital motion parameters var orbitAngle = angle; var orbitSpeed = 0.015 + Math.random() * 0.025; // Smoother orbital speed var orbitRadius = radius; var spiralRate = 0.997 + Math.random() * 0.002; // More varied spiral rates // Enhanced particle animation with better transitions tween(particle, { alpha: 0, scaleX: 0.3, // Smoother scale transition scaleY: 0.3, rotation: (Math.random() - 0.5) * Math.PI * 4 // Added rotation for visual interest }, { duration: 1800 + Math.random() * 1200, // Enhanced duration range easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); // Store orbital properties on particle for main update loop particle.orbitAngle = orbitAngle; particle.orbitSpeed = orbitSpeed; particle.orbitRadius = orbitRadius; particle.spiralRate = spiralRate; particle.targetObject = targetObject; particle.isOrbitalParticle = true; } // Optimized continuous particle system var particleSpawnTimer = 0; var particleSpawnInterval = 15; // Reduced spawn rate to prevent performance issues // Optimized visual effects function function enhanceObjectVisuals() { particleSpawnTimer++; if (particleSpawnTimer >= particleSpawnInterval) { // Create fewer particles around each object // Create particles around left object for (var i = 0; i < 2; i++) { createContinuousParticleEffect(leftObject, 0xFFD700); } // Create particles around center object for (var i = 0; i < 2; i++) { createContinuousParticleEffect(centerObject, 0xFF1493); } // Create particles around right object for (var i = 0; i < 2; i++) { createContinuousParticleEffect(rightObject, 0x9370DB); } particleSpawnTimer = 0; } }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Note = Container.expand(function (trackIndex, isPowerNote) {
var self = Container.call(this);
self.trackIndex = trackIndex;
self.isPowerNote = isPowerNote || false;
self.speed = 4;
self.hasBeenTapped = false;
self.lastY = 0;
var noteGraphics = self.attachAsset(self.isPowerNote ? 'powerNote' : 'note', {
anchorX: 0.5,
anchorY: 0.5
});
if (self.isPowerNote) {
noteGraphics.tint = 0xFFD93D;
self.scale.set(1.2);
}
self.update = function () {
if (self.lastY === undefined) self.lastY = self.y;
if (self.lastInTargetZone === undefined) self.lastInTargetZone = false;
// Check if note just entered target zone
var targetY = 1600; // unifiedTargetZone.y
var inTargetZone = Math.abs(self.y - targetY) <= 100; // Within target zone range
// Additional check: ensure no other note is currently in target zone
var otherNoteInZone = false;
for (var k = 0; k < notes.length; k++) {
var otherNote = notes[k];
if (otherNote !== self && !otherNote.hasBeenTapped && Math.abs(otherNote.y - targetY) <= 100) {
otherNoteInZone = true;
break;
}
}
if (!self.lastInTargetZone && inTargetZone && !self.hasBeenTapped && !otherNoteInZone) {
// Note just entered target zone and no other note is present - trigger explosion
self.triggerExplosion();
}
// Check if note just left target zone without being tapped (missed)
if (self.lastInTargetZone && !inTargetZone && !self.hasBeenTapped) {
// Note was missed - play miss sound
LK.getSound('miss').play();
}
self.lastY = self.y;
self.lastInTargetZone = inTargetZone;
self.y += self.speed;
};
self.checkTiming = function () {
var targetY = unifiedTargetZone.y;
var distance = Math.abs(self.y - targetY);
if (distance <= 30) {
return 'perfect';
} else if (distance <= 60) {
return 'good';
}
return 'miss';
};
self.triggerExplosion = function () {
if (self.hasBeenTapped) return;
var timing = self.checkTiming();
if (timing !== 'miss') {
self.hasBeenTapped = true;
var points = 0;
if (timing === 'perfect') {
points = 1;
LK.getSound('perfect').play();
createParticleEffect(self.x, self.y, self.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = 1;
LK.getSound('tap').play();
createParticleEffect(self.x, self.y, 0x87CEEB);
}
updateScore(points);
// Start background music on first successful hit
if (!musicStarted) {
currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.playMusic(currentMusicTrack);
musicStarted = true;
}
unifiedTargetZone.flash();
// Trigger explosion animation on corresponding bottom object
var bottomObjects = [leftObject, centerObject, rightObject];
if (bottomObjects[self.trackIndex]) {
var targetObject = bottomObjects[self.trackIndex];
// Flash the bottom object
var originalAlpha = targetObject.alpha;
tween(targetObject, {
alpha: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
tween(targetObject, {
alpha: originalAlpha
}, {
duration: 200
});
}
});
// Scale pulse effect
var originalScale = targetObject.scaleX;
tween(targetObject, {
scaleX: originalScale * 1.1,
scaleY: originalScale * 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(targetObject, {
scaleX: originalScale,
scaleY: originalScale
}, {
duration: 150
});
}
});
}
// Explode the note
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
for (var j = 0; j < notes.length; j++) {
if (notes[j] === self) {
notes.splice(j, 1);
break;
}
}
}
});
}
};
return self;
});
var TargetZone = Container.expand(function (trackIndex) {
var self = Container.call(this);
self.trackIndex = trackIndex;
var zoneGraphics = self.attachAsset('targetZone', {
anchorX: 0.5,
anchorY: 0.5
});
zoneGraphics.alpha = 0.9;
self.flash = function () {
zoneGraphics.alpha = 1.0;
tween(zoneGraphics, {
alpha: 0.9
}, {
duration: 200
});
};
return self;
});
var Track = Container.expand(function (trackIndex) {
var self = Container.call(this);
self.trackIndex = trackIndex;
var trackGraphics = self.attachAsset('track', {
anchorX: 0.5,
anchorY: 0
});
trackGraphics.alpha = 0.1;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game variables
var notes = [];
var tracks = [];
var targetZones = [];
var numTracks = 3;
var trackWidth = 300;
var gameWidth = 2048;
var score = 0;
var noteSpawnTimer = 0;
var noteSpawnInterval = 120;
var gameSpeed = 1;
var difficultyTimer = 0;
// Note queue system to prevent simultaneous target zone entry
var noteQueue = [];
var lastTargetZoneEntry = 0;
var minTimeBetweenEntries = 80; // Further increased minimum frames between notes entering target zone
// Vertical spacing system to prevent notes from overlapping
var minVerticalSpacing = 250; // Increased minimum pixels between notes vertically
// Bottom objects for explosion effects
var leftObject, centerObject, rightObject;
// Strip line references for sway effects
var leftStripLine, centerStripLine, rightStripLine;
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120; // Position away from platform menu icon
scoreTxt.y = 220; // Move even further down from top
LK.gui.topLeft.addChild(scoreTxt);
// Add background image
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
background.x = 0;
background.y = 0;
background.tint = 0x000000;
game.addChild(background);
// Initialize tracks and unified target zone
var startX = (gameWidth - numTracks * trackWidth) / 2 + trackWidth / 2;
for (var i = 0; i < numTracks; i++) {
var track = new Track(i);
track.x = startX + i * trackWidth;
track.y = 0;
tracks.push(track);
game.addChild(track);
}
// Create single unified target zone covering all tracks
var unifiedTargetZone = new TargetZone(0);
unifiedTargetZone.x = gameWidth / 2; // Center of screen
unifiedTargetZone.y = 1600;
// Scale the target zone to cover all tracks
unifiedTargetZone.scale.x = numTracks * trackWidth / 350; // Scale to cover all track widths
targetZones.push(unifiedTargetZone);
// Add unified background covering entire play area
var unifiedBg = LK.getAsset('unifiedBackground', {
anchorX: 0.5,
anchorY: 0
});
unifiedBg.x = gameWidth / 2; // Center horizontally
unifiedBg.y = 0; // Start from top of screen
unifiedBg.width = gameWidth + 800; // Extend much further beyond screen width on both sides
unifiedBg.height = 3500; // Extend further downward beyond screen height
unifiedBg.alpha = 0.8; // Slightly transparent to show game elements clearly
game.addChild(unifiedBg);
// Re-add strip lines and unified target zone to foreground
for (var i = 0; i < numTracks; i++) {
// Add strip line for each track (moved to foreground)
var stripLine = LK.getAsset('stripLine', {
anchorX: 0.5,
anchorY: 0
});
stripLine.x = startX + i * trackWidth;
stripLine.y = 0;
stripLine.alpha = 0.8;
// Store original position for vibration reset
stripLine.originalX = stripLine.x;
game.addChild(stripLine);
// Store references to strip lines
if (i === 0) leftStripLine = stripLine;else if (i === 1) centerStripLine = stripLine;else if (i === 2) rightStripLine = stripLine;
}
// Add unified target zone to foreground
game.addChild(unifiedTargetZone);
// Create rounded border around unified target zone
var borderThickness = 8;
var targetZoneWidth = 350 * unifiedTargetZone.scale.x;
var targetZoneHeight = 200;
// Top border
var topBorder = LK.getAsset('stripLine', {
anchorX: 0.5,
anchorY: 0.5
});
topBorder.width = targetZoneWidth - borderThickness;
topBorder.height = borderThickness;
topBorder.x = unifiedTargetZone.x;
topBorder.y = unifiedTargetZone.y - targetZoneHeight / 2 - borderThickness / 2;
topBorder.alpha = 1.0;
game.addChild(topBorder);
// Bottom border
var bottomBorder = LK.getAsset('stripLine', {
anchorX: 0.5,
anchorY: 0.5
});
bottomBorder.width = targetZoneWidth - borderThickness;
bottomBorder.height = borderThickness;
bottomBorder.x = unifiedTargetZone.x;
bottomBorder.y = unifiedTargetZone.y + targetZoneHeight / 2 + borderThickness / 2;
bottomBorder.alpha = 1.0;
game.addChild(bottomBorder);
// Left border
var leftBorder = LK.getAsset('stripLine', {
anchorX: 0.5,
anchorY: 0.5
});
leftBorder.width = borderThickness;
leftBorder.height = targetZoneHeight - borderThickness;
leftBorder.x = unifiedTargetZone.x - targetZoneWidth / 2 - borderThickness / 2;
leftBorder.y = unifiedTargetZone.y;
leftBorder.alpha = 1.0;
game.addChild(leftBorder);
// Right border
var rightBorder = LK.getAsset('stripLine', {
anchorX: 0.5,
anchorY: 0.5
});
rightBorder.width = borderThickness;
rightBorder.height = targetZoneHeight - borderThickness;
rightBorder.x = unifiedTargetZone.x + targetZoneWidth / 2 + borderThickness / 2;
rightBorder.y = unifiedTargetZone.y;
rightBorder.alpha = 1.0;
game.addChild(rightBorder);
// Add rounded corners with ellipses
// Top-left corner
var topLeftCorner = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
topLeftCorner.x = unifiedTargetZone.x - targetZoneWidth / 2;
topLeftCorner.y = unifiedTargetZone.y - targetZoneHeight / 2;
topLeftCorner.alpha = 1.0;
game.addChild(topLeftCorner);
// Top-right corner
var topRightCorner = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
topRightCorner.x = unifiedTargetZone.x + targetZoneWidth / 2;
topRightCorner.y = unifiedTargetZone.y - targetZoneHeight / 2;
topRightCorner.alpha = 1.0;
game.addChild(topRightCorner);
// Bottom-left corner
var bottomLeftCorner = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
bottomLeftCorner.x = unifiedTargetZone.x - targetZoneWidth / 2;
bottomLeftCorner.y = unifiedTargetZone.y + targetZoneHeight / 2;
bottomLeftCorner.alpha = 1.0;
game.addChild(bottomLeftCorner);
// Bottom-right corner
var bottomRightCorner = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
bottomRightCorner.x = unifiedTargetZone.x + targetZoneWidth / 2;
bottomRightCorner.y = unifiedTargetZone.y + targetZoneHeight / 2;
bottomRightCorner.alpha = 1.0;
game.addChild(bottomRightCorner);
// Helper functions
function spawnNote() {
var trackIndex = Math.floor(Math.random() * numTracks);
var isPowerNote = Math.random() < 0.1;
// Add to queue instead of spawning directly
noteQueue.push({
trackIndex: trackIndex,
isPowerNote: isPowerNote,
readyTime: LK.ticks + Math.max(0, lastTargetZoneEntry + minTimeBetweenEntries - LK.ticks)
});
}
function processNoteQueue() {
for (var i = noteQueue.length - 1; i >= 0; i--) {
var queuedNote = noteQueue[i];
if (LK.ticks >= queuedNote.readyTime) {
// Check if any note is currently in or approaching target zone
var canSpawn = true;
var targetY = 1600;
var spawnY = -50;
var targetZoneBuffer = 200; // Extended buffer zone around target
for (var j = 0; j < notes.length; j++) {
var existingNote = notes[j];
// Check if note is in extended target zone area (larger buffer for safety)
if (Math.abs(existingNote.y - targetY) <= targetZoneBuffer) {
canSpawn = false;
break;
}
// Check if note will reach target zone soon (prediction based on speed)
var timeToTarget = (targetY - existingNote.y) / existingNote.speed;
if (timeToTarget > 0 && timeToTarget <= 50) {
// Within 50 frames of reaching target
canSpawn = false;
break;
}
// Check vertical spacing collision - prevent notes from being too close vertically
if (Math.abs(existingNote.y - spawnY) < minVerticalSpacing) {
canSpawn = false;
break;
}
}
if (canSpawn) {
// Spawn the note
var note = new Note(queuedNote.trackIndex, queuedNote.isPowerNote);
note.x = startX + queuedNote.trackIndex * trackWidth;
note.y = spawnY;
note.speed = 4 * gameSpeed;
notes.push(note);
game.addChild(note);
lastTargetZoneEntry = LK.ticks;
noteQueue.splice(i, 1);
} else {
// Delay this note by adding minimum time
queuedNote.readyTime = LK.ticks + minTimeBetweenEntries;
}
}
}
}
function updateScore(points) {
score += points;
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
}
function createParticleEffect(x, y, color) {
// Create optimized particle effects
var totalParticles = 40; // Reduced particle count for performance
var primaryParticles = 20;
var secondaryParticles = 12;
var trailParticles = 8;
// Primary burst particles - fast moving with enhanced visuals
for (var i = 0; i < primaryParticles; i++) {
var particle = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
particle.x = x;
particle.y = y;
// Enhanced color with gradient-like effect
var colorVariation = 0x202020 * Math.random();
particle.tint = (color || 0xFFD93D) + colorVariation;
particle.alpha = 0.9 + Math.random() * 0.1;
game.addChild(particle);
// Calculate random direction and speed for each particle
var angle = i / primaryParticles * Math.PI * 2 + (Math.random() - 0.5) * 1.8;
var speed = 600 + Math.random() * 500; // Enhanced speed range
var targetX = x + Math.cos(angle) * speed;
var targetY = y + Math.sin(angle) * speed;
// Enhanced particle scaling with better proportions
particle.scaleX = 2.5 + Math.random() * 2.0; // Better balanced particle size
particle.scaleY = particle.scaleX + (Math.random() - 0.5) * 0.5; // Slight asymmetry for organic feel
// Animate particle flying outward with enhanced effects
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.05,
// Smoother scale transition
scaleY: 0.05,
rotation: (Math.random() - 0.5) * Math.PI * 12 // Enhanced rotation
}, {
duration: 800 + Math.random() * 700,
// Optimized duration for better visual flow
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Secondary slower particles for depth with improved visuals
for (var i = 0; i < secondaryParticles; i++) {
var particle = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
particle.x = x + (Math.random() - 0.5) * 40; // Refined initial spread
particle.y = y + (Math.random() - 0.5) * 40;
// Enhanced secondary particle coloring
var secondaryColor = color || 0xFFD93D;
var brightness = 0.7 + Math.random() * 0.3;
particle.tint = secondaryColor * brightness;
particle.alpha = 0.75 + Math.random() * 0.25;
game.addChild(particle);
var angle = Math.random() * Math.PI * 2;
var speed = 350 + Math.random() * 250; // Enhanced secondary particle speed
var targetX = x + Math.cos(angle) * speed;
var targetY = y + Math.sin(angle) * speed;
// Enhanced secondary particle scaling
particle.scaleX = 1.8 + Math.random() * 1.5; // Better proportioned secondary particles
particle.scaleY = particle.scaleX * (0.8 + Math.random() * 0.4); // Varied proportions
// Delayed animation for staggered effect with enhanced timing
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
// Smoother scale transition
scaleY: 0.1,
rotation: (Math.random() - 0.5) * Math.PI * 10 // Enhanced rotation
}, {
duration: 1000 + Math.random() * 800,
// Refined duration
easing: tween.easeInOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Enhanced trail particles that move upward
for (var i = 0; i < trailParticles; i++) {
var particle = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
particle.x = x + (Math.random() - 0.5) * 60; // Enhanced initial spread
particle.y = y;
// Enhanced trail particle coloring with glow effect
var trailColor = color || 0xFFD93D;
var glowIntensity = 0.8 + Math.random() * 0.2;
particle.tint = trailColor * glowIntensity;
particle.alpha = 0.6 + Math.random() * 0.3;
game.addChild(particle);
// Enhanced trail particle scaling with better proportions
particle.scaleX = 3.0 + Math.random() * 2.0; // Better balanced trail particles
particle.scaleY = particle.scaleX * (0.6 + Math.random() * 0.8); // More varied shapes
// Animate upward with enhanced gravity-like effect
tween(particle, {
x: particle.x + (Math.random() - 0.5) * 200,
// Enhanced horizontal spread
y: y - 350 - Math.random() * 250,
// Enhanced upward movement
alpha: 0,
scaleX: 0.2,
// Smoother scale transition
scaleY: 0.2,
rotation: (Math.random() - 0.5) * Math.PI * 8 // Enhanced rotation
}, {
duration: 1200 + Math.random() * 900,
// Optimized duration
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
}
function checkNoteInTrack(trackIndex) {
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
if (note.trackIndex === trackIndex && !note.hasBeenTapped) {
var timing = note.checkTiming();
if (timing !== 'miss') {
note.hasBeenTapped = true;
var points = 0;
if (timing === 'perfect') {
points = 1;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = 1;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
// Start background music on first successful hit
if (!musicStarted) {
currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.playMusic(currentMusicTrack);
musicStarted = true;
}
unifiedTargetZone.flash();
note.destroy();
notes.splice(i, 1);
return true;
}
}
}
return false;
}
// Touch handlers
game.down = function (x, y, obj) {
for (var i = 0; i < numTracks; i++) {
var trackX = startX + i * trackWidth;
if (x >= trackX - trackWidth / 2 && x <= trackX + trackWidth / 2) {
if (!checkNoteInTrack(i)) {
LK.getSound('miss').play();
}
break;
}
}
};
// Main game loop
game.update = function () {
// Spawn notes
noteSpawnTimer++;
if (noteSpawnTimer >= noteSpawnInterval) {
spawnNote();
noteSpawnTimer = 0;
}
// Process note queue to ensure no simultaneous target zone entries
processNoteQueue();
// Update difficulty
difficultyTimer++;
if (difficultyTimer >= 1800) {
// Every 30 seconds
gameSpeed += 0.2;
noteSpawnInterval = Math.max(20, noteSpawnInterval - 2);
difficultyTimer = 0;
}
// Update notes
for (var i = notes.length - 1; i >= 0; i--) {
var note = notes[i];
// Check if note missed target zone - let it pass slightly further before removing
if (!note.hasBeenTapped && note.lastY <= 1800 && note.y > 1800) {
note.destroy();
notes.splice(i, 1);
continue;
}
// Remove notes that are off screen
if (note.y > 2800) {
note.destroy();
notes.splice(i, 1);
}
}
// Update orbital particles and clean up off-screen particles
var allChildren = game.children.slice(); // Create a copy to avoid modification during iteration
for (var i = allChildren.length - 1; i >= 0; i--) {
var child = allChildren[i];
// Update orbital particles
if (child && child.isOrbitalParticle && child.targetObject) {
child.orbitAngle += child.orbitSpeed;
child.orbitRadius *= child.spiralRate;
// Orbital positioning with vertical oscillation
var verticalOffset = Math.sin(child.orbitAngle * 3) * 10;
child.x = child.targetObject.x + Math.cos(child.orbitAngle) * child.orbitRadius;
child.y = child.targetObject.y + Math.sin(child.orbitAngle) * child.orbitRadius + verticalOffset;
}
// Check if this is a particle (has particle-like properties)
if (child && child.x !== undefined && child.y !== undefined && child.width <= 10 && child.height <= 10) {
// Remove particles that are far off-screen or destroyed
if (child.x < -500 || child.x > 2548 || child.y < -500 || child.y > 3232 || child.destroyed) {
if (child.destroy) {
child.destroy();
} else {
game.removeChild(child);
}
}
}
}
// Create continuous particle effects around the three objects
enhanceObjectVisuals();
// Win condition
if (score >= 10000) {
LK.showYouWin();
}
};
// Add 3 objects at bottom of target zone (left, center, right)
var targetBottomY = unifiedTargetZone.y + targetZoneHeight / 2 + 800; // Move objects much further down
var objectSpacing = targetZoneWidth / 1.5; // Increased spacing for better separation between objects
// Left object
leftObject = LK.getAsset('leftObjectAsset', {
anchorX: 0.5,
anchorY: 0.5
});
leftObject.x = unifiedTargetZone.x - objectSpacing;
leftObject.y = targetBottomY;
// Scale up the left object
leftObject.scaleX = 2.0;
leftObject.scaleY = 2.0;
// Animate color change for left object
tween(leftObject, {
tint: 0xFFD700 // Change to gold color
}, {
duration: 1500,
easing: tween.easeInOut
});
leftObject.alpha = 0.8;
game.addChild(leftObject);
// Center object
centerObject = LK.getAsset('centerObjectAsset', {
anchorX: 0.5,
anchorY: 0.5
});
centerObject.x = unifiedTargetZone.x;
centerObject.y = targetBottomY;
// Scale up the center object
centerObject.scaleX = 2.0;
centerObject.scaleY = 2.0;
// Animate color change for center object
tween(centerObject, {
tint: 0xFF1493 // Change to deep pink color
}, {
duration: 1500,
easing: tween.easeInOut
});
centerObject.alpha = 0.8;
game.addChild(centerObject);
// Right object
rightObject = LK.getAsset('rightObjectAsset', {
anchorX: 0.5,
anchorY: 0.5
});
rightObject.x = unifiedTargetZone.x + objectSpacing;
rightObject.y = targetBottomY;
// Scale up the right object
rightObject.scaleX = 2.0;
rightObject.scaleY = 2.0;
// Animate color change for right object
tween(rightObject, {
tint: 0x9370DB // Change to medium purple color
}, {
duration: 1500,
easing: tween.easeInOut
});
rightObject.alpha = 0.8;
game.addChild(rightObject);
// Objects are now properly sized - no extreme scaling needed
// Move objects to topmost layer for better visibility
game.removeChild(leftObject);
game.addChild(leftObject);
game.removeChild(centerObject);
game.addChild(centerObject);
game.removeChild(rightObject);
game.addChild(rightObject);
// Add touch handlers to the 3 bottom objects
leftObject.down = function (x, y, obj) {
// Create particle effect when touched
createParticleEffect(leftObject.x, leftObject.y, 0xFFD700);
// Add guitar string vibration effect to left track strip line
if (leftStripLine) {
// Use stored original position instead of current position
var originalX = leftStripLine.originalX;
var _vibrateString = function vibrateString() {
if (vibrationCount >= maxVibrations) {
// Reset to original position when vibration completes
tween(leftStripLine, {
x: originalX
}, {
duration: 100,
easing: tween.easeOut
});
return;
}
var amplitude = baseAmplitude * (1 - vibrationCount / maxVibrations);
var direction = vibrationCount % 2 === 0 ? 1 : -1;
tween(leftStripLine, {
x: originalX + amplitude * direction
}, {
duration: 40,
easing: tween.easeInOut,
onFinish: function onFinish() {
vibrationCount++;
_vibrateString();
}
});
};
// Guitar string effect - rapid horizontal vibrations that decay
var vibrationCount = 0;
var maxVibrations = 15;
var baseAmplitude = 25;
_vibrateString();
}
// Check for notes in left track (track 0) within target zone
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
if (note.trackIndex === 0 && !note.hasBeenTapped) {
var timing = note.checkTiming();
if (timing !== 'miss') {
// Explode the note
note.hasBeenTapped = true;
var points = 0;
if (timing === 'perfect') {
points = 1;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = 1;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
// Start background music on first successful hit
if (!musicStarted) {
currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.playMusic(currentMusicTrack);
musicStarted = true;
}
unifiedTargetZone.flash();
// Scale animation for explosion effect
tween(note, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
note.destroy();
for (var j = 0; j < notes.length; j++) {
if (notes[j] === note) {
notes.splice(j, 1);
break;
}
}
}
});
break;
}
}
}
};
centerObject.down = function (x, y, obj) {
// Create particle effect when touched
createParticleEffect(centerObject.x, centerObject.y, 0xFF1493);
// Add guitar string vibration effect to center track strip line
if (centerStripLine) {
// Use stored original position instead of current position
var originalX = centerStripLine.originalX;
var _vibrateString2 = function vibrateString() {
if (vibrationCount >= maxVibrations) {
// Reset to original position when vibration completes
tween(centerStripLine, {
x: originalX
}, {
duration: 100,
easing: tween.easeOut
});
return;
}
var amplitude = baseAmplitude * (1 - vibrationCount / maxVibrations);
var direction = vibrationCount % 2 === 0 ? 1 : -1;
tween(centerStripLine, {
x: originalX + amplitude * direction
}, {
duration: 40,
easing: tween.easeInOut,
onFinish: function onFinish() {
vibrationCount++;
_vibrateString2();
}
});
};
// Guitar string effect - rapid horizontal vibrations that decay
var vibrationCount = 0;
var maxVibrations = 15;
var baseAmplitude = 25;
_vibrateString2();
}
// Check for notes in center track (track 1) within target zone
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
if (note.trackIndex === 1 && !note.hasBeenTapped) {
var timing = note.checkTiming();
if (timing !== 'miss') {
// Explode the note
note.hasBeenTapped = true;
var points = 0;
if (timing === 'perfect') {
points = 1;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = 1;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
// Start background music on first successful hit
if (!musicStarted) {
currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.playMusic(currentMusicTrack);
musicStarted = true;
}
unifiedTargetZone.flash();
// Scale animation for explosion effect
tween(note, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
note.destroy();
for (var j = 0; j < notes.length; j++) {
if (notes[j] === note) {
notes.splice(j, 1);
break;
}
}
}
});
break;
}
}
}
};
rightObject.down = function (x, y, obj) {
// Create particle effect when touched
createParticleEffect(rightObject.x, rightObject.y, 0x9370DB);
// Add guitar string vibration effect to right track strip line
if (rightStripLine) {
// Use stored original position instead of current position
var originalX = rightStripLine.originalX;
var _vibrateString3 = function vibrateString() {
if (vibrationCount >= maxVibrations) {
// Reset to original position when vibration completes
tween(rightStripLine, {
x: originalX
}, {
duration: 100,
easing: tween.easeOut
});
return;
}
var amplitude = baseAmplitude * (1 - vibrationCount / maxVibrations);
var direction = vibrationCount % 2 === 0 ? 1 : -1;
tween(rightStripLine, {
x: originalX + amplitude * direction
}, {
duration: 40,
easing: tween.easeInOut,
onFinish: function onFinish() {
vibrationCount++;
_vibrateString3();
}
});
};
// Guitar string effect - rapid horizontal vibrations that decay
var vibrationCount = 0;
var maxVibrations = 15;
var baseAmplitude = 25;
_vibrateString3();
}
// Check for notes in right track (track 2) within target zone
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
if (note.trackIndex === 2 && !note.hasBeenTapped) {
var timing = note.checkTiming();
if (timing !== 'miss') {
// Explode the note
note.hasBeenTapped = true;
var points = 0;
if (timing === 'perfect') {
points = 1;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = 1;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
// Start background music on first successful hit
if (!musicStarted) {
currentMusicTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.playMusic(currentMusicTrack);
musicStarted = true;
}
unifiedTargetZone.flash();
// Scale animation for explosion effect
tween(note, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
note.destroy();
for (var j = 0; j < notes.length; j++) {
if (notes[j] === note) {
notes.splice(j, 1);
break;
}
}
}
});
break;
}
}
}
};
// Music will start when first note is hit
var musicStarted = false;
var musicTracks = ['bgmusic', 'bgmusic2', 'bgmusic3', 'bgmusic4', 'bgmusic5'];
var currentMusicTrack = null;
// Add continuous particle effects around the three bottom objects
function createContinuousParticleEffect(targetObject, color) {
var particle = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced positioning with better distribution
var angle = Math.random() * Math.PI * 2;
var radius = 100 + Math.random() * 120; // Enhanced radius range
var startX = targetObject.x + Math.cos(angle) * radius;
var startY = targetObject.y + Math.sin(angle) * radius;
particle.x = startX;
particle.y = startY;
// Enhanced color with subtle variations
var colorVariation = 0x151515 * (Math.random() - 0.5);
particle.tint = color + colorVariation;
particle.alpha = 0.6 + Math.random() * 0.4; // Enhanced alpha range
// Enhanced particle scaling with better proportions
particle.scaleX = 1.2 + Math.random() * 1.8; // Better balanced continuous particles
particle.scaleY = particle.scaleX * (0.8 + Math.random() * 0.4); // Varied shapes for organic feel
game.addChild(particle);
// Enhanced orbital motion parameters
var orbitAngle = angle;
var orbitSpeed = 0.015 + Math.random() * 0.025; // Smoother orbital speed
var orbitRadius = radius;
var spiralRate = 0.997 + Math.random() * 0.002; // More varied spiral rates
// Enhanced particle animation with better transitions
tween(particle, {
alpha: 0,
scaleX: 0.3,
// Smoother scale transition
scaleY: 0.3,
rotation: (Math.random() - 0.5) * Math.PI * 4 // Added rotation for visual interest
}, {
duration: 1800 + Math.random() * 1200,
// Enhanced duration range
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
// Store orbital properties on particle for main update loop
particle.orbitAngle = orbitAngle;
particle.orbitSpeed = orbitSpeed;
particle.orbitRadius = orbitRadius;
particle.spiralRate = spiralRate;
particle.targetObject = targetObject;
particle.isOrbitalParticle = true;
}
// Optimized continuous particle system
var particleSpawnTimer = 0;
var particleSpawnInterval = 15; // Reduced spawn rate to prevent performance issues
// Optimized visual effects function
function enhanceObjectVisuals() {
particleSpawnTimer++;
if (particleSpawnTimer >= particleSpawnInterval) {
// Create fewer particles around each object
// Create particles around left object
for (var i = 0; i < 2; i++) {
createContinuousParticleEffect(leftObject, 0xFFD700);
}
// Create particles around center object
for (var i = 0; i < 2; i++) {
createContinuousParticleEffect(centerObject, 0xFF1493);
}
// Create particles around right object
for (var i = 0; i < 2; i++) {
createContinuousParticleEffect(rightObject, 0x9370DB);
}
particleSpawnTimer = 0;
}
}
Gitar gövde kısmı
Do müzik notası
Mavi pastel renkli daire. In-Game asset. 2d. High contrast. No shadows
Kalp. In-Game asset. 2d. High contrast. No shadows
Gitar aksesuarı turuncu pastel renk. In-Game asset. 2d. High contrast. No shadows
Kırmızı pastel renk gitar çalma aksesuarı. In-Game asset. 2d. High contrast. No shadows