User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var localPos = self.toLocal(obj.parent.toGlobal(obj.position));' Line Number: 181
User prompt
layer them behind cymballs too and play the sonds only touched to the cymballs not stikcs
User prompt
move the cymball sticks a little upwards and make them layer down from toms
User prompt
add a new open hat visual and audio asset
User prompt
add new texture to the drums so the buttons look like the leather of the drums and create a 3d looking illusion. add stands for the cymbals and hats
User prompt
make the buttons bigger for better control
User prompt
add a sound asset for each part of the drum
User prompt
add 3 toms 1 floor 2 crash 1 ride and position them as a real drum layout
User prompt
Position the keys as if you were looking at a real drum from above.
Code edit (1 edits merged)
Please save this source code
User prompt
Drum Master
Initial prompt
make me a drum game like DrumKnee
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var DrumPad = Container.expand(function (drumType, x, y, width, height) { var self = Container.call(this); self.drumType = drumType; self.x = x; self.y = y; // Create tom bodies first (under snare drum layer) var bodyGraphics = null; if (drumType === 'highTom' || drumType === 'midTom' || drumType === 'floorTom') { bodyGraphics = self.attachAsset(drumType + 'Body', { anchorX: 0.5, anchorY: 0.0 }); if (drumType === 'floorTom') { bodyGraphics.y = -70; // Position floor tom body down by 30 pixels } else if (drumType === 'highTom') { bodyGraphics.y = -40; // Position high tom body up by 70 pixels } else if (drumType === 'midTom') { bodyGraphics.y = -40; // Position mid tom body up by 70 pixels } else { bodyGraphics.y = 30; // Position other tom bodies below the drum head } } // Create kick and snare drum bodies after tom bodies if (drumType === 'kickDrum' || drumType === 'snareDrum') { bodyGraphics = self.attachAsset(drumType + 'Body', { anchorX: 0.5, anchorY: 0.0 }); if (drumType === 'snareDrum') { bodyGraphics.y = -100; // Position snare body even higher bodyGraphics.x = -10; // Move snare body left } else if (drumType === 'kickDrum') { bodyGraphics.y = -380; // Move kick drum body up by 30 pixels (from -350 to -380) } else { bodyGraphics.y = 30; // Position other drum bodies below the drum head } } // Create rim layer (darker, larger) - SECOND layer var rimGraphics = null; if (drumType !== 'crashCymbal' && drumType !== 'rideCymbal' && drumType !== 'hiHat') { rimGraphics = self.attachAsset(drumType + 'Rim', { anchorX: 0.5, anchorY: 0.5 }); } else { rimGraphics = self.attachAsset(drumType + 'Rim', { anchorX: 0.5, anchorY: 0.5 }); } // Create main drum shell - THIRD layer var drumGraphics = self.attachAsset(drumType, { anchorX: 0.5, anchorY: 0.5 }); // Create drum head layer (leather texture) - TOP layer var headGraphics = null; if (drumType !== 'crashCymbal' && drumType !== 'rideCymbal' && drumType !== 'hiHat') { headGraphics = self.attachAsset(drumType + 'Head', { anchorX: 0.5, anchorY: 0.5 }); } // Hit effect that appears on tap var hitEffect = self.attachAsset('hitEffect', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.playSound = function () { var soundName = drumType.replace('Drum', '').toLowerCase(); if (soundName === 'hihat') soundName = 'hihat'; if (soundName === 'openhat') soundName = 'openhat'; if (soundName === 'crashcymbal') soundName = 'crash'; if (soundName === 'ridecymbal') soundName = 'ride'; if (soundName === 'hightom') soundName = 'hightom'; if (soundName === 'midtom') soundName = 'midtom'; if (soundName === 'floortom') soundName = 'floortom'; LK.getSound(soundName).play(); }; self.showHitEffect = function () { hitEffect.alpha = 1; hitEffect.scaleX = 1.5; hitEffect.scaleY = 1.5; tween(hitEffect, { alpha: 0, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); // Drum bounce effect on main drum drumGraphics.scaleX = 1.1; drumGraphics.scaleY = 1.1; tween(drumGraphics, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); // Drum head bounce effect (if exists) if (headGraphics) { headGraphics.scaleX = 1.08; headGraphics.scaleY = 1.08; tween(headGraphics, { scaleX: 1, scaleY: 1 }, { duration: 180, easing: tween.easeOut }); } // Drum body bounce effect (if exists) if (bodyGraphics) { bodyGraphics.scaleX = 1.05; bodyGraphics.scaleY = 1.05; tween(bodyGraphics, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); } }; self.down = function (x, y, obj) { self.playSound(); self.showHitEffect(); // Update score LK.setScore(LK.getScore() + 10); scoreText.setText(LK.getScore().toString()); }; return self; }); var PatternNote = Container.expand(function (drumType, timing) { var self = Container.call(this); self.drumType = drumType; self.timing = timing; self.hit = false; var noteGraphics = self.attachAsset('hitEffect', { anchorX: 0.5, anchorY: 0.5, tint: 0x00FF00 }); self.speed = 3; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Drum heads with leather texture appearance // Background music // Drum sounds // Drum kit components // Game variables var gameMode = 'freeplay'; // 'freeplay' or 'pattern' var drumPads = []; var patternNotes = []; var combo = 0; var maxCombo = 0; // UI Elements var scoreText = new Text2('0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var comboText = new Text2('Combo: 0', { size: 40, fill: 0xFFFF00 }); comboText.anchor.set(1, 0); comboText.x = 2048 - 50; comboText.y = 100; game.addChild(comboText); var modeText = new Text2('Free Play Mode', { size: 50, fill: 0x00FF00 }); modeText.anchor.set(0, 0); modeText.x = 150; modeText.y = 100; game.addChild(modeText); // Create drum kit layout - positioned as if viewing from above like a real drum kit function setupDrumKit() { // Add cymbal stands as background visuals first var crashStand1 = LK.getAsset('cymbalStand', { anchorX: 0.5, anchorY: 1 }); crashStand1.x = 650; crashStand1.y = 1600; game.addChild(crashStand1); var crashStand2 = LK.getAsset('cymbalStand', { anchorX: 0.5, anchorY: 1 }); crashStand2.x = 1400; crashStand2.y = 1600; game.addChild(crashStand2); var rideStand = LK.getAsset('cymbalStand', { anchorX: 0.5, anchorY: 1 }); rideStand.x = 1650; rideStand.y = 2000; game.addChild(rideStand); var hiHatStandGraphics = LK.getAsset('hiHatStand', { anchorX: 0.5, anchorY: 0 }); hiHatStandGraphics.x = 450; hiHatStandGraphics.y = 1400; game.addChild(hiHatStandGraphics); var openHatStandGraphics = LK.getAsset('hiHatStand', { anchorX: 0.5, anchorY: 0 }); openHatStandGraphics.x = 300; openHatStandGraphics.y = 1300; game.addChild(openHatStandGraphics); // Kick drum (bottom center - closest to drummer) var kickDrum = new DrumPad('kickDrum', 1024, 2200, 600, 300); drumPads.push(kickDrum); game.addChild(kickDrum); // Snare drum (center position) var snareDrum = new DrumPad('snareDrum', 1024, 1600, 375, 180); drumPads.push(snareDrum); game.addChild(snareDrum); // Hi-hat (left side, slightly forward) var hiHat = new DrumPad('hiHat', 450, 1400, 270, 120); drumPads.push(hiHat); game.addChild(hiHat); // Open hi-hat (next to closed hi-hat, slightly left) var openHat = new DrumPad('openHat', 300, 1300, 270, 120); drumPads.push(openHat); game.addChild(openHat); // High tom (left of snare, above snare level) var highTom = new DrumPad('highTom', 800, 1300, 300, 150); drumPads.push(highTom); game.addChild(highTom); // Mid tom (right of snare, above snare level) var midTom = new DrumPad('midTom', 1250, 1300, 330, 165); drumPads.push(midTom); game.addChild(midTom); // Floor tom (right side, lower than snare) var floorTom = new DrumPad('floorTom', 1450, 1800, 420, 210); drumPads.push(floorTom); game.addChild(floorTom); // Crash cymbal 1 (left side, above high tom) var crashCymbal1 = new DrumPad('crashCymbal', 650, 1000, 360, 165); drumPads.push(crashCymbal1); game.addChild(crashCymbal1); // Crash cymbal 2 (right side, above mid tom) var crashCymbal2 = new DrumPad('crashCymbal', 1400, 1000, 360, 165); drumPads.push(crashCymbal2); game.addChild(crashCymbal2); // Ride cymbal (far right, behind floor tom) var rideCymbal = new DrumPad('rideCymbal', 1650, 1400, 420, 195); drumPads.push(rideCymbal); game.addChild(rideCymbal); } // Pattern mode functions var patternTimer = 0; var patternInterval = 120; // Spawn pattern every 2 seconds at 60fps var patternSequence = ['kick', 'snare', 'hihat', 'kick', 'crashcymbal', 'snare', 'hightom', 'midtom', 'floortom', 'ride', 'openhat']; var patternIndex = 0; function spawnPatternNote() { var drumType = patternSequence[patternIndex] + 'Drum'; var targetDrum = null; // Find corresponding drum pad for (var i = 0; i < drumPads.length; i++) { if (drumPads[i].drumType === drumType) { targetDrum = drumPads[i]; break; } } if (targetDrum) { var note = new PatternNote(drumType, LK.ticks); note.x = targetDrum.x; note.y = 200; patternNotes.push(note); game.addChild(note); } patternIndex = (patternIndex + 1) % patternSequence.length; } function toggleGameMode() { if (gameMode === 'freeplay') { gameMode = 'pattern'; modeText.setText('Pattern Mode'); modeText.fill = '#ff6600'; LK.playMusic('drumLoop'); } else { gameMode = 'freeplay'; modeText.setText('Free Play Mode'); modeText.fill = '#00ff00'; LK.stopMusic(); // Clear existing pattern notes for (var i = patternNotes.length - 1; i >= 0; i--) { patternNotes[i].destroy(); patternNotes.splice(i, 1); } } } // Create background var background = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); background.x = 0; background.y = 0; background.alpha = 1; // Make background fully visible game.addChild(background); // Add additional background textures to fill empty spaces var background2 = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); background2.x = 0; background2.y = 1000; // Position below first background background2.alpha = 1; game.addChild(background2); var background3 = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); background3.x = 0; background3.y = 2000; // Position below second background background3.alpha = 1; game.addChild(background3); // Initialize drum kit setupDrumKit(); // Game controls game.down = function (x, y, obj) { // Check if clicking on mode toggle area (top center) if (x > 800 && x < 1248 && y < 200) { toggleGameMode(); return; } }; // Main game update loop game.update = function () { // Pattern mode logic if (gameMode === 'pattern') { patternTimer++; // Spawn new pattern notes if (patternTimer >= patternInterval) { spawnPatternNote(); patternTimer = 0; } // Update pattern notes for (var i = patternNotes.length - 1; i >= 0; i--) { var note = patternNotes[i]; if (note.lastY === undefined) note.lastY = note.y; // Check if note went off screen if (note.lastY < 2732 && note.y >= 2732) { if (!note.hit) { combo = 0; comboText.setText('Combo: ' + combo); } note.destroy(); patternNotes.splice(i, 1); continue; } // Check for hits near drum pads for (var j = 0; j < drumPads.length; j++) { var drum = drumPads[j]; if (note.drumType === drum.drumType) { var distance = Math.sqrt(Math.pow(note.x - drum.x, 2) + Math.pow(note.y - drum.y, 2)); if (distance < 150 && !note.hit) { // Auto-hit when note reaches drum pad note.hit = true; combo++; if (combo > maxCombo) maxCombo = combo; comboText.setText('Combo: ' + combo); // Bonus points for combo var bonusPoints = Math.floor(combo * 5); LK.setScore(LK.getScore() + 20 + bonusPoints); scoreText.setText(LK.getScore().toString()); note.destroy(); patternNotes.splice(i, 1); break; } } } note.lastY = note.y; } } // Update high score in storage var highScore = storage.highScore || 0; if (LK.getScore() > highScore) { storage.highScore = LK.getScore(); } var highCombo = storage.highCombo || 0; if (maxCombo > highCombo) { storage.highCombo = maxCombo; } }; // Initialize score display scoreText.setText(LK.getScore().toString());
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var DrumPad = Container.expand(function (drumType, x, y, width, height) {
var self = Container.call(this);
self.drumType = drumType;
self.x = x;
self.y = y;
// Create tom bodies first (under snare drum layer)
var bodyGraphics = null;
if (drumType === 'highTom' || drumType === 'midTom' || drumType === 'floorTom') {
bodyGraphics = self.attachAsset(drumType + 'Body', {
anchorX: 0.5,
anchorY: 0.0
});
if (drumType === 'floorTom') {
bodyGraphics.y = -70; // Position floor tom body down by 30 pixels
} else if (drumType === 'highTom') {
bodyGraphics.y = -40; // Position high tom body up by 70 pixels
} else if (drumType === 'midTom') {
bodyGraphics.y = -40; // Position mid tom body up by 70 pixels
} else {
bodyGraphics.y = 30; // Position other tom bodies below the drum head
}
}
// Create kick and snare drum bodies after tom bodies
if (drumType === 'kickDrum' || drumType === 'snareDrum') {
bodyGraphics = self.attachAsset(drumType + 'Body', {
anchorX: 0.5,
anchorY: 0.0
});
if (drumType === 'snareDrum') {
bodyGraphics.y = -100; // Position snare body even higher
bodyGraphics.x = -10; // Move snare body left
} else if (drumType === 'kickDrum') {
bodyGraphics.y = -380; // Move kick drum body up by 30 pixels (from -350 to -380)
} else {
bodyGraphics.y = 30; // Position other drum bodies below the drum head
}
}
// Create rim layer (darker, larger) - SECOND layer
var rimGraphics = null;
if (drumType !== 'crashCymbal' && drumType !== 'rideCymbal' && drumType !== 'hiHat') {
rimGraphics = self.attachAsset(drumType + 'Rim', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
rimGraphics = self.attachAsset(drumType + 'Rim', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Create main drum shell - THIRD layer
var drumGraphics = self.attachAsset(drumType, {
anchorX: 0.5,
anchorY: 0.5
});
// Create drum head layer (leather texture) - TOP layer
var headGraphics = null;
if (drumType !== 'crashCymbal' && drumType !== 'rideCymbal' && drumType !== 'hiHat') {
headGraphics = self.attachAsset(drumType + 'Head', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Hit effect that appears on tap
var hitEffect = self.attachAsset('hitEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.playSound = function () {
var soundName = drumType.replace('Drum', '').toLowerCase();
if (soundName === 'hihat') soundName = 'hihat';
if (soundName === 'openhat') soundName = 'openhat';
if (soundName === 'crashcymbal') soundName = 'crash';
if (soundName === 'ridecymbal') soundName = 'ride';
if (soundName === 'hightom') soundName = 'hightom';
if (soundName === 'midtom') soundName = 'midtom';
if (soundName === 'floortom') soundName = 'floortom';
LK.getSound(soundName).play();
};
self.showHitEffect = function () {
hitEffect.alpha = 1;
hitEffect.scaleX = 1.5;
hitEffect.scaleY = 1.5;
tween(hitEffect, {
alpha: 0,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
// Drum bounce effect on main drum
drumGraphics.scaleX = 1.1;
drumGraphics.scaleY = 1.1;
tween(drumGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
// Drum head bounce effect (if exists)
if (headGraphics) {
headGraphics.scaleX = 1.08;
headGraphics.scaleY = 1.08;
tween(headGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 180,
easing: tween.easeOut
});
}
// Drum body bounce effect (if exists)
if (bodyGraphics) {
bodyGraphics.scaleX = 1.05;
bodyGraphics.scaleY = 1.05;
tween(bodyGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
};
self.down = function (x, y, obj) {
self.playSound();
self.showHitEffect();
// Update score
LK.setScore(LK.getScore() + 10);
scoreText.setText(LK.getScore().toString());
};
return self;
});
var PatternNote = Container.expand(function (drumType, timing) {
var self = Container.call(this);
self.drumType = drumType;
self.timing = timing;
self.hit = false;
var noteGraphics = self.attachAsset('hitEffect', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x00FF00
});
self.speed = 3;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Drum heads with leather texture appearance
// Background music
// Drum sounds
// Drum kit components
// Game variables
var gameMode = 'freeplay'; // 'freeplay' or 'pattern'
var drumPads = [];
var patternNotes = [];
var combo = 0;
var maxCombo = 0;
// UI Elements
var scoreText = new Text2('0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var comboText = new Text2('Combo: 0', {
size: 40,
fill: 0xFFFF00
});
comboText.anchor.set(1, 0);
comboText.x = 2048 - 50;
comboText.y = 100;
game.addChild(comboText);
var modeText = new Text2('Free Play Mode', {
size: 50,
fill: 0x00FF00
});
modeText.anchor.set(0, 0);
modeText.x = 150;
modeText.y = 100;
game.addChild(modeText);
// Create drum kit layout - positioned as if viewing from above like a real drum kit
function setupDrumKit() {
// Add cymbal stands as background visuals first
var crashStand1 = LK.getAsset('cymbalStand', {
anchorX: 0.5,
anchorY: 1
});
crashStand1.x = 650;
crashStand1.y = 1600;
game.addChild(crashStand1);
var crashStand2 = LK.getAsset('cymbalStand', {
anchorX: 0.5,
anchorY: 1
});
crashStand2.x = 1400;
crashStand2.y = 1600;
game.addChild(crashStand2);
var rideStand = LK.getAsset('cymbalStand', {
anchorX: 0.5,
anchorY: 1
});
rideStand.x = 1650;
rideStand.y = 2000;
game.addChild(rideStand);
var hiHatStandGraphics = LK.getAsset('hiHatStand', {
anchorX: 0.5,
anchorY: 0
});
hiHatStandGraphics.x = 450;
hiHatStandGraphics.y = 1400;
game.addChild(hiHatStandGraphics);
var openHatStandGraphics = LK.getAsset('hiHatStand', {
anchorX: 0.5,
anchorY: 0
});
openHatStandGraphics.x = 300;
openHatStandGraphics.y = 1300;
game.addChild(openHatStandGraphics);
// Kick drum (bottom center - closest to drummer)
var kickDrum = new DrumPad('kickDrum', 1024, 2200, 600, 300);
drumPads.push(kickDrum);
game.addChild(kickDrum);
// Snare drum (center position)
var snareDrum = new DrumPad('snareDrum', 1024, 1600, 375, 180);
drumPads.push(snareDrum);
game.addChild(snareDrum);
// Hi-hat (left side, slightly forward)
var hiHat = new DrumPad('hiHat', 450, 1400, 270, 120);
drumPads.push(hiHat);
game.addChild(hiHat);
// Open hi-hat (next to closed hi-hat, slightly left)
var openHat = new DrumPad('openHat', 300, 1300, 270, 120);
drumPads.push(openHat);
game.addChild(openHat);
// High tom (left of snare, above snare level)
var highTom = new DrumPad('highTom', 800, 1300, 300, 150);
drumPads.push(highTom);
game.addChild(highTom);
// Mid tom (right of snare, above snare level)
var midTom = new DrumPad('midTom', 1250, 1300, 330, 165);
drumPads.push(midTom);
game.addChild(midTom);
// Floor tom (right side, lower than snare)
var floorTom = new DrumPad('floorTom', 1450, 1800, 420, 210);
drumPads.push(floorTom);
game.addChild(floorTom);
// Crash cymbal 1 (left side, above high tom)
var crashCymbal1 = new DrumPad('crashCymbal', 650, 1000, 360, 165);
drumPads.push(crashCymbal1);
game.addChild(crashCymbal1);
// Crash cymbal 2 (right side, above mid tom)
var crashCymbal2 = new DrumPad('crashCymbal', 1400, 1000, 360, 165);
drumPads.push(crashCymbal2);
game.addChild(crashCymbal2);
// Ride cymbal (far right, behind floor tom)
var rideCymbal = new DrumPad('rideCymbal', 1650, 1400, 420, 195);
drumPads.push(rideCymbal);
game.addChild(rideCymbal);
}
// Pattern mode functions
var patternTimer = 0;
var patternInterval = 120; // Spawn pattern every 2 seconds at 60fps
var patternSequence = ['kick', 'snare', 'hihat', 'kick', 'crashcymbal', 'snare', 'hightom', 'midtom', 'floortom', 'ride', 'openhat'];
var patternIndex = 0;
function spawnPatternNote() {
var drumType = patternSequence[patternIndex] + 'Drum';
var targetDrum = null;
// Find corresponding drum pad
for (var i = 0; i < drumPads.length; i++) {
if (drumPads[i].drumType === drumType) {
targetDrum = drumPads[i];
break;
}
}
if (targetDrum) {
var note = new PatternNote(drumType, LK.ticks);
note.x = targetDrum.x;
note.y = 200;
patternNotes.push(note);
game.addChild(note);
}
patternIndex = (patternIndex + 1) % patternSequence.length;
}
function toggleGameMode() {
if (gameMode === 'freeplay') {
gameMode = 'pattern';
modeText.setText('Pattern Mode');
modeText.fill = '#ff6600';
LK.playMusic('drumLoop');
} else {
gameMode = 'freeplay';
modeText.setText('Free Play Mode');
modeText.fill = '#00ff00';
LK.stopMusic();
// Clear existing pattern notes
for (var i = patternNotes.length - 1; i >= 0; i--) {
patternNotes[i].destroy();
patternNotes.splice(i, 1);
}
}
}
// Create background
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
background.x = 0;
background.y = 0;
background.alpha = 1; // Make background fully visible
game.addChild(background);
// Add additional background textures to fill empty spaces
var background2 = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
background2.x = 0;
background2.y = 1000; // Position below first background
background2.alpha = 1;
game.addChild(background2);
var background3 = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
background3.x = 0;
background3.y = 2000; // Position below second background
background3.alpha = 1;
game.addChild(background3);
// Initialize drum kit
setupDrumKit();
// Game controls
game.down = function (x, y, obj) {
// Check if clicking on mode toggle area (top center)
if (x > 800 && x < 1248 && y < 200) {
toggleGameMode();
return;
}
};
// Main game update loop
game.update = function () {
// Pattern mode logic
if (gameMode === 'pattern') {
patternTimer++;
// Spawn new pattern notes
if (patternTimer >= patternInterval) {
spawnPatternNote();
patternTimer = 0;
}
// Update pattern notes
for (var i = patternNotes.length - 1; i >= 0; i--) {
var note = patternNotes[i];
if (note.lastY === undefined) note.lastY = note.y;
// Check if note went off screen
if (note.lastY < 2732 && note.y >= 2732) {
if (!note.hit) {
combo = 0;
comboText.setText('Combo: ' + combo);
}
note.destroy();
patternNotes.splice(i, 1);
continue;
}
// Check for hits near drum pads
for (var j = 0; j < drumPads.length; j++) {
var drum = drumPads[j];
if (note.drumType === drum.drumType) {
var distance = Math.sqrt(Math.pow(note.x - drum.x, 2) + Math.pow(note.y - drum.y, 2));
if (distance < 150 && !note.hit) {
// Auto-hit when note reaches drum pad
note.hit = true;
combo++;
if (combo > maxCombo) maxCombo = combo;
comboText.setText('Combo: ' + combo);
// Bonus points for combo
var bonusPoints = Math.floor(combo * 5);
LK.setScore(LK.getScore() + 20 + bonusPoints);
scoreText.setText(LK.getScore().toString());
note.destroy();
patternNotes.splice(i, 1);
break;
}
}
}
note.lastY = note.y;
}
}
// Update high score in storage
var highScore = storage.highScore || 0;
if (LK.getScore() > highScore) {
storage.highScore = LK.getScore();
}
var highCombo = storage.highCombo || 0;
if (maxCombo > highCombo) {
storage.highCombo = maxCombo;
}
};
// Initialize score display
scoreText.setText(LK.getScore().toString());