/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Dice = Container.expand(function () { var self = Container.call(this); // Add numeric variable valor self.valor = 1; // Add rolling animation variables self.isRolling = false; self.rollCount = 0; self.rollTarget = 0; self.rollTimer = 0; var diceGraphics = self.attachAsset('Dice' + self.valor, { anchorX: 0.5, anchorY: 0.5 }); // Method to update dice visual based on valor self.updateVisual = function () { // Create new graphics based on valor first var newGraphics = self.attachAsset('Dice' + self.valor, { anchorX: 0.5, anchorY: 0.5 }); // Remove old graphics after new one is created self.removeChild(diceGraphics); // Update reference to new graphics diceGraphics = newGraphics; // Add bounce effect when value changes during rolling if (self.isRolling) { self.playDiceSound(); diceGraphics.scaleX = 1; diceGraphics.scaleY = 1; tween(diceGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.bounceOut, onFinish: function onFinish() { tween(diceGraphics, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.bounceOut }); } }); } }; // Method to play dice sound self.playDiceSound = function () { LK.getSound('Roll').play(); }; // Method to start rolling animation self.startRoll = function () { self.isRolling = true; self.rollCount = 0; self.rollTarget = Math.floor(Math.random() * 7) + 6; // 6 to 12 rolls self.rollTimer = 0; }; // Update method for rolling animation self.update = function () { if (self.isRolling) { var rollSpeed = Math.floor(self.rollCount * 1.5) + 3; // Start fast, get slower if (self.rollTimer >= rollSpeed) { self.valor = Math.floor(Math.random() * 6) + 1; self.updateVisual(); self.rollCount++; self.rollTimer = 0; if (self.rollCount >= self.rollTarget) { self.isRolling = false; } } else { self.rollTimer++; } } }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('Particula', { anchorX: 0.5, anchorY: 0.5 }); // Initialize particle properties self.velocityX = (Math.random() - 0.5) * 10; self.velocityY = Math.random() * -8 - 2; self.gravity = 0.3; self.life = 1.0; self.fadeSpeed = Math.random() * 0.02 + 0.01; // Randomize initial scale and color with more variety var initialScale = Math.random() * 0.6 + 0.2; particleGraphics.scaleX = initialScale; particleGraphics.scaleY = initialScale; var colors = [0xFFD700, 0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE00, 0xF38BA8, 0xFF9500, 0x8E44AD, 0xE74C3C]; particleGraphics.tint = colors[Math.floor(Math.random() * colors.length)]; // Add rotation and pulsing effect self.rotationSpeed = (Math.random() - 0.5) * 0.2; self.pulseSpeed = Math.random() * 0.1 + 0.05; self.pulseOffset = Math.random() * Math.PI * 2; self.update = function () { // Update position self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; // Add rotation particleGraphics.rotation += self.rotationSpeed; // Add pulsing effect var pulseScale = 1 + Math.sin(LK.ticks * self.pulseSpeed + self.pulseOffset) * 0.2; // Update life and fade self.life -= self.fadeSpeed; particleGraphics.alpha = Math.max(0, self.life); // Scale down over time with pulse effect var scale = initialScale * self.life * pulseScale; particleGraphics.scaleX = scale; particleGraphics.scaleY = scale; // Remove when life is over if (self.life <= 0) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ // Create array to hold all dice var game = new LK.Game({ backgroundColor: 0xFFFFFF }); /**** * Game Code ****/ // Create array to hold all dice var diceArray = []; // Create array to hold particles var particles = []; // Add lanzamiento boolean variable var lanzamiento = false; // Add timer to enforce minimum 1 second wait between rolls var lastRollFinishTime = 0; var minimumWaitTime = 1000; // 1 second in milliseconds // Add best score tracking - load from storage with defaults var bestScore = storage.bestScore || 0; var previousScore = storage.previousScore || 0; var actualScore = storage.actualScore || 0; // Add time tracking variables var startTime = Date.now(); var totalPlayTime = storage.totalPlayTime || 0; // Load saved time in seconds var timeTimer = null; // Calculate center positions for two columns var centerX = 2048 / 2; var centerY = 2732 / 2; var columnSpacing = 330; // Space between columns var rowSpacing = 300; // Space between rows // Create play time display text at the very top var playTimeText = new Text2('Play Time: 0:00', { size: 60, fill: 0x424242, align: 'center', font: "'Helvetica Neue', 'Arial', sans-serif" }); playTimeText.anchor.set(0.5, 0); playTimeText.y = 20; // Position at very top LK.gui.top.addChild(playTimeText); // Create matching dice counter text var counterText = new Text2('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: ' + actualScore + '/8', { size: 80, fill: 0x2E7D32, align: 'center', font: "'Helvetica Neue', 'Arial', sans-serif" }); counterText.anchor.set(0.5, 0); counterText.y = 140; // Move down to make space for play time text LK.gui.top.addChild(counterText); // Create status text above dice var statusText = new Text2('Tap to roll', { size: 60, fill: 0x1976D2, font: "'Helvetica Neue', 'Arial', sans-serif" }); statusText.anchor.set(0.5, 0.5); statusText.x = centerX; statusText.y = centerY - 700; // Position above dice grid game.addChild(statusText); // Create countdown text var countdownText = new Text2('', { size: 50, fill: 0xF57C00, font: "'Helvetica Neue', 'Arial', sans-serif" }); countdownText.anchor.set(0.5, 0.5); countdownText.x = centerX; countdownText.y = centerY - 640; // Position below status text game.addChild(countdownText); // Create probability text at bottom of screen var probabilityText = new Text2('', { size: 80, fill: 0x7B1FA2, align: 'center', font: "'Helvetica Neue', 'Arial', sans-serif" }); probabilityText.anchor.set(0.5, 1); probabilityText.x = centerX; probabilityText.y = 2732 - 50; // Position at bottom with margin game.addChild(probabilityText); // Function to count matching dice function countMatchingDice() { var counts = {}; // Count occurrences of each dice value for (var i = 0; i < diceArray.length; i++) { var value = diceArray[i].valor; counts[value] = (counts[value] || 0) + 1; } // Find the highest count var maxCount = 0; for (var value in counts) { if (counts[value] > maxCount) { maxCount = counts[value]; } } return maxCount; } // Function to calculate factorial function factorial(n) { if (n <= 1) return 1; var result = 1; for (var i = 2; i <= n; i++) { result *= i; } return result; } // Function to calculate multinomial coefficient function multinomial(n, counts) { var result = factorial(n); for (var i = 0; i < counts.length; i++) { result /= factorial(counts[i]); } return result; } // Function to generate all partitions of 8 with maximum value k function generatePartitions(sum, maxValue, numSlots) { var partitions = []; function backtrack(remaining, currentPartition, maxSoFar, slot) { if (slot === numSlots) { if (remaining === 0 && maxSoFar === maxValue) { partitions.push(currentPartition.slice()); } return; } for (var i = 0; i <= remaining; i++) { currentPartition[slot] = i; var newMaxSoFar = Math.max(maxSoFar, i); if (newMaxSoFar <= maxValue) { backtrack(remaining - i, currentPartition, newMaxSoFar, slot + 1); } } } var partition = new Array(numSlots); backtrack(sum, partition, 0, 0); return partitions; } // Function to calculate probability of getting exactly N matching dice in 8 rolls function calculateProbability(n) { if (n < 1 || n > 8) return 0; // Using the formula: P(exactly k) = (1/6^8) * sum of multinomial coefficients // where the sum is over all partitions with maximum value k var partitions = generatePartitions(8, n, 6); var sum = 0; for (var i = 0; i < partitions.length; i++) { sum += multinomial(8, partitions[i]); } var probability = sum / Math.pow(6, 8); return probability; } // Function to update probability display function updateProbabilityDisplay() { var matchingCount = countMatchingDice(); var probability = calculateProbability(matchingCount); var oneInX = Math.round(1 / probability); probabilityText.setText('Probability:\n1 in ' + oneInX); } // Function to create particles for largest matching group function createParticlesForLargestGroup() { var counts = {}; // Count occurrences of each dice value for (var i = 0; i < diceArray.length; i++) { var value = diceArray[i].valor; counts[value] = (counts[value] || 0) + 1; } // Find the highest count and value var maxCount = 0; var maxValue = 0; for (var value in counts) { if (counts[value] > maxCount) { maxCount = counts[value]; maxValue = parseInt(value); } } // Create particles for each die in the largest group for (var i = 0; i < diceArray.length; i++) { var dice = diceArray[i]; if (dice.valor == maxValue && counts[maxValue] == maxCount && maxCount > 1) { // Create 8-12 particles per die in largest group var particleCount = Math.floor(Math.random() * 5) + 8; for (var p = 0; p < particleCount; p++) { var particle = new Particle(); particle.x = dice.x + (Math.random() - 0.5) * 80; particle.y = dice.y + (Math.random() - 0.5) * 80; // Add tween animation to particles for extra visual effect tween(particle, { scaleX: Math.random() * 0.5 + 0.8, scaleY: Math.random() * 0.5 + 0.8, rotation: Math.random() * Math.PI * 2 }, { duration: 1000 + Math.random() * 500, easing: tween.easeOut }); game.addChild(particle); particles.push(particle); } } } } // Function to apply tint colors to dice based on matching groups function applyDiceTints() { var counts = {}; // Count occurrences of each dice value for (var i = 0; i < diceArray.length; i++) { var value = diceArray[i].valor; counts[value] = (counts[value] || 0) + 1; } // Find the highest count and value var maxCount = 0; var maxValue = 0; for (var value in counts) { if (counts[value] > maxCount) { maxCount = counts[value]; maxValue = parseInt(value); } } // Generate random colors for smaller groups var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE00, 0xF38BA8]; var colorIndex = 0; var usedColors = {}; // Apply tints to all dice for (var i = 0; i < diceArray.length; i++) { var dice = diceArray[i]; var value = dice.valor; if (value == maxValue && counts[value] == maxCount) { // Largest group gets soft yellow tint dice.children[0].tint = 0xFFFF99; // Soft yellow } else if (counts[value] > 1) { // Smaller matching groups get random colors if (!usedColors[value]) { usedColors[value] = randomColors[colorIndex % randomColors.length]; colorIndex++; } dice.children[0].tint = usedColors[value]; } else { // Single dice get no tint (white) dice.children[0].tint = 0xFFFFFF; } } } // Function to format time in minutes:seconds function formatTime(seconds) { var minutes = Math.floor(seconds / 60); var remainingSeconds = seconds % 60; return minutes + ':' + (remainingSeconds < 10 ? '0' : '') + remainingSeconds; } // Function to update play time display function updatePlayTime() { var currentSessionTime = Math.floor((Date.now() - startTime) / 1000); var totalTime = totalPlayTime + currentSessionTime; playTimeText.setText('Play Time: ' + formatTime(totalTime)); // Save total play time to storage storage.totalPlayTime = totalTime; } // Set up timer to update play time every second (only once) if (!timeTimer) { timeTimer = LK.setInterval(function () { updatePlayTime(); }, 1000); } // Initial update of play time display updatePlayTime(); // Create 8 dice in two columns (4 rows each) for (var col = 0; col < 2; col++) { for (var row = 0; row < 4; row++) { var dice = new Dice(); // Assign random valor from 1 to 6 dice.valor = Math.floor(Math.random() * 6) + 1; // Update visual based on valor dice.updateVisual(); // Position dice in grid dice.x = centerX + (col - 0.5) * columnSpacing; dice.y = centerY + (row - 1.5) * rowSpacing; // Add to game and array game.addChild(dice); diceArray.push(dice); } // Game update method to handle dice rolling game.update = function () { // Update status and countdown text based on current state var currentTime = Date.now(); var timeSinceLastRoll = currentTime - lastRollFinishTime; var timeRemaining = minimumWaitTime - timeSinceLastRoll; if (lanzamiento) { // Currently rolling statusText.setText('Rolling dice...'); countdownText.setText(''); } else if (timeRemaining > 0) { // Waiting period - show countdown statusText.setText('Wait to roll'); var secondsRemaining = timeRemaining / 1000; countdownText.setText(secondsRemaining.toFixed(2) + 's'); } else { // Ready to roll statusText.setText('Tap to roll'); countdownText.setText(''); } // Check if all dice have finished rolling if (lanzamiento) { var allFinished = true; for (var i = 0; i < diceArray.length; i++) { if (diceArray[i].isRolling) { allFinished = false; break; } } // Reset lanzamiento when all dice are done if (allFinished) { lanzamiento = false; // Record the time when rolling finished lastRollFinishTime = Date.now(); // Update counter text with matching dice count var matchingCount = countMatchingDice(); actualScore = matchingCount; // Update best score if current is better if (matchingCount > bestScore) { bestScore = matchingCount; } // Save scores to storage storage.bestScore = bestScore; storage.previousScore = previousScore; storage.actualScore = actualScore; counterText.setText('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: ' + matchingCount + '/8'); // Apply tint colors to dice based on matching groups applyDiceTints(); // Create particles for largest matching group createParticlesForLargestGroup(); // Create extra celebration particles for high scores if (matchingCount >= 4) { var burstCount = matchingCount * 3; // More particles for higher scores for (var b = 0; b < burstCount; b++) { var burstParticle = new Particle(); burstParticle.x = centerX + (Math.random() - 0.5) * 300; burstParticle.y = centerY + (Math.random() - 0.5) * 200; burstParticle.velocityX = (Math.random() - 0.5) * 15; burstParticle.velocityY = Math.random() * -12 - 3; // Add sparkle effect with tweening tween(burstParticle, { rotation: Math.PI * 4, scaleX: 0.1, scaleY: 0.1 }, { duration: 2000, easing: tween.easeOut }); game.addChild(burstParticle); particles.push(burstParticle); } } // Update probability display updateProbabilityDisplay(); } } // Clean up destroyed particles for (var i = particles.length - 1; i >= 0; i--) { if (particles[i].destroyed) { particles.splice(i, 1); } } }; // Add screen tap handler for lanzamiento event game.down = function (x, y, obj) { // Check if enough time has passed since last roll finished var currentTime = Date.now(); var timeSinceLastRoll = currentTime - lastRollFinishTime; // Only allow new roll if not currently rolling AND minimum wait time has passed if (!lanzamiento && timeSinceLastRoll >= minimumWaitTime) { // Copy current score to previous score when starting new roll var currentMatchingCount = countMatchingDice(); previousScore = currentMatchingCount; // Save previous score to storage storage.previousScore = previousScore; // Update counter text to show actual as 0/8 during rolling counterText.setText('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: 0/8'); lanzamiento = true; // Start rolling animation for all dice for (var i = 0; i < diceArray.length; i++) { diceArray[i].startRoll(); } } }; }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Dice = Container.expand(function () {
var self = Container.call(this);
// Add numeric variable valor
self.valor = 1;
// Add rolling animation variables
self.isRolling = false;
self.rollCount = 0;
self.rollTarget = 0;
self.rollTimer = 0;
var diceGraphics = self.attachAsset('Dice' + self.valor, {
anchorX: 0.5,
anchorY: 0.5
});
// Method to update dice visual based on valor
self.updateVisual = function () {
// Create new graphics based on valor first
var newGraphics = self.attachAsset('Dice' + self.valor, {
anchorX: 0.5,
anchorY: 0.5
});
// Remove old graphics after new one is created
self.removeChild(diceGraphics);
// Update reference to new graphics
diceGraphics = newGraphics;
// Add bounce effect when value changes during rolling
if (self.isRolling) {
self.playDiceSound();
diceGraphics.scaleX = 1;
diceGraphics.scaleY = 1;
tween(diceGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(diceGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.bounceOut
});
}
});
}
};
// Method to play dice sound
self.playDiceSound = function () {
LK.getSound('Roll').play();
};
// Method to start rolling animation
self.startRoll = function () {
self.isRolling = true;
self.rollCount = 0;
self.rollTarget = Math.floor(Math.random() * 7) + 6; // 6 to 12 rolls
self.rollTimer = 0;
};
// Update method for rolling animation
self.update = function () {
if (self.isRolling) {
var rollSpeed = Math.floor(self.rollCount * 1.5) + 3; // Start fast, get slower
if (self.rollTimer >= rollSpeed) {
self.valor = Math.floor(Math.random() * 6) + 1;
self.updateVisual();
self.rollCount++;
self.rollTimer = 0;
if (self.rollCount >= self.rollTarget) {
self.isRolling = false;
}
} else {
self.rollTimer++;
}
}
};
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('Particula', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize particle properties
self.velocityX = (Math.random() - 0.5) * 10;
self.velocityY = Math.random() * -8 - 2;
self.gravity = 0.3;
self.life = 1.0;
self.fadeSpeed = Math.random() * 0.02 + 0.01;
// Randomize initial scale and color with more variety
var initialScale = Math.random() * 0.6 + 0.2;
particleGraphics.scaleX = initialScale;
particleGraphics.scaleY = initialScale;
var colors = [0xFFD700, 0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE00, 0xF38BA8, 0xFF9500, 0x8E44AD, 0xE74C3C];
particleGraphics.tint = colors[Math.floor(Math.random() * colors.length)];
// Add rotation and pulsing effect
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.pulseSpeed = Math.random() * 0.1 + 0.05;
self.pulseOffset = Math.random() * Math.PI * 2;
self.update = function () {
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Add rotation
particleGraphics.rotation += self.rotationSpeed;
// Add pulsing effect
var pulseScale = 1 + Math.sin(LK.ticks * self.pulseSpeed + self.pulseOffset) * 0.2;
// Update life and fade
self.life -= self.fadeSpeed;
particleGraphics.alpha = Math.max(0, self.life);
// Scale down over time with pulse effect
var scale = initialScale * self.life * pulseScale;
particleGraphics.scaleX = scale;
particleGraphics.scaleY = scale;
// Remove when life is over
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
// Create array to hold all dice
var game = new LK.Game({
backgroundColor: 0xFFFFFF
});
/****
* Game Code
****/
// Create array to hold all dice
var diceArray = [];
// Create array to hold particles
var particles = [];
// Add lanzamiento boolean variable
var lanzamiento = false;
// Add timer to enforce minimum 1 second wait between rolls
var lastRollFinishTime = 0;
var minimumWaitTime = 1000; // 1 second in milliseconds
// Add best score tracking - load from storage with defaults
var bestScore = storage.bestScore || 0;
var previousScore = storage.previousScore || 0;
var actualScore = storage.actualScore || 0;
// Add time tracking variables
var startTime = Date.now();
var totalPlayTime = storage.totalPlayTime || 0; // Load saved time in seconds
var timeTimer = null;
// Calculate center positions for two columns
var centerX = 2048 / 2;
var centerY = 2732 / 2;
var columnSpacing = 330; // Space between columns
var rowSpacing = 300; // Space between rows
// Create play time display text at the very top
var playTimeText = new Text2('Play Time: 0:00', {
size: 60,
fill: 0x424242,
align: 'center',
font: "'Helvetica Neue', 'Arial', sans-serif"
});
playTimeText.anchor.set(0.5, 0);
playTimeText.y = 20; // Position at very top
LK.gui.top.addChild(playTimeText);
// Create matching dice counter text
var counterText = new Text2('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: ' + actualScore + '/8', {
size: 80,
fill: 0x2E7D32,
align: 'center',
font: "'Helvetica Neue', 'Arial', sans-serif"
});
counterText.anchor.set(0.5, 0);
counterText.y = 140; // Move down to make space for play time text
LK.gui.top.addChild(counterText);
// Create status text above dice
var statusText = new Text2('Tap to roll', {
size: 60,
fill: 0x1976D2,
font: "'Helvetica Neue', 'Arial', sans-serif"
});
statusText.anchor.set(0.5, 0.5);
statusText.x = centerX;
statusText.y = centerY - 700; // Position above dice grid
game.addChild(statusText);
// Create countdown text
var countdownText = new Text2('', {
size: 50,
fill: 0xF57C00,
font: "'Helvetica Neue', 'Arial', sans-serif"
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = centerX;
countdownText.y = centerY - 640; // Position below status text
game.addChild(countdownText);
// Create probability text at bottom of screen
var probabilityText = new Text2('', {
size: 80,
fill: 0x7B1FA2,
align: 'center',
font: "'Helvetica Neue', 'Arial', sans-serif"
});
probabilityText.anchor.set(0.5, 1);
probabilityText.x = centerX;
probabilityText.y = 2732 - 50; // Position at bottom with margin
game.addChild(probabilityText);
// Function to count matching dice
function countMatchingDice() {
var counts = {};
// Count occurrences of each dice value
for (var i = 0; i < diceArray.length; i++) {
var value = diceArray[i].valor;
counts[value] = (counts[value] || 0) + 1;
}
// Find the highest count
var maxCount = 0;
for (var value in counts) {
if (counts[value] > maxCount) {
maxCount = counts[value];
}
}
return maxCount;
}
// Function to calculate factorial
function factorial(n) {
if (n <= 1) return 1;
var result = 1;
for (var i = 2; i <= n; i++) {
result *= i;
}
return result;
}
// Function to calculate multinomial coefficient
function multinomial(n, counts) {
var result = factorial(n);
for (var i = 0; i < counts.length; i++) {
result /= factorial(counts[i]);
}
return result;
}
// Function to generate all partitions of 8 with maximum value k
function generatePartitions(sum, maxValue, numSlots) {
var partitions = [];
function backtrack(remaining, currentPartition, maxSoFar, slot) {
if (slot === numSlots) {
if (remaining === 0 && maxSoFar === maxValue) {
partitions.push(currentPartition.slice());
}
return;
}
for (var i = 0; i <= remaining; i++) {
currentPartition[slot] = i;
var newMaxSoFar = Math.max(maxSoFar, i);
if (newMaxSoFar <= maxValue) {
backtrack(remaining - i, currentPartition, newMaxSoFar, slot + 1);
}
}
}
var partition = new Array(numSlots);
backtrack(sum, partition, 0, 0);
return partitions;
}
// Function to calculate probability of getting exactly N matching dice in 8 rolls
function calculateProbability(n) {
if (n < 1 || n > 8) return 0;
// Using the formula: P(exactly k) = (1/6^8) * sum of multinomial coefficients
// where the sum is over all partitions with maximum value k
var partitions = generatePartitions(8, n, 6);
var sum = 0;
for (var i = 0; i < partitions.length; i++) {
sum += multinomial(8, partitions[i]);
}
var probability = sum / Math.pow(6, 8);
return probability;
}
// Function to update probability display
function updateProbabilityDisplay() {
var matchingCount = countMatchingDice();
var probability = calculateProbability(matchingCount);
var oneInX = Math.round(1 / probability);
probabilityText.setText('Probability:\n1 in ' + oneInX);
}
// Function to create particles for largest matching group
function createParticlesForLargestGroup() {
var counts = {};
// Count occurrences of each dice value
for (var i = 0; i < diceArray.length; i++) {
var value = diceArray[i].valor;
counts[value] = (counts[value] || 0) + 1;
}
// Find the highest count and value
var maxCount = 0;
var maxValue = 0;
for (var value in counts) {
if (counts[value] > maxCount) {
maxCount = counts[value];
maxValue = parseInt(value);
}
}
// Create particles for each die in the largest group
for (var i = 0; i < diceArray.length; i++) {
var dice = diceArray[i];
if (dice.valor == maxValue && counts[maxValue] == maxCount && maxCount > 1) {
// Create 8-12 particles per die in largest group
var particleCount = Math.floor(Math.random() * 5) + 8;
for (var p = 0; p < particleCount; p++) {
var particle = new Particle();
particle.x = dice.x + (Math.random() - 0.5) * 80;
particle.y = dice.y + (Math.random() - 0.5) * 80;
// Add tween animation to particles for extra visual effect
tween(particle, {
scaleX: Math.random() * 0.5 + 0.8,
scaleY: Math.random() * 0.5 + 0.8,
rotation: Math.random() * Math.PI * 2
}, {
duration: 1000 + Math.random() * 500,
easing: tween.easeOut
});
game.addChild(particle);
particles.push(particle);
}
}
}
}
// Function to apply tint colors to dice based on matching groups
function applyDiceTints() {
var counts = {};
// Count occurrences of each dice value
for (var i = 0; i < diceArray.length; i++) {
var value = diceArray[i].valor;
counts[value] = (counts[value] || 0) + 1;
}
// Find the highest count and value
var maxCount = 0;
var maxValue = 0;
for (var value in counts) {
if (counts[value] > maxCount) {
maxCount = counts[value];
maxValue = parseInt(value);
}
}
// Generate random colors for smaller groups
var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE00, 0xF38BA8];
var colorIndex = 0;
var usedColors = {};
// Apply tints to all dice
for (var i = 0; i < diceArray.length; i++) {
var dice = diceArray[i];
var value = dice.valor;
if (value == maxValue && counts[value] == maxCount) {
// Largest group gets soft yellow tint
dice.children[0].tint = 0xFFFF99; // Soft yellow
} else if (counts[value] > 1) {
// Smaller matching groups get random colors
if (!usedColors[value]) {
usedColors[value] = randomColors[colorIndex % randomColors.length];
colorIndex++;
}
dice.children[0].tint = usedColors[value];
} else {
// Single dice get no tint (white)
dice.children[0].tint = 0xFFFFFF;
}
}
}
// Function to format time in minutes:seconds
function formatTime(seconds) {
var minutes = Math.floor(seconds / 60);
var remainingSeconds = seconds % 60;
return minutes + ':' + (remainingSeconds < 10 ? '0' : '') + remainingSeconds;
}
// Function to update play time display
function updatePlayTime() {
var currentSessionTime = Math.floor((Date.now() - startTime) / 1000);
var totalTime = totalPlayTime + currentSessionTime;
playTimeText.setText('Play Time: ' + formatTime(totalTime));
// Save total play time to storage
storage.totalPlayTime = totalTime;
}
// Set up timer to update play time every second (only once)
if (!timeTimer) {
timeTimer = LK.setInterval(function () {
updatePlayTime();
}, 1000);
}
// Initial update of play time display
updatePlayTime();
// Create 8 dice in two columns (4 rows each)
for (var col = 0; col < 2; col++) {
for (var row = 0; row < 4; row++) {
var dice = new Dice();
// Assign random valor from 1 to 6
dice.valor = Math.floor(Math.random() * 6) + 1;
// Update visual based on valor
dice.updateVisual();
// Position dice in grid
dice.x = centerX + (col - 0.5) * columnSpacing;
dice.y = centerY + (row - 1.5) * rowSpacing;
// Add to game and array
game.addChild(dice);
diceArray.push(dice);
}
// Game update method to handle dice rolling
game.update = function () {
// Update status and countdown text based on current state
var currentTime = Date.now();
var timeSinceLastRoll = currentTime - lastRollFinishTime;
var timeRemaining = minimumWaitTime - timeSinceLastRoll;
if (lanzamiento) {
// Currently rolling
statusText.setText('Rolling dice...');
countdownText.setText('');
} else if (timeRemaining > 0) {
// Waiting period - show countdown
statusText.setText('Wait to roll');
var secondsRemaining = timeRemaining / 1000;
countdownText.setText(secondsRemaining.toFixed(2) + 's');
} else {
// Ready to roll
statusText.setText('Tap to roll');
countdownText.setText('');
}
// Check if all dice have finished rolling
if (lanzamiento) {
var allFinished = true;
for (var i = 0; i < diceArray.length; i++) {
if (diceArray[i].isRolling) {
allFinished = false;
break;
}
}
// Reset lanzamiento when all dice are done
if (allFinished) {
lanzamiento = false;
// Record the time when rolling finished
lastRollFinishTime = Date.now();
// Update counter text with matching dice count
var matchingCount = countMatchingDice();
actualScore = matchingCount;
// Update best score if current is better
if (matchingCount > bestScore) {
bestScore = matchingCount;
}
// Save scores to storage
storage.bestScore = bestScore;
storage.previousScore = previousScore;
storage.actualScore = actualScore;
counterText.setText('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: ' + matchingCount + '/8');
// Apply tint colors to dice based on matching groups
applyDiceTints();
// Create particles for largest matching group
createParticlesForLargestGroup();
// Create extra celebration particles for high scores
if (matchingCount >= 4) {
var burstCount = matchingCount * 3; // More particles for higher scores
for (var b = 0; b < burstCount; b++) {
var burstParticle = new Particle();
burstParticle.x = centerX + (Math.random() - 0.5) * 300;
burstParticle.y = centerY + (Math.random() - 0.5) * 200;
burstParticle.velocityX = (Math.random() - 0.5) * 15;
burstParticle.velocityY = Math.random() * -12 - 3;
// Add sparkle effect with tweening
tween(burstParticle, {
rotation: Math.PI * 4,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 2000,
easing: tween.easeOut
});
game.addChild(burstParticle);
particles.push(burstParticle);
}
}
// Update probability display
updateProbabilityDisplay();
}
}
// Clean up destroyed particles
for (var i = particles.length - 1; i >= 0; i--) {
if (particles[i].destroyed) {
particles.splice(i, 1);
}
}
};
// Add screen tap handler for lanzamiento event
game.down = function (x, y, obj) {
// Check if enough time has passed since last roll finished
var currentTime = Date.now();
var timeSinceLastRoll = currentTime - lastRollFinishTime;
// Only allow new roll if not currently rolling AND minimum wait time has passed
if (!lanzamiento && timeSinceLastRoll >= minimumWaitTime) {
// Copy current score to previous score when starting new roll
var currentMatchingCount = countMatchingDice();
previousScore = currentMatchingCount;
// Save previous score to storage
storage.previousScore = previousScore;
// Update counter text to show actual as 0/8 during rolling
counterText.setText('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: 0/8');
lanzamiento = true;
// Start rolling animation for all dice
for (var i = 0; i < diceArray.length; i++) {
diceArray[i].startRoll();
}
}
};
}