User prompt
Add animated rocket-Fireworks effect to the upper half of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add animated Cake-rocket-Fireworks effect to the upper half of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add animated Cake-Fireworks effect to the upper half of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add animated Cake Fireworks effect tobthe upper half of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'CakeFireworks is not defined' in or related to this line: 'var cakeFireworks = new CakeFireworks();' Line Number: 893
User prompt
Add nimated Cake Fireworks tobthe upper half of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Confetti particles are too big. Scale down their size to the quarter
User prompt
Add Confetti explode and rain animation to the upper half of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add neongreen laser lines to lasershow effect
User prompt
Move down the dancing man and women assets by 69 units
User prompt
Please fix the bug: 'ReferenceError: highlight is not defined' in or related to this line: 'highlight.x = -ballRadius * 0.32 + Math.cos(t * 1.2) * ballRadius * 0.13;' Line Number: 363
User prompt
There is a white oval particle In front of the discoball. Remove it.
User prompt
Remove the first shine effect oval from the discoball
User prompt
Scale down the reflectors to the half
User prompt
Ensure reflector cannot cover discoball
User prompt
Mive reflectors behind the discoball in display
User prompt
But now reflectors are hided
User prompt
Reflectors should be behing the discoball in display
User prompt
Reflectors should be circle and not just oval
User prompt
Add flashing white reflectors to the top of the screen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove dark overlay from equalizer
User prompt
Remove dark overlay from lasershows
User prompt
Dancing man and women assets should be behing the lasershow in display
User prompt
Dancing man and women assets should be under the lasershow in display
User prompt
Add animated reflector flash to the upper half of the map ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// --- Reflectors (behind discoball) ---
var reflectors = [];
var numReflectors = 7;
var reflectorSpacing = 2048 / (numReflectors + 1);
var reflectorY = 80; // Top, but below menu area
// Create reflectors but do not add to game yet
for (var i = 0; i < numReflectors; i++) {
	var rx = reflectorSpacing * (i + 1);
	var reflector = LK.getAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 60,
		height: 60
	});
	reflector.tint = 0xffffff;
	reflector.alpha = 0.0;
	reflector.x = rx;
	reflector.y = reflectorY;
	reflectors.push(reflector);
}
// --- Discoball (top of screen) ---
// Asset for dancing woman
// Asset for dancing man
var discoball = new Discoball();
// Add reflectors behind discoball in display order
for (var i = 0; i < reflectors.length; i++) {
	game.addChild(reflectors[i]);
}
// Insert discoball after reflectors so it appears above them
game.addChild(discoball);
discoball.x = 2048 / 2;
discoball.y = 200 - 69; // Move discoball up by 69 units
discoball.scaleX = 0.8;
discoball.scaleY = 0.8;
// --- Extra white particles for upper half sparkle effect ---
var extraWhiteParticles = [];
var numExtraParticles = 32;
for (var i = 0; i < numExtraParticles; i++) {
	// Random position in upper half, avoid top 100px (menu)
	var px = 100 + Math.random() * (2048 - 200);
	var py = 120 + Math.random() * (1366 - 220);
	var size = 8 + Math.random() * 10;
	var particle = LK.getAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: size,
		height: size
	});
	particle.tint = 0xffffff;
	particle.alpha = 0.18 + Math.random() * 0.22;
	particle.x = px;
	particle.y = py;
	game.addChild(particle);
	extraWhiteParticles.push({
		obj: particle,
		baseX: px,
		baseY: py,
		phase: Math.random() * Math.PI * 2,
		baseAlpha: particle.alpha,
		baseSize: size
	});
}
// Animate extra particles in game.update
// --- Fog Effect (upper half) ---
var fogEffect = new FogEffect();
game.addChild(fogEffect);
fogEffect.y = 0; // Position at the top of the screen
// --- Fireworks Effect (upper half) ---
var fireworksEffect = new FireworksEffect();
game.addChild(fireworksEffect);
fireworksEffect.y = 0; // Position at the top of the screen
// --- Confetti Effect (upper half) ---
var confettiEffect = new ConfettiEffect();
game.addChild(confettiEffect);
confettiEffect.y = 0; // Position at the top of the screen
// --- DJ Deck Asset ---
var djDeck = LK.getAsset('djDeck', {
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(djDeck);
djDeck.x = 2048 / 2;
djDeck.y = 2732 / 2 + 333 + 12; // Move the DJ deck down by 345 units
// --- Dancing People ---
var dancingPeople = [];
var numPeople = 8;
var peopleAreaY = djDeck.y - djDeck.height / 2 - 200 + 200 + 69; // Position above the DJ deck, moved down by 200 units, then down by 69 more
var peopleAreaWidth = 1600; // Area width for dancing people
var startX = 2048 / 2 - peopleAreaWidth / 2;
var personSpacing = peopleAreaWidth / (numPeople - 1);
for (var i = 0; i < numPeople; i++) {
	var person = new DancingPerson();
	person.x = startX + i * personSpacing;
	person.baseY = peopleAreaY; // Set the base Y position for animation
	game.addChild(person);
	dancingPeople.push(person);
}
// --- Laser Show (upper half) ---
var laserShow = new LaserShow();
game.addChild(laserShow);
laserShow.y = -456; // Move laser effect up by 456 units (333 + 123)
// --- DJ Deck Asset ---
var djDeck = LK.getAsset('djDeck', {
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(djDeck);
djDeck.x = 2048 / 2;
djDeck.y = 2732 / 2 + 333 + 12; // Move the DJ deck down by 345 units
// No dark overlay is present, so nothing to remove.
// --- Decks --- 
// Sound effects (dummy, as actual music is handled by LK)
// Beat lights
// FX Button
// Crossfader
// Deck platters (turntables)
// --- Layout constants ---
var deckY = 1366; // Move decks to vertical center of 2732px screen
var deckSpacing = 1000;
var crossfaderY = 1800;
var fxButtonY = 2200;
// --- Equalizer Waves (upper half) ---
var equalizer = new EqualizerWaves();
equalizer.y += 200; // Move the equalizer down by 200 units
game.addChild(equalizer);
// --- Decks ---
var leftDeck = new DeckPlatter();
leftDeck.setTrack('A');
game.addChild(leftDeck);
leftDeck.x = 2048 / 2 - deckSpacing / 2;
leftDeck.y = deckY;
var rightDeck = new DeckPlatter();
rightDeck.setTrack('B');
game.addChild(rightDeck);
rightDeck.x = 2048 / 2 + deckSpacing / 2;
rightDeck.y = deckY;
// --- Crossfader ---
var crossfader = new Crossfader();
game.addChild(crossfader);
crossfader.x = 2048 / 2;
crossfader.y = crossfaderY;
crossfader.setValue(0.5);
// --- FX Button ---
var fxButton = new FXButton();
game.addChild(fxButton);
fxButton.x = 2048 / 2;
fxButton.y = fxButtonY;
// --- Score / Combo / Energy ---
var energy = 50; // 0-100
var combo = 0;
var score = 0;
// Energy bar
var energyBarBg = LK.getAsset('crossfaderTrack', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 600,
	height: 40
});
energyBarBg.tint = 0x222222;
energyBarBg.y = 0;
var energyBar = LK.getAsset('crossfaderTrack', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 600,
	height: 40
});
energyBar.tint = 0x00ff00;
energyBar.y = 0;
var energyBarContainer = new Container();
energyBarContainer.addChild(energyBarBg);
energyBarContainer.addChild(energyBar);
energyBarContainer.x = 2048 / 2;
energyBarContainer.y = 200;
LK.gui.top.addChild(energyBarContainer);
// --- Fog Button under pause button (top left, but not in 0,0 area) ---
var fogButton = LK.getAsset('fogButton', {
	anchorX: 1.0,
	anchorY: 0.0
});
LK.gui.topRight.addChild(fogButton);
fogButton.x = 0;
fogButton.y = 0;
// Score text
var scoreTxt = new Text2('Score: 0', {
	size: 80,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.x = 2048 / 2;
scoreTxt.y = 300;
// Combo text
var comboTxt = new Text2('', {
	size: 60,
	fill: "#ff0"
});
comboTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(comboTxt);
comboTxt.x = 2048 / 2;
comboTxt.y = 400;
// --- State ---
var dragging = null; // Which control is being dragged
var lastTouchObj = null;
// --- Beat simulation ---
var beatInterval = 600; // ms per beat
var beatTimer = 0;
var lastTickTime = Date.now();
// --- Music ---
LK.playMusic('trackA', {
	loop: true
});
LK.playMusic('trackB', {
	loop: true
});
// HSV to RGB helper for background color
function hsvToRgb(h, s, v) {
	var r, g, b;
	var i = Math.floor(h * 6);
	var f = h * 6 - i;
	var p = v * (1 - s);
	var q = v * (1 - f * s);
	var t = v * (1 - (1 - f) * s);
	switch (i % 6) {
		case 0:
			r = v, g = t, b = p;
			break;
		case 1:
			r = q, g = v, b = p;
			break;
		case 2:
			r = p, g = v, b = t;
			break;
		case 3:
			r = p, g = q, b = v;
			break;
		case 4:
			r = t, g = p, b = v;
			break;
		case 5:
			r = v, g = p, b = q;
			break;
	}
	return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
var trackAVol = 1;
var trackBVol = 1;
// --- Touch handling ---
function getTouchedControl(x, y) {
	// Check decks
	var lx = leftDeck.toLocal(game.toGlobal({
		x: x,
		y: y
	})).x;
	var ly = leftDeck.toLocal(game.toGlobal({
		x: x,
		y: y
	})).y;
	if (Math.pow(lx - leftDeck.width / 2, 2) + Math.pow(ly - leftDeck.height / 2, 2) < 200 * 200) return leftDeck;
	var rx = rightDeck.toLocal(game.toGlobal({
		x: x,
		y: y
	})).x;
	var ry = rightDeck.toLocal(game.toGlobal({
		x: x,
		y: y
	})).y;
	if (Math.pow(rx - rightDeck.width / 2, 2) + Math.pow(ry - rightDeck.height / 2, 2) < 200 * 200) return rightDeck;
	// Crossfader
	var cf = crossfader.toLocal(game.toGlobal({
		x: x,
		y: y
	}));
	if (cf.x > 0 && cf.x < crossfader.width && cf.y > 0 && cf.y < crossfader.height) return crossfader;
	// FX Button
	var fx = fxButton.toLocal(game.toGlobal({
		x: x,
		y: y
	}));
	if (Math.pow(fx.x - fxButton.width / 2, 2) + Math.pow(fx.y - fxButton.height / 2, 2) < 60 * 60) return fxButton;
	return null;
}
game.down = function (x, y, obj) {
	var control = getTouchedControl(x, y);
	dragging = control;
	lastTouchObj = obj;
	if (control && control.down) {
		// Convert to local
		var local = control.toLocal(game.toGlobal({
			x: x,
			y: y
		}));
		control.down(local.x, local.y, obj);
	}
};
game.up = function (x, y, obj) {
	if (dragging && dragging.up) {
		var local = dragging.toLocal(game.toGlobal({
			x: x,
			y: y
		}));
		dragging.up(local.x, local.y, obj);
	}
	dragging = null;
	lastTouchObj = null;
};
game.move = function (x, y, obj) {
	if (dragging && dragging.move) {
		var local = dragging.toLocal(game.toGlobal({
			x: x,
			y: y
		}));
		dragging.move(local.x, local.y, obj);
	}
};
// --- Game update ---
game.update = function () {
	// Update discoball animation
	discoball.update();
	// Update fog effect animation
	fogEffect.update();
	// Update fireworks effect animation
	fireworksEffect.update();
	// Update confetti effect animation
	confettiEffect.update();
	// Update dancing people animations
	for (var i = 0; i < dancingPeople.length; i++) {
		dancingPeople[i].update();
	}
	// Animate extra white particles (subtle sparkle and movement)
	if (extraWhiteParticles) {
		var t = Date.now() * 0.001;
		for (var i = 0; i < extraWhiteParticles.length; i++) {
			var p = extraWhiteParticles[i];
			// Subtle float and twinkle
			p.obj.x = p.baseX + Math.sin(t * 1.2 + p.phase + i) * 8;
			p.obj.y = p.baseY + Math.cos(t * 1.1 + p.phase + i * 0.7) * 6;
			p.obj.alpha = p.baseAlpha + 0.10 * Math.sin(t * 2.2 + p.phase + i * 0.5);
			var s = p.baseSize * (0.95 + 0.12 * Math.sin(t * 1.7 + p.phase + i));
			p.obj.width = s;
			p.obj.height = s;
		}
	}
	// Animate flashing white reflectors
	if (reflectors) {
		var t = Date.now() * 0.001;
		for (var i = 0; i < reflectors.length; i++) {
			// Staggered flash, each reflector flashes in sequence
			var phase = t * 2.2 + i * 0.5;
			// Use a sharp pulse for flash, then fade out
			var flash = Math.max(0, Math.sin(phase));
			// Sharpen the flash curve for a strobe effect
			flash = Math.pow(flash, 6);
			reflectors[i].alpha = 0.18 + 0.82 * flash;
			// Animate as perfect circles for extra pop (half size base)
			var size = 60 + 20 * flash;
			// Prevent reflectors from covering the discoball
			// Compute distance from reflector to discoball center
			var dx = reflectors[i].x - discoball.x;
			var dy = reflectors[i].y - discoball.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// Discoball's visible radius (scaled)
			var discoballRadius = 150 * discoball.scaleX; // matches Discoball class
			// If reflector would overlap discoball, shrink it so it cannot cover
			if (dist < discoballRadius + size / 2) {
				// Max allowed size so edge of reflector does not enter discoball
				var maxSize = Math.max(0, 2 * (dist - discoballRadius));
				if (size > maxSize) size = maxSize;
				if (size < 0) size = 0;
			}
			reflectors[i].width = size;
			reflectors[i].height = size;
		}
	}
	// Update equalizer animation
	equalizer.update();
	// Update laser show animation
	laserShow.update();
	// Update decks
	leftDeck.update();
	rightDeck.update();
	// Simulate beat
	var now = Date.now();
	beatTimer += now - lastTickTime;
	lastTickTime = now;
	if (beatTimer >= beatInterval) {
		beatTimer -= beatInterval;
		leftDeck.flashBeat();
		rightDeck.flashBeat();
		LK.getSound('beat').play();
		// Energy drops if not scratching or mixing
		if (!leftDeck.isScratching && !rightDeck.isScratching && crossfader.value > 0.2 && crossfader.value < 0.8) {
			energy -= 2;
			combo = 0;
		} else {
			// Combo up if scratching or crossfading
			combo += 1;
			score += 10 * combo;
			energy += 2;
			if (energy > 100) energy = 100;
		}
		if (energy < 0) energy = 0;
		// Update visuals
		scoreTxt.setText('Score: ' + score);
		if (combo > 1) {
			comboTxt.setText('Combo x' + combo);
		} else {
			comboTxt.setText('');
		}
	}
	// Update energy bar
	energyBar.width = 600 * (energy / 100);
	// Crossfader logic: adjust music volumes
	trackAVol = 1 - crossfader.value;
	trackBVol = crossfader.value;
	// (In a real game, would set music volumes here, but LK handles music globally.)
	// End game if energy is 0
	if (energy <= 0) {
		// Game over event disabled
	}
	// Animate background color
	var time = Date.now() * 0.0005; // Time for animation
	var hue = time * 360 % 360; // Cycle through hues over time
	var rgb = hsvToRgb(hue / 360, 0.6, 0.5); // Convert HSV to RGB (adjust saturation and value for desired effect)
	game.setBackgroundColor(rgb[0] << 16 | rgb[1] << 8 | rgb[2]);
	// Win if score is high
	if (score >= 5000) {
		LK.effects.flashScreen(0x00ff00, 1000);
		LK.showYouWin();
	}
}; ===================================================================
--- original.js
+++ change.js
@@ -3,779 +3,8 @@
 ****/ 
 var tween = LK.import("@upit/tween.v1");
 
 /**** 
-* Classes
-****/ 
-// ConfettiEffect: Animated confetti falling from the top
-var ConfettiEffect = Container.expand(function () {
-	var self = Container.call(this);
-	// Config
-	var numParticles = 100;
-	var particles = [];
-	var particleMinSize = 2.5;
-	var particleMaxSize = 7.5;
-	var speedY = 5; // pixels per second
-	var speedX = 2; // horizontal drift
-	// Create confetti particles
-	for (var i = 0; i < numParticles; i++) {
-		var size = particleMinSize + Math.random() * (particleMaxSize - particleMinSize);
-		var particle = LK.getAsset('centerCircle', {
-			anchorX: 0.5,
-			anchorY: 0.5,
-			width: size,
-			height: size
-		});
-		// Random color (rainbow)
-		var hue = Math.random();
-		var rgb = hsvToRgb(hue, 1, 1);
-		particle.tint = rgb[0] << 16 | rgb[1] << 8 | rgb[2];
-		// Random initial position in upper half, above screen for seamless loop
-		var px = Math.random() * 2048;
-		var py = -particleMaxSize - Math.random() * 500;
-		particle.x = px;
-		particle.y = py;
-		self.addChild(particle);
-		particles.push({
-			obj: particle,
-			speedScale: 0.8 + Math.random() * 0.4,
-			// particles fall at slightly different speeds
-			phase: Math.random() * Math.PI * 2
-		});
-	}
-	// HSV to RGB helper
-	function hsvToRgb(h, s, v) {
-		var r, g, b;
-		var i = Math.floor(h * 6);
-		var f = h * 6 - i;
-		var p = v * (1 - s);
-		var q = v * (1 - f * s);
-		var t = v * (1 - (1 - f) * s);
-		switch (i % 6) {
-			case 0:
-				r = v, g = t, b = p;
-				break;
-			case 1:
-				r = q, g = v, b = p;
-				break;
-			case 2:
-				r = p, g = v, b = t;
-				break;
-			case 3:
-				r = p, g = q, b = v;
-				break;
-			case 4:
-				r = t, g = p, b = v;
-				break;
-			case 5:
-				r = v, g = p, b = q;
-				break;
-		}
-		return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
-	}
-	// Animation
-	self.update = function () {
-		var t = Date.now() * 0.001;
-		for (var i = 0; i < particles.length; i++) {
-			var p = particles[i];
-			// Move particles down with horizontal drift
-			p.obj.y += speedY * p.speedScale;
-			p.obj.x += speedX * Math.sin(t + p.phase);
-			// Wrap around vertically (from bottom to top)
-			if (p.obj.y > 2732) {
-				p.obj.y = -particleMaxSize;
-				p.obj.x = Math.random() * 2048; // new random x position
-			}
-			// Animate rotation
-			p.obj.rotation += 0.05 * p.speedScale;
-			// Animate scale for flicker
-			// Use the original particle size for flicker, not the possibly already scaled width
-			var baseSize = p.obj.width / (0.98 + 0.04 * Math.sin(t * 3 + p.phase)); // undo previous flicker
-			var s = baseSize * (0.98 + 0.04 * Math.sin(t * 3 + p.phase));
-			p.obj.width = s;
-			p.obj.height = s;
-		}
-	};
-	return self;
-});
-// Crossfader: Controls mix between decks
-var Crossfader = Container.expand(function () {
-	var self = Container.call(this);
-	// State
-	self.value = 0.5; // 0 = left, 1 = right
-	self.dragging = false;
-	// Visuals
-	var track = self.attachAsset('crossfaderTrack', {
-		anchorX: 0.5,
-		anchorY: 0.5
-	});
-	var knob = self.attachAsset('crossfaderKnob', {
-		anchorX: 0.5,
-		anchorY: 0.5
-	});
-	knob.y = 0;
-	// Methods
-	self.setValue = function (val) {
-		self.value = Math.max(0, Math.min(1, val));
-		knob.x = (self.value - 0.5) * (track.width - knob.width);
-	};
-	// Touch events
-	self.down = function (x, y, obj) {
-		self.dragging = true;
-		self.setValue(x / track.width);
-	};
-	self.up = function (x, y, obj) {
-		self.dragging = false;
-	};
-	self.move = function (x, y, obj) {
-		if (self.dragging) {
-			self.setValue(x / track.width);
-		}
-	};
-	return self;
-});
-// DancingPerson: Animated dancing people (women and men)
-var DancingPerson = Container.expand(function () {
-	var self = Container.call(this);
-	// Config
-	// Use the correct asset for dancing woman (image asset 'dancingWoman') and man (keep purple box for man)
-	var assets = ['dancingWoman', 'dancingMan']; // Use image for woman, box for man
-	var assetId = assets[Math.floor(Math.random() * assets.length)];
-	// Visuals
-	var personGraphics = self.attachAsset(assetId, {
-		anchorX: 0.5,
-		anchorY: 1.0 // Anchor at the bottom center (feet)
-	});
-	// Animation state
-	self.baseY = 0;
-	self.phaseOffset = Math.random() * Math.PI * 2; // Random start phase for animation
-	// Animation
-	self.update = function () {
-		var t = Date.now() * 0.002; // Time for animation
-		// Simple bouncing and swaying animation
-		self.y = self.baseY + Math.sin(t * 3 + self.phaseOffset) * 15; // Bounce up/down
-		self.rotation = Math.sin(t * 2 + self.phaseOffset) * 0.08; // Sway left/right
-	};
-	return self;
-});
-// DeckPlatter: Represents a turntable platter
-var DeckPlatter = Container.expand(function () {
-	var self = Container.call(this);
-	// State
-	self.isActive = false;
-	self.isScratching = false;
-	self.lastAngle = 0;
-	self.rotationOffset = 0;
-	self.currentRotation = 0;
-	self.track = 'A'; // 'A' or 'B'
-	self.playing = true;
-	self.scratchSpeed = 0;
-	self.lastTouchAngle = null;
-	// Visuals
-	var platter = self.attachAsset('deckPlatter', {
-		anchorX: 0.5,
-		anchorY: 0.5
-	});
-	var highlight = self.attachAsset('deckPlatterHighlight', {
-		anchorX: 0.5,
-		anchorY: 0.5
-	});
-	highlight.alpha = 0;
-	var label = self.attachAsset('deckLabel', {
-		anchorX: 0.5,
-		anchorY: 0.5,
-		y: 140
-	});
-	// Label text
-	var labelTxt = new Text2(self.track, {
-		size: 40,
-		fill: "#222"
-	});
-	labelTxt.anchor.set(0.5, 0.5);
-	label.addChild(labelTxt);
-	// Beat light
-	var beatLight = self.attachAsset('beatLight', {
-		anchorX: 0.5,
-		anchorY: 0.5,
-		y: -140
-	});
-	beatLight.alpha = 0.2;
-	// Methods
-	self.setActive = function (active) {
-		self.isActive = active;
-		highlight.alpha = active ? 0.4 : 0;
-	};
-	self.setTrack = function (track) {
-		self.track = track;
-		labelTxt.setText(track);
-	};
-	self.flashBeat = function () {
-		beatLight.alpha = 1;
-		tween(beatLight, {
-			alpha: 0.2
-		}, {
-			duration: 200,
-			easing: tween.easeOut
-		});
-	};
-	// Touch events
-	self.down = function (x, y, obj) {
-		self.isScratching = true;
-		self.setActive(true);
-		// Calculate angle from center
-		var dx = x - self.width / 2;
-		var dy = y - self.height / 2;
-		self.lastTouchAngle = Math.atan2(dy, dx);
-		self.scratchSpeed = 0;
-		LK.getSound('scratch').play();
-	};
-	self.up = function (x, y, obj) {
-		self.isScratching = false;
-		self.setActive(false);
-		self.scratchSpeed = 0;
-		self.lastTouchAngle = null;
-	};
-	self.move = function (x, y, obj) {
-		if (!self.isScratching) return;
-		// Calculate angle from center
-		var dx = x - self.width / 2;
-		var dy = y - self.height / 2;
-		var angle = Math.atan2(dy, dx);
-		if (self.lastTouchAngle !== null) {
-			var delta = angle - self.lastTouchAngle;
-			// Normalize delta
-			if (delta > Math.PI) delta -= 2 * Math.PI;
-			if (delta < -Math.PI) delta += 2 * Math.PI;
-			self.rotationOffset += delta;
-			self.scratchSpeed = delta;
-		}
-		self.lastTouchAngle = angle;
-	};
-	// Called every tick
-	self.update = function () {
-		// If not scratching, platter rotates at normal speed
-		if (!self.isScratching && self.playing) {
-			self.rotationOffset += 0.02; // Normal play speed
-			self.scratchSpeed = 0.02;
-		}
-		// Apply rotation
-		self.currentRotation = self.rotationOffset;
-		self.rotation = self.currentRotation;
-	};
-	return self;
-});
-// Discoball: True 3D disco ball illusion with spinning mirrored tiles and shining white light particles
-var Discoball = Container.expand(function () {
-	var self = Container.call(this);
-	// Config
-	var ballRadius = 150;
-	var ballDiameter = ballRadius * 2;
-	var numLat = 13; // latitude tiles (vertical)
-	var numLon = 24; // longitude tiles (horizontal)
-	var tileSize = ballDiameter / numLat * 0.95;
-	var tileGap = tileSize * 0.12;
-	var tiles = [];
-	var shineParticles = [];
-	var numShine = 18;
-	var shineRadius = ballRadius * 1.08;
-	var shineMinAlpha = 0.25;
-	var shineMaxAlpha = 0.95;
-	var shineMinSize = tileSize * 0.7;
-	var shineMaxSize = tileSize * 1.7;
-	var spinY = 0; // radians, for y-axis rotation
-	var spinSpeed = 0.012;
-	var spinDir = 1;
-	// --- Mirrored Tiles Grid ---
-	// Render both front and back halves for a full 3D ball illusion
-	for (var lat = 0; lat < numLat; lat++) {
-		var theta = Math.PI * (lat + 0.5) / numLat; // 0 (top) to PI (bottom)
-		var y = Math.cos(theta) * ballRadius;
-		var r = Math.sin(theta) * ballRadius;
-		for (var lon = 0; lon < numLon; lon++) {
-			var phi = 2 * Math.PI * lon / numLon;
-			// 3D to 2D projection with y-axis spin
-			var x3d = Math.cos(phi) * r;
-			var z3d = Math.sin(phi) * r;
-			// Y-axis spin
-			var x2d = x3d * Math.cos(spinY) - z3d * Math.sin(spinY);
-			var z2d = x3d * Math.sin(spinY) + z3d * Math.cos(spinY);
-			// Draw both front and back tiles, but make back tiles dimmer and behind
-			for (var side = 0; side < 2; side++) {
-				// side 0: front (z2d > 0), side 1: back (z2d < 0)
-				var isFront = side === 0;
-				// Always create both front and back tiles, but only show one at a time
-				var tile = LK.getAsset('centerCircle', {
-					anchorX: 0.5,
-					anchorY: 0.5,
-					width: tileSize,
-					height: tileSize
-				});
-				// Mirror color: light gray, with some random sparkle
-				var base = 0xbb + Math.floor(Math.random() * 0x22);
-				var color = base << 16 | base << 8 | base;
-				tile.tint = color;
-				// Back tiles are dimmer and more transparent
-				if (isFront) {
-					tile.alpha = 0.92 - 0.18 * (lat / numLat) + Math.random() * 0.08;
-				} else {
-					tile.alpha = 0.32 - 0.10 * (lat / numLat) + Math.random() * 0.04;
-				}
-				// Position
-				tile.x = x2d;
-				tile.y = y;
-				// Simulate 3D: scaleX based on z2d
-				tile.scaleX = 1 + 0.18 * (Math.abs(z2d) / ballRadius);
-				tile.scaleY = 1;
-				// For back tiles, send to back (add first), for front tiles, add last
-				if (isFront) {
-					self.addChild(tile);
-				} else {
-					self.addChildAt(tile, 0);
-				}
-				tiles.push({
-					tile: tile,
-					lat: lat,
-					lon: lon,
-					theta: theta,
-					phi: phi,
-					isFront: isFront
-				});
-			}
-		}
-	}
-	// --- Specular highlight (white spot) ---
-	// Removed the white oval particle in front of the discoball
-	// --- Shining white light particles ---
-	for (var i = 0; i < numShine; i++) {
-		var angle = 2 * Math.PI * i / numShine + Math.random() * 0.2;
-		var dist = shineRadius * (0.92 + Math.random() * 0.12);
-		var particle = LK.getAsset('centerCircle', {
-			anchorX: 0.5,
-			anchorY: 0.5,
-			width: shineMinSize + Math.random() * (shineMaxSize - shineMinSize),
-			height: shineMinSize + Math.random() * (shineMaxSize - shineMinSize)
-		});
-		particle.tint = 0xffffff;
-		particle.alpha = shineMinAlpha + Math.random() * (shineMaxAlpha - shineMinAlpha);
-		particle.x = Math.cos(angle) * dist;
-		particle.y = Math.sin(angle) * dist;
-		self.addChild(particle);
-		shineParticles.push({
-			particle: particle,
-			baseAngle: angle,
-			baseDist: dist,
-			phase: Math.random() * Math.PI * 2
-		});
-	}
-	// --- Light beams (background) ---
-	var numBeams = 32;
-	var beams = [];
-	var lightBeamLength = 1200; // Increased from 800 to 1200 for longer beams
-	for (var i = 0; i < numBeams; i++) {
-		var beam = LK.getAsset('crossfaderTrack', {
-			anchorX: 0.5,
-			anchorY: 0,
-			width: 8,
-			height: lightBeamLength
-		});
-		beam.tint = 0xffffff;
-		beam.alpha = 0.12 + Math.random() * 0.28;
-		beam.rotation = Math.PI * 2 / numBeams * i + Math.random() * 0.1;
-		beams.push(beam);
-		self.addChild(beam);
-	}
-	// --- Animation ---
-	self.update = function () {
-		// Animate y-axis spin in a full 360-degree circle
-		spinY += spinSpeed * spinDir;
-		if (spinY > Math.PI * 2) spinY -= Math.PI * 2;
-		if (spinY < 0) spinY += Math.PI * 2;
-		self._spinY = spinY; // direct assignment for full rotation
-		// Update mirrored tiles positions for y-axis spin
-		for (var i = 0; i < tiles.length; i++) {
-			var t = tiles[i];
-			// 3D to 2D projection with y-axis spin
-			var x3d = Math.cos(t.phi) * Math.sin(t.theta) * ballRadius;
-			var y3d = Math.cos(t.theta) * ballRadius;
-			var z3d = Math.sin(t.phi) * Math.sin(t.theta) * ballRadius;
-			// Y-axis spin
-			var x2d = x3d * Math.cos(self._spinY) - z3d * Math.sin(self._spinY);
-			var z2d = x3d * Math.sin(self._spinY) + z3d * Math.cos(self._spinY);
-			// For front tiles, show if z2d > 0; for back tiles, show if z2d < 0
-			if (t.isFront && z2d > 0 || !t.isFront && z2d < 0) {
-				t.tile.visible = true;
-				t.tile.x = x2d;
-				t.tile.y = y3d;
-				t.tile.scaleX = 1 + 0.18 * (Math.abs(z2d) / ballRadius);
-				t.tile.scaleY = 1;
-				// Flicker for disco effect
-				if (t.isFront) {
-					t.tile.alpha = 0.88 - 0.18 * (t.lat / numLat) + Math.random() * 0.09;
-				} else {
-					t.tile.alpha = 0.28 - 0.10 * (t.lat / numLat) + Math.random() * 0.04;
-				}
-			} else {
-				t.tile.visible = false;
-			}
-		}
-		// Animate highlight to move in a small circle for extra 3D effect
-		// (highlight removed, nothing to animate here)
-		var t = Date.now() * 0.001;
-		// Animate shine particles
-		for (var i = 0; i < shineParticles.length; i++) {
-			var s = shineParticles[i];
-			var phase = t * 1.2 + s.phase;
-			var r = s.baseDist + Math.sin(phase) * 12;
-			s.particle.x = Math.cos(s.baseAngle + Math.sin(phase) * 0.12) * r;
-			s.particle.y = Math.sin(s.baseAngle + Math.cos(phase) * 0.12) * r;
-			s.particle.alpha = shineMinAlpha + (shineMaxAlpha - shineMinAlpha) * (0.5 + 0.5 * Math.sin(phase * 2 + i));
-			var size = shineMinSize + (shineMaxSize - shineMinSize) * (0.5 + 0.5 * Math.cos(phase * 1.5 + i));
-			s.particle.width = size;
-			s.particle.height = size;
-		}
-		// Animate beams (spin and flicker)
-		for (var i = 0; i < beams.length; i++) {
-			var beam = beams[i];
-			beam.rotation += 0.015;
-			beam.alpha = 0.12 + Math.random() * 0.28;
-		}
-	};
-	return self;
-});
-// EqualizerWaves: Animated equalizer bars/waves for visual feedback
-var EqualizerWaves = Container.expand(function () {
-	var self = Container.call(this);
-	// Config
-	var numBars = 32;
-	var barWidth = 40;
-	var barSpacing = 16;
-	var barMaxHeight = 220;
-	var barMinHeight = 40;
-	var bars = [];
-	// Create bars
-	for (var i = 0; i < numBars; i++) {
-		var bar = LK.getAsset('crossfaderTrack', {
-			anchorX: 0.5,
-			anchorY: 1.0,
-			width: barWidth,
-			height: barMinHeight,
-			x: i * (barWidth + barSpacing),
-			y: 0
-		});
-		// Rainbow gradient: hue from 0 to 360 across bars
-		var hue = Math.floor(i / numBars * 360);
-		var rgb = hsvToRgb(hue / 360, 1, 1);
-		bar.tint = rgb[0] << 16 | rgb[1] << 8 | rgb[2];
-		// No dark overlay or background is added to the equalizer.
-		self.addChild(bar);
-		bars.push(bar);
-	}
-	// HSV to RGB helper
-	function hsvToRgb(h, s, v) {
-		var r, g, b;
-		var i = Math.floor(h * 6);
-		var f = h * 6 - i;
-		var p = v * (1 - s);
-		var q = v * (1 - f * s);
-		var t = v * (1 - (1 - f) * s);
-		switch (i % 6) {
-			case 0:
-				r = v, g = t, b = p;
-				break;
-			case 1:
-				r = q, g = v, b = p;
-				break;
-			case 2:
-				r = p, g = v, b = t;
-				break;
-			case 3:
-				r = p, g = q, b = v;
-				break;
-			case 4:
-				r = t, g = p, b = v;
-				break;
-			case 5:
-				r = v, g = p, b = q;
-				break;
-		}
-		return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
-	}
-	// Center and scale down the whole equalizer to half size
-	self.width = numBars * (barWidth + barSpacing) * 0.5;
-	self.height = barMaxHeight * 0.5;
-	self.scaleX = 0.5;
-	self.scaleY = 0.5;
-	self.x = 2048 / 2 - self.width / 2;
-	self.y = 600; // Upper half of screen, below GUI
-	// Animation state
-	self.phase = [];
-	for (var j = 0; j < numBars; j++) {
-		self.phase[j] = Math.random() * Math.PI * 2;
-	}
-	// Animate bars
-	self.update = function () {
-		var t = Date.now() * 0.002;
-		for (var i = 0; i < numBars; i++) {
-			// Simulate music: combine sine waves and random
-			var wave = Math.sin(t + self.phase[i]) * 0.5 + 0.5;
-			var beatPulse = (Math.sin(t * 2 + i * 0.2) * 0.5 + 0.5) * 0.5;
-			var randomPulse = Math.random() * 0.15;
-			var h = barMinHeight + (barMaxHeight - barMinHeight) * (wave * 0.6 + beatPulse * 0.3 + randomPulse);
-			bars[i].height = h;
-		}
-	};
-	return self;
-});
-// FXButton: Triggers a sound effect
-var FXButton = Container.expand(function () {
-	var self = Container.call(this);
-	// Visuals
-	var btn = self.attachAsset('fxButton', {
-		anchorX: 0.5,
-		anchorY: 0.5
-	});
-	var txt = new Text2('FX', {
-		size: 48,
-		fill: "#fff"
-	});
-	txt.anchor.set(0.5, 0.5);
-	btn.addChild(txt);
-	// State
-	self.cooldown = false;
-	// Touch
-	self.down = function (x, y, obj) {
-		if (self.cooldown) return;
-		self.cooldown = true;
-		LK.getSound('fx').play();
-		tween(btn, {
-			scaleX: 1.2,
-			scaleY: 1.2
-		}, {
-			duration: 80,
-			onFinish: function onFinish() {
-				tween(btn, {
-					scaleX: 1,
-					scaleY: 1
-				}, {
-					duration: 120
-				});
-			}
-		});
-		LK.setTimeout(function () {
-			self.cooldown = false;
-		}, 400);
-	};
-	return self;
-});
-// FogEffect: Animated fog in upper half of the map
-var FogEffect = Container.expand(function () {
-	var self = Container.call(this);
-	// Config
-	var numParticles = 60;
-	var particles = [];
-	var particleMinSize = 200;
-	var particleMaxSize = 800;
-	var speedX = 3; // pixels per second, increased horizontal speed
-	var speedY = 0.2; // pixels per second, decreased vertical speed
-	var particleAlpha = 0.18; // Increased particle alpha for denser fog
-	// Create fog particles
-	for (var i = 0; i < numParticles; i++) {
-		var size = particleMinSize + Math.random() * (particleMaxSize - particleMinSize);
-		var particle = LK.getAsset('crossfaderTrack', {
-			anchorX: 0.5,
-			anchorY: 0.5,
-			width: size * 2.0,
-			// Make particles significantly wider
-			height: size * 0.4 // Make particles much flatter
-		});
-		particle.tint = 0xffffff; // white fog
-		particle.alpha = particleAlpha;
-		// Random initial position in upper half, extending slightly beyond bounds for seamless loop
-		var px = Math.random() * (2048 + particleMaxSize) - particleMaxSize / 2;
-		var py = 100 + Math.random() * (1366 - 100);
-		particle.x = px;
-		particle.y = py;
-		self.addChild(particle);
-		particles.push({
-			obj: particle,
-			speedScale: 0.5 + Math.random() * 1.0,
-			// particles move at different speeds
-			baseAlpha: particleAlpha
-		});
-	}
-	// Animation
-	self.update = function () {
-		var t = Date.now() * 0.001;
-		for (var i = 0; i < particles.length; i++) {
-			var p = particles[i];
-			// Move particles from right to left
-			p.obj.x -= speedX * p.speedScale;
-			p.obj.y += speedY * p.speedScale;
-			// Wrap around horizontally (from left to right)
-			if (p.obj.x < -particleMaxSize / 2) {
-				p.obj.x = 2048 + particleMaxSize / 2;
-				p.obj.y = Math.random() * (2732 / 2 - 100) + 100; // new random y position within upper half
-			}
-			// Animate alpha for subtle flow and density changes
-			p.obj.alpha = p.baseAlpha + 0.08 * Math.sin(t * 0.8 + i); // Increased alpha animation range
-		}
-	};
-	return self;
-});
-// LaserShow: Realistic party laser show with moving heads and multi-color animated beams
-var LaserShow = Container.expand(function () {
-	var self = Container.call(this);
-	// Config
-	var numHeads = 6;
-	var beamsPerHead = 3;
-	var headRadius = 700; // Reduced from 1100 to 700 to move heads closer to the middle
-	var centerX = 2048 / 2;
-	var centerY = 400;
-	var beamLength = 1200; // Reduced from 1600 to 1200 to keep beams inside the new head radius
-	var beamWidth = 18;
-	var beamAlpha = 0.65;
-	var headAlpha = 0.7;
-	var heads = [];
-	var beams = [];
-	// Predefined rainbow colors for beams
-	var beamColors = [0xff0000,
-	// red
-	0xff8000,
-	// orange
-	0xffff00,
-	// yellow
-	0x00ff00,
-	// green
-	0x00ffff,
-	// cyan
-	0x0000ff,
-	// blue
-	0x8000ff,
-	// violet
-	0xff00ff // magenta
-	];
-	// Create moving heads and beams
-	for (var h = 0; h < numHeads; h++) {
-		// Head position in a semi-circle
-		var angle = Math.PI * (h + 1) / (numHeads + 1);
-		var hx = centerX + Math.cos(angle) * headRadius;
-		var hy = centerY + Math.sin(angle) * 200;
-		// Head (visual: ellipse, colored)
-		// Use rainbowEllipse for gradient rainbow look
-		var head = LK.getAsset('rainbowEllipse', {
-			anchorX: 0.5,
-			anchorY: 0.5,
-			x: hx,
-			y: hy,
-			width: 20,
-			height: 20
-		});
-		head.alpha = headAlpha;
-		// Animate color: store initial hue offset for each head
-		head._rainbowHueOffset = h * (360 / numHeads);
-		self.addChild(head);
-		heads.push(head);
-		// Beams for this head
-		for (var b = 0; b < beamsPerHead; b++) {
-			var beam = LK.getAsset('crossfaderTrack', {
-				anchorX: 0.5,
-				anchorY: 0,
-				x: hx,
-				y: hy,
-				width: beamWidth,
-				height: beamLength
-			});
-			// Assign color in a rainbow pattern, offset by head and beam
-			beam.tint = beamColors[(h * beamsPerHead + b) % beamColors.length];
-			beam.alpha = beamAlpha;
-			// Initial rotation
-			beam.rotation = 0;
-			self.addChild(beam);
-			beams.push({
-				obj: beam,
-				headIdx: h,
-				beamIdx: b,
-				baseAngle: angle
-			});
-		}
-	}
-	// Animate heads and beams
-	self.update = function () {
-		var t = Date.now() * 0.001;
-		// Animate heads in a subtle up/down and color pulse
-		for (var h = 0; h < heads.length; h++) {
-			var head = heads[h];
-			// Sway up/down
-			head.y = centerY + Math.sin(Math.PI * (h + 1) / (numHeads + 1)) * 200 + Math.sin(t * 1.2 + h) * 18;
-			// Pulse alpha
-			head.alpha = headAlpha + 0.15 * Math.sin(t * 2 + h);
-			// Animate rainbow color: cycle hue every second
-			// Full cycle every 1 second (t mod 1.0)
-			var hue = (head._rainbowHueOffset + t * 360) % 360 / 360;
-			// HSV to RGB conversion
-			var i = Math.floor(hue * 6);
-			var f = hue * 6 - i;
-			var q = 1 - f;
-			var tcol = 1 - (1 - f);
-			var r, g, b;
-			switch (i % 6) {
-				case 0:
-					r = 1, g = tcol, b = 0;
-					break;
-				case 1:
-					r = q, g = 1, b = 0;
-					break;
-				case 2:
-					r = 0, g = 1, b = tcol;
-					break;
-				case 3:
-					r = 0, g = q, b = 1;
-					break;
-				case 4:
-					r = tcol, g = 0, b = 1;
-					break;
-				case 5:
-					r = 1, g = 0, b = q;
-					break;
-			}
-			var tint = Math.round(r * 255) << 16 | Math.round(g * 255) << 8 | Math.round(b * 255);
-			// Tween the head tint for smooth color change
-			tween(head, {
-				tint: tint
-			}, {
-				duration: 120,
-				easing: tween.linear
-			});
-		}
-		// Animate beams: sweep, flicker, and color pulse
-		for (var i = 0; i < beams.length; i++) {
-			var beamData = beams[i];
-			var beam = beamData.obj;
-			var h = beamData.headIdx;
-			var b = beamData.beamIdx;
-			var baseAngle = beamData.baseAngle;
-			// Beam origin follows head
-			var head = heads[h];
-			beam.x = head.x;
-			beam.y = head.y;
-			// Animate beam angle: base + sweeping + per-beam offset
-			var sweep = Math.sin(t * 1.1 + h + b * 0.7) * 0.25 + Math.sin(t * 0.7 + b) * 0.12;
-			var beatPulse = Math.sin(t * 2.5 + h + b) * 0.08;
-			beam.rotation = baseAngle - Math.PI / 2 + sweep + beatPulse;
-			// Animate beam length for flicker
-			var flicker = 1 + 0.12 * Math.sin(t * 3 + h * 2 + b * 1.5 + Math.sin(t * 1.5 + b));
-			beam.height = beamLength * flicker;
-			// Animate color pulse (simulate RGB laser color mixing)
-			var colorIdx = (h * beamsPerHead + b + Math.floor(t * 2 + h + b)) % beamColors.length;
-			beam.tint = beamColors[colorIdx];
-			// Animate alpha for strobe effect
-			beam.alpha = beamAlpha + 0.15 * Math.abs(Math.sin(t * 4 + h + b));
-		}
-	};
-	return self;
-});
-
-/**** 
 * Initialize Game
 ****/ 
 var game = new LK.Game({
 	backgroundColor: 0x000000
@@ -850,16 +79,16 @@
 // --- Fog Effect (upper half) ---
 var fogEffect = new FogEffect();
 game.addChild(fogEffect);
 fogEffect.y = 0; // Position at the top of the screen
+// --- Fireworks Effect (upper half) ---
+var fireworksEffect = new FireworksEffect();
+game.addChild(fireworksEffect);
+fireworksEffect.y = 0; // Position at the top of the screen
 // --- Confetti Effect (upper half) ---
 var confettiEffect = new ConfettiEffect();
 game.addChild(confettiEffect);
 confettiEffect.y = 0; // Position at the top of the screen
-// --- Cake Rocket Fireworks (upper half) ---
-var cakeFireworks = new CakeRocketFireworks();
-game.addChild(cakeFireworks);
-cakeFireworks.y = 0; // Position at the top of the screen
 // --- DJ Deck Asset ---
 var djDeck = LK.getAsset('djDeck', {
 	anchorX: 0.5,
 	anchorY: 0.5
@@ -1103,12 +332,12 @@
 	// Update discoball animation
 	discoball.update();
 	// Update fog effect animation
 	fogEffect.update();
+	// Update fireworks effect animation
+	fireworksEffect.update();
 	// Update confetti effect animation
 	confettiEffect.update();
-	// Update cake rocket fireworks animation
-	cakeFireworks.update();
 	// Update dancing people animations
 	for (var i = 0; i < dancingPeople.length; i++) {
 		dancingPeople[i].update();
 	}
 
 
 Photorealistic Ferris cabin, sideview
 
 
 
 
 
 Grey circle with transparent inner place, front view
 there are 4 piece of holes in the image, repair it
 
 
 
 photorealistic grey Tablet lying down on dj deck, front view. The screen should be dark monocrome screen in power of mode without text.
 
 
 Photorealistic transparent rectange dj deck sample button with white rounded corners, front view. No text needed on image
 Transparent ballon shape.
 
 Replace arrow to OK text
 Dancing woman in a white top filled with multi-colored UV ink palm prints. UV luminous bracelet on the arm
 
 Photorealistic dollar, front view
 Dancing man in a white shirt filled with multi-colored UV ink palm prints. UV luminous bracelet on the arm
 
 White thin pencil in 45 degrees instead of arrow.
 Replace arrow to white X
 Change the orange filling color from the middle to black
 
 simple grey colored DJZ logo
 REPLACE THE PENCIL WITH WHITE MENU TEXT
 Replace pencil with white REC text, but no other changes!
1
Music
trackA
Music
trackB
Music
sample1
Sound effect
sample2
Sound effect
sample3
Sound effect
sample4
Sound effect
Sample5
Sound effect
sample6
Sound effect
sample7
Sound effect
sample8
Sound effect
sample9
Sound effect
sample10
Sound effect
sample11
Sound effect
sample12
Sound effect
sample13
Sound effect
sample14
Sound effect
sample15
Sound effect
sample16
Sound effect