/****
* 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 || {
dx: 0,
dy: 0
};
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++;
if (scoreTxt) {
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 (x, y, obj) {
self.dragStartGem = gem;
self.dragStartGemStartPosition = {
x: gem.x,
y: gem.y
};
var currentPos = game.toLocal(obj.global);
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 (x, y, obj) {
if (!self.dragStartGem) {
return;
}
var currentPos = game.toLocal(obj.global);
//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 floatGravity = 1 + 20 * Math.random();
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.y -= floatGravity; // Apply upward gravity to make confetti float upwards
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_migrated = 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();
};
});
var FireworkEffect = Container.expand(function (x, y, numParticles, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
for (var i = 0; i < numParticles; i++) {
var angle = i / numParticles * 2 * Math.PI;
var speed = 5 + Math.random() * 5; // Random speed between 5 and 10
var expansionSize = 0.5 + Math.random() * 1.5; // Variable size of expansion between 0.5 and 2
var particle = new FireworkParticle();
particle.init(self.x, self.y, angle, speed, color);
self.addChild(particle);
}
});
// FireworkParticle class
var FireworkParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('fireworkParticle', {
anchorX: 0.5,
anchorY: 0.5
});
self.init = function (x, y, angle, speed, color) {
particleGraphics.tint = color;
particleGraphics.scale.set(.5 + Math.random() * 1);
particleGraphics.rotation = Math.PI * 2 * Math.random();
self.x = x;
self.y = y;
self.angle = angle;
self.speed = speed;
self.alpha = 1;
var decay = 0.95;
var gravity = 0.05;
self._move_migrated = function () {
var decay = 0.95;
var gravity = 0.05;
self.x += Math.cos(self.angle) * self.speed;
self.y += Math.sin(self.angle) * self.speed;
self.speed *= decay;
self.y += gravity;
self.alpha *= decay;
if (self.alpha < 0.05) {
self.destroy();
}
};
LK.on('tick', function () {
self._move_migrated();
});
};
});
// 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
****/
game.width = 2048;
game.height = 2732;
// 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
// FireworkEffect class
function _typeof3(o) {
"@babel/helpers - typeof";
return _typeof3 = "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;
}, _typeof3(o);
}
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, _toPropertyKey3(descriptor.key), descriptor);
}
}
function _createClass2(Constructor, protoProps, staticProps) {
if (protoProps) {
__defineProperties(Constructor.prototype, protoProps);
}
if (staticProps) {
__defineProperties(Constructor, staticProps);
}
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
function _toPropertyKey3(t) {
var i = _toPrimitive3(t, "string");
return "symbol" == _typeof3(i) ? i : String(i);
}
function _toPrimitive3(t, r) {
if ("object" != _typeof3(t) || !t) {
return t;
}
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof3(i)) {
return i;
}
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _classCallCheck2(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _callSuper2(t, o, e) {
return o = _getPrototypeOf2(o), _possibleConstructorReturn2(t, _isNativeReflectConstruct2() ? Reflect.construct(o, e || [], _getPrototypeOf2(t).constructor) : o.apply(t, e));
}
function _possibleConstructorReturn2(self, call) {
if (call && (_typeof3(call) === "object" || typeof call === "function")) {
return call;
} else if (call !== void 0) {
throw new TypeError("Derived constructors may only return object or undefined");
}
return _assertThisInitialized2(self);
}
function _assertThisInitialized2(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct2() {
try {
var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
} catch (t) {}
return (_isNativeReflectConstruct2 = function _isNativeReflectConstruct2() {
return !!t;
})();
}
function _getPrototypeOf2(o) {
_getPrototypeOf2 = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf2(o);
}
function _inherits2(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) {
_setPrototypeOf2(subClass, superClass);
}
}
function _setPrototypeOf2(o, p) {
_setPrototypeOf2 = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf2(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);
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 board = new Board();
game.addChild(board);
board.initBoard();
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_migrated();
}
}
var nextSpawnTime = 5000 + Math.random() * 10000; // Random interval between 5 to 15 seconds
dragonSpawnTimer = LK.setTimeout(triggerDragon, nextSpawnTime);
}
triggerDragon();
var goalGemType;
var goalTxt = new Text2('', {
size: 100,
weight: 500,
fill: "#ffffff",
x: 0,
y: 50,
anchorX: 0,
anchorY: 0,
dropShadow: true,
dropShadowColor: '#000000',
shadowBlur: 4,
shadowOffsetX: 2,
shadowOffsetY: 2,
strokeThickness: 7
});
var goalBackground = LK.getAsset('goalBackgroundSprite', {
x: 2048 - 100,
y: 50,
anchorX: .5,
anchorY: .5
});
goalBackground.y = goalTxt.y;
goalBackground.x = goalTxt.x - 100;
goalBackground.anchor.set(0.5, 0.5);
goalBackground.alpha = .6;
board.addChild(goalTxt);
goalTxt.anchor.set(0, .5);
goalTxt.y = 100;
goalTxt.x = 450;
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 welcomeText = new Text2("Spooky Match", {
size: 110,
fill: "#ffff00",
x: 1024,
// Center of the screen
y: 1366,
// Middle of the screen
anchorX: 0.5,
anchorY: 0.5,
stroke: true,
weight: 800,
dropShadow: true,
dropShadowDistance: 20,
strokeColor: '#ff0000',
strokeThickness: 14
});
welcomeText.anchor.set(.5);
LK.gui.center.addChild(welcomeText); // Add countdown display to the center GUI layer
welcomeText.y = -200;
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,
strokeThickness: 14
});
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) {
var triggerFirework = function triggerFirework(fireworkDelay) {
LK.setTimeout(function () {
var x = -300 + Math.random() * 600;
var y = -500 + Math.random() * 1000;
var colors = [0xFFFFFF, 0xFF0000, 0x00FF00, 0xddddFF, 0xFFFF00, 0xFF00FF];
var color = colors[Math.floor(Math.random() * colors.length)];
var fireworkEffect = new FireworkEffect(x, y, 50, color);
LK.gui.center.addChild(fireworkEffect);
}, fireworkDelay);
};
;
countdownTxt.setText('Trick or Treat!');
countdownTxt.y = -50;
countdownTxt.setStyle({
size: 90,
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,
dropShadowDistance: 20,
strokeColor: '#ff0000',
strokeThickness: 14
});
// Trigger firework effects at various places on the screen
for (var i = 0; i < 16; i++) {
triggerFirework(i * 100 + Math.random() * 500);
}
spinHourglass();
// Bounce effect
var scaleUpDuration = 1200; // Duration to scale up in milliseconds
var scaleDownDuration = 200; // Duration to scale down in milliseconds
var maxScale = 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 fadeOutDuration = 1000; // 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
welcomeText.alpha = 1 - progress; // Fade out
if (progress < 1) {
LK.setTimeout(fadeStep, 16);
} else {
welcomeText.destroy(); // Remove countdown text after animation
countdownTxt.destroy(); // Remove countdown text after animation
LK.clearInterval(countdownInterval);
setRandomGoalGemType();
}
};
fadeStep();
};
LK.setTimeout(scaleDown, 200);
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 scoreTxt = new Text2(score.toString(), {
size: 110,
weight: 500,
fill: "#ffffff",
x: 1024,
y: 0,
anchorX: 0.5,
anchorY: 0,
dropShadow: true,
dropShadowColor: '#000000',
shadowBlur: 4,
shadowOffsetX: 2,
shadowOffsetY: 2,
stroke: true,
strokeColor: '#000000',
strokeThickness: 7
});
scoreTxt.anchor.set(.5, .5);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt);
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);
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
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.
Town of Halloween. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
blue bat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
green bat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
purple bat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
yellow bat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
spooky ghost. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
spooky halloween forest. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
dark magic particle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
stylized vampire head. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
stylized halloween pumpkin. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
stylized orange pumpkin. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
stylized purple werwolf head. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
stylized wich head. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
white scull. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
old dark cemetery, 4k, high quality, landscape, digital art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
abandoned manor, halloween, 4k, high quality, landscape, digital art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
witch's cauldron. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
horror haloween Checkmark. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.