User prompt
Move basket up by 25 units
User prompt
Move down the basket by 300 units
User prompt
Move down the top of the basket to the center of the eggbase
User prompt
Move down the top of the basket to the center of the map
User prompt
Ensure brush slider function is change brush tool thickness
User prompt
Add thickness selector function to brush slider
User prompt
Ensure thickness slider pops up if brush tool is selected
User prompt
Color every slider color to the same as it button's color
User prompt
I don't care just ensure a similar 3d spinning effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Do it
User prompt
Move spin button up by 250 units
User prompt
Add spin button above the eraser button
User prompt
Change 256 color palette to a 256 Glitter powder color palette
User prompt
Move the glitter button up by 200 units
User prompt
Add Glitter button to the map above the all colors button
User prompt
Decrease font size for 'all color' button label text by 5 units
User prompt
Decrease font size for all color label text by 5 units
User prompt
Reduce text size on the 'All Colors' button by 10 font size units
User prompt
Reduce the size of the text on the all colors button by 5 fonts to fit the full text on the button.
User prompt
Reduce the size of the text on the all colors button by 10 units to fit the full text on the button.
User prompt
Reduce the size of the text on the all colors button by 5 units to fit the full text on the button.
User prompt
Move the all colors button 'All' text right by 3 units
User prompt
The letter A protrudes beyond the edge of the all colors button, bring it a little further inside so that it doesn't stick out
User prompt
I mean hazelnut brown
User prompt
Change Save button color to brown
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BrushStroke = Container.expand(function (color, size) { var self = Container.call(this); var stroke = self.attachAsset('brushStroke', { anchorX: 0.5, anchorY: 0.5, scaleX: size / 30, scaleY: size / 30 }); stroke.tint = color; return self; }); var Button = Container.expand(function (label, color) { var self = Container.call(this); var background = self.attachAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5 }); var text = new Text2(label, { size: 30, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); self.addChild(text); if (color !== undefined) { background.tint = color; } self.down = function () { tween(background, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.up = function () { tween(background, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }; return self; }); var ColorButton = Container.expand(function (color) { var self = Container.call(this); var button = self.attachAsset('colorButton', { anchorX: 0.5, anchorY: 0.5 }); button.tint = color; self.color = color; self.down = function () { tween(button, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); }; self.up = function () { tween(button, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }; return self; }); var ColorPalette = Container.expand(function () { var self = Container.call(this); var background = LK.getAsset('colorPanel', { anchorX: 0.5, anchorY: 0.5, scaleX: 1881 / 1880, // Set to exact size 1881 scaleY: 1899 / 277 // Set to exact size 1899 }); self.addChild(background); var colorButtons = []; // Generate 256 color gradient palette var paletteColors = []; var buttonSize = 90; // Increased from 30 to 90 (3x larger) var spacing = 12; // Increased from 4 to 12 (3x larger) var columns = 16; var rows = 16; // Generate rainbow gradient colors for the full 256 color palette for (var i = 0; i < 256; i++) { var hue = i / 256; var r, g, b; // Convert HSV to RGB (simplified rainbow gradient) if (hue < 1 / 6) { r = 1; g = hue * 6; b = 0; } else if (hue < 2 / 6) { r = (2 / 6 - hue) * 6; g = 1; b = 0; } else if (hue < 3 / 6) { r = 0; g = 1; b = (hue - 2 / 6) * 6; } else if (hue < 4 / 6) { r = 0; g = (4 / 6 - hue) * 6; b = 1; } else if (hue < 5 / 6) { r = (hue - 4 / 6) * 6; b = 1; g = 0; } else { r = 1; g = 0; b = (1 - hue) * 6; } // Convert to 0-255 range var red = Math.floor(r * 255); var green = Math.floor(g * 255); var blue = Math.floor(b * 255); var color = red << 16 | green << 8 | blue; paletteColors.push(color); } for (var i = 0; i < paletteColors.length; i++) { var row = Math.floor(i / columns); var col = i % columns; var colorBtn = new ColorButton(paletteColors[i]); colorBtn.x = col * (buttonSize + spacing) - (columns - 1) * (buttonSize + spacing) / 2; colorBtn.y = row * (buttonSize + spacing) - (rows - 1) * (buttonSize + spacing) / 2; colorBtn.scaleX = 4.5; // Increased from 1.5 to 4.5 (3x larger) colorBtn.scaleY = 4.5; // Increased from 1.5 to 4.5 (3x larger) self.addChild(colorBtn); // Create a closure to capture the current color (function (color, btn) { btn.down = function () { currentColor = color; self.visible = false; // Notify the game that a color was selected if (self.onColorSelected) { self.onColorSelected(color); } }; })(paletteColors[i], colorBtn); colorButtons.push(colorBtn); } // Add selector ring var selector = LK.getAsset('brushStroke', { anchorX: 0.5, anchorY: 0.5, scaleX: 7.5, // Increased from 2.5 to 7.5 (3x larger) scaleY: 7.5 // Increased from 2.5 to 7.5 (3x larger) }); selector.tint = 0xFFFFFF; selector.alpha = 0.7; self.addChild(selector); // Set selector initial position selector.x = colorButtons[0].x; selector.y = colorButtons[0].y; // Hide palette initially self.visible = false; // Method to update selector position self.updateSelector = function (color) { for (var i = 0; i < paletteColors.length; i++) { if (paletteColors[i] === color) { selector.x = colorButtons[i].x; selector.y = colorButtons[i].y; break; } } }; return self; }); var CompletedEgg = Container.expand(function (baseColor) { var self = Container.call(this); var eggGraphic = self.attachAsset('completedEgg', { anchorX: 0.5, anchorY: 0.5 }); eggGraphic.tint = baseColor || 0xFFFFFF; // Add some random decoration to make each egg look unique for (var i = 0; i < 5; i++) { var glitter = self.attachAsset('glitter', { anchorX: 0.5, anchorY: 0.5, x: (Math.random() - 0.5) * 80, y: (Math.random() - 0.5) * 120 }); glitter.tint = 0xFFD700 + Math.floor(Math.random() * 0x555555); } return self; }); var EasterEgg = Container.expand(function () { var self = Container.call(this); var eggBase = self.attachAsset('eggBase', { anchorX: 0.5, anchorY: 0.5 }); var designContainer = new Container(); self.designContainer = designContainer; // Make accessible outside self.addChild(designContainer); self.addDesign = function (x, y, designElement) { var localPosition = designContainer.toLocal({ x: x, y: y }, game); // Check if the point is within the bounds of the eggBase // Convert to egg's local coordinates for hit testing var eggLocalPosition = self.toLocal({ x: x, y: y }, game); // Calculate distance from center of egg var dx = eggLocalPosition.x; var dy = eggLocalPosition.y; var distance = Math.sqrt(dx * dx + dy * dy); // Check if point is inside the egg (ellipse) // Using the egg's dimensions to determine the ellipse bounds var eggWidth = eggBase.width / 2; var eggHeight = eggBase.height / 2; // Formula for point in ellipse: (x/a)² + (y/b)² <= 1 // where a is half-width and b is half-height var isInEgg = dx * dx / (eggWidth * eggWidth) + dy * dy / (eggHeight * eggHeight) <= 1; // Only add design if point is inside the egg if (isInEgg) { designElement.x = localPosition.x; designElement.y = localPosition.y; designContainer.addChild(designElement); // Add to design history for undo functionality designHistory.push({ element: designElement, index: designContainer.children.length - 1 }); } }; self.clearDesigns = function () { while (designContainer.children.length > 0) { designContainer.removeChild(designContainer.children[0]); } }; self.rotate = function (angle) { eggBase.rotation += angle; designContainer.rotation += angle; }; self.captureDesign = function () { // In a real implementation, this would create a snapshot of the egg // For this simplified version, we just create a new completed egg with the same tint var completedEgg = new CompletedEgg(eggBase.tint); return completedEgg; }; return self; }); var Eraser = Container.expand(function (size) { var self = Container.call(this); // Create a visual representation of the eraser var eraserVisual = self.attachAsset('brushStroke', { anchorX: 0.5, anchorY: 0.5, scaleX: size / 30, scaleY: size / 30 }); // Make it white with a border eraserVisual.tint = 0xFFFFFF; eraserVisual.alpha = 0.7; return self; }); var Slider = Container.expand(function (minVal, maxVal, defaultVal, width, color) { var self = Container.call(this); // Track properties self.minValue = minVal || 0; self.maxValue = maxVal || 100; self.value = defaultVal || 50; self.trackWidth = width || 300; self.trackColor = color || 0xCCCCCC; // Create track var track = LK.getAsset('buttonBg', { anchorX: 0, anchorY: 0.5, scaleX: self.trackWidth / 120, scaleY: 0.3 }); track.tint = self.trackColor; self.addChild(track); self.track = track; // Store track reference for external access // Create handle var handle = LK.getAsset('colorButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); handle.tint = 0xFFFFFF; handle.x = (self.value - self.minValue) / (self.maxValue - self.minValue) * self.trackWidth; self.addChild(handle); self.handle = handle; // No value label is needed // Method definitions // Convert value to x position self.getXForValue = function (val) { return (val - self.minValue) / (self.maxValue - self.minValue) * self.trackWidth; }; // Convert x position to value self.getValueForX = function (x) { return self.minValue + x / self.trackWidth * (self.maxValue - self.minValue); }; // Update handle position self.updateHandlePosition = function () { handle.x = self.getXForValue(self.value); }; // Set value self.setValue = function (val) { self.value = Math.max(self.minValue, Math.min(self.maxValue, val)); self.updateHandlePosition(); if (self.onValueChanged) { self.onValueChanged(self.value); } }; // Handle drag self.down = function (x, y) { self.isDragging = true; self.setValue(self.getValueForX(x)); }; self.move = function (x, y) { if (self.isDragging) { self.setValue(self.getValueForX(Math.max(0, Math.min(self.trackWidth, x)))); } }; self.up = function () { self.isDragging = false; }; return self; }); var Sticker = Container.expand(function (type, scale) { var self = Container.call(this); var stickerAsset; if (type === 'star') { stickerAsset = self.attachAsset('stickerStar', { anchorX: 0.5, anchorY: 0.5, scaleX: scale * 5, scaleY: scale * 5 }); } else if (type === 'heart') { stickerAsset = self.attachAsset('stickerHeart', { anchorX: 0.5, anchorY: 0.5, scaleX: scale * 5, scaleY: scale * 5 }); } self.down = function () { tween(stickerAsset, { scaleX: scale * 5 * 0.9, scaleY: scale * 5 * 0.9 }, { duration: 100 }); }; self.up = function () { tween(stickerAsset, { scaleX: scale * 5, scaleY: scale * 5 }, { duration: 100 }); }; return self; }); var Watermark = Container.expand(function (text, opacity) { var self = Container.call(this); // Set default values if not provided self.text = text || "FRVR Easter"; self.opacity = opacity || 0.35; // Create corner text elements function createCornerText(x, y, rotation) { var cornerText = new Text2(self.text, { size: 28, fill: 0x333333 }); cornerText.anchor.set(0.5, 0.5); cornerText.x = x; cornerText.y = y; cornerText.rotation = rotation || 0; cornerText.alpha = self.opacity; self.addChild(cornerText); return cornerText; } // Create text for each corner, avoiding top-left 100x100 area self.topRight = createCornerText(2048 - 120, 120, Math.PI / 4); self.bottomRight = createCornerText(2048 - 120, 2732 - 120, -Math.PI / 4); self.bottomLeft = createCornerText(120, 2732 - 120, Math.PI / 4); // Top left is placed with extra margin to avoid the platform menu icon self.topLeft = createCornerText(180, 180, -Math.PI / 4); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xAFEEEE // Light turquoise background color }); /**** * Game Code ****/ // Define color palette - arranged in rainbow gradient var colors = [ // Black (left) 0x000000, // Violet group 0x9400D3, // Violet 0x4B0082, // Indigo 0x8A2BE2, // Blue Violet // Blue group 0x0000FF, // Blue 0x000080, // Navy Blue 0x00FFFF, // Cyan 0x008080, // Teal // Green group 0x00FF00, // Green 0x32CD32, // Lime Green 0x808000, // Olive // Red group 0x800000, // Maroon 0xA52A2A, // Brown 0xFF0000, // Red 0xFF7F00, // Orange // Yellow group 0xFFD700, // Gold 0xFFFF00, // Yellow // Pink group 0xFF69B4, // Hot Pink // Gray 0x808080, // White (right) 0xFFFFFF]; // Define brush sizes var brushSizes = [10, 20, 30]; // Initialize game variables var currentColor = colors[0]; var currentBrushSize = brushSizes[1]; var currentEraserSize = 50; var currentStickerSize = 1.2; var currentTool = 'brush'; var previousTool = null; var isPainting = false; var lastX, lastY; var selectedColorButton = null; // Keep track of actions for undo functionality var designHistory = []; // Initialize empty savedEggs array var savedEggs = []; // Basket already created earlier // Create main egg var easterEgg = new EasterEgg(); easterEgg.x = 2048 / 2; easterEgg.y = 2732 / 2 - 200; game.addChild(easterEgg); // Create UI components // Tool panel var toolPanel = LK.getAsset('toolPanel', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 5, y: 2732 - 100 // Moved up by 20 units }); game.addChild(toolPanel); // Color panel var colorPanel = LK.getAsset('colorPanel', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 - 345 // Moved down by 5 units }); game.addChild(colorPanel); // Add color buttons var colorButtons = []; for (var i = 0; i < colors.length; i++) { var colorButton = new ColorButton(colors[i]); // Position in two rows (10 in first row, 10 in second row) if (i < 10) { // First row colorButton.x = i * 130 + 160; // Changed spacing from 145 to 130, moved left by 10 units colorButton.y = 2732 - 410; // First row - moved up by 10 units } else { // Second row colorButton.x = (i - 10) * 130 + 160; // Changed spacing from 145 to 130, moved left by 10 units colorButton.y = 2732 - 280; // Second row } game.addChild(colorButton); colorButtons.push(colorButton); // Scale up by 2x tween(colorButton, { scaleX: 2, scaleY: 2 }, { duration: 300 }); // Add click handler (function (color, button) { colorButton.down = function () { tween(colorButton, { scaleX: 1.8, scaleY: 1.8 }, { duration: 100 }); currentColor = color; }; colorButton.up = function () { tween(colorButton, { scaleX: 2, scaleY: 2 }, { duration: 100 }); // Stop any animations on previously selected button if (selectedColorButton) { tween.stop(selectedColorButton); tween(selectedColorButton, { scaleX: 2, scaleY: 2 }, { duration: 100 }); } // Set new selected button selectedColorButton = button; // Start pulsing animation function pulseButton() { tween(selectedColorButton, { scaleX: 2.2, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(selectedColorButton, { scaleX: 1.8, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: pulseButton }); } }); } // Start the pulsing animation pulseButton(); }; })(colors[i], colorButton); } // Create tool buttons // Calculate button width including scale factor var buttonWidth = 120 * 2; // 120px width * 2 scale var buttonSpacing = 25; // 25 units apart var startX = 300; // Starting X position // Create tool buttons var brushButton = new Button("Brush", 0x6495ED); brushButton.x = startX - 75; // Moved left by 25 more units brushButton.y = 2732 - 100; // Moved up by 20 units game.addChild(brushButton); tween(brushButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); brushButton.down = function () { tween(brushButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; brushButton.up = function () { tween(brushButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Hide any previous tool's sliders first sizeSlider.visible = false; eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Store previous tool and set current tool to brush previousTool = currentTool; currentTool = 'brush'; // Stop any animations on buttons tween.stop(brushButton); tween.stop(stickerStarButton); tween.stop(stickerHeartButton); tween.stop(eraserButton); tween.stop(rotateLeftButton); tween.stop(rotateRightButton); tween.stop(saveButton); tween.stop(clearButton); // Reset all buttons to normal size tween(stickerStarButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerHeartButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(saveButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Start pulsing animation for brush button function pulseBrushButton() { tween(brushButton, { scaleX: 2.4, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(brushButton, { scaleX: 2.0, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: pulseBrushButton }); } }); } // Start the pulsing animation pulseBrushButton(); }; var stickerStarButton = new Button("Star", 0xFFD700); stickerStarButton.x = startX + (buttonWidth + buttonSpacing) * 1 - 75; // Moved left by 25 more units stickerStarButton.y = 2732 - 100; // Moved up by 20 units game.addChild(stickerStarButton); // Set background to gold color stickerStarButton.children[0].tint = 0xFFD700; // Gold color tween(stickerStarButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); stickerStarButton.down = function () { tween(stickerStarButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; stickerStarButton.up = function () { tween(stickerStarButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Store previous tool and set current tool to star previousTool = currentTool; currentTool = 'star'; // First hide any previously visible sliders eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Show size slider for star (not toggle) sizeSlider.visible = true; // Update slider track color to black sizeSlider.trackColor = 0x000000; // Black color sizeSlider.track.tint = 0x000000; // Stop any animations on buttons tween.stop(brushButton); tween.stop(stickerStarButton); tween.stop(stickerHeartButton); tween.stop(eraserButton); tween.stop(rotateLeftButton); tween.stop(rotateRightButton); tween.stop(saveButton); tween.stop(clearButton); // Reset all buttons to normal size tween(brushButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerHeartButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(saveButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Start pulsing animation for star button function pulseStarButton() { tween(stickerStarButton, { scaleX: 2.4, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(stickerStarButton, { scaleX: 2.0, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: pulseStarButton }); } }); } // Start the pulsing animation pulseStarButton(); }; var stickerHeartButton = new Button("Heart", 0xFF0000); stickerHeartButton.x = startX + (buttonWidth + buttonSpacing) * 2 - 75; // Moved left by 25 more units stickerHeartButton.y = 2732 - 100; // Moved up by 20 units game.addChild(stickerHeartButton); tween(stickerHeartButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); stickerHeartButton.down = function () { tween(stickerHeartButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; stickerHeartButton.up = function () { tween(stickerHeartButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Store previous tool and set current tool to heart previousTool = currentTool; currentTool = 'heart'; // First hide any previously visible sliders eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Show size slider for heart (not toggle) sizeSlider.visible = true; // Update slider track color to black sizeSlider.trackColor = 0x000000; // Black color sizeSlider.track.tint = 0x000000; // Keep handle white for better visibility // Stop any animations on buttons tween.stop(brushButton); tween.stop(stickerStarButton); tween.stop(stickerHeartButton); tween.stop(eraserButton); tween.stop(rotateLeftButton); tween.stop(rotateRightButton); tween.stop(saveButton); tween.stop(clearButton); // Reset all buttons to normal size tween(brushButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerStarButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(saveButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Start pulsing animation for heart button function pulseHeartButton() { tween(stickerHeartButton, { scaleX: 2.4, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(stickerHeartButton, { scaleX: 2.0, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: pulseHeartButton }); } }); } // Start the pulsing animation pulseHeartButton(); }; var rotateLeftButton = new Button("< Rotate", 0x9370DB); rotateLeftButton.x = startX + (buttonWidth + buttonSpacing) * 3 - 75; // Moved left by 25 more units rotateLeftButton.y = 2732 - 100; // Moved up by 20 units game.addChild(rotateLeftButton); tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); rotateLeftButton.down = function () { tween(rotateLeftButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; rotateLeftButton.up = function () { tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Hide any open sliders sizeSlider.visible = false; eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Store previous tool before rotation previousTool = currentTool; easterEgg.rotate(-Math.PI / 8); }; // Add a thin grey vertical divider between rotate buttons var divider = LK.getAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5, x: startX + (buttonWidth + buttonSpacing) * 3.5 - 75, // Position between the two rotate buttons y: 2732 - 100, // Same Y as buttons scaleX: 0.05, // Make it thin scaleY: 2 // Same height as buttons }); divider.tint = 0xe6e6fa; // Light lavender color game.addChild(divider); var rotateRightButton = new Button("Rotate >", 0x9370DB); rotateRightButton.x = startX + (buttonWidth + buttonSpacing) * 4 - 75; // Moved left by 25 more units rotateRightButton.y = 2732 - 100; // Moved up by 20 units game.addChild(rotateRightButton); tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); rotateRightButton.down = function () { tween(rotateRightButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; rotateRightButton.up = function () { tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Hide any open sliders sizeSlider.visible = false; eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Store previous tool before rotation previousTool = currentTool; easterEgg.rotate(Math.PI / 8); }; var saveButton = new Button("Undo", 0x8B4513); saveButton.x = startX + (buttonWidth + buttonSpacing) * 5 - 75; // Moved left by 25 more units saveButton.y = 2732 - 100; // Moved up by 20 units game.addChild(saveButton); tween(saveButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); saveButton.down = function () { tween(saveButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); // Start continuous undo functionality var performUndo = function performUndo() { if (designHistory.length > 0) { var lastDesign = designHistory.pop(); // Handle clear operation undo (restore all elements that were cleared) if (lastDesign.clearOperation) { // First clear any current elements to avoid duplicates easterEgg.clearDesigns(); // Add back all elements that were cleared for (var i = 0; i < lastDesign.elements.length; i++) { easterEgg.designContainer.addChild(lastDesign.elements[i]); } LK.getSound('saveSound').play(); } // Handle erased element undo (add back erased element) else if (lastDesign.erased) { easterEgg.designContainer.addChildAt(lastDesign.element, lastDesign.index); LK.getSound('saveSound').play(); } // Handle regular element undo (remove added element) else if (easterEgg.designContainer && easterEgg.designContainer.children.length > 0) { // Check if the element is still at the expected index if (easterEgg.designContainer.children[lastDesign.index] === lastDesign.element) { easterEgg.designContainer.removeChild(lastDesign.element); } else { // If not at expected index, find and remove it by reference for (var i = 0; i < easterEgg.designContainer.children.length; i++) { if (easterEgg.designContainer.children[i] === lastDesign.element) { easterEgg.designContainer.removeChild(lastDesign.element); break; } } } LK.getSound('saveSound').play(); } } }; // Perform first undo immediately performUndo(); // Setup interval for continuous undo while button is pressed saveButton.undoInterval = LK.setInterval(function () { performUndo(); }, 150); // Undo every 150ms while pressed (2x faster) }; saveButton.up = function () { tween(saveButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Hide any previous tool's sliders first sizeSlider.visible = false; eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Stop continuous undo when releasing the button if (saveButton.undoInterval) { LK.clearInterval(saveButton.undoInterval); saveButton.undoInterval = null; } // Deactivate previous tool and activate save tool if (currentTool !== 'save') { var _pulseSaveButton = function pulseSaveButton() { tween(saveButton, { scaleX: 2.4, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(saveButton, { scaleX: 2.0, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: _pulseSaveButton }); } }); }; // Start the pulsing animation // Stop any animations on buttons tween.stop(brushButton); tween.stop(stickerStarButton); tween.stop(stickerHeartButton); tween.stop(eraserButton); tween.stop(rotateLeftButton); tween.stop(rotateRightButton); tween.stop(saveButton); tween.stop(clearButton); // Reset all buttons to normal size tween(brushButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerStarButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerHeartButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Store previous tool and set current tool to save previousTool = currentTool; currentTool = 'save'; // Start pulsing animation for save button _pulseSaveButton(); } }; var eraserButton = new Button("Eraser", 0x808080); eraserButton.x = colorPanel.x + colorPanel.width / 2 - 145; // Moved right by 100 units eraserButton.y = colorPanel.y - colorPanel.height / 2 + 139; // Moved down to match all colors button game.addChild(eraserButton); tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 300 }); eraserButton.down = function () { tween(eraserButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; eraserButton.up = function () { tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); // Toggle eraser mode if (currentTool === 'eraser') { var _pulseBrushButton = function pulseBrushButton() { tween(brushButton, { scaleX: 2.4, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(brushButton, { scaleX: 2.0, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: _pulseBrushButton }); } }); }; // Store previous tool and switch back to brush previousTool = currentTool; currentTool = 'brush'; // Stop animation on eraser button tween.stop(eraserButton); tween(eraserButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); // Hide eraser size slider eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Start pulsing animation for brush button _pulseBrushButton(); } else { var _pulseEraserButton = function pulseEraserButton() { tween(eraserButton, { scaleX: 2.4, scaleY: 3.3 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(eraserButton, { scaleX: 2.0, scaleY: 2.9 }, { duration: 500, easing: tween.easeInOut, onFinish: _pulseEraserButton }); } }); }; // Store previous tool and switch to eraser mode previousTool = currentTool; currentTool = 'eraser'; // Stop animations on all other buttons tween.stop(brushButton); tween.stop(stickerStarButton); tween.stop(stickerHeartButton); tween.stop(rotateLeftButton); tween.stop(rotateRightButton); tween.stop(clearButton); // Reset all buttons to normal size tween(brushButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerStarButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(stickerHeartButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(rotateLeftButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(rotateRightButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // First hide any previously visible sliders sizeSlider.visible = false; // Show eraser size slider eraserSizeSlider.visible = true; eraserSizeLabel.visible = true; // Start pulsing animation for eraser button _pulseEraserButton(); } }; // Add color palette button var allColorButton = new Button("All Colors", 0x9370DB); allColorButton.x = colorPanel.x + colorPanel.width / 2 - 415; // Position it - moved left by 100 units (from -315 to -415) allColorButton.y = colorPanel.y - colorPanel.height / 2 + 139; // Moved down by 4 units (from 135 to 139) game.addChild(allColorButton); tween(allColorButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 300 }); // Apply rainbow gradient to all colors button var btnBackground = allColorButton.children[0]; var rainbowColors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; var colorIndex = 0; var duration = 3000; // 3 seconds for full rainbow cycle // Function to cycle through rainbow colors function cycleRainbowColors() { tween(btnBackground, { tint: rainbowColors[colorIndex] }, { duration: duration / rainbowColors.length, onFinish: function onFinish() { colorIndex = (colorIndex + 1) % rainbowColors.length; cycleRainbowColors(); } }); } // Start the rainbow cycle cycleRainbowColors(); allColorButton.down = function () { tween(allColorButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; allColorButton.up = function () { // Reset to normal size first tween(allColorButton, { scaleX: 2.2, scaleY: 3.1 }, { duration: 100 }); // Toggle the full color palette colorPalette.visible = !colorPalette.visible; // Update selector position to match current selected color if (colorPalette.visible) { colorPalette.updateSelector(currentColor); } }; var clearButton = new Button("Clear", 0x444444); clearButton.x = startX + (buttonWidth + buttonSpacing) * 6 - 75; // Moved next to save button clearButton.y = 2732 - 100; // Moved up by 20 units game.addChild(clearButton); tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 300 }); clearButton.down = function () { tween(clearButton, { scaleX: 1.98, scaleY: 1.8 }, { duration: 100 }); }; clearButton.up = function () { tween(clearButton, { scaleX: 2.2, scaleY: 2 }, { duration: 100 }); // Hide any open sliders sizeSlider.visible = false; eraserSizeSlider.visible = false; eraserSizeLabel.visible = false; // Store previous tool before clearing previousTool = currentTool; // Save the current design state for potential undo if (easterEgg.designContainer && easterEgg.designContainer.children.length > 0) { // Create a special history entry for the clear operation designHistory.push({ clearOperation: true, elements: easterEgg.designContainer.children.slice() // Make a copy of all elements }); } easterEgg.clearDesigns(); LK.getSound('clearSound').play(); }; // Function to toggle eraser tool function toggleEraserThicknessSlider(visible) { // Set eraser as current tool when enabled if (visible) { currentTool = 'eraser'; } } // Create basket display var basket = LK.getAsset('basket', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 - 800 // Moved up by 60 units to make room for two rows of color buttons }); game.addChildAt(basket, 0); // Add at index 0 to ensure it's behind the egg // Bring the easterEgg to the front to ensure proper display order game.removeChild(easterEgg); game.addChild(easterEgg); // Title text var titleText = new Text2("Easter Egg Artist", { size: 100, fill: 0x8B4513 // Dark brown }); titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 50; game.addChild(titleText); // Score display - hidden but kept in code for reference var scoreText = new Text2("Eggs: 0", { size: 60, fill: 0x4B0082 // Indigo }); scoreText.anchor.set(0, 0); scoreText.x = 120; scoreText.y = 120; scoreText.visible = false; // Hide the score text // Function to display saved eggs (placeholder for new implementation) function displaySavedEggs() { // Remove any existing displayed eggs for (var i = game.children.length - 1; i >= 0; i--) { if (game.children[i].isCompletedEgg) { game.removeChild(game.children[i]); } } // Display saved eggs (will be reimplemented) for (var i = 0; i < savedEggs.length; i++) { var eggData = savedEggs[i]; var displayedEgg = new CompletedEgg(eggData.color); displayedEgg.x = eggData.x; displayedEgg.y = eggData.y; displayedEgg.isCompletedEgg = true; game.addChild(displayedEgg); } } // Display any saved eggs displaySavedEggs(); // Game event handlers game.down = function (x, y) { if (y < 2732 - 350) { isPainting = true; lastX = x; lastY = y; if (currentTool === 'brush') { var brushStroke = new BrushStroke(currentColor, currentBrushSize); easterEgg.addDesign(x, y, brushStroke); LK.getSound('brushSound').play(); } else if (currentTool === 'star' || currentTool === 'heart') { var size = currentStickerSize; var sticker = new Sticker(currentTool, size); easterEgg.addDesign(x, y, sticker); LK.getSound('stickerSound').play(); } else if (currentTool === 'eraser') { // Create a visual eraser element but don't actually add it to the design var eraser = new Eraser(eraserSizeSlider.value); // Store reference to enable updating size from slider game.eraser = eraser; // Convert to egg's local coordinates for hit testing var eggLocalPosition = easterEgg.toLocal({ x: x, y: y }, game); // Check if point is inside egg boundary var eggBase = easterEgg.children[0]; // The eggBase is the first child var eggWidth = eggBase.width / 2; var eggHeight = eggBase.height / 2; var dx = eggLocalPosition.x; var dy = eggLocalPosition.y; var isInEgg = dx * dx / (eggWidth * eggWidth) + dy * dy / (eggHeight * eggHeight) <= 1; if (isInEgg && easterEgg.designContainer && easterEgg.designContainer.children.length > 0) { // Find and remove elements near the eraser position for (var i = easterEgg.designContainer.children.length - 1; i >= 0; i--) { var element = easterEgg.designContainer.children[i]; var distance = Math.sqrt(Math.pow(element.x - eggLocalPosition.x, 2) + Math.pow(element.y - eggLocalPosition.y, 2)); // If element is within eraser size, remove it if (distance < eraserSizeSlider.value / 2) { // Save the removed element to history for potential undo designHistory.push({ element: element, index: i, erased: true // Mark as erased rather than added }); easterEgg.designContainer.removeChild(element); LK.getSound('brushSound').play(); break; // Remove one element at a time for better control } } } } } }; game.move = function (x, y) { if (isPainting && (currentTool === 'brush' || currentTool === 'eraser')) { // Calculate distance between last point and current point var dx = x - lastX; var dy = y - lastY; var distance = Math.sqrt(dx * dx + dy * dy); // Get current size based on tool var currentSize = currentTool === 'brush' ? currentBrushSize : currentEraserSize; // Get current color based on tool var strokeColor = currentTool === 'brush' ? currentColor : 0xFFFFFF; // Play brush sound occasionally while using eraser if (currentTool === 'eraser' && Math.random() < 0.05) { LK.getSound('brushSound').play(); } // If distance is greater than half the size, add intermediate points if (distance > currentSize / 2) { var steps = Math.ceil(distance / (currentSize / 2)); for (var i = 1; i <= steps; i++) { var pointX = lastX + dx * i / steps; var pointY = lastY + dy * i / steps; if (currentTool === 'eraser') { // Calculate egg local position for eraser var eggLocalPosition = easterEgg.toLocal({ x: pointX, y: pointY }, game); // Check if point is inside egg boundary var eggBase = easterEgg.children[0]; var eggWidth = eggBase.width / 2; var eggHeight = eggBase.height / 2; var localDx = eggLocalPosition.x; var localDy = eggLocalPosition.y; var isInEgg = localDx * localDx / (eggWidth * eggWidth) + localDy * localDy / (eggHeight * eggHeight) <= 1; if (isInEgg && easterEgg.designContainer && easterEgg.designContainer.children.length > 0) { // Find and remove elements near the eraser position for (var j = easterEgg.designContainer.children.length - 1; j >= 0; j--) { var element = easterEgg.designContainer.children[j]; var eraseDist = Math.sqrt(Math.pow(element.x - eggLocalPosition.x, 2) + Math.pow(element.y - eggLocalPosition.y, 2)); // If element is within eraser size, remove it if (eraseDist < eraserSizeSlider.value / 2) { // Save the removed element to history for potential undo designHistory.push({ element: element, index: j, erased: true // Mark as erased rather than added }); easterEgg.designContainer.removeChild(element); break; // Remove one element at a time for better control } } } } else { var stroke = new BrushStroke(strokeColor, currentSize); easterEgg.addDesign(pointX, pointY, stroke); } } } else { if (currentTool === 'eraser') { // Calculate egg local position for eraser var eggLocalPosition = easterEgg.toLocal({ x: x, y: y }, game); // Check if point is inside egg boundary var eggBase = easterEgg.children[0]; var eggWidth = eggBase.width / 2; var eggHeight = eggBase.height / 2; var localDx = eggLocalPosition.x; var localDy = eggLocalPosition.y; var isInEgg = localDx * localDx / (eggWidth * eggWidth) + localDy * localDy / (eggHeight * eggHeight) <= 1; if (isInEgg && easterEgg.designContainer && easterEgg.designContainer.children.length > 0) { // Find and remove elements near the eraser position for (var j = easterEgg.designContainer.children.length - 1; j >= 0; j--) { var element = easterEgg.designContainer.children[j]; var eraseDist = Math.sqrt(Math.pow(element.x - eggLocalPosition.x, 2) + Math.pow(element.y - eggLocalPosition.y, 2)); // If element is within eraser size, remove it if (eraseDist < eraserSizeSlider.value / 2) { // Save the removed element to history for potential undo designHistory.push({ element: element, index: j, erased: true // Mark as erased rather than added }); easterEgg.designContainer.removeChild(element); break; // Remove one element at a time for better control } } } } else { var stroke = new BrushStroke(strokeColor, currentSize); easterEgg.addDesign(x, y, stroke); } } lastX = x; lastY = y; } }; game.up = function () { isPainting = false; }; // Update function game.update = function () { // Update score display scoreText.setText("Eggs: " + LK.getScore()); }; // Create and add the full color palette var colorPalette = new ColorPalette(); colorPalette.x = 2048 / 2; colorPalette.y = 2732 / 2 - 150; // Position at center, aligned with the egg, moved down by 50 units game.addChild(colorPalette); // Set up color selection callback colorPalette.onColorSelected = function (color) { currentColor = color; // Stop any animations on previously selected button if (selectedColorButton) { tween.stop(selectedColorButton); tween(selectedColorButton, { scaleX: 2, scaleY: 2 }, { duration: 100 }); } // Find button with matching color and set as selected var _loop = function _loop() { if (colorButtons[i].color === color) { var _pulseSelectedButton2 = function pulseSelectedButton() { tween(selectedColorButton, { scaleX: 2.2, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(selectedColorButton, { scaleX: 1.8, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: _pulseSelectedButton2 }); } }); }; // Start the pulsing animation selectedColorButton = colorButtons[i]; // Start pulsing animation _pulseSelectedButton2(); return 1; // break } }; for (var i = 0; i < colorButtons.length; i++) { if (_loop()) { break; } } }; // Create size slider for star stickers var sizeSlider = new Slider(0.5, 3, 1.2, 1801, 0xFFD700); // Gold color, width matches colorPanel width minus 80 units (1801) sizeSlider.x = 2048 / 2 - 900; // Position at center of map, moved left by 900 units sizeSlider.y = 2732 / 2 + 800; // Moved down by 800 units sizeSlider.visible = false; // Hidden by default game.addChild(sizeSlider); // Add label above slider var sizeLabel = new Text2("Sticker Size", { size: 80, fill: 0x000000 // Black color }); sizeLabel.anchor.set(0.5, 0.5); sizeLabel.x = sizeSlider.x + 150; sizeLabel.y = sizeSlider.y - 95; // Moved up by 25 units sizeLabel.visible = false; game.addChild(sizeLabel); // Create eraser size slider var eraserSizeSlider = new Slider(20, 100, 50, 1801, 0x808080); // Gray color, width matches colorPanel width minus 80 units (1801) eraserSizeSlider.x = 2048 / 2 - 900; // Position at center of map, moved left by 900 units eraserSizeSlider.y = 2732 / 2 + 800; // Moved down to same position as star and heart slider eraserSizeSlider.visible = false; // Hidden by default game.addChild(eraserSizeSlider); // Add label for eraser size slider var eraserSizeLabel = new Text2("Eraser Size", { size: 80, fill: 0x000000 // Black color }); eraserSizeLabel.anchor.set(0.5, 0.5); eraserSizeLabel.x = eraserSizeSlider.x + 150; eraserSizeLabel.y = eraserSizeSlider.y - 95; // Moved up by 25 units eraserSizeLabel.visible = false; game.addChild(eraserSizeLabel); // Update sticker size when slider value changes sizeSlider.onValueChanged = function (value) { // Update sticker size for next sticker if (currentTool === 'star' || currentTool === 'heart') { currentStickerSize = value; } }; // Update eraser size when eraser slider value changes eraserSizeSlider.onValueChanged = function (value) { // Update eraser size for eraser tool currentEraserSize = value; // Update any active eraser visual if it exists if (currentTool === 'eraser' && game.eraser) { var eraserVisual = game.eraser.children[0]; eraserVisual.scaleX = value / 30; eraserVisual.scaleY = value / 30; } }; // Make label visible when slider is visible game.update = function () { // Update score display scoreText.setText("Eggs: " + LK.getScore()); // Update size label visibility to match slider sizeLabel.visible = sizeSlider.visible; // Update eraser size label visibility to match slider eraserSizeLabel.visible = eraserSizeSlider.visible; }; // Start background music LK.playMusic('easterMusic', { fade: { start: 0, end: 0.2, duration: 1000 } }); // Initialize first color button as selected with animation if (colorButtons.length > 0) { var _pulseSelectedButton = function pulseSelectedButton() { tween(selectedColorButton, { scaleX: 2.2, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(selectedColorButton, { scaleX: 1.8, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: _pulseSelectedButton }); } }); }; // Start the initial pulsing animation selectedColorButton = colorButtons[0]; // Start pulsing animation for first color button _pulseSelectedButton(); } // Add watermark to the game with forced persistence var watermark = new Watermark("@jzubora", 0.35); game.addChild(watermark); // This interval ensures the watermark always exists, regenerating it if removed LK.setInterval(function () { // Check if watermark still exists in the game var watermarkExists = false; for (var i = 0; i < game.children.length; i++) { if (game.children[i] === watermark) { watermarkExists = true; break; } } // If watermark doesn't exist, recreate it if (!watermarkExists) { watermark = new Watermark("@jzubora", 0.35); game.addChild(watermark); // Restart the flashing animation flashWatermark(); } }, 1000); // Check every second // Add flashing animation to watermark function flashWatermark() { // Flash watermark by alternating opacity tween(watermark, { alpha: 0.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(watermark, { alpha: 0.8 }, { duration: 800, easing: tween.easeInOut, onFinish: flashWatermark }); } }); } // Start watermark flashing animation flashWatermark();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BrushStroke = Container.expand(function (color, size) {
var self = Container.call(this);
var stroke = self.attachAsset('brushStroke', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size / 30,
scaleY: size / 30
});
stroke.tint = color;
return self;
});
var Button = Container.expand(function (label, color) {
var self = Container.call(this);
var background = self.attachAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5
});
var text = new Text2(label, {
size: 30,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
if (color !== undefined) {
background.tint = color;
}
self.down = function () {
tween(background, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.up = function () {
tween(background, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
return self;
});
var ColorButton = Container.expand(function (color) {
var self = Container.call(this);
var button = self.attachAsset('colorButton', {
anchorX: 0.5,
anchorY: 0.5
});
button.tint = color;
self.color = color;
self.down = function () {
tween(button, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
self.up = function () {
tween(button, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
return self;
});
var ColorPalette = Container.expand(function () {
var self = Container.call(this);
var background = LK.getAsset('colorPanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1881 / 1880,
// Set to exact size 1881
scaleY: 1899 / 277 // Set to exact size 1899
});
self.addChild(background);
var colorButtons = [];
// Generate 256 color gradient palette
var paletteColors = [];
var buttonSize = 90; // Increased from 30 to 90 (3x larger)
var spacing = 12; // Increased from 4 to 12 (3x larger)
var columns = 16;
var rows = 16;
// Generate rainbow gradient colors for the full 256 color palette
for (var i = 0; i < 256; i++) {
var hue = i / 256;
var r, g, b;
// Convert HSV to RGB (simplified rainbow gradient)
if (hue < 1 / 6) {
r = 1;
g = hue * 6;
b = 0;
} else if (hue < 2 / 6) {
r = (2 / 6 - hue) * 6;
g = 1;
b = 0;
} else if (hue < 3 / 6) {
r = 0;
g = 1;
b = (hue - 2 / 6) * 6;
} else if (hue < 4 / 6) {
r = 0;
g = (4 / 6 - hue) * 6;
b = 1;
} else if (hue < 5 / 6) {
r = (hue - 4 / 6) * 6;
b = 1;
g = 0;
} else {
r = 1;
g = 0;
b = (1 - hue) * 6;
}
// Convert to 0-255 range
var red = Math.floor(r * 255);
var green = Math.floor(g * 255);
var blue = Math.floor(b * 255);
var color = red << 16 | green << 8 | blue;
paletteColors.push(color);
}
for (var i = 0; i < paletteColors.length; i++) {
var row = Math.floor(i / columns);
var col = i % columns;
var colorBtn = new ColorButton(paletteColors[i]);
colorBtn.x = col * (buttonSize + spacing) - (columns - 1) * (buttonSize + spacing) / 2;
colorBtn.y = row * (buttonSize + spacing) - (rows - 1) * (buttonSize + spacing) / 2;
colorBtn.scaleX = 4.5; // Increased from 1.5 to 4.5 (3x larger)
colorBtn.scaleY = 4.5; // Increased from 1.5 to 4.5 (3x larger)
self.addChild(colorBtn);
// Create a closure to capture the current color
(function (color, btn) {
btn.down = function () {
currentColor = color;
self.visible = false;
// Notify the game that a color was selected
if (self.onColorSelected) {
self.onColorSelected(color);
}
};
})(paletteColors[i], colorBtn);
colorButtons.push(colorBtn);
}
// Add selector ring
var selector = LK.getAsset('brushStroke', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 7.5,
// Increased from 2.5 to 7.5 (3x larger)
scaleY: 7.5 // Increased from 2.5 to 7.5 (3x larger)
});
selector.tint = 0xFFFFFF;
selector.alpha = 0.7;
self.addChild(selector);
// Set selector initial position
selector.x = colorButtons[0].x;
selector.y = colorButtons[0].y;
// Hide palette initially
self.visible = false;
// Method to update selector position
self.updateSelector = function (color) {
for (var i = 0; i < paletteColors.length; i++) {
if (paletteColors[i] === color) {
selector.x = colorButtons[i].x;
selector.y = colorButtons[i].y;
break;
}
}
};
return self;
});
var CompletedEgg = Container.expand(function (baseColor) {
var self = Container.call(this);
var eggGraphic = self.attachAsset('completedEgg', {
anchorX: 0.5,
anchorY: 0.5
});
eggGraphic.tint = baseColor || 0xFFFFFF;
// Add some random decoration to make each egg look unique
for (var i = 0; i < 5; i++) {
var glitter = self.attachAsset('glitter', {
anchorX: 0.5,
anchorY: 0.5,
x: (Math.random() - 0.5) * 80,
y: (Math.random() - 0.5) * 120
});
glitter.tint = 0xFFD700 + Math.floor(Math.random() * 0x555555);
}
return self;
});
var EasterEgg = Container.expand(function () {
var self = Container.call(this);
var eggBase = self.attachAsset('eggBase', {
anchorX: 0.5,
anchorY: 0.5
});
var designContainer = new Container();
self.designContainer = designContainer; // Make accessible outside
self.addChild(designContainer);
self.addDesign = function (x, y, designElement) {
var localPosition = designContainer.toLocal({
x: x,
y: y
}, game);
// Check if the point is within the bounds of the eggBase
// Convert to egg's local coordinates for hit testing
var eggLocalPosition = self.toLocal({
x: x,
y: y
}, game);
// Calculate distance from center of egg
var dx = eggLocalPosition.x;
var dy = eggLocalPosition.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if point is inside the egg (ellipse)
// Using the egg's dimensions to determine the ellipse bounds
var eggWidth = eggBase.width / 2;
var eggHeight = eggBase.height / 2;
// Formula for point in ellipse: (x/a)² + (y/b)² <= 1
// where a is half-width and b is half-height
var isInEgg = dx * dx / (eggWidth * eggWidth) + dy * dy / (eggHeight * eggHeight) <= 1;
// Only add design if point is inside the egg
if (isInEgg) {
designElement.x = localPosition.x;
designElement.y = localPosition.y;
designContainer.addChild(designElement);
// Add to design history for undo functionality
designHistory.push({
element: designElement,
index: designContainer.children.length - 1
});
}
};
self.clearDesigns = function () {
while (designContainer.children.length > 0) {
designContainer.removeChild(designContainer.children[0]);
}
};
self.rotate = function (angle) {
eggBase.rotation += angle;
designContainer.rotation += angle;
};
self.captureDesign = function () {
// In a real implementation, this would create a snapshot of the egg
// For this simplified version, we just create a new completed egg with the same tint
var completedEgg = new CompletedEgg(eggBase.tint);
return completedEgg;
};
return self;
});
var Eraser = Container.expand(function (size) {
var self = Container.call(this);
// Create a visual representation of the eraser
var eraserVisual = self.attachAsset('brushStroke', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size / 30,
scaleY: size / 30
});
// Make it white with a border
eraserVisual.tint = 0xFFFFFF;
eraserVisual.alpha = 0.7;
return self;
});
var Slider = Container.expand(function (minVal, maxVal, defaultVal, width, color) {
var self = Container.call(this);
// Track properties
self.minValue = minVal || 0;
self.maxValue = maxVal || 100;
self.value = defaultVal || 50;
self.trackWidth = width || 300;
self.trackColor = color || 0xCCCCCC;
// Create track
var track = LK.getAsset('buttonBg', {
anchorX: 0,
anchorY: 0.5,
scaleX: self.trackWidth / 120,
scaleY: 0.3
});
track.tint = self.trackColor;
self.addChild(track);
self.track = track; // Store track reference for external access
// Create handle
var handle = LK.getAsset('colorButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
handle.tint = 0xFFFFFF;
handle.x = (self.value - self.minValue) / (self.maxValue - self.minValue) * self.trackWidth;
self.addChild(handle);
self.handle = handle;
// No value label is needed
// Method definitions
// Convert value to x position
self.getXForValue = function (val) {
return (val - self.minValue) / (self.maxValue - self.minValue) * self.trackWidth;
};
// Convert x position to value
self.getValueForX = function (x) {
return self.minValue + x / self.trackWidth * (self.maxValue - self.minValue);
};
// Update handle position
self.updateHandlePosition = function () {
handle.x = self.getXForValue(self.value);
};
// Set value
self.setValue = function (val) {
self.value = Math.max(self.minValue, Math.min(self.maxValue, val));
self.updateHandlePosition();
if (self.onValueChanged) {
self.onValueChanged(self.value);
}
};
// Handle drag
self.down = function (x, y) {
self.isDragging = true;
self.setValue(self.getValueForX(x));
};
self.move = function (x, y) {
if (self.isDragging) {
self.setValue(self.getValueForX(Math.max(0, Math.min(self.trackWidth, x))));
}
};
self.up = function () {
self.isDragging = false;
};
return self;
});
var Sticker = Container.expand(function (type, scale) {
var self = Container.call(this);
var stickerAsset;
if (type === 'star') {
stickerAsset = self.attachAsset('stickerStar', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: scale * 5,
scaleY: scale * 5
});
} else if (type === 'heart') {
stickerAsset = self.attachAsset('stickerHeart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: scale * 5,
scaleY: scale * 5
});
}
self.down = function () {
tween(stickerAsset, {
scaleX: scale * 5 * 0.9,
scaleY: scale * 5 * 0.9
}, {
duration: 100
});
};
self.up = function () {
tween(stickerAsset, {
scaleX: scale * 5,
scaleY: scale * 5
}, {
duration: 100
});
};
return self;
});
var Watermark = Container.expand(function (text, opacity) {
var self = Container.call(this);
// Set default values if not provided
self.text = text || "FRVR Easter";
self.opacity = opacity || 0.35;
// Create corner text elements
function createCornerText(x, y, rotation) {
var cornerText = new Text2(self.text, {
size: 28,
fill: 0x333333
});
cornerText.anchor.set(0.5, 0.5);
cornerText.x = x;
cornerText.y = y;
cornerText.rotation = rotation || 0;
cornerText.alpha = self.opacity;
self.addChild(cornerText);
return cornerText;
}
// Create text for each corner, avoiding top-left 100x100 area
self.topRight = createCornerText(2048 - 120, 120, Math.PI / 4);
self.bottomRight = createCornerText(2048 - 120, 2732 - 120, -Math.PI / 4);
self.bottomLeft = createCornerText(120, 2732 - 120, Math.PI / 4);
// Top left is placed with extra margin to avoid the platform menu icon
self.topLeft = createCornerText(180, 180, -Math.PI / 4);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xAFEEEE // Light turquoise background color
});
/****
* Game Code
****/
// Define color palette - arranged in rainbow gradient
var colors = [
// Black (left)
0x000000,
// Violet group
0x9400D3,
// Violet
0x4B0082,
// Indigo
0x8A2BE2,
// Blue Violet
// Blue group
0x0000FF,
// Blue
0x000080,
// Navy Blue
0x00FFFF,
// Cyan
0x008080,
// Teal
// Green group
0x00FF00,
// Green
0x32CD32,
// Lime Green
0x808000,
// Olive
// Red group
0x800000,
// Maroon
0xA52A2A,
// Brown
0xFF0000,
// Red
0xFF7F00,
// Orange
// Yellow group
0xFFD700,
// Gold
0xFFFF00,
// Yellow
// Pink group
0xFF69B4,
// Hot Pink
// Gray
0x808080,
// White (right)
0xFFFFFF];
// Define brush sizes
var brushSizes = [10, 20, 30];
// Initialize game variables
var currentColor = colors[0];
var currentBrushSize = brushSizes[1];
var currentEraserSize = 50;
var currentStickerSize = 1.2;
var currentTool = 'brush';
var previousTool = null;
var isPainting = false;
var lastX, lastY;
var selectedColorButton = null;
// Keep track of actions for undo functionality
var designHistory = [];
// Initialize empty savedEggs array
var savedEggs = [];
// Basket already created earlier
// Create main egg
var easterEgg = new EasterEgg();
easterEgg.x = 2048 / 2;
easterEgg.y = 2732 / 2 - 200;
game.addChild(easterEgg);
// Create UI components
// Tool panel
var toolPanel = LK.getAsset('toolPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 5,
y: 2732 - 100 // Moved up by 20 units
});
game.addChild(toolPanel);
// Color panel
var colorPanel = LK.getAsset('colorPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 - 345 // Moved down by 5 units
});
game.addChild(colorPanel);
// Add color buttons
var colorButtons = [];
for (var i = 0; i < colors.length; i++) {
var colorButton = new ColorButton(colors[i]);
// Position in two rows (10 in first row, 10 in second row)
if (i < 10) {
// First row
colorButton.x = i * 130 + 160; // Changed spacing from 145 to 130, moved left by 10 units
colorButton.y = 2732 - 410; // First row - moved up by 10 units
} else {
// Second row
colorButton.x = (i - 10) * 130 + 160; // Changed spacing from 145 to 130, moved left by 10 units
colorButton.y = 2732 - 280; // Second row
}
game.addChild(colorButton);
colorButtons.push(colorButton);
// Scale up by 2x
tween(colorButton, {
scaleX: 2,
scaleY: 2
}, {
duration: 300
});
// Add click handler
(function (color, button) {
colorButton.down = function () {
tween(colorButton, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 100
});
currentColor = color;
};
colorButton.up = function () {
tween(colorButton, {
scaleX: 2,
scaleY: 2
}, {
duration: 100
});
// Stop any animations on previously selected button
if (selectedColorButton) {
tween.stop(selectedColorButton);
tween(selectedColorButton, {
scaleX: 2,
scaleY: 2
}, {
duration: 100
});
}
// Set new selected button
selectedColorButton = button;
// Start pulsing animation
function pulseButton() {
tween(selectedColorButton, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(selectedColorButton, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulseButton
});
}
});
}
// Start the pulsing animation
pulseButton();
};
})(colors[i], colorButton);
}
// Create tool buttons
// Calculate button width including scale factor
var buttonWidth = 120 * 2; // 120px width * 2 scale
var buttonSpacing = 25; // 25 units apart
var startX = 300; // Starting X position
// Create tool buttons
var brushButton = new Button("Brush", 0x6495ED);
brushButton.x = startX - 75; // Moved left by 25 more units
brushButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(brushButton);
tween(brushButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
brushButton.down = function () {
tween(brushButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
brushButton.up = function () {
tween(brushButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Hide any previous tool's sliders first
sizeSlider.visible = false;
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Store previous tool and set current tool to brush
previousTool = currentTool;
currentTool = 'brush';
// Stop any animations on buttons
tween.stop(brushButton);
tween.stop(stickerStarButton);
tween.stop(stickerHeartButton);
tween.stop(eraserButton);
tween.stop(rotateLeftButton);
tween.stop(rotateRightButton);
tween.stop(saveButton);
tween.stop(clearButton);
// Reset all buttons to normal size
tween(stickerStarButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerHeartButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(saveButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Start pulsing animation for brush button
function pulseBrushButton() {
tween(brushButton, {
scaleX: 2.4,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(brushButton, {
scaleX: 2.0,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulseBrushButton
});
}
});
}
// Start the pulsing animation
pulseBrushButton();
};
var stickerStarButton = new Button("Star", 0xFFD700);
stickerStarButton.x = startX + (buttonWidth + buttonSpacing) * 1 - 75; // Moved left by 25 more units
stickerStarButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(stickerStarButton);
// Set background to gold color
stickerStarButton.children[0].tint = 0xFFD700; // Gold color
tween(stickerStarButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
stickerStarButton.down = function () {
tween(stickerStarButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
stickerStarButton.up = function () {
tween(stickerStarButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Store previous tool and set current tool to star
previousTool = currentTool;
currentTool = 'star';
// First hide any previously visible sliders
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Show size slider for star (not toggle)
sizeSlider.visible = true;
// Update slider track color to black
sizeSlider.trackColor = 0x000000; // Black color
sizeSlider.track.tint = 0x000000;
// Stop any animations on buttons
tween.stop(brushButton);
tween.stop(stickerStarButton);
tween.stop(stickerHeartButton);
tween.stop(eraserButton);
tween.stop(rotateLeftButton);
tween.stop(rotateRightButton);
tween.stop(saveButton);
tween.stop(clearButton);
// Reset all buttons to normal size
tween(brushButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerHeartButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(saveButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Start pulsing animation for star button
function pulseStarButton() {
tween(stickerStarButton, {
scaleX: 2.4,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(stickerStarButton, {
scaleX: 2.0,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulseStarButton
});
}
});
}
// Start the pulsing animation
pulseStarButton();
};
var stickerHeartButton = new Button("Heart", 0xFF0000);
stickerHeartButton.x = startX + (buttonWidth + buttonSpacing) * 2 - 75; // Moved left by 25 more units
stickerHeartButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(stickerHeartButton);
tween(stickerHeartButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
stickerHeartButton.down = function () {
tween(stickerHeartButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
stickerHeartButton.up = function () {
tween(stickerHeartButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Store previous tool and set current tool to heart
previousTool = currentTool;
currentTool = 'heart';
// First hide any previously visible sliders
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Show size slider for heart (not toggle)
sizeSlider.visible = true;
// Update slider track color to black
sizeSlider.trackColor = 0x000000; // Black color
sizeSlider.track.tint = 0x000000;
// Keep handle white for better visibility
// Stop any animations on buttons
tween.stop(brushButton);
tween.stop(stickerStarButton);
tween.stop(stickerHeartButton);
tween.stop(eraserButton);
tween.stop(rotateLeftButton);
tween.stop(rotateRightButton);
tween.stop(saveButton);
tween.stop(clearButton);
// Reset all buttons to normal size
tween(brushButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerStarButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(saveButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Start pulsing animation for heart button
function pulseHeartButton() {
tween(stickerHeartButton, {
scaleX: 2.4,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(stickerHeartButton, {
scaleX: 2.0,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulseHeartButton
});
}
});
}
// Start the pulsing animation
pulseHeartButton();
};
var rotateLeftButton = new Button("< Rotate", 0x9370DB);
rotateLeftButton.x = startX + (buttonWidth + buttonSpacing) * 3 - 75; // Moved left by 25 more units
rotateLeftButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(rotateLeftButton);
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
rotateLeftButton.down = function () {
tween(rotateLeftButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
rotateLeftButton.up = function () {
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Hide any open sliders
sizeSlider.visible = false;
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Store previous tool before rotation
previousTool = currentTool;
easterEgg.rotate(-Math.PI / 8);
};
// Add a thin grey vertical divider between rotate buttons
var divider = LK.getAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
x: startX + (buttonWidth + buttonSpacing) * 3.5 - 75,
// Position between the two rotate buttons
y: 2732 - 100,
// Same Y as buttons
scaleX: 0.05,
// Make it thin
scaleY: 2 // Same height as buttons
});
divider.tint = 0xe6e6fa; // Light lavender color
game.addChild(divider);
var rotateRightButton = new Button("Rotate >", 0x9370DB);
rotateRightButton.x = startX + (buttonWidth + buttonSpacing) * 4 - 75; // Moved left by 25 more units
rotateRightButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(rotateRightButton);
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
rotateRightButton.down = function () {
tween(rotateRightButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
rotateRightButton.up = function () {
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Hide any open sliders
sizeSlider.visible = false;
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Store previous tool before rotation
previousTool = currentTool;
easterEgg.rotate(Math.PI / 8);
};
var saveButton = new Button("Undo", 0x8B4513);
saveButton.x = startX + (buttonWidth + buttonSpacing) * 5 - 75; // Moved left by 25 more units
saveButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(saveButton);
tween(saveButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
saveButton.down = function () {
tween(saveButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
// Start continuous undo functionality
var performUndo = function performUndo() {
if (designHistory.length > 0) {
var lastDesign = designHistory.pop();
// Handle clear operation undo (restore all elements that were cleared)
if (lastDesign.clearOperation) {
// First clear any current elements to avoid duplicates
easterEgg.clearDesigns();
// Add back all elements that were cleared
for (var i = 0; i < lastDesign.elements.length; i++) {
easterEgg.designContainer.addChild(lastDesign.elements[i]);
}
LK.getSound('saveSound').play();
}
// Handle erased element undo (add back erased element)
else if (lastDesign.erased) {
easterEgg.designContainer.addChildAt(lastDesign.element, lastDesign.index);
LK.getSound('saveSound').play();
}
// Handle regular element undo (remove added element)
else if (easterEgg.designContainer && easterEgg.designContainer.children.length > 0) {
// Check if the element is still at the expected index
if (easterEgg.designContainer.children[lastDesign.index] === lastDesign.element) {
easterEgg.designContainer.removeChild(lastDesign.element);
} else {
// If not at expected index, find and remove it by reference
for (var i = 0; i < easterEgg.designContainer.children.length; i++) {
if (easterEgg.designContainer.children[i] === lastDesign.element) {
easterEgg.designContainer.removeChild(lastDesign.element);
break;
}
}
}
LK.getSound('saveSound').play();
}
}
};
// Perform first undo immediately
performUndo();
// Setup interval for continuous undo while button is pressed
saveButton.undoInterval = LK.setInterval(function () {
performUndo();
}, 150); // Undo every 150ms while pressed (2x faster)
};
saveButton.up = function () {
tween(saveButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Hide any previous tool's sliders first
sizeSlider.visible = false;
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Stop continuous undo when releasing the button
if (saveButton.undoInterval) {
LK.clearInterval(saveButton.undoInterval);
saveButton.undoInterval = null;
}
// Deactivate previous tool and activate save tool
if (currentTool !== 'save') {
var _pulseSaveButton = function pulseSaveButton() {
tween(saveButton, {
scaleX: 2.4,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(saveButton, {
scaleX: 2.0,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _pulseSaveButton
});
}
});
}; // Start the pulsing animation
// Stop any animations on buttons
tween.stop(brushButton);
tween.stop(stickerStarButton);
tween.stop(stickerHeartButton);
tween.stop(eraserButton);
tween.stop(rotateLeftButton);
tween.stop(rotateRightButton);
tween.stop(saveButton);
tween.stop(clearButton);
// Reset all buttons to normal size
tween(brushButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerStarButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerHeartButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Store previous tool and set current tool to save
previousTool = currentTool;
currentTool = 'save';
// Start pulsing animation for save button
_pulseSaveButton();
}
};
var eraserButton = new Button("Eraser", 0x808080);
eraserButton.x = colorPanel.x + colorPanel.width / 2 - 145; // Moved right by 100 units
eraserButton.y = colorPanel.y - colorPanel.height / 2 + 139; // Moved down to match all colors button
game.addChild(eraserButton);
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 300
});
eraserButton.down = function () {
tween(eraserButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
eraserButton.up = function () {
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
// Toggle eraser mode
if (currentTool === 'eraser') {
var _pulseBrushButton = function pulseBrushButton() {
tween(brushButton, {
scaleX: 2.4,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(brushButton, {
scaleX: 2.0,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _pulseBrushButton
});
}
});
};
// Store previous tool and switch back to brush
previousTool = currentTool;
currentTool = 'brush';
// Stop animation on eraser button
tween.stop(eraserButton);
tween(eraserButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
// Hide eraser size slider
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Start pulsing animation for brush button
_pulseBrushButton();
} else {
var _pulseEraserButton = function pulseEraserButton() {
tween(eraserButton, {
scaleX: 2.4,
scaleY: 3.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(eraserButton, {
scaleX: 2.0,
scaleY: 2.9
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _pulseEraserButton
});
}
});
};
// Store previous tool and switch to eraser mode
previousTool = currentTool;
currentTool = 'eraser';
// Stop animations on all other buttons
tween.stop(brushButton);
tween.stop(stickerStarButton);
tween.stop(stickerHeartButton);
tween.stop(rotateLeftButton);
tween.stop(rotateRightButton);
tween.stop(clearButton);
// Reset all buttons to normal size
tween(brushButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerStarButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(stickerHeartButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(rotateLeftButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(rotateRightButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// First hide any previously visible sliders
sizeSlider.visible = false;
// Show eraser size slider
eraserSizeSlider.visible = true;
eraserSizeLabel.visible = true;
// Start pulsing animation for eraser button
_pulseEraserButton();
}
};
// Add color palette button
var allColorButton = new Button("All Colors", 0x9370DB);
allColorButton.x = colorPanel.x + colorPanel.width / 2 - 415; // Position it - moved left by 100 units (from -315 to -415)
allColorButton.y = colorPanel.y - colorPanel.height / 2 + 139; // Moved down by 4 units (from 135 to 139)
game.addChild(allColorButton);
tween(allColorButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 300
});
// Apply rainbow gradient to all colors button
var btnBackground = allColorButton.children[0];
var rainbowColors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
var colorIndex = 0;
var duration = 3000; // 3 seconds for full rainbow cycle
// Function to cycle through rainbow colors
function cycleRainbowColors() {
tween(btnBackground, {
tint: rainbowColors[colorIndex]
}, {
duration: duration / rainbowColors.length,
onFinish: function onFinish() {
colorIndex = (colorIndex + 1) % rainbowColors.length;
cycleRainbowColors();
}
});
}
// Start the rainbow cycle
cycleRainbowColors();
allColorButton.down = function () {
tween(allColorButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
allColorButton.up = function () {
// Reset to normal size first
tween(allColorButton, {
scaleX: 2.2,
scaleY: 3.1
}, {
duration: 100
});
// Toggle the full color palette
colorPalette.visible = !colorPalette.visible;
// Update selector position to match current selected color
if (colorPalette.visible) {
colorPalette.updateSelector(currentColor);
}
};
var clearButton = new Button("Clear", 0x444444);
clearButton.x = startX + (buttonWidth + buttonSpacing) * 6 - 75; // Moved next to save button
clearButton.y = 2732 - 100; // Moved up by 20 units
game.addChild(clearButton);
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 300
});
clearButton.down = function () {
tween(clearButton, {
scaleX: 1.98,
scaleY: 1.8
}, {
duration: 100
});
};
clearButton.up = function () {
tween(clearButton, {
scaleX: 2.2,
scaleY: 2
}, {
duration: 100
});
// Hide any open sliders
sizeSlider.visible = false;
eraserSizeSlider.visible = false;
eraserSizeLabel.visible = false;
// Store previous tool before clearing
previousTool = currentTool;
// Save the current design state for potential undo
if (easterEgg.designContainer && easterEgg.designContainer.children.length > 0) {
// Create a special history entry for the clear operation
designHistory.push({
clearOperation: true,
elements: easterEgg.designContainer.children.slice() // Make a copy of all elements
});
}
easterEgg.clearDesigns();
LK.getSound('clearSound').play();
};
// Function to toggle eraser tool
function toggleEraserThicknessSlider(visible) {
// Set eraser as current tool when enabled
if (visible) {
currentTool = 'eraser';
}
}
// Create basket display
var basket = LK.getAsset('basket', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 - 800 // Moved up by 60 units to make room for two rows of color buttons
});
game.addChildAt(basket, 0); // Add at index 0 to ensure it's behind the egg
// Bring the easterEgg to the front to ensure proper display order
game.removeChild(easterEgg);
game.addChild(easterEgg);
// Title text
var titleText = new Text2("Easter Egg Artist", {
size: 100,
fill: 0x8B4513 // Dark brown
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 50;
game.addChild(titleText);
// Score display - hidden but kept in code for reference
var scoreText = new Text2("Eggs: 0", {
size: 60,
fill: 0x4B0082 // Indigo
});
scoreText.anchor.set(0, 0);
scoreText.x = 120;
scoreText.y = 120;
scoreText.visible = false; // Hide the score text
// Function to display saved eggs (placeholder for new implementation)
function displaySavedEggs() {
// Remove any existing displayed eggs
for (var i = game.children.length - 1; i >= 0; i--) {
if (game.children[i].isCompletedEgg) {
game.removeChild(game.children[i]);
}
}
// Display saved eggs (will be reimplemented)
for (var i = 0; i < savedEggs.length; i++) {
var eggData = savedEggs[i];
var displayedEgg = new CompletedEgg(eggData.color);
displayedEgg.x = eggData.x;
displayedEgg.y = eggData.y;
displayedEgg.isCompletedEgg = true;
game.addChild(displayedEgg);
}
}
// Display any saved eggs
displaySavedEggs();
// Game event handlers
game.down = function (x, y) {
if (y < 2732 - 350) {
isPainting = true;
lastX = x;
lastY = y;
if (currentTool === 'brush') {
var brushStroke = new BrushStroke(currentColor, currentBrushSize);
easterEgg.addDesign(x, y, brushStroke);
LK.getSound('brushSound').play();
} else if (currentTool === 'star' || currentTool === 'heart') {
var size = currentStickerSize;
var sticker = new Sticker(currentTool, size);
easterEgg.addDesign(x, y, sticker);
LK.getSound('stickerSound').play();
} else if (currentTool === 'eraser') {
// Create a visual eraser element but don't actually add it to the design
var eraser = new Eraser(eraserSizeSlider.value);
// Store reference to enable updating size from slider
game.eraser = eraser;
// Convert to egg's local coordinates for hit testing
var eggLocalPosition = easterEgg.toLocal({
x: x,
y: y
}, game);
// Check if point is inside egg boundary
var eggBase = easterEgg.children[0]; // The eggBase is the first child
var eggWidth = eggBase.width / 2;
var eggHeight = eggBase.height / 2;
var dx = eggLocalPosition.x;
var dy = eggLocalPosition.y;
var isInEgg = dx * dx / (eggWidth * eggWidth) + dy * dy / (eggHeight * eggHeight) <= 1;
if (isInEgg && easterEgg.designContainer && easterEgg.designContainer.children.length > 0) {
// Find and remove elements near the eraser position
for (var i = easterEgg.designContainer.children.length - 1; i >= 0; i--) {
var element = easterEgg.designContainer.children[i];
var distance = Math.sqrt(Math.pow(element.x - eggLocalPosition.x, 2) + Math.pow(element.y - eggLocalPosition.y, 2));
// If element is within eraser size, remove it
if (distance < eraserSizeSlider.value / 2) {
// Save the removed element to history for potential undo
designHistory.push({
element: element,
index: i,
erased: true // Mark as erased rather than added
});
easterEgg.designContainer.removeChild(element);
LK.getSound('brushSound').play();
break; // Remove one element at a time for better control
}
}
}
}
}
};
game.move = function (x, y) {
if (isPainting && (currentTool === 'brush' || currentTool === 'eraser')) {
// Calculate distance between last point and current point
var dx = x - lastX;
var dy = y - lastY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Get current size based on tool
var currentSize = currentTool === 'brush' ? currentBrushSize : currentEraserSize;
// Get current color based on tool
var strokeColor = currentTool === 'brush' ? currentColor : 0xFFFFFF;
// Play brush sound occasionally while using eraser
if (currentTool === 'eraser' && Math.random() < 0.05) {
LK.getSound('brushSound').play();
}
// If distance is greater than half the size, add intermediate points
if (distance > currentSize / 2) {
var steps = Math.ceil(distance / (currentSize / 2));
for (var i = 1; i <= steps; i++) {
var pointX = lastX + dx * i / steps;
var pointY = lastY + dy * i / steps;
if (currentTool === 'eraser') {
// Calculate egg local position for eraser
var eggLocalPosition = easterEgg.toLocal({
x: pointX,
y: pointY
}, game);
// Check if point is inside egg boundary
var eggBase = easterEgg.children[0];
var eggWidth = eggBase.width / 2;
var eggHeight = eggBase.height / 2;
var localDx = eggLocalPosition.x;
var localDy = eggLocalPosition.y;
var isInEgg = localDx * localDx / (eggWidth * eggWidth) + localDy * localDy / (eggHeight * eggHeight) <= 1;
if (isInEgg && easterEgg.designContainer && easterEgg.designContainer.children.length > 0) {
// Find and remove elements near the eraser position
for (var j = easterEgg.designContainer.children.length - 1; j >= 0; j--) {
var element = easterEgg.designContainer.children[j];
var eraseDist = Math.sqrt(Math.pow(element.x - eggLocalPosition.x, 2) + Math.pow(element.y - eggLocalPosition.y, 2));
// If element is within eraser size, remove it
if (eraseDist < eraserSizeSlider.value / 2) {
// Save the removed element to history for potential undo
designHistory.push({
element: element,
index: j,
erased: true // Mark as erased rather than added
});
easterEgg.designContainer.removeChild(element);
break; // Remove one element at a time for better control
}
}
}
} else {
var stroke = new BrushStroke(strokeColor, currentSize);
easterEgg.addDesign(pointX, pointY, stroke);
}
}
} else {
if (currentTool === 'eraser') {
// Calculate egg local position for eraser
var eggLocalPosition = easterEgg.toLocal({
x: x,
y: y
}, game);
// Check if point is inside egg boundary
var eggBase = easterEgg.children[0];
var eggWidth = eggBase.width / 2;
var eggHeight = eggBase.height / 2;
var localDx = eggLocalPosition.x;
var localDy = eggLocalPosition.y;
var isInEgg = localDx * localDx / (eggWidth * eggWidth) + localDy * localDy / (eggHeight * eggHeight) <= 1;
if (isInEgg && easterEgg.designContainer && easterEgg.designContainer.children.length > 0) {
// Find and remove elements near the eraser position
for (var j = easterEgg.designContainer.children.length - 1; j >= 0; j--) {
var element = easterEgg.designContainer.children[j];
var eraseDist = Math.sqrt(Math.pow(element.x - eggLocalPosition.x, 2) + Math.pow(element.y - eggLocalPosition.y, 2));
// If element is within eraser size, remove it
if (eraseDist < eraserSizeSlider.value / 2) {
// Save the removed element to history for potential undo
designHistory.push({
element: element,
index: j,
erased: true // Mark as erased rather than added
});
easterEgg.designContainer.removeChild(element);
break; // Remove one element at a time for better control
}
}
}
} else {
var stroke = new BrushStroke(strokeColor, currentSize);
easterEgg.addDesign(x, y, stroke);
}
}
lastX = x;
lastY = y;
}
};
game.up = function () {
isPainting = false;
};
// Update function
game.update = function () {
// Update score display
scoreText.setText("Eggs: " + LK.getScore());
};
// Create and add the full color palette
var colorPalette = new ColorPalette();
colorPalette.x = 2048 / 2;
colorPalette.y = 2732 / 2 - 150; // Position at center, aligned with the egg, moved down by 50 units
game.addChild(colorPalette);
// Set up color selection callback
colorPalette.onColorSelected = function (color) {
currentColor = color;
// Stop any animations on previously selected button
if (selectedColorButton) {
tween.stop(selectedColorButton);
tween(selectedColorButton, {
scaleX: 2,
scaleY: 2
}, {
duration: 100
});
}
// Find button with matching color and set as selected
var _loop = function _loop() {
if (colorButtons[i].color === color) {
var _pulseSelectedButton2 = function pulseSelectedButton() {
tween(selectedColorButton, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(selectedColorButton, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _pulseSelectedButton2
});
}
});
}; // Start the pulsing animation
selectedColorButton = colorButtons[i];
// Start pulsing animation
_pulseSelectedButton2();
return 1; // break
}
};
for (var i = 0; i < colorButtons.length; i++) {
if (_loop()) {
break;
}
}
};
// Create size slider for star stickers
var sizeSlider = new Slider(0.5, 3, 1.2, 1801, 0xFFD700); // Gold color, width matches colorPanel width minus 80 units (1801)
sizeSlider.x = 2048 / 2 - 900; // Position at center of map, moved left by 900 units
sizeSlider.y = 2732 / 2 + 800; // Moved down by 800 units
sizeSlider.visible = false; // Hidden by default
game.addChild(sizeSlider);
// Add label above slider
var sizeLabel = new Text2("Sticker Size", {
size: 80,
fill: 0x000000 // Black color
});
sizeLabel.anchor.set(0.5, 0.5);
sizeLabel.x = sizeSlider.x + 150;
sizeLabel.y = sizeSlider.y - 95; // Moved up by 25 units
sizeLabel.visible = false;
game.addChild(sizeLabel);
// Create eraser size slider
var eraserSizeSlider = new Slider(20, 100, 50, 1801, 0x808080); // Gray color, width matches colorPanel width minus 80 units (1801)
eraserSizeSlider.x = 2048 / 2 - 900; // Position at center of map, moved left by 900 units
eraserSizeSlider.y = 2732 / 2 + 800; // Moved down to same position as star and heart slider
eraserSizeSlider.visible = false; // Hidden by default
game.addChild(eraserSizeSlider);
// Add label for eraser size slider
var eraserSizeLabel = new Text2("Eraser Size", {
size: 80,
fill: 0x000000 // Black color
});
eraserSizeLabel.anchor.set(0.5, 0.5);
eraserSizeLabel.x = eraserSizeSlider.x + 150;
eraserSizeLabel.y = eraserSizeSlider.y - 95; // Moved up by 25 units
eraserSizeLabel.visible = false;
game.addChild(eraserSizeLabel);
// Update sticker size when slider value changes
sizeSlider.onValueChanged = function (value) {
// Update sticker size for next sticker
if (currentTool === 'star' || currentTool === 'heart') {
currentStickerSize = value;
}
};
// Update eraser size when eraser slider value changes
eraserSizeSlider.onValueChanged = function (value) {
// Update eraser size for eraser tool
currentEraserSize = value;
// Update any active eraser visual if it exists
if (currentTool === 'eraser' && game.eraser) {
var eraserVisual = game.eraser.children[0];
eraserVisual.scaleX = value / 30;
eraserVisual.scaleY = value / 30;
}
};
// Make label visible when slider is visible
game.update = function () {
// Update score display
scoreText.setText("Eggs: " + LK.getScore());
// Update size label visibility to match slider
sizeLabel.visible = sizeSlider.visible;
// Update eraser size label visibility to match slider
eraserSizeLabel.visible = eraserSizeSlider.visible;
};
// Start background music
LK.playMusic('easterMusic', {
fade: {
start: 0,
end: 0.2,
duration: 1000
}
});
// Initialize first color button as selected with animation
if (colorButtons.length > 0) {
var _pulseSelectedButton = function pulseSelectedButton() {
tween(selectedColorButton, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(selectedColorButton, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: _pulseSelectedButton
});
}
});
}; // Start the initial pulsing animation
selectedColorButton = colorButtons[0];
// Start pulsing animation for first color button
_pulseSelectedButton();
}
// Add watermark to the game with forced persistence
var watermark = new Watermark("@jzubora", 0.35);
game.addChild(watermark);
// This interval ensures the watermark always exists, regenerating it if removed
LK.setInterval(function () {
// Check if watermark still exists in the game
var watermarkExists = false;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] === watermark) {
watermarkExists = true;
break;
}
}
// If watermark doesn't exist, recreate it
if (!watermarkExists) {
watermark = new Watermark("@jzubora", 0.35);
game.addChild(watermark);
// Restart the flashing animation
flashWatermark();
}
}, 1000); // Check every second
// Add flashing animation to watermark
function flashWatermark() {
// Flash watermark by alternating opacity
tween(watermark, {
alpha: 0.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(watermark, {
alpha: 0.8
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashWatermark
});
}
});
}
// Start watermark flashing animation
flashWatermark();