User prompt
Boyut küçült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Boyut küçült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
3 nesnenin görüntü kalitesini düzelt
User prompt
Biraz daha küçült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Dahada küçült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
3 nesneyi küçült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sag orta sol nesne rengi için varlık oluştur ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
3 nesne için resim ekle
User prompt
3 nesne rengi degiş ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
3 buton düzgün gözüksün
User prompt
Hala bozuk
User prompt
3 nesne daha görünür olsun
User prompt
En üst katmana taşı
User prompt
Düzgün görünmesi için üst katmana taşı
User prompt
Biraz büyült
User prompt
3 nesne boyutunu küçült
User prompt
4x yap
User prompt
Nesne varlıklaeı cok büyük
User prompt
Alttaki 3 yuvarlak nesne resim degişimi için varlık oluştur
User prompt
3 nesne için resim varlığı ekle
User prompt
Nota yumurtlama hızı azalt
User prompt
Oyun müzik sesi ilk nota vuruldugunda devreye girer
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof score === 'number' && score >= 10000) {' Line Number: 657
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (typeof score === 'number' && score >= 10000) {' Line Number: 657
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'if (score >= 10000) {' Line Number: 653
/**** * 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 if (!self.lastInTargetZone && inTargetZone && !self.hasBeenTapped) { // Note just entered target zone - trigger explosion with corresponding bottom object self.triggerExplosion(); } 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 = self.isPowerNote ? 200 : 100; LK.getSound('perfect').play(); createParticleEffect(self.x, self.y, self.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = self.isPowerNote ? 100 : 50; LK.getSound('tap').play(); createParticleEffect(self.x, self.y, 0x87CEEB); } updateScore(points); updateCombo(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 combo = 0; var maxCombo = 0; var missedNotes = 0; var maxMissedNotes = 5; var noteSpawnTimer = 0; var noteSpawnInterval = 45; var gameSpeed = 1; var difficultyTimer = 0; // Note queue system to prevent simultaneous target zone entry var noteQueue = []; var lastTargetZoneEntry = 0; var minTimeBetweenEntries = 20; // Minimum frames between notes entering target zone // Vertical spacing system to prevent notes from overlapping var minVerticalSpacing = 150; // 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.5, 0); LK.gui.top.addChild(scoreTxt); var comboTxt = new Text2('Combo: 0', { size: 50, fill: 0xFFD93D }); comboTxt.anchor.set(0, 0); comboTxt.x = 150; comboTxt.y = 150; LK.gui.top.addChild(comboTxt); var missedTxt = new Text2('Missed: 0/5', { size: 40, fill: 0xFF6B6B }); missedTxt.anchor.set(1, 0); LK.gui.topRight.addChild(missedTxt); // Add background image var background = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); background.x = 0; background.y = 0; background.tint = 0x000000; game.addChild(background); // Create a mask to clip all content to screen boundaries var screenMask = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); screenMask.x = 0; screenMask.y = 0; screenMask.width = 2048; screenMask.height = 2732; game.addChild(screenMask); game.mask = screenMask; // 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; // Keep within screen width unifiedBg.height = 2732; // Keep within 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; 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 target zone var canSpawn = true; var targetY = 1600; var spawnY = -50; for (var j = 0; j < notes.length; j++) { var existingNote = notes[j]; // Check target zone collision if (Math.abs(existingNote.y - targetY) <= 100) { 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) { // Ensure score is always a number if (typeof score !== 'number') { score = 0; } score += points * Math.max(1, Math.floor(combo / 5)); scoreTxt.setText('Score: ' + score); LK.setScore(score); } function updateCombo(increase) { if (increase) { combo++; maxCombo = Math.max(maxCombo, combo); } else { combo = 0; } comboTxt.setText('Combo: ' + combo); } function updateMissed() { missedNotes++; missedTxt.setText('Missed: ' + missedNotes + '/' + maxMissedNotes); // Player is now immortal - no game over on missed notes } function createParticleEffect(x, y, color) { // Create multiple layers of particles for enhanced effect var totalParticles = 80; // Significantly increased from 30 var primaryParticles = 50; var secondaryParticles = 20; var trailParticles = 10; // Primary burst particles - fast moving for (var i = 0; i < primaryParticles; i++) { var particle = LK.getAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); particle.x = x; particle.y = y; particle.tint = color || 0xFFD93D; particle.alpha = 1.0; game.addChild(particle); // Calculate random direction and speed for each particle var angle = i / primaryParticles * Math.PI * 2 + (Math.random() - 0.5) * 2.5; var speed = 500 + Math.random() * 400; // Much higher speed range for wider spread var targetX = x + Math.cos(angle) * speed; var targetY = y + Math.sin(angle) * speed; // Constrain particles to stay within screen boundaries targetX = Math.max(0, Math.min(2048, targetX)); targetY = Math.max(0, Math.min(2732, targetY)); // Make particles much larger with more variation particle.scaleX = 2.0 + Math.random() * 2.5; // Increased from 1.5 + 1.0 particle.scaleY = particle.scaleX; // Animate particle flying outward with enhanced effects tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: (Math.random() - 0.5) * Math.PI * 10 // More rotation }, { duration: 1000 + Math.random() * 800, // Longer duration easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Secondary slower particles for depth 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) * 50; // Slight initial spread particle.y = y + (Math.random() - 0.5) * 50; particle.tint = color || 0xFFD93D; particle.alpha = 0.8; game.addChild(particle); var angle = Math.random() * Math.PI * 2; var speed = 300 + Math.random() * 200; // Increased secondary particle speed var targetX = x + Math.cos(angle) * speed; var targetY = y + Math.sin(angle) * speed; // Constrain secondary particles to stay within screen boundaries targetX = Math.max(0, Math.min(2048, targetX)); targetY = Math.max(0, Math.min(2732, targetY)); particle.scaleX = 1.5 + Math.random() * 1.5; particle.scaleY = particle.scaleX; // Delayed animation for staggered effect tween(particle, { x: targetX, y: targetY, alpha: 0, scaleX: 0.2, scaleY: 0.2, rotation: (Math.random() - 0.5) * Math.PI * 8 }, { duration: 1200 + Math.random() * 600, easing: tween.easeInOut, onFinish: function onFinish() { particle.destroy(); } }); } // 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) * 80; // Wider initial spread particle.y = y; particle.tint = color || 0xFFD93D; particle.alpha = 0.6; game.addChild(particle); particle.scaleX = 3.0 + Math.random() * 2.0; // Very large trail particles particle.scaleY = particle.scaleX; // Animate upward with gravity-like effect var trailTargetX = particle.x + (Math.random() - 0.5) * 250; var trailTargetY = y - 400 - Math.random() * 300; // Constrain trail particles to stay within screen boundaries trailTargetX = Math.max(0, Math.min(2048, trailTargetX)); trailTargetY = Math.max(0, Math.min(2732, trailTargetY)); tween(particle, { x: trailTargetX, // Much wider horizontal spread y: trailTargetY, // Increased upward movement // Move upward alpha: 0, scaleX: 0.3, scaleY: 0.3, rotation: (Math.random() - 0.5) * Math.PI * 6 // More rotation }, { duration: 1500 + Math.random() * 1000, 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 = note.isPowerNote ? 200 : 100; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = note.isPowerNote ? 100 : 50; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); updateCombo(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)) { updateCombo(false); 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 if (!note.hasBeenTapped && note.lastY <= 1700 && note.y > 1700) { updateCombo(false); updateMissed(); note.destroy(); notes.splice(i, 1); continue; } // Remove notes that are off screen if (note.y > 2800) { note.destroy(); notes.splice(i, 1); } } // Win condition - ensure score is a valid number if (typeof score === 'number' && score >= 10000) { LK.showYouWin(); } }; // Add 3 objects at bottom of target zone (left, center, right) var targetBottomY = unifiedTargetZone.y + targetZoneHeight / 2 + 600; // Position even further down var objectSpacing = targetZoneWidth / 1.5; // Further increase spacing between objects // Left object leftObject = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); leftObject.x = unifiedTargetZone.x - objectSpacing; leftObject.y = targetBottomY; leftObject.tint = 0xff6b6b; // Red color for distinction leftObject.alpha = 0.8; game.addChild(leftObject); // Center object centerObject = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); centerObject.x = unifiedTargetZone.x; centerObject.y = targetBottomY; centerObject.tint = 0x00ff00; // Green color for distinction centerObject.alpha = 0.8; game.addChild(centerObject); // Right object rightObject = LK.getAsset('cornerEllipse', { anchorX: 0.5, anchorY: 0.5 }); rightObject.x = unifiedTargetZone.x + objectSpacing; rightObject.y = targetBottomY; rightObject.tint = 0x4169e1; // Blue color for distinction rightObject.alpha = 0.8; game.addChild(rightObject); // Scale all 3 objects to 30x using tween tween(leftObject, { scaleX: 30, scaleY: 30 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Move to topmost layer after scaling game.removeChild(leftObject); game.addChild(leftObject); } }); tween(centerObject, { scaleX: 30, scaleY: 30 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Move to topmost layer after scaling game.removeChild(centerObject); game.addChild(centerObject); } }); tween(rightObject, { scaleX: 30, scaleY: 30 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Move to topmost layer after scaling game.removeChild(rightObject); game.addChild(rightObject); } }); // Add touch handlers to the 3 bottom objects leftObject.down = function (x, y, obj) { // Add guitar string vibration effect to left track strip line if (leftStripLine) { // Store original position before vibration starts var originalX = leftStripLine.x; 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 = note.isPowerNote ? 200 : 100; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = note.isPowerNote ? 100 : 50; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); updateCombo(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) { // Add guitar string vibration effect to center track strip line if (centerStripLine) { // Store original position before vibration starts var originalX = centerStripLine.x; 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 = note.isPowerNote ? 200 : 100; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = note.isPowerNote ? 100 : 50; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); updateCombo(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) { // Add guitar string vibration effect to right track strip line if (rightStripLine) { // Store original position before vibration starts var originalX = rightStripLine.x; 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 = note.isPowerNote ? 200 : 100; LK.getSound('perfect').play(); createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00); } else if (timing === 'good') { points = note.isPowerNote ? 100 : 50; LK.getSound('tap').play(); createParticleEffect(note.x, note.y, 0x87CEEB); } updateScore(points); updateCombo(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; } } } }; // Start background music LK.playMusic('bgmusic'); ; ;
/****
* 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
if (!self.lastInTargetZone && inTargetZone && !self.hasBeenTapped) {
// Note just entered target zone - trigger explosion with corresponding bottom object
self.triggerExplosion();
}
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 = self.isPowerNote ? 200 : 100;
LK.getSound('perfect').play();
createParticleEffect(self.x, self.y, self.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = self.isPowerNote ? 100 : 50;
LK.getSound('tap').play();
createParticleEffect(self.x, self.y, 0x87CEEB);
}
updateScore(points);
updateCombo(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 combo = 0;
var maxCombo = 0;
var missedNotes = 0;
var maxMissedNotes = 5;
var noteSpawnTimer = 0;
var noteSpawnInterval = 45;
var gameSpeed = 1;
var difficultyTimer = 0;
// Note queue system to prevent simultaneous target zone entry
var noteQueue = [];
var lastTargetZoneEntry = 0;
var minTimeBetweenEntries = 20; // Minimum frames between notes entering target zone
// Vertical spacing system to prevent notes from overlapping
var minVerticalSpacing = 150; // 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.5, 0);
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 50,
fill: 0xFFD93D
});
comboTxt.anchor.set(0, 0);
comboTxt.x = 150;
comboTxt.y = 150;
LK.gui.top.addChild(comboTxt);
var missedTxt = new Text2('Missed: 0/5', {
size: 40,
fill: 0xFF6B6B
});
missedTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(missedTxt);
// Add background image
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
background.x = 0;
background.y = 0;
background.tint = 0x000000;
game.addChild(background);
// Create a mask to clip all content to screen boundaries
var screenMask = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
screenMask.x = 0;
screenMask.y = 0;
screenMask.width = 2048;
screenMask.height = 2732;
game.addChild(screenMask);
game.mask = screenMask;
// 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; // Keep within screen width
unifiedBg.height = 2732; // Keep within 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;
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 target zone
var canSpawn = true;
var targetY = 1600;
var spawnY = -50;
for (var j = 0; j < notes.length; j++) {
var existingNote = notes[j];
// Check target zone collision
if (Math.abs(existingNote.y - targetY) <= 100) {
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) {
// Ensure score is always a number
if (typeof score !== 'number') {
score = 0;
}
score += points * Math.max(1, Math.floor(combo / 5));
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
}
function updateCombo(increase) {
if (increase) {
combo++;
maxCombo = Math.max(maxCombo, combo);
} else {
combo = 0;
}
comboTxt.setText('Combo: ' + combo);
}
function updateMissed() {
missedNotes++;
missedTxt.setText('Missed: ' + missedNotes + '/' + maxMissedNotes);
// Player is now immortal - no game over on missed notes
}
function createParticleEffect(x, y, color) {
// Create multiple layers of particles for enhanced effect
var totalParticles = 80; // Significantly increased from 30
var primaryParticles = 50;
var secondaryParticles = 20;
var trailParticles = 10;
// Primary burst particles - fast moving
for (var i = 0; i < primaryParticles; i++) {
var particle = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
particle.x = x;
particle.y = y;
particle.tint = color || 0xFFD93D;
particle.alpha = 1.0;
game.addChild(particle);
// Calculate random direction and speed for each particle
var angle = i / primaryParticles * Math.PI * 2 + (Math.random() - 0.5) * 2.5;
var speed = 500 + Math.random() * 400; // Much higher speed range for wider spread
var targetX = x + Math.cos(angle) * speed;
var targetY = y + Math.sin(angle) * speed;
// Constrain particles to stay within screen boundaries
targetX = Math.max(0, Math.min(2048, targetX));
targetY = Math.max(0, Math.min(2732, targetY));
// Make particles much larger with more variation
particle.scaleX = 2.0 + Math.random() * 2.5; // Increased from 1.5 + 1.0
particle.scaleY = particle.scaleX;
// Animate particle flying outward with enhanced effects
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: (Math.random() - 0.5) * Math.PI * 10 // More rotation
}, {
duration: 1000 + Math.random() * 800,
// Longer duration
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Secondary slower particles for depth
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) * 50; // Slight initial spread
particle.y = y + (Math.random() - 0.5) * 50;
particle.tint = color || 0xFFD93D;
particle.alpha = 0.8;
game.addChild(particle);
var angle = Math.random() * Math.PI * 2;
var speed = 300 + Math.random() * 200; // Increased secondary particle speed
var targetX = x + Math.cos(angle) * speed;
var targetY = y + Math.sin(angle) * speed;
// Constrain secondary particles to stay within screen boundaries
targetX = Math.max(0, Math.min(2048, targetX));
targetY = Math.max(0, Math.min(2732, targetY));
particle.scaleX = 1.5 + Math.random() * 1.5;
particle.scaleY = particle.scaleX;
// Delayed animation for staggered effect
tween(particle, {
x: targetX,
y: targetY,
alpha: 0,
scaleX: 0.2,
scaleY: 0.2,
rotation: (Math.random() - 0.5) * Math.PI * 8
}, {
duration: 1200 + Math.random() * 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// 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) * 80; // Wider initial spread
particle.y = y;
particle.tint = color || 0xFFD93D;
particle.alpha = 0.6;
game.addChild(particle);
particle.scaleX = 3.0 + Math.random() * 2.0; // Very large trail particles
particle.scaleY = particle.scaleX;
// Animate upward with gravity-like effect
var trailTargetX = particle.x + (Math.random() - 0.5) * 250;
var trailTargetY = y - 400 - Math.random() * 300;
// Constrain trail particles to stay within screen boundaries
trailTargetX = Math.max(0, Math.min(2048, trailTargetX));
trailTargetY = Math.max(0, Math.min(2732, trailTargetY));
tween(particle, {
x: trailTargetX,
// Much wider horizontal spread
y: trailTargetY,
// Increased upward movement
// Move upward
alpha: 0,
scaleX: 0.3,
scaleY: 0.3,
rotation: (Math.random() - 0.5) * Math.PI * 6 // More rotation
}, {
duration: 1500 + Math.random() * 1000,
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 = note.isPowerNote ? 200 : 100;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = note.isPowerNote ? 100 : 50;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
updateCombo(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)) {
updateCombo(false);
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
if (!note.hasBeenTapped && note.lastY <= 1700 && note.y > 1700) {
updateCombo(false);
updateMissed();
note.destroy();
notes.splice(i, 1);
continue;
}
// Remove notes that are off screen
if (note.y > 2800) {
note.destroy();
notes.splice(i, 1);
}
}
// Win condition - ensure score is a valid number
if (typeof score === 'number' && score >= 10000) {
LK.showYouWin();
}
};
// Add 3 objects at bottom of target zone (left, center, right)
var targetBottomY = unifiedTargetZone.y + targetZoneHeight / 2 + 600; // Position even further down
var objectSpacing = targetZoneWidth / 1.5; // Further increase spacing between objects
// Left object
leftObject = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
leftObject.x = unifiedTargetZone.x - objectSpacing;
leftObject.y = targetBottomY;
leftObject.tint = 0xff6b6b; // Red color for distinction
leftObject.alpha = 0.8;
game.addChild(leftObject);
// Center object
centerObject = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
centerObject.x = unifiedTargetZone.x;
centerObject.y = targetBottomY;
centerObject.tint = 0x00ff00; // Green color for distinction
centerObject.alpha = 0.8;
game.addChild(centerObject);
// Right object
rightObject = LK.getAsset('cornerEllipse', {
anchorX: 0.5,
anchorY: 0.5
});
rightObject.x = unifiedTargetZone.x + objectSpacing;
rightObject.y = targetBottomY;
rightObject.tint = 0x4169e1; // Blue color for distinction
rightObject.alpha = 0.8;
game.addChild(rightObject);
// Scale all 3 objects to 30x using tween
tween(leftObject, {
scaleX: 30,
scaleY: 30
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move to topmost layer after scaling
game.removeChild(leftObject);
game.addChild(leftObject);
}
});
tween(centerObject, {
scaleX: 30,
scaleY: 30
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move to topmost layer after scaling
game.removeChild(centerObject);
game.addChild(centerObject);
}
});
tween(rightObject, {
scaleX: 30,
scaleY: 30
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move to topmost layer after scaling
game.removeChild(rightObject);
game.addChild(rightObject);
}
});
// Add touch handlers to the 3 bottom objects
leftObject.down = function (x, y, obj) {
// Add guitar string vibration effect to left track strip line
if (leftStripLine) {
// Store original position before vibration starts
var originalX = leftStripLine.x;
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 = note.isPowerNote ? 200 : 100;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = note.isPowerNote ? 100 : 50;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
updateCombo(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) {
// Add guitar string vibration effect to center track strip line
if (centerStripLine) {
// Store original position before vibration starts
var originalX = centerStripLine.x;
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 = note.isPowerNote ? 200 : 100;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = note.isPowerNote ? 100 : 50;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
updateCombo(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) {
// Add guitar string vibration effect to right track strip line
if (rightStripLine) {
// Store original position before vibration starts
var originalX = rightStripLine.x;
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 = note.isPowerNote ? 200 : 100;
LK.getSound('perfect').play();
createParticleEffect(note.x, note.y, note.isPowerNote ? 0xFFD93D : 0x00FF00);
} else if (timing === 'good') {
points = note.isPowerNote ? 100 : 50;
LK.getSound('tap').play();
createParticleEffect(note.x, note.y, 0x87CEEB);
}
updateScore(points);
updateCombo(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;
}
}
}
};
// Start background music
LK.playMusic('bgmusic');
;
;
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