User prompt
in the matching particle effect, make the gravity influence the particles movement
User prompt
Please fix the bug: 'Uncaught ReferenceError: gravity is not defined' in or related to this line: 'particle.y += gravity;' Line Number: 1360
Code edit (10 edits merged)
Please save this source code
User prompt
The particle effect on matching gems, give some of the particles a gravity effect
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: undefined is not an object (evaluating 'self.y = gemToRemove.y')' in or related to this line: 'self.y = gemToRemove.y; // Random y position within game bounds' Line Number: 1714
User prompt
Please fix the bug: 'Timeout.tick error: undefined is not an object (evaluating 'self.y = gemToRemove.y')' in or related to this line: 'self.y = gemToRemove.y; // Random y position within game bounds' Line Number: 1713
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: Can't find variable: dragonGraphics' in or related to this line: 'dragonGraphics.scale.x *= -1; // Flip the dragon image on the horizontal axis if it comes from the right' Line Number: 1711
User prompt
Please fix the bug: 'Timeout.tick error: undefined is not an object (evaluating 'this.scale.x')' in or related to this line: 'this.scale.x *= -1; // Flip the dragon image on the horizontal axis if it comes from the right' Line Number: 1711
User prompt
Please fix the bug: 'Timeout.tick error: Can't find variable: dragonGraphics' in or related to this line: 'dragonGraphics.scale.x *= -1; // Flip the dragon image on the horizontal axis if it comes from the right' Line Number: 1711
User prompt
Please fix the bug: 'Timeout.tick error: dragon.flip is not a function. (In 'dragon.flip()', 'dragon.flip' is undefined)' in or related to this line: 'dragon.flip(); // Flip the dragon image if it comes from the right' Line Number: 1711
User prompt
Sometimes Dragon comes from the other side and it’s image is left on the horizontal axis
Code edit (1 edits merged)
Please save this source code
/**** * Classes ****/ // Board class var Board = Container.expand(function () { var self = Container.call(this); // Function to shuffle gems around randomly Board.prototype.shuffleGems = function () { console.log("shuffleGems"); self.isShuffling = true; // Removed usage of Set for compatibility for (var i = this.gems.length - 1; i > 0; i--) { this.gems[i].newPosition = false; } for (var i = this.gems.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); // Swap the gems var tempNewPosition = this.gems[i].newPosition || { x: this.gems[i].x, y: this.gems[i].y }; this.gems[i].newPosition = this.gems[j].newPosition || { x: this.gems[j].x, y: this.gems[j].y }; this.gems[j].newPosition = tempNewPosition; } // The rest of your method remains unchanged function animateGemToPosition(gem, x, y) { var animationDuration = 1000; // Duration of the animation in milliseconds var startX = gem.x; var startY = gem.y; var deltaX = x - startX; var deltaY = y - startY; var startTime = Date.now(); var animate = function animate() { var now = Date.now(); var progress = Math.min(1, (now - startTime) / animationDuration); gem.x = startX + deltaX * progress; gem.y = startY + deltaY * progress; if (progress < 1) { LK.setTimeout(animate, 16); // Aim for roughly 60fps } else { gem.x = x; gem.y = y; self.isShuffling = false; } }; LK.setTimeout(animate, 16); } // Update the positions of the shuffled gems and ensure they have the correct new position in the gems array var newGemsArray = new Array(this.gems.length); this.gems.forEach(function (gem, index) { if (gem.newPosition) { var newPositionIndex = this.gems.findIndex(function (g) { return g.x === gem.newPosition.x && g.y === gem.newPosition.y; }); var aNewPosition = this.snapToGrid(gem.newPosition.x, gem.newPosition.y); animateGemToPosition(gem, aNewPosition.x, aNewPosition.y); newGemsArray[newPositionIndex] = gem; } }.bind(this)); this.gems = newGemsArray.filter(function (g) { return g !== undefined; }); LK.setTimeout(self.checkForMatches, 1000); }; // Method to round or snap any position to the nearest position in the grid made by the 6x8 gems this.snapToGrid = function (x, y) { // Ensure there is at least one gem in the array before accessing its properties var margin = 10; var boardWidth = game.width * .9; var boardHeight = game.height * .9; var gemsPerRow = 6; var gemsPerColumn = 8; var totalMarginWidth = margin * (gemsPerRow + 1); var totalMarginHeight = margin * (gemsPerColumn + 1); var availableWidth = boardWidth - totalMarginWidth; var availableHeight = boardHeight - totalMarginHeight; var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn); var xOffset = (game.width - boardWidth) / 2 + scaledGemSize / 2; var yOffset = (game.height - boardHeight) / 2 + scaledGemSize / 2 + 80; var columnWidth = (boardWidth - margin) / 6; var rowHeight = (boardHeight - margin) / 8; var snappedX = Math.round((x - xOffset) / columnWidth) * columnWidth + xOffset; var snappedY = Math.round((y - yOffset) / rowHeight) * rowHeight + yOffset; return { x: snappedX, y: snappedY }; }; // Method to show a hint for a possible match this.showHint = function () { console.log('showHint function started'); var possibleMatches = this.checkIfAnyMoveCausesMatch(); if (possibleMatches.length > 0) { var animateMove = function animateMove(repeatCount) { if (move.gem.isUsed) { // Start fade-out effect for hint overlay var fadeOutDuration = 500; // Fade out over 500ms var startTime = Date.now(); var fadeStep = function fadeStep() { var currentTime = Date.now(); var progress = (currentTime - startTime) / fadeOutDuration; hintOverlay.alpha = 1 - progress; // Fade out effect if (progress < 1) { LK.setTimeout(fadeStep, 16); // Continue fading } else { hintOverlay.destroy(); // Destroy after faded out } }; fadeStep(); return; } var totalDuration = 1000; // Half a second for each back and forth movement var repeatLimit = 1; // Repeat the animation three times var animationCount = 0; var startTime = Date.now(); var animateStep = function animateStep() { if (move.gem.isUsed || !hintOverlay) { if (hintOverlay) { hintOverlay.destroy(); } return; } var currentTime = Date.now(); var progress = (currentTime - startTime) / totalDuration; var waveProgress = (Math.sin(progress * Math.PI * 2) + 1) / 2; // Adjusted to ensure it never goes below zero hintOverlay.x = move.gemStartPosition.x + moveDirection.dx * moveDistance * waveProgress; hintOverlay.y = move.gemStartPosition.y + moveDirection.dy * moveDistance * waveProgress; if (progress >= 1) { animationCount++; if (animationCount < repeatLimit) { startTime = Date.now(); // Reset start time for the next cycle animateStep(); // Continue animation } else { hintOverlay.destroy(); } } else { LK.setTimeout(animateStep, 16); // Continue animation } }; animateStep(); }; console.log('Possible matches:', possibleMatches); var move = possibleMatches[0]; var hintOverlay = LK.getAsset('hintOverlay', {}); self.lastHintOverlay = hintOverlay; hintOverlay.anchor.set(0, 0); self.addChild(hintOverlay); hintOverlay.x = move.gem.x; hintOverlay.y = move.gem.y; move.gemStartPosition = { x: move.gem.x, y: move.gem.y }; // Track starting position for animation var moveDirection = move.move; var moveDistance = move.gem.spacing; // Distance to move back and forth var moveDuration = 500; // Duration of each move animateMove(); } else { console.log("no possible matches"); if (!self.fillingEmptySpaces && !self.gemsFalling && !self.isShuffling && !isDragoning) { triggerDragon(); } } }; // Method to find possible matches on the board // Method to find possible matches on the board // Method to find possible matches on the board this.findPossibleMatches = function () { var matches = []; var width = 6; // Board width var height = 8; // Board height for (var i = 0; i < height; i++) { for (var j = 0; j < width; j++) { var currentGem = this.gems[i * width + j]; // Check right and down for potential matches var directions = [{ dx: 1, dy: 0 }, // Right { dx: 0, dy: 1 } // Down ]; directions.forEach(function (dir) { var match = [currentGem]; for (var k = 1; k < 3; k++) { var nextGemX = j + dir.dx * k; var nextGemY = i + dir.dy * k; if (nextGemX < width && nextGemY < height) { var nextGem = this.gems[nextGemY * width + nextGemX]; if (nextGem && currentGem && nextGem.color === currentGem.color) { match.push(nextGem); } else { break; } } } if (match.length >= 3) { // Allows for matches longer than 3 matches.push(match); } }, this); } } return matches; }; // Method to check if moving any gem results in a match this.checkIfAnyMoveCausesMatch = function () { var matches = []; var width = 6; // Board width var height = 8; // Board height // Simulate moving each gem in all four directions and check for matches for (var i = 0; i < height; i++) { for (var j = 0; j < width; j++) { var currentGem = this.gems[i * width + j]; if (!currentGem) { continue; } // Possible moves: up, down, left, right var moves = [{ dx: -1, dy: 0 }, { dx: 1, dy: 0 }, { dx: 0, dy: -1 }, { dx: 0, dy: 1 }]; moves.forEach(function (move) { var newX = j + move.dx; var newY = i + move.dy; // Check if the new position is within the board if (newX >= 0 && newX < width && newY >= 0 && newY < height) { var targetGem = this.findGemByPosition(currentGem.x + currentGem.spacing * move.dx, currentGem.y + currentGem.spacing * move.dy); if (targetGem && this.wouldSwapResultInMatch(currentGem, targetGem)) { matches.push({ gem: currentGem, move: move }); } } }, this); } } return matches; }; // Check if swapping two gems would result in a match this.wouldSwapResultInMatch = function (gemA, gemB) { var gemAIndex = this.gems.indexOf(gemA); var gemBIndex = this.gems.indexOf(gemB); this.gems[gemAIndex] = gemB; this.gems[gemBIndex] = gemA; // Check for matches var matchFound = false; var matchedGems = []; // Check for horizontal matches for (var i = 0; i < 8; i++) { for (var j = 0; j < 6; j++) { // Adjust to allow checks across all columns var gem1 = this.gems[i * 6 + j]; var nowMatchingGems = []; for (var k = j; k < 6; k++) { var nextGem = this.gems[i * 6 + k]; if (nextGem && nextGem.color === gem1.color) { nowMatchingGems.push(nextGem); } else { break; } } if (nowMatchingGems.length >= 3) { matchFound = true; matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) { return matchedGems.indexOf(gem) === -1; })); } } } // Check for vertical matches for (var i = 0; i < 6; i++) { for (var j = 0; j < 8; j++) { // Adjust to allow checks across all rows var gem1 = this.gems[j * 6 + i]; var nowMatchingGems = []; for (var k = j; k < 8; k++) { var nextGem = this.gems[k * 6 + i]; if (nextGem && nextGem.color === gem1.color) { nowMatchingGems.push(nextGem); } else { break; } } if (nowMatchingGems.length >= 3) { matchFound = true; matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) { return matchedGems.indexOf(gem) === -1; })); } } } // Swap back this.gems[gemAIndex] = gemA; this.gems[gemBIndex] = gemB; return matchFound; }; this.swapGems = function (gem1, gem2) { var gem1Index = this.gems.indexOf(gem1); var gem2Index = this.gems.indexOf(gem2); if (gem1Index !== -1 && gem2Index !== -1) { // Animate swap positions with easing var swapDuration = 150; // Duration in milliseconds var gem1StartPos = { x: gem1.x, y: gem1.y }; if (!gem2) { return; } // Prevent TypeError if gem2 is null var gem2StartPos = { x: gem2.x, y: gem2.y }; gem1.isUsed = true; gem2.isUsed = true; gem1.alpha = 1; gem2.alpha = 1; var startTime = Date.now(); var animateSwap = function animateSwap() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / swapDuration); var easeInOut = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress; gem1.x = gem1StartPos.x + (gem2StartPos.x - gem1StartPos.x) * easeInOut; gem1.y = gem1StartPos.y + (gem2StartPos.y - gem1StartPos.y) * easeInOut; gem2.x = gem2StartPos.x + (gem1StartPos.x - gem2StartPos.x) * easeInOut; gem2.y = gem2StartPos.y + (gem1StartPos.y - gem2StartPos.y) * easeInOut; if (progress < 1) { LK.setTimeout(animateSwap, 16); // Aim for roughly 60fps } else { gem1.isUsed = false; gem2.isUsed = false; var snappedOne = self.snapToGrid(gem1.x, gem1.y); gem1.x = snappedOne.x; gem1.y = snappedOne.y; var snappedOne = self.snapToGrid(gem2.x, gem2.y); gem2.x = snappedOne.x; gem2.y = snappedOne.y; self.checkForMatches(); } }; animateSwap(); // Swap in gems array this.gems[gem1Index] = gem2; this.gems[gem2Index] = gem1; // Check for matches after swap } }; this.faintSwapGems = function (gem1, gem2, firstFaint) { var gem1Index = this.gems.indexOf(gem1); var gem2Index = this.gems.indexOf(gem2); if (gem1Index !== -1 && gem2Index !== -1) { // Animate swap positions with easing var swapDuration = 150; // Duration in milliseconds var gem1StartPos = { x: gem1.x, y: gem1.y }; var gem2StartPos = { x: gem2.x, y: gem2.y }; var startTime = Date.now(); var animateSwap = function animateSwap() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / swapDuration); var easeInOut = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress; gem1.x = gem1StartPos.x + (gem2StartPos.x - gem1StartPos.x) * easeInOut; gem1.y = gem1StartPos.y + (gem2StartPos.y - gem1StartPos.y) * easeInOut; gem2.x = gem2StartPos.x + (gem1StartPos.x - gem2StartPos.x) * easeInOut; gem2.y = gem2StartPos.y + (gem1StartPos.y - gem2StartPos.y) * easeInOut; if (progress < 1) { LK.setTimeout(animateSwap, 16); // Aim for roughly 60fps } else if (firstFaint) { self.faintSwapGems(gem1, gem2); } }; animateSwap(); // Swap in gems array this.gems[gem1Index] = gem2; this.gems[gem2Index] = gem1; } }; // Find a gem by its position this.findGemByPosition = function (x, y, exceptThisGem) { for (var i = 0; i < this.gems.length; i++) { var gem = this.gems[i]; if (gem == exceptThisGem) { continue; } if (gem) { var tolerance = gem.spacing / 2; // Tolerance in pixels for approximate position if (Math.abs(x - gem.x) < tolerance && Math.abs(y - gem.y) < tolerance) { return gem; } } } return null; }; this.fillEmptySpaces = function () { self.fillingEmptySpaces = true; var _animateGemDown = function animateGemDown(newGem, finalY, initialY) { var snappedOne = self.snapToGrid(newGem.x, finalY); finalY = snappedOne.y; var animationDuration = 250; // Duration in milliseconds var startTime = Date.now(); var animate = function animate() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / animationDuration); // Apply easing for smoother animation var easedProgress = Math.sin(progress * Math.PI / 2); if (progress < 1) { newGem.y = initialY + (finalY - initialY) * easedProgress; LK.setTimeout(animate, 16); // Aim for roughly 60fps } else { newGem.y = finalY; // Ensure final position is accurate self.fillingEmptySpaces = false; } }; animate(); }; for (var i = 0; i < 8; i++) { for (var j = 0; j < 6; j++) { var index = i * 6 + j; if (!self.gems[index]) { var possibleColors = ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan']; // Filter colors to ensure at least one possible match var colors = possibleColors.filter(function (color) { return true; }, this); var color = colors.length > 0 ? colors[Math.floor(Math.random() * colors.length)] : possibleColors[Math.floor(Math.random() * possibleColors.length)]; var newGem = new Gem(color); // Calculate x and y position for new gems when there are no existing gems to reference var gemSize = 100; var margin = 10; var boardWidth = 1800; // Assuming the board width is known var boardHeight = 2400; // Assuming the board height is known var gemsPerRow = 6; var gemsPerColumn = 8; var totalMarginWidth = margin * (gemsPerRow + 1); var totalMarginHeight = margin * (gemsPerColumn + 1); var availableWidth = boardWidth - totalMarginWidth; var availableHeight = boardHeight - totalMarginHeight; var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn); var xOffset = (2048 - boardWidth) / 2 + scaledGemSize / 2; // Assuming game width is 2048 var yOffset = (2732 - boardHeight) / 2 + scaledGemSize / 2; // Assuming game height is 2732 var snapped = self.snapToGrid(xOffset + (scaledGemSize + margin) * j, yOffset + (scaledGemSize + margin) * i); newGem.x = snapped.x; // Calculate initial y position for animation start // Calculate initial y position for animation start var initialY = -gemSize; // Start above the screen to simulate falling into place newGem.y = initialY; // Animate gem to its final position var finalY = snapped.y; _animateGemDown(newGem, finalY, initialY); newGem.spacing = scaledGemSize + margin; newGem.scale.set(scaledGemSize / gemSize); newGem.baseScale = scaledGemSize / gemSize; self.addChild(newGem); self.gems[index] = newGem; self.handleGemClick(newGem); } } } }; self.gems = []; this.handleFallingGems = function () { console.log("handle Falling gems"); var didFall = false; for (var i = 0; i < 6; i++) { for (var j = 7; j >= 0; j--) { var index = j * 6 + i; if (index >= 0 && index < self.gems.length && !self.gems[index]) { var emptySpaces = 1; for (var k = j - 1; k >= 0; k--) { var aboveIndex = k * 6 + i; if (!self.gems[aboveIndex]) { emptySpaces++; } else { var gemAbove = self.gems[aboveIndex]; var targetIndex = (k + emptySpaces) * 6 + i; self.gems[targetIndex] = gemAbove; self.gems[aboveIndex] = null; // Calculate the new Y position based on the number of empty spaces var margin = 10; var snapped = self.snapToGrid(gemAbove.x, gemAbove.y + gemAbove.spacing * emptySpaces); var newY = snapped.y; // Animate the gem moving to the new position gemAbove.alpha = 1; animateGemToPosition(gemAbove, gemAbove.x, newY); didFall = true; break; } } } } } if (didFall) { self.gemsFalling = true; LK.setTimeout(function () { self.fillEmptySpaces(); LK.setTimeout(function () { self.gemsFalling = false; self.checkForMatches(); }, 250); }, 250); } else { // Trigger fillEmptySpaces even if no gems fell to ensure no gaps are left self.fillEmptySpaces(); LK.setTimeout(function () { self.checkForMatches(); }, 250); } }; function animateGemToPosition(gem, newX, newY) { var fallDuration = 500; // Duration for the gem to fall to its new position var bounceDuration = 300; // Duration for the bounce effect, slightly longer for realism var scaleDuration = 150; // Duration for the scale effect after bouncing var startTime = Date.now(); var animateStep = function animateStep() { var currentTime = Date.now(); var elapsedTime = currentTime - startTime; var progress = elapsedTime / fallDuration; // First, handle the falling animation with a linear or ease-in effect if (progress < 1) { var fallProgress = Math.min(1, progress); // Ensure progress doesn't exceed 1 // Simple linear interpolation for falling gem.y = gem.y + (newY - gem.y) * fallProgress; if (fallProgress < 1) { LK.setTimeout(animateStep, 16); // Continue the fall animation } else { gem.y = newY; gem.isUsed = false; } } }; animateStep(); // Start the animation with the fall } this.handleGemMatched = function (gem) { if (gem.color == goalGemType) { matchedGemCount++; goalTxt.setText(matchedGemCount + "/" + goalGemCount); if (matchedGemCount >= goalGemCount) { game.timer += 10; timerTxt.setText(game.timer.toString()); stopTimer(); // Show modal pop-up for 10 more seconds var modalContainer = new Container(); LK.gui.center.addChild(modalContainer); var modalBackground = LK.getAsset('goalCompleteBg', {}); modalBackground.anchor.set(.5, .5); modalBackground.alpha = .75; modalContainer.addChild(modalBackground); // Animate scale of the modal container for excitement var scaleStartTime = Date.now(); var scaleDuration = 500; // Scale animation duration in milliseconds var animateScale = function animateScale() { var currentTime = Date.now(); var progress = (currentTime - scaleStartTime) / scaleDuration; var scale = 1 + 0.1 * Math.sin(progress * Math.PI * 2); // Oscillate scale between 1 and 1.1 modalContainer.scale.set(scale); if (progress < 1) { LK.setTimeout(animateScale, 16); } }; animateScale(); // Trigger lots of confetti balls on mission complete for (var i = 0; i < 100; i++) { var confetti = new ConfettiParticle(); confetti.init(Math.random() * game.width, Math.random() * game.height); game.addChild(confetti); } showPastGoalSprite = LK.getAsset(goalGemType, { // Align with the timer's top margin anchorX: .5, // Anchor right for right alignment anchorY: .5 // Anchor top for top alignment }); goalGemType = false; // Add hourglass sprite next to the timer var pastGoalBackground = LK.getAsset('newSpriteId', {}); pastGoalBackground.y = 0; pastGoalBackground.x = -100; pastGoalBackground.anchor.set(0.5, 0.5); // Align with the timer's top margin modalContainer.addChild(pastGoalBackground); pastGoalBackground.alpha = .75; showPastGoalSprite.y = pastGoalBackground.y; showPastGoalSprite.x = pastGoalBackground.x; showPastGoalSprite.anchor.set(.5, 0.5); // Align with the timer's top margin modalContainer.addChild(showPastGoalSprite); showPastGoalSprite.rotation = -.2; var showPastGoalText = new Text2(matchedGemCount + "/" + goalGemCount, { size: 100, weight: 600, fill: "#ffffff", x: 1024, y: 1366, anchorX: 0.5, anchorY: 0.5, dropShadow: true, dropShadowColor: '#000000', dropShadowBlur: 8, dropShadowOffsetX: 4, dropShadowOffsetY: 4, stroke: true, strokeColor: '#000000', strokeThickness: 4 }); showPastGoalText.y = pastGoalBackground.y; showPastGoalText.x = 0; showPastGoalText.anchor.set(0, 0.5); // Align with the timer's top margin modalContainer.addChild(showPastGoalText); var modalInfoText = new Text2('MISSION COMPLETE:', { size: 50, weight: 600, fill: "#ffffff", x: 1024, y: 1366, anchorX: 0.5, anchorY: 0.5, dropShadow: true, dropShadowColor: '#000000', dropShadowBlur: 8, dropShadowOffsetX: 4, dropShadowOffsetY: 4, stroke: true, strokeColor: '#000000', strokeThickness: 2 }); modalInfoText.anchor.set(.5); modalInfoText.y = -100; modalContainer.addChild(modalInfoText); var modalText = new Text2('+10 seconds!', { size: 100, weight: 600, fill: "#ffffff", x: 1024 + 70, // Adjust x position to make space for the hourglass sprite y: 1366, anchorX: 0.5, anchorY: 0.5, dropShadow: true, dropShadowColor: '#000000', dropShadowBlur: 8, dropShadowOffsetX: 4, dropShadowOffsetY: 4, stroke: true, strokeColor: '#000000', strokeThickness: 2 }); modalText.anchor.set(.5); modalText.y = 100; modalContainer.addChild(modalText); // Add hourglass sprite next to the '+10 seconds!' text var hourglassSpriteModal = LK.getAsset('hourglass', { anchorX: .5, anchorY: .5 }); hourglassSpriteModal.x = 1024 - 70; // Position hourglass to the left of the text hourglassSpriteModal.y = 1366; modalContainer.addChild(hourglassSpriteModal); var thumbUpSprite = LK.getAsset('thumbUp', { // Align with the timer's top margin anchorX: .5, // Anchor right for right alignment anchorY: .5 // Anchor top for top alignment }); thumbUpSprite.y = 0; thumbUpSprite.x = -500; thumbUpSprite.anchor.set(.5, 0.5); // Align with the timer's top margin modalContainer.addChild(thumbUpSprite); var thumbUpSprite2 = LK.getAsset('woodLockAcid', { // Align with the timer's top margin anchorX: .5, // Anchor right for right alignment anchorY: .5 // Anchor top for top alignment }); thumbUpSprite2.y = 0; thumbUpSprite2.x = 500; thumbUpSprite2.anchor.set(.5, 0.5); // Align with the timer's top margin modalContainer.addChild(thumbUpSprite2); var modalText = new Text2('+', { size: 120, weight: 600, fill: "#ffffff", x: 1024 + 70, // Adjust x position to make space for the hourglass sprite y: 1366, anchorX: 0.5, anchorY: 0.5, dropShadow: true, dropShadowColor: '#000000', dropShadowBlur: 8, dropShadowOffsetX: 4, dropShadowOffsetY: 4, stroke: true, strokeColor: '#000000', strokeThickness: 2 }); modalText.anchor.set(.5); modalText.x = 400; modalText.y = 0; modalContainer.addChild(modalText); // Automatically remove the modal and background after 2 seconds // Start animation for modal elements var duration = 2000; // 3 seconds for the animation LK.setTimeout(function () { var startTime = Date.now(); var simpleCountdownInterval = LK.setInterval(function () { var currentTime = Date.now(); var progress = (currentTime - startTime) / duration; var moveDistance = 2048; // Move to the right side off-screen modalContainer.x += moveDistance * progress; if (progress >= 1) { LK.clearInterval(simpleCountdownInterval); modalContainer.destroy(); startTimer(); } }, 16); }, 2000); goalLevel++; updateBackground(); setRandomGoalGemType(); } } }; this.checkForMatches = function (matchFoundPreviously) { var matchFound = false; var matchedGems = []; // Check for horizontal matches for (var i = 0; i < 8; i++) { for (var j = 0; j < 6; j++) { // Adjust to allow checks across all columns if (!this.gems || !this.gems[i * 6 + j] || typeof this.gems[i * 6 + j] === 'undefined') { continue; } var gem1 = this.gems[i * 6 + j]; if (!gem1) { continue; } var gem1 = this.gems[i * 6 + j]; var nowMatchingGems = []; for (var k = j; k < 6; k++) { var nextGem = this.gems[i * 6 + k]; if (nextGem && nextGem.color === gem1.color) { nowMatchingGems.push(nextGem); } else { break; } } if (nowMatchingGems.length >= 3) { matchFound = true; matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) { return matchedGems.indexOf(gem) === -1; })); } } } // Check for vertical matches for (var i = 0; i < 6; i++) { for (var j = 0; j < 8; j++) { // Adjust to allow checks across all rows if (!this.gems || !this.gems[j * 6 + i]) { continue; } var gem1 = this.gems[j * 6 + i]; var nowMatchingGems = []; for (var k = j; k < 8; k++) { var nextGem = this.gems[k * 6 + i]; if (nextGem && nextGem.color === gem1.color) { nowMatchingGems.push(nextGem); } else { break; } } if (nowMatchingGems.length >= 3) { matchFound = true; matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) { return matchedGems.indexOf(gem) === -1; })); } } } var matchesHandled = 0; matchedGems.forEach(function (gem) { if (gem.color == goalGemType) { self.handleGemMatched(gem); // Move gem to the goalGemSprite instead of destroying it matchesHandled++; game.addChild(gem); var moveGemToGoal = function moveGemToGoal(gem) { LK.setTimeout(function () { var goalGemSpriteX = currentGoalGemSprite ? currentGoalGemSprite.x + (currentGoalGemSprite.parent ? currentGoalGemSprite.parent.x : 0) : 0; var goalGemSpriteY = currentGoalGemSprite ? currentGoalGemSprite.y + (currentGoalGemSprite.parent ? currentGoalGemSprite.parent.y : 0) : 0; if (currentGoalGemSprite) { var goalGemSpriteScale = currentGoalGemSprite.scale.x; } var moveDuration = 500 + matchesHandled * 100; // Duration in milliseconds var startTime = Date.now(); var animateMove = function animateMove() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / moveDuration); var newX = gem.x + (goalGemSpriteX - gem.x) * progress; var newY = gem.y + (goalGemSpriteY - gem.y) * progress; var newScale = gem.scale.x + (goalGemSpriteScale - gem.scale.x) * progress; gem.x = newX; gem.y = newY; gem.scale.set(newScale); if (progress < 1) { LK.setTimeout(animateMove, 16); // Aim for roughly 60fps } else { gem.destroy(); // Destroy gem after reaching the goal } }; animateMove(); }, matchesHandled * 100); }; moveGemToGoal(gem); } else { self.handleGemMatched(gem); gem.scaleUpAndDisappear(); // Trigger glowing particles effect at the gem's position var glowingParticles = new GlowingParticles(); glowingParticles.init(gem.x, gem.y); self.addChild(glowingParticles); } var index = self.gems.indexOf(gem); if (index > -1) { self.gems[index] = false; // Increase score based on combo multiplier var pointsAwarded = 10 * self.comboMultiplier; score += pointsAwarded; // Update score with points awarded based on combo multiplier LK.setScore(score); // Display points at the gem's location with animation var pointsText = new Text2("+" + pointsAwarded.toString(), { size: 80, weight: 600, fill: "#ffffff", anchorX: 0.5, anchorY: 0.5, dropShadow: true, dropShadowColor: '#000000', dropShadowBlur: 8, dropShadowOffsetX: 4, dropShadowOffsetY: 4, outline: true, outlineColor: '#000000', outlineThickness: 5 }); pointsText.y -= 20; // Make it a little bit higher pointsText.anchor.set(.5); pointsText.x = gem.x; pointsText.y = gem.y; game.addChild(pointsText); // Animate points text: scale up and fade out var scaleUpDuration = 500; // Duration to scale up in milliseconds var fadeOutDuration = 500; // Duration to fade out in milliseconds var maxScale = 1.5; // Maximum scale factor var originalScale = 1; // Original scale var startTime = Date.now(); var animate = function animate() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration); pointsText.scale.set(originalScale + (maxScale - originalScale) * progress); pointsText.alpha = 1 - progress; // Fade out if (progress < 1) { LK.setTimeout(animate, 16); // Aim for roughly 60fps } else { pointsText.destroy(); // Destroy text after animation } }; animate(); // Increase combo multiplier for each consecutive match self.comboMultiplier++; scoreTxt.setText(score.toString()); // Update score display } }); if (matchFound) { // If no match was found previously and it's not the first check, reset the combo multiplier if (!matchFoundPreviously && matchFound) { self.comboMultiplier = 1; } else if (matchFound) { // Increase combo multiplier for each consecutive match self.comboMultiplier++; } self.checkForMatches(true); } else if (matchFoundPreviously) { LK.setTimeout(function () { this.handleFallingGems(); }.bind(this), 200); } return matchFound; }; self.handleGemClick = function (gem) { gem.on('down', function (obj) { self.dragStartGem = gem; self.dragStartGemStartPosition = { x: gem.x, y: gem.y }; var currentPos = obj.event.getLocalPosition(game); self.dragStartPos = { x: currentPos.x, y: currentPos.y }; // Highlight the drag start gem self.dragStartGem.alpha = 0.5; self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1.1); }); gem.on('move', function (obj) { if (!self.dragStartGem) { return; } var currentPos = obj.event.getLocalPosition(game); //self.dragStartGem.x = self.dragStartGemStartPosition.x + currentPos.x - self.dragStartPos.x; //self.dragStartGem.y = self.dragStartGemStartPosition.y + currentPos.y - self.dragStartPos.y; var dx = currentPos.x - self.dragStartPos.x; var dy = currentPos.y - self.dragStartPos.y; if (Math.abs(dx) > gem.spacing / 2 || Math.abs(dy) > gem.spacing / 2) { var directionX = dx > 0 ? 1 : -1; var directionY = dy > 0 ? 1 : -1; // Correctly identify if we should swap horizontally or vertically if (Math.abs(dx) > Math.abs(dy)) { // Swap horizontally var swapGem = self.findGemByPosition(self.dragStartGem.x + gem.spacing * directionX, self.dragStartGem.y, self.dragStartGem); } else { // Swap vertically var swapGem = self.findGemByPosition(self.dragStartGem.x, self.dragStartGem.y + gem.spacing * directionY, self.dragStartGem); } if (self.lastHintOverlay) { self.lastHintOverlay.destroy(); } if (swapGem && self.wouldSwapResultInMatch(self.dragStartGem, swapGem)) { self.swapGems(self.dragStartGem, swapGem); } else { self.faintSwapGems(self.dragStartGem, swapGem, true); } self.dragStartGem.alpha = 1; self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1); self.dragStartGem = null; self.dragStartPos = null; } }); gem.on('up', function () { if (self.dragStartGem) { self.dragStartGem.alpha = 1; // Reset alpha to unhighlight the gem self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1); } self.dragStartGem = null; self.dragStartPos = null; }); }; self.initBoard = function () { var colors = game.timer > 60 ? ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'] : ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange']; for (var i = 0; i < 8; i++) { for (var j = 0; j < 6; j++) { var color = colors[Math.floor(Math.random() * colors.length)]; var gem = new Gem(color); var gem = new Gem(color); var gemSize = 100; var margin = 10; var boardWidth = game.width * .9; var boardHeight = game.height * .9; var gemsPerRow = 6; var gemsPerColumn = 8; var totalMarginWidth = margin * (gemsPerRow + 1); var totalMarginHeight = margin * (gemsPerColumn + 1); var availableWidth = boardWidth - totalMarginWidth; var availableHeight = boardHeight - totalMarginHeight; var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn); var xOffset = (game.width - boardWidth) / 2 + scaledGemSize / 2; var yOffset = (game.height - boardHeight) / 2 + scaledGemSize / 2; gem.spacing = scaledGemSize + margin; self.spacing = gem.spacing; var snappedPos = self.snapToGrid(xOffset + (scaledGemSize + margin) * j, yOffset + (scaledGemSize + margin) * i); gem.x = snappedPos.x; gem.y = snappedPos.y; gem.scale.set(scaledGemSize / gemSize); gem.scale.set(scaledGemSize / gemSize); gem.baseScale = scaledGemSize / gemSize; self.addChild(gem); self.gems.push(gem); self.handleGemClick(gem); } } self.comboMultiplier = 1; // Initialize combo multiplier self.checkForMatches(); }; }); // ChineseRedEnvelope class var ChineseRedEnvelope = Container.expand(function () { var self = Container.call(this); var envelopeGraphics = self.attachAsset('redEnvelope', { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y) { self.x = x; self.y = y; var scaleAnimation = function scaleAnimation() { var scaleUp = true; var scaleValue = 1; LK.setInterval(function () { if (scaleUp) { scaleValue += 0.01; } else { scaleValue -= 0.01; } if (scaleValue >= 1.1) { scaleUp = false; } if (scaleValue <= 1) { scaleUp = true; } self.scale.set(scaleValue * 2.0); // Make the envelope significantly larger }, 100); }; scaleAnimation(); self.on('down', function () { var targetX = timerTxt.x; var targetY = timerTxt.y; var moveDuration = 1000; // Duration in milliseconds var startTime = Date.now(); var animateMove = function animateMove() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / moveDuration); // Apply a quadratic easing for a smooth curve var curveProgress = Math.pow(progress, 2); self.x = self.x + (targetX - self.x) * curveProgress; self.y = self.y - 75 * Math.sin(Math.PI * progress) + (targetY - self.y) * curveProgress; // Add a sine wave pattern for vertical movement if (progress < 1) { LK.setTimeout(animateMove, 16); } else { game.timer += 5; // Grant 5 more seconds timerTxt.setText(game.timer.toString()); // Update timer display self.destroy(); // Remove the envelope after reaching the timer } }; animateMove(); }); // Initiate continuous glowing effect function glowEffect() { var glowParticle = new GlowingParticlesForRedEnvelopes(.3); glowParticle.init(0, 0); self.addChildAt(glowParticle, 0); } ; glowEffect(); // LK.setInterval(glowEffect, 500); // Add a glowing particle effect every 500ms }; }); // ConfettiParticle class var ConfettiParticle = Container.expand(function () { var self = Container.call(this); var confettiColors = ['confettiRed', 'confettiBlue', 'confettiGreen', 'confettiYellow', 'confettiPurple']; var randomColor = confettiColors[Math.floor(Math.random() * confettiColors.length)]; var confettiGraphics = self.attachAsset(randomColor, { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y) { self.x = x; self.y = y; var angle = Math.random() * Math.PI * 2; var speed = 0.5 + Math.random(); // Reduced speed for smoother appearance var duration = 1500 + Math.random() * 2500; // Extended duration for smoother fade var startTime = Date.now(); var animate = function animate() { var currentTime = Date.now(); var progress = (currentTime - startTime) / duration; self.x += Math.cos(angle) * speed; self.y += Math.sin(angle) * speed; self.alpha = Math.sin(progress * Math.PI); // Smooth in and out fading effect if (progress < 1) { LK.setTimeout(animate, 16); } else { self.destroy(); } }; animate(); }; }); // Dragon class var Dragon = Container.expand(function (gem) { var self = Container.call(this); var dragonGraphics = self.attachAsset('dragon', { anchorX: 0.5, anchorY: 0.5 }); dragonGraphics.anchor.set(1, .7); self.speed = 5; var hasTakenGem = false; self.move = function () { var endX = 2048 + self.width; // Ensure dragon ends off-screen to the right var startX = -self.width; // Start off-screen to the left var travelDistance = endX - startX; var travelTime = 3000; // Time in milliseconds for the dragon to cross the screen var startTime = Date.now(); var particleParts = []; function animate() { var currentTime = Date.now(); var elapsedTime = currentTime - startTime; var progress = elapsedTime / travelTime; self.x = startX + travelDistance * progress; if (self.x > gem.x && !hasTakenGem) { hasTakenGem = true; self.addChild(gem); // Animate gem scale upon grabbing var scaleAnimationDuration = 300; // Duration of the scale animation in milliseconds var scaleAnimationStartTime = Date.now(); var animateGemScale = function animateGemScale() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - scaleAnimationStartTime) / scaleAnimationDuration); gem.scale.set(gem.baseScale * (.8 + .2 * Math.sin(progress * Math.PI * 2))); // Animate scale if (progress < 1) { LK.setTimeout(animateGemScale, 16); } else { gem.scale.set(gem.baseScale * .8); } }; animateGemScale(); gem.x = 50; gem.y = 0; var index = board.gems.indexOf(gem); if (index > -1) { if (board.gems[index] == gem) { board.gems[index] = false; } } LK.setTimeout(function () { board.handleFallingGems(); }, 200); } if (hasTakenGem) { self.addChild(gem); //gem.scale.set(gem.baseScale * .8); gem.x = 50; gem.y = 0; } // Generate particle trail if (progress < 1) { LK.setTimeout(animate, 16); // Aim for roughly 60fps } else { var fadeoutparticle = function fadeoutparticle(particle) { // Start fade out effect var fadeOutDuration = 500; // Duration for the fade out in milliseconds var fadeStartTime = Date.now(); var fadeStep = function fadeStep() { var currentTime = Date.now(); var progress = (currentTime - fadeStartTime) / fadeOutDuration; particle.alpha = 1 - progress; // Fade out if (progress < 1) { LK.setTimeout(fadeStep, 16); } else { particle.destroy(); // Destroy particle after fade out } }; fadeStep(); }; ; // Spawn a red envelope at a random position //var envelope = new ChineseRedEnvelope(); //envelope.init(Math.random() * game.width, self.y); //game.addChild(envelope); // Destroy the dragon instance once it crosses the screen isDragoning = false; particleParts.forEach(function (particle) { fadeoutparticle(particle); }); self.destroy(); } } animate(); }; }); // Gem class var Gem = Container.expand(function (color) { var self = Container.call(this); self.scaleUpAndDown = function (delay) { LK.setTimeout(function () { var scaleUpDuration = 150; // Duration to scale up in milliseconds var scaleDownDuration = 150; // Duration to scale down in milliseconds var maxScale = self.baseScale * 1.3; // Maximum scale factor var originalScale = self.baseScale; // Remember the original scale var scaleUp = function scaleUp() { var startTime = Date.now(); var scaleStep = function scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration); self.scale.set(originalScale + (maxScale - originalScale) * progress); if (progress < 1) { LK.setTimeout(scaleStep, 16); } else { scaleDown(); } }; scaleStep(); }; var scaleDown = function scaleDown() { var startTime = Date.now(); var scaleStep = function scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleDownDuration); self.scale.set(maxScale - (maxScale - originalScale) * progress); if (progress < 1) { LK.setTimeout(scaleStep, 16); } }; scaleStep(); }; scaleUp(); }, delay); }; self.scaleUpAndDisappear = function scaleUpAndDisappear() { var scaleUpDuration = 100; // Duration to scale up in milliseconds var scaleDownDuration = 200; // Duration to scale down to zero var maxScale = self.baseScale * 1.2; // Maximum scale factor var disappearScale = 0; // Scale factor to disappear var originalScale = self.baseScale; // Remember the original scale // Animate scale up // Start scale up var scaleUpDuration = 100; // Duration to scale up in milliseconds var disappearDuration = 200; // Duration to scale down to zero var maxScale = self.baseScale * 1.2; // Maximum scale factor var disappearScale = 0; // Scale factor to disappear var originalScale = self.baseScale; // Remember the original scale // Animate scale up var startTime = Date.now(); var _scaleStep2 = function _scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration); self.scale.set(originalScale + (maxScale - originalScale) * progress); if (progress < 1) { LK.setTimeout(_scaleStep2, 16); } else { // Once scaled up, start disappearing startTime = Date.now(); _scaleStep2 = function scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / disappearDuration); self.scale.set(maxScale - (maxScale - disappearScale) * progress); if (progress < 1) { LK.setTimeout(_scaleStep2, 16); } else { self.destroy(); } }; _scaleStep2(); } }; _scaleStep2(); }; var gemGraphics = self.attachAsset(color, { anchorX: 0.5, anchorY: 0.5 }); self.color = color; self.isSelected = false; self.toggleSelect = function () { self.isSelected = !self.isSelected; if (self.isSelected) { gemGraphics.alpha = 0.5; self.scale.set(self.baseScale * 1.1); } else { gemGraphics.alpha = 1; self.scale.set(self.baseScale); } }; }); // GlowingParticles class enhancement var GlowingParticles = Container.expand(function () { var self = Container.call(this); scaleMultiplier = 1; var _animateParticle = function animateParticle(particle) { var currentTime = Date.now(); var elapsedTime = currentTime - particle.startTime; var progress = elapsedTime / particle.duration; if (progress < 1) { particle.x += Math.cos(particle.angle) * particle.speed; particle.y += Math.sin(particle.angle) * particle.speed; particle.alpha = Math.cos(progress * Math.PI); // Smooth in and out fading effect particle.rotation += particle.rotationVelocity; // Add rotation to each particle LK.setTimeout(function () { _animateParticle(particle); }, 16); } else { particle.destroy(); } }; self.init = function (x, y) { for (var i = 0; i < 50; i++) { var particle = self.attachAsset('glowEffect', { x: x, y: y, anchorX: 0.5, anchorY: 0.5 }); particle.blendMode = 1; particle.angle = Math.random() * Math.PI * 2; // Random angle for direction particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic // Introduce gravity effect to some particles for (var i = 0; i < 50; i++) { var particle = self.attachAsset('glowEffect', { x: x, y: y, anchorX: 0.5, anchorY: 0.5 }); particle.blendMode = 1; particle.angle = Math.random() * Math.PI * 2; // Random angle for direction particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic particle.gravity = Math.random() > 0.5 ? 0.01 : 0; // Half the particles have a gravity effect particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable particle.startTime = Date.now(); particle.rotationVelocity = -0.1 + Math.random() * .2; particle.x += Math.cos(particle.angle) * Math.random() * 80; particle.y += Math.sin(particle.angle) * Math.random() * 80; _animateParticle(particle); } particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable particle.startTime = Date.now(); particle.rotationVelocity = -0.1 + Math.random() * .2; particle.x += Math.cos(particle.angle) * Math.random() * 80; particle.y += Math.sin(particle.angle) * Math.random() * 80; _animateParticle(particle); } }; }); // Define the GlowingParticlesForRedEnvelope class var GlowingParticlesForRedEnvelope = Container.expand(function (scaleMultiplier) { var self = Container.call(this); var _animateParticle = function animateParticle(particle) { var currentTime = Date.now(); var elapsedTime = currentTime - particle.startTime; var progress = elapsedTime / particle.duration; if (progress < 1) { // Update particle properties for movement, fading, and rotation particle.x += Math.cos(particle.angle) * particle.speed; particle.y += Math.sin(particle.angle) * particle.speed; particle.alpha = Math.cos(progress * Math.PI); // Fading effect particle.rotation += particle.rotationVelocity; } else { // Reset particle to create a continuous effect particle.startTime = Date.now(); // Reset start time // Optionally, re-randomize properties for varied continuous effect particle.angle = Math.random() * Math.PI * 2; particle.speed = 1 + Math.random() * 1.5; particle.duration = 500 + Math.random() * 1000; particle.rotationVelocity = -0.1 + Math.random() * 0.2; particle.x = particle.initialX + Math.cos(particle.angle) * Math.random() * 50; particle.y = particle.initialY + Math.sin(particle.angle) * Math.random() * 50; } LK.setTimeout(function () { _animateParticle(particle); }, 16); // Continue animation loop }; self.init = function (x, y) { for (var i = 0; i < 50; i++) { var particle = self.attachAsset('glowEffect', { x: x, y: y, anchorX: 0.5, anchorY: 0.5 }); particle.blendMode = 1; particle.alpha = 0; particle.initialX = x; // Store initial position particle.initialY = y; particle.angle = Math.random() * Math.PI * 2; particle.speed = 1 + Math.random() * 1.5; particle.duration = 500 + Math.random() * 1000; particle.targetScale = 0.5 + Math.random() * 1.5; particle.scale.set(particle.targetScale * scaleMultiplier); particle.startTime = Date.now(); particle.rotationVelocity = -0.1 + Math.random() * 0.2; particle.x += Math.cos(particle.angle) * Math.random() * 70; particle.y += Math.sin(particle.angle) * Math.random() * 70; _animateParticle(particle); } }; }); var GlowingParticlesForRedEnvelopes = Container.expand(function (scaleMultiplier) { var self = Container.call(this); var _animateParticle = function animateParticle(particle) { var currentTime = Date.now(); var elapsedTime = currentTime - particle.startTime; var progress = elapsedTime / particle.duration; if (progress < 1) { // Update particle properties for movement, fading, and rotation particle.x += Math.cos(particle.angle) * particle.speed; particle.y += Math.sin(particle.angle) * particle.speed; particle.alpha = Math.cos(progress * Math.PI); // Fading effect particle.rotation += particle.rotationVelocity; } else { // Reset particle to create a continuous effect particle.startTime = Date.now(); // Reset start time // Optionally, re-randomize properties for varied continuous effect particle.angle = Math.random() * Math.PI * 2; particle.speed = 1 + Math.random() * 1.5; particle.duration = 500 + Math.random() * 1000; particle.rotationVelocity = -0.1 + Math.random() * 0.2; particle.x = particle.initialX + Math.cos(particle.angle) * Math.random() * 50; particle.y = particle.initialY + Math.sin(particle.angle) * Math.random() * 50; } LK.setTimeout(function () { _animateParticle(particle); }, 16); // Continue animation loop }; self.init = function (x, y) { for (var i = 0; i < 50; i++) { var particle = self.attachAsset('glowEffect', { x: x, y: y, anchorX: 0.5, anchorY: 0.5 }); particle.blendMode = 1; particle.alpha = 0; particle.initialX = x; // Store initial position particle.initialY = y; particle.angle = Math.random() * Math.PI * 2; particle.speed = 1 + Math.random() * 1.5; particle.duration = 500 + Math.random() * 1000; particle.targetScale = 0.5 + Math.random() * 1.5; particle.scale.set(particle.targetScale * scaleMultiplier); particle.startTime = Date.now(); particle.rotationVelocity = -0.1 + Math.random() * 0.2; particle.x += Math.cos(particle.angle) * Math.random() * 70; particle.y += Math.sin(particle.angle) * Math.random() * 70; _animateParticle(particle); } }; }); // LineSprite class var LineSprite = Container.expand(function () { var self = Container.call(this); self.updateLine = function (startX, startY, endX, endY) { var dx = endX - startX; var dy = endY - startY; var distance = Math.sqrt(dx * dx + dy * dy); self.width = distance; self.height = 5; // Fixed height for the line self.rotation = Math.atan2(dy, dx); self.x = startX + dx / 2; self.y = startY + dy / 2; self.anchorX = 0.5; self.anchorY = 0.5; }; }); // RowBlasterGem class var RowBlasterGem = Container.expand(function (color) { var self = Container.call(this); var gemGraphics = self.attachAsset(color, { anchorX: 0.5, anchorY: 0.5 }); self.color = color; // Unique behavior for RowBlasterGem self.activate = function () { // Logic to blast the entire row console.log('Blasting row...'); }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Init game with black background }); /**** * Game Code ****/ // SagaMap class // SagaMap class // Dragon spawn timer // Goal gem type and count // Initialize large countdown at the beginning of the game // Initialize score // Initialize 2-minute timer // Initialize a timer for showing hints var SagaMap = /*#__PURE__*/function (_Container) { _inherits(SagaMap, _Container); function SagaMap() { var _this; _classCallCheck(this, SagaMap); _this = _callSuper(this, SagaMap); _this.levels = []; _this.currentLevel = 0; return _this; } _createClass(SagaMap, [{ key: "addLevel", value: function addLevel(level) { this.levels.push(level); } }, { key: "goToLevel", value: function goToLevel(index) { this.currentLevel = index; // Logic to switch to the specified level console.log('Switching to level:', index); } }, { key: "nextLevel", value: function nextLevel() { if (this.currentLevel < this.levels.length - 1) { this.goToLevel(this.currentLevel + 1); } else { console.log('No more levels!'); } } }]); return SagaMap; }(Container); function _typeof2(o) { "@babel/helpers - typeof"; return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof2(o); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, _toPropertyKey2(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) { _defineProperties(Constructor.prototype, protoProps); } if (staticProps) { _defineProperties(Constructor, staticProps); } Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _toPropertyKey2(t) { var i = _toPrimitive2(t, "string"); return "symbol" == _typeof2(i) ? i : String(i); } function _toPrimitive2(t, r) { if ("object" != _typeof2(t) || !t) { return t; } var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof2(i)) { return i; } throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _possibleConstructorReturn(self, call) { if (call && (_typeof2(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) { _setPrototypeOf(subClass, superClass); } } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } var SagaMap = /*#__PURE__*/function (_Container) { _inherits(SagaMap, _Container); function SagaMap() { var _this; _classCallCheck(this, SagaMap); _this = _callSuper(this, SagaMap); _this.levels = []; _this.currentLevel = 0; return _this; } _createClass(SagaMap, [{ key: "addLevel", value: function addLevel(level) { this.levels.push(level); } }, { key: "goToLevel", value: function goToLevel(index) { this.currentLevel = index; // Logic to switch to the specified level console.log('Switching to level:', index); } }, { key: "nextLevel", value: function nextLevel() { if (this.currentLevel < this.levels.length - 1) { this.goToLevel(this.currentLevel + 1); } else { console.log('No more levels!'); } } }]); return SagaMap; }(Container); var dragonSpawnTimer; var isDragoning = false; function triggerDragon() { if (dragonSpawnTimer) { LK.clearTimeout(dragonSpawnTimer); } if (!isDragoning && board && board.gems && board.gems.length > 0) { isDragoning = true; var randomIndex = Math.floor(Math.random() * board.gems.length); var gemToRemove = board.gems[randomIndex]; if (gemToRemove) { var dragon = new Dragon(gemToRemove); dragon.x = -100; // Ensure dragon starts off-screen to the left dragon.y = gemToRemove.y; // Random y position within game bounds game.addChild(dragon); dragon.move(); } } var nextSpawnTime = 5000 + Math.random() * 10000; // Random interval between 5 to 15 seconds dragonSpawnTimer = LK.setTimeout(triggerDragon, nextSpawnTime); } triggerDragon(); var goalGemType; var matchedGemCount = 0; var hintTimer; var currentGoalGemSprite = false; var goalLevel = 0; // Function to randomly set the goal gem type from the available gem colors function setRandomGoalGemType() { var gemColors = ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan']; goalGemType = gemColors[Math.floor(Math.random() * gemColors.length)]; goalGemCount = 3 + Math.floor(Math.random() * goalLevel); matchedGemCount = 0; LK.setTimeout(function () { // Update the goal text with the chosen gem type goalTxt.setText(matchedGemCount + '/' + goalGemCount); // Add hourglass sprite next to the timer if (currentGoalGemSprite) { currentGoalGemSprite.destroy(); } currentGoalGemSprite = LK.getAsset(goalGemType, { x: 2048 - 100, // Position next to the timer y: 50, // Align with the timer's top margin anchorX: .5, // Anchor right for right alignment anchorY: .5 // Anchor top for top alignment }); currentGoalGemSprite.y = goalTxt.y; currentGoalGemSprite.x = goalBackground.x; // Position next to the timer currentGoalGemSprite.anchor.set(0.5, 0.5); // Align with the timer's top margin currentGoalGemSprite.rotation = -.2; currentGoalGemSprite.scale.set(1.6); if (goalBackground.parent) { goalBackground.parent.removeChild(goalBackground); } if (goalTxt.parent) { goalTxt.parent.removeChild(goalTxt); } if (currentGoalGemSprite.parent) { currentGoalGemSprite.parent.removeChild(currentGoalGemSprite); } LK.setTimeout(function () { board.addChild(goalBackground); game.addChild(goalBackground); game.addChild(goalTxt); game.addChild(currentGoalGemSprite); }, 1000); }, 1000); } // setRandomGoalGemType(); // Initialize the goal gem type at the start of the game // This call has been moved to after the definition of goalTxt to fix the bug // Function to reset and start the hint timer function resetHintTimer() { if (hintTimer) { LK.clearTimeout(hintTimer); } hintTimer = LK.setTimeout(function () { board.showHint(); resetHintTimer(); }, 5000); // Show hint after 5 seconds of inactivity } resetHintTimer(); // Reset the hint timer whenever a move is made LK.on('tick', function () { // This is a placeholder for any game action, e.g., gem swap, that resets the hint timer // resetHintTimer(); }); function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) { return t; } var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) { return i; } throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var countdownValue = 3; // Start countdown from 3 var countdownTxt = new Text2(countdownValue.toString(), { size: 300, fill: "#ffffff", x: 1024, // Center of the screen y: 1366, // Middle of the screen anchorX: 0.5, anchorY: 0.5, stroke: true, weight: 800, dropShadow: true }); countdownTxt.anchor.set(.5); LK.gui.center.addChild(countdownTxt); // Add countdown display to the center GUI layer var countdownInterval = LK.setInterval(function () { countdownValue -= 1; if (countdownValue > 0) { countdownTxt.setText(countdownValue.toString()); // Bounce effect for countdown numbers var scaleUpDuration = 100; // Duration to scale up in milliseconds var scaleDownDuration = 100; // Duration to scale down in milliseconds var maxScale = 1.2; // Maximum scale factor var originalScale = 1; // Remember the original scale var scaleUp = function scaleUp() { var startTime = Date.now(); var scaleStep = function scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration); countdownTxt.scale.set(originalScale + (maxScale - originalScale) * progress); if (progress < 1) { LK.setTimeout(scaleStep, 16); } else { scaleDown(); } }; scaleStep(); }; var scaleDown = function scaleDown() { var startTime = Date.now(); var scaleStep = function scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleDownDuration); countdownTxt.scale.set(maxScale - (maxScale - originalScale) * progress); if (progress < 1) { LK.setTimeout(scaleStep, 16); } }; scaleStep(); }; scaleUp(); } else if (countdownValue === 0) { countdownTxt.setText('GO!'); spinHourglass(); // Bounce effect var scaleUpDuration = 200; // Duration to scale up in milliseconds var scaleDownDuration = 200; // Duration to scale down in milliseconds var maxScale = 1.5; // Maximum scale factor var originalScale = 1; // Remember the original scale var scaleUp = function scaleUp() { var startTime = Date.now(); var scaleStep = function scaleStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration); countdownTxt.scale.set(originalScale + (maxScale - originalScale) * progress); if (progress < 1) { LK.setTimeout(scaleStep, 16); } else { scaleDown(); } }; scaleStep(); }; var scaleDown = function scaleDown() { var fadeOutDuration = 500; // Duration for the fade out in milliseconds var startTime = Date.now(); var fadeStep = function fadeStep() { var currentTime = Date.now(); var progress = Math.min(1, (currentTime - startTime) / fadeOutDuration); countdownTxt.alpha = 1 - progress; // Fade out if (progress < 1) { LK.setTimeout(fadeStep, 16); } else { countdownTxt.destroy(); // Remove countdown text after animation LK.clearInterval(countdownInterval); setRandomGoalGemType(); } }; fadeStep(); }; scaleUp(); } }, 1000); // Update countdown every second game.timer = 120; // 2 minutes in seconds // Implement a three second delay before starting the timer text interval LK.setTimeout(function () { // Timer control is now handled inside the modal display logic to pause during the modal display. }, 3000); var score = 0; // Starting score var scoreBg; var scoreBgNode = LK.getAsset('scoreBg', { x: 1024 - 150, // Centered based on the background size y: 0, anchorX: 0.5, anchorY: 0 }); scoreBgNode.anchor.set(.5); scoreBgNode.y = 50; scoreBgNode.alpha = 1; // Set the background transparency to fully opaque to ensure visibility LK.gui.top.addChild(scoreBgNode); var scoreTxt = new Text2(score.toString(), _defineProperty(_defineProperty({ size: 110, weight: 500, fill: "#ffffff", x: 1024, // Center of the screen y: 0, // Adjusted to be within the background anchorX: 0.5, // Center horizontally anchorY: 0, // Anchor at the top dropShadow: true, dropShadowColor: '#000000', shadowBlur: 4, shadowOffsetX: 2, shadowOffsetY: 2, stroke: true, strokeColor: '#000000' }, "stroke", '#000000'), "strokeThickness", 7)); scoreTxt.anchor.set(.5, .5); scoreTxt.y = 50; LK.gui.top.addChild(scoreTxt); // Add score display to the top GUI layer // List of background images for different goal levels var backgroundImages = ['magicalBackground', 'enchantedForest', 'mysticCave', 'celestialRealm']; // Function to update the game background according to the current goal level function updateBackground() { var backgroundImageId = backgroundImages[goalLevel % backgroundImages.length]; var oldBackground = game.background; if (oldBackground) { LK.setTimeout(function () { oldBackground.destroy(); }, 1000); } var background = LK.getAsset(backgroundImageId, { anchorX: 0.5, anchorY: 0.5 }); background.x = game.width / 2; background.y = game.height / 2; background.scale.set(Math.max(game.height / background.height, game.width / background.width)); background.alpha = 0; // Start fully transparent var fadeInDuration = 1000; // Duration for the fade in milliseconds var fadeInStartTime = Date.now(); var fadeInStep = function fadeInStep() { var currentTime = Date.now(); var progress = (currentTime - fadeInStartTime) / fadeInDuration; background.alpha = progress; // Fade in if (progress < 1) { LK.setTimeout(fadeInStep, 16); } else { background.alpha = 1; if (oldBackground) {} } }; fadeInStep(); // This line is removed to prevent script errors related to incorrect usage of addChildAt. // Instead, we'll use addChild and manage layering through careful addition order. game.addChildAt(background, Math.min(1, game.children.length)); game.background = background; } // Initially set the background updateBackground(); // Add the game board background to the game var gameBoardBg = game.addChild(LK.getAsset('gameBoardBg', { x: 0, y: 0, anchorX: 0, anchorY: 0 })); gameBoardBg.width = game.width * 0.9; gameBoardBg.height = game.height * 0.9; gameBoardBg.x = (game.width - gameBoardBg.width) / 2; gameBoardBg.y = (game.height - gameBoardBg.height) / 2 + 80; gameBoardBg.alpha = 0.6; // Set the background transparency to make it slightly visible // Initialize the board // Define assets for the game var board = new Board(); game.addChild(board); board.initBoard(); function animateGemsInWave(board) { for (var i = 0; i < 8; i++) { for (var j = 0; j < 6; j++) { var gem = board.gems[i * 6 + j]; if (gem && typeof gem.scaleUpAndDown === 'function') { gem.scaleUpAndDown((i + j) * 50); } } } } animateGemsInWave(board); // Game logic LK.on('tick', function () { // Add game logic that needs to run every frame // For example, checking for matches, handling animations, etc. }); // Add a label with the same styling as the timer text, but with the opposite x-coordinate var goalTxt = new Text2('', { size: 100, weight: 500, fill: "#ffffff", x: 0, // Opposite x-coordinate y: 50, anchorX: 0, anchorY: 0, dropShadow: true, dropShadowColor: '#000000', shadowBlur: 4, shadowOffsetX: 2, shadowOffsetY: 2, strokeThickness: 7 }); board.addChild(goalTxt); goalTxt.anchor.set(0, .5); goalTxt.y = 100; goalTxt.x = 450; // Add hourglass sprite next to the timer var goalBackground = LK.getAsset('goalBackgroundSprite', { x: 2048 - 100, // Position next to the timer y: 50, // Align with the timer's top margin anchorX: .5, // Anchor right for right alignment anchorY: .5 // Anchor top for top alignment }); goalBackground.y = goalTxt.y; goalBackground.x = goalTxt.x - 100; // Position next to the timer goalBackground.anchor.set(0.5, 0.5); // Align with the timer's top margin goalBackground.alpha = .6; var timerTxt = new Text2(game.timer.toString(), { size: 100, // Made the text smaller weight: 500, fill: "#ffffff", x: 2048 - 200, y: 50, anchorX: 1, anchorY: 0, dropShadow: true, dropShadowColor: '#000000', shadowBlur: 4, shadowOffsetX: 2, shadowOffsetY: 2, strokeThickness: 7 }); // Add hourglass sprite next to the timer var hourglassSprite = LK.getAsset('hourglass', { x: 2048 - 100, // Position next to the timer y: 50, // Align with the timer's top margin anchorX: .5, // Anchor right for right alignment anchorY: .5 // Anchor top for top alignment }); function stopTimer() { if (board.timerInterval) { LK.clearInterval(board.timerInterval); } } function startTimer() { // Resume the game timer after the modal disappears stopTimer(); board.timerInterval = LK.setInterval(function () { game.timer -= 1; timerTxt.setText(game.timer.toString()); if (game.timer <= 0) { LK.showGameOver('Final Score: ' + score); } }, 1000); } // Logic to spin the hourglass var spinHourglass = function spinHourglass() { var rotationDuration = 500; // Duration of the spin in milliseconds var startTime = Date.now(); var spinStep = function spinStep() { var currentTime = Date.now(); var progress = (currentTime - startTime) / rotationDuration; hourglassSprite.rotation = progress * 2 * Math.PI; // Complete rotation if (progress < 1) { LK.setTimeout(spinStep, 16); // Aim for roughly 60fps } else { hourglassSprite.rotation = 0; startTimer(); } }; spinStep(); }; board.addChild(hourglassSprite); timerTxt.anchor.set(1, .5); timerTxt.y = 100; timerTxt.x = 2048 - 240; board.addChild(timerTxt); // Add timer display to the top GUI layer hourglassSprite.y = timerTxt.y; hourglassSprite.x = timerTxt.x + 70; // Position next to the timer hourglassSprite.anchor.set(0.5, 0.5); // Align with the timer's top margin
===================================================================
--- original.js
+++ change.js
@@ -1315,18 +1315,34 @@
particle.angle = Math.random() * Math.PI * 2; // Random angle for direction
particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement
particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic
// Introduce gravity effect to some particles
- particle.gravity = Math.random() > 0.5 ? 0.01 : 0; // Half the particles have a gravity effect
+ for (var i = 0; i < 50; i++) {
+ var particle = self.attachAsset('glowEffect', {
+ x: x,
+ y: y,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ particle.blendMode = 1;
+ particle.angle = Math.random() * Math.PI * 2; // Random angle for direction
+ particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement
+ particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic
+ particle.gravity = Math.random() > 0.5 ? 0.01 : 0; // Half the particles have a gravity effect
+ particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety
+ particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable
+ particle.startTime = Date.now();
+ particle.rotationVelocity = -0.1 + Math.random() * .2;
+ particle.x += Math.cos(particle.angle) * Math.random() * 80;
+ particle.y += Math.sin(particle.angle) * Math.random() * 80;
+ _animateParticle(particle);
+ }
particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety
particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable
particle.startTime = Date.now();
particle.rotationVelocity = -0.1 + Math.random() * .2;
particle.x += Math.cos(particle.angle) * Math.random() * 80;
particle.y += Math.sin(particle.angle) * Math.random() * 80;
- if (particle.gravity) {
- particle.y += particle.gravity * elapsedTime; // Apply gravity effect based on elapsed time
- }
_animateParticle(particle);
}
};
});
@@ -1475,16 +1491,16 @@
/****
* Game Code
****/
-// Initialize a timer for showing hints
-// Initialize 2-minute timer
-// Initialize score
-// Initialize large countdown at the beginning of the game
-// Goal gem type and count
-// Dragon spawn timer
// SagaMap class
// SagaMap class
+// Dragon spawn timer
+// Goal gem type and count
+// Initialize large countdown at the beginning of the game
+// Initialize score
+// Initialize 2-minute timer
+// Initialize a timer for showing hints
var SagaMap = /*#__PURE__*/function (_Container) {
_inherits(SagaMap, _Container);
function SagaMap() {
var _this;
a magical landscape of wonder and joy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Magic, purple gem. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
glow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Hourglass icon white. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Glow glare star. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Shiny red envelope bao, chinese new years. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Magic greem gem in odd shape. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Flying unicorn fullbody sideview. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Magic Orange Gem. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Magic Blue Drop Shaped Gem. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
remove
Brilliant Gold Checkmark. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Magic diamond. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Enchanted forest. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Celestial reAlm. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Mystic cavern. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.