/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { collectedFootballs: [] }); /**** * Classes ****/ //Library for using the camera (the background becomes the user's camera video feed) and the microphone. It can access face coordinates for interactive play, as well detect microphone volume / voice interactions // var facekit = LK.import('@upit/facekit.v1'); //Classes can only be defined here. You cannot create inline classes in the games code. var Football = Container.expand(function (id) { var self = Container.call(this); self.id = id; // Unique ID for the football // Use the correct asset for each football type var assetId = id; // Defensive: fallback to generic if asset not found var validAssets = { 'Tropical': true, 'Cave': true, 'Crystal': true, 'Fire': true, 'Galaxy': true, 'Magic': true, 'Snow': true, 'Gold': true, 'Honey': true, 'Ocean': true, 'Plant': true, 'Rainbow': true, 'Regular': true, 'Slime': true, 'Night': true, 'Sky': true, 'Cheese': true, 'Popcorn': true, 'Mismi': true, 'Volcano': true, 'Soapy': true, 'Ice': true, 'Neon': true, 'Nuclear': true, 'Coral': true, 'Astronaut': true, 'Icecream': true, 'Medival': true, 'Star': true, 'Coconut': true, 'Clock': true, 'Jellyfish': true, 'Airplane': true, 'Bacon': true, 'Potato': true, 'Money': true, 'Pickle': true, 'Pumpkin': true, 'Rock': true, 'Gummy': true, 'Wizard': true, 'Polka': true }; if (!validAssets[assetId]) assetId = 'football'; self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); return self; }); var InventorySlot = Container.expand(function (footballId) { var self = Container.call(this); self.footballId = footballId; self.attachAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5 }); // Display the football if it has been collected if (isFootballCollected(footballId)) { var football = new Football(footballId); football.scale.set(1.75); // Scale up to fit in slot football.x = self.width / 2; football.y = self.height / 2; self.addChild(football); } else { // Display a placeholder or question mark for uncollected footballs var placeholder = new Text2('?', { size: 150, fill: 0xFFFFFF }); placeholder.anchor.set(0.5); placeholder.x = self.width / 2; placeholder.y = self.height / 2; self.addChild(placeholder); } return self; }); var Pack = Container.expand(function () { var self = Container.call(this); self.attachAsset('pack', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { // Open the pack when pressed openPack(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a // Dark background }); /**** * Game Code ****/ //Storage library which should be used for persistent game data //Minimalistic tween library which should be used for animations over time, including tinting / colouring an object, scaling, rotating, or changing any game object property. //Only include the plugins you need to create the game. //We have access to the following plugins. (Note that the variable names used are mandetory for each plugin) // Initialize music // Placeholder football graphic // Initialize assets used in this game. Scale them according to what is needed for the game. // or via static code analysis based on their usage in the code. // Assets are automatically created and loaded either dynamically during gameplay /* Supported Types: 1. Shape: - Simple geometric figures with these properties: * width: (required) pixel width of the shape. * height: (required) pixel height of the shape. * color: (required) color of the shape. * shape: (required) type of shape. Valid options: 'box', 'ellipse'. 2. Image: - Imported images with these properties: * width: (required) pixel resolution width. * height: (required) pixel resolution height. * id: (required) identifier for the image. * flipX: (optional) horizontal flip. Valid values: 0 (no flip), 1 (flip). * flipY: (optional) vertical flip. Valid values: 0 (no flip), 1 (flip). * orientation: (optional) rotation in multiples of 90 degrees, clockwise. Valid values: - 0: No rotation. - 1: Rotate 90 degrees. - 2: Rotate 180 degrees. - 3: Rotate 270 degrees. Note: Width and height remain unchanged upon flipping. 3. Sound: - Sound effects with these properties: * id: (required) identifier for the sound. * volume: (optional) custom volume. Valid values are a float from 0 to 1. 4. Music: - In contract to sound effects, only one music can be played at a time - Music is using the same API to initilize just like sound. - Music loops by default - Music with these config options: * id: (required) identifier for the sound. * volume: (optional) custom volume. Valid values are a float from 0 to 1. * start: (optional) a float from 0 to 1 used for cropping and indicates the start of the cropping * end: (optional) a float from 0 to 1 used for cropping and indicates the end of the cropping */ var allFootballs = []; // Array of all possible football IDs var packNode = null; // The visual representation of the pack var inventoryContainer = null; // Container for inventory slots var scoreTxt = null; // Text display for collection progress // Define all possible football IDs (actual asset names) allFootballs = ['Tropical', 'Cave', 'Crystal', 'Fire', 'Galaxy', 'Magic', 'Snow', 'Gold', 'Honey', 'Ocean', 'Plant', 'Rainbow', 'Regular', 'Slime', 'Night', 'Sky', 'Cheese', 'Popcorn', 'Mismi', 'Volcano', 'Soapy', 'Ice', 'Neon', 'Nuclear', 'Coral', 'Astronaut', 'Icecream', 'Medival', 'Star', 'Coconut', 'Clock', 'Jellyfish', 'Airplane', 'Bacon', 'Potato', 'Money', 'Pickle', 'Pumpkin', 'Rock', 'Gummy', 'Wizard', 'Polka']; // Function to check if a football ID is in the player's collection function isFootballCollected(footballId) { return storage.collectedFootballs.indexOf(footballId) !== -1; } // Function to get a random uncollected football ID function getRandomUncollectedFootballId() { var uncollected = allFootballs.filter(function (id) { return !isFootballCollected(id); }); if (uncollected.length === 0) { return null; // All footballs collected } var randomIndex = Math.floor(Math.random() * uncollected.length); return uncollected[randomIndex]; } // Function to get a random football ID (collected or uncollected) function getRandomFootballId() { var randomIndex = Math.floor(Math.random() * allFootballs.length); return allFootballs[randomIndex]; } // Function to open a pack function openPack() { // Remove the pack node if (packNode) { packNode.destroy(); packNode = null; } LK.getSound('openPack').play(); var revealedFootballs = []; // Generate 4 footballs. Allow duplicates, but if not all collected, bias toward uncollected for at least one slot var guaranteedUncollected = !allFootballs.every(isFootballCollected); var uncollectedGiven = false; for (var i = 0; i < 4; i++) { var footballId; // Guarantee at least one uncollected if possible if (guaranteedUncollected && !uncollectedGiven) { footballId = getRandomUncollectedFootballId(); if (footballId !== null) { uncollectedGiven = true; } else { footballId = getRandomFootballId(); } } else { footballId = getRandomFootballId(); } revealedFootballs.push(footballId); // Add to collection if not already collected if (!isFootballCollected(footballId)) { storage.collectedFootballs.push(footballId); LK.getSound('collectFootball').play(); } } // Update storage immediately (ensure persistence) storage.collectedFootballs = storage.collectedFootballs; // Display the revealed footballs var startX = (game.width - (revealedFootballs.length * 300 + (revealedFootballs.length - 1) * 50)) / 2 + 150; var startY = game.height / 2; for (var j = 0; j < revealedFootballs.length; j++) { var football = new Football(revealedFootballs[j]); football.scale.set(1.75); // Increase scale for visibility football.x = startX + j * 350; football.y = startY; game.addChild(football); // Simple animation tween(football, { y: football.y - 200 }, { duration: 500, easing: tween.easeOut }); tween(football, { rotation: Math.PI * 2 }, { duration: 1000, easing: tween.linear }); // Delete football after animation is done (after 1000ms) // Delete football after animation is done (after 1000ms) (function (footballRef) { var thisJ = j; // capture the current value of j for this closure LK.setTimeout(function () { // Always destroy the football after animation, do not leave it visible if (footballRef && footballRef.parent) { // Optionally, you could play a quick scale-down animation before destroy tween(footballRef, { scaleX: 0.5, scaleY: 0.5 }, { duration: 200, easing: tween.easeOut, complete: function complete() { if (footballRef && footballRef.parent) { footballRef.destroy(); } } }); } }, 1000); })(football); } // Update collection progress display updateCollectionProgress(); // After a delay, show the inventory again LK.setTimeout(showInventory, 3000); // Show inventory after 3 seconds } // Function to update the collection progress display function updateCollectionProgress() { var collectedCount = storage.collectedFootballs.length; var totalCount = allFootballs.length; scoreTxt.setText('Collected: ' + collectedCount + '/' + totalCount); // Check for win condition if (collectedCount === totalCount) { LK.showYouWin(); } } // Function to show the inventory function showInventory() { // Remove any revealed footballs from pack opening game.children.forEach(function (child) { if (child instanceof Football) { child.destroy(); } }); // Create or show the inventory container if (!inventoryContainer) { inventoryContainer = new Container(); // Configure for horizontal scrolling inventoryContainer.interactive = true; inventoryContainer.overflow = 'scroll'; inventoryContainer.scrollDirection = 'horizontal'; // Add drag functionality for manual horizontal scrolling var dragging = false; var lastMouseX = 0; var scrollOffset = 0; var minScroll = 0; var slotWidth = 300; var slotHeight = 300; var padding = 50; var totalContentWidth = allFootballs.length * (slotWidth + padding) - padding; var maxScroll = Math.max(0, totalContentWidth - game.width); inventoryContainer.down = function (x, y, obj) { dragging = true; lastMouseX = x; }; inventoryContainer.move = function (x, y, obj) { if (dragging) { var deltaX = x - lastMouseX; scrollOffset += deltaX; // Clamp scrollOffset to bounds if (scrollOffset > minScroll) scrollOffset = minScroll; if (scrollOffset < -maxScroll) scrollOffset = -maxScroll; // Move all slots accordingly for (var i = 0; i < inventoryContainer.children.length; i++) { var child = inventoryContainer.children[i]; // Only move InventorySlot, not buttons if (child instanceof InventorySlot) { child.x = i * (slotWidth + padding) + slotWidth / 2 + scrollOffset; } } lastMouseX = x; } }; inventoryContainer.up = function (x, y, obj) { dragging = false; }; inventoryContainer.upoutside = function (x, y, obj) { dragging = false; }; inventoryContainer.width = game.width; // Set the visible width inventoryContainer.height = game.height - 400; // Set the visible height, leaving space for buttons // Position the inventory container (example positioning) inventoryContainer.x = 0; // Align to the left edge inventoryContainer.y = 300; // Offset from top, moved down by 100 pixels game.addChild(inventoryContainer); // Arrange inventory slots in a single row var slotWidth = 300; var slotHeight = 300; var padding = 50; // Calculate the total width needed for the single row var totalContentWidth = allFootballs.length * (slotWidth + padding) - padding; inventoryContainer.contentWidth = totalContentWidth; // Set the scrollable width for (var i = 0; i < allFootballs.length; i++) { var footballId = allFootballs[i]; var slot = new InventorySlot(footballId); slot.x = i * (slotWidth + padding) + slotWidth / 2; slot.y = slotHeight / 2; // Position vertically relative to the slot's height, keeping it in a straight line at the top of the container. inventoryContainer.addChild(slot); } // Add a button to open a pack var openPackButton = new Container(); var buttonGraphic = openPackButton.attachAsset('pack', { anchorX: 0.5, anchorY: 0.5 }); // Use pack graphic for button buttonGraphic.width = 300; buttonGraphic.height = 400; var buttonText = new Text2('Open Pack', { size: 60, fill: 0xFFFFFF }); buttonText.anchor.set(0.5); buttonText.x = buttonGraphic.width / 2; buttonText.y = buttonGraphic.height / 2; openPackButton.addChild(buttonText); openPackButton.x = game.width / 2; openPackButton.y = game.height - 150; // Position at the bottom, adjusted for larger inventory area openPackButton.down = function () { // Remove the inventory and show the pack if (inventoryContainer) { // Destroy children first inventoryContainer.children.forEach(function (child) { child.destroy(); }); inventoryContainer.destroy(); inventoryContainer = null; } showPack(); }; game.addChild(openPackButton); // Add a reset progress button at the bottom left (avoid top left 100x100 for menu) var resetButton = new Container(); var resetButtonGraphic = resetButton.attachAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5 }); resetButtonGraphic.width = 220; resetButtonGraphic.height = 120; var resetText = new Text2('Reset', { size: 60, fill: 0xFFFFFF }); resetText.anchor.set(0.5); resetText.x = resetButtonGraphic.width / 2; resetText.y = resetButtonGraphic.height / 2; resetButton.addChild(resetText); // Place at bottom left, but not in the top left 100x100 resetButton.x = 120; resetButton.y = game.height - 120; // Keep at the bottom left resetButton.down = function () { // Clear collection and restart storage.collectedFootballs = []; // Remove inventory and pack if present if (inventoryContainer) { inventoryContainer.children.forEach(function (child) { child.destroy(); }); inventoryContainer.destroy(); inventoryContainer = null; } if (packNode) { packNode.destroy(); packNode = null; } // Reset progress display updateCollectionProgress(); // Show inventory again showInventory(); }; game.addChild(resetButton); } else { inventoryContainer.visible = true; } // Update the content of the inventory slots based on collected footballs inventoryContainer.children.forEach(function (child) { if (child instanceof InventorySlot) { // Clear existing content in the slot child.children.forEach(function (slotChild) { slotChild.destroy(); }); child.children = []; // Clear children array // Add appropriate graphic based on collection status if (isFootballCollected(child.footballId)) { var football = new Football(child.footballId); football.scale.set(1.75); // Ensure scale is correct on update football.x = child.width / 2; football.y = child.height / 2; child.addChild(football); } else { var placeholder = new Text2('?', { size: 150, fill: 0xFFFFFF }); placeholder.anchor.set(0.5); placeholder.x = child.width / 2; placeholder.y = child.height / 2; child.addChild(placeholder); } } }); } // Function to show the pack function showPack() { // Remove inventory if visible if (inventoryContainer) { inventoryContainer.visible = false; } if (!packNode) { packNode = new Pack(); packNode.x = game.width / 2; packNode.y = game.height / 2; game.addChild(packNode); } else { packNode.visible = true; } } // Initial setup scoreTxt = new Text2('Collected: 0/0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.x = LK.gui.top.width / 2; scoreTxt.y = 100; // Offset from the very top to avoid the menu icon LK.gui.top.addChild(scoreTxt); updateCollectionProgress(); // Initialize the score display showInventory(); // Start by showing the inventory // Play background music LK.playMusic('backgroundMusic'); // Main game loop (not needed for this simple UI game) // game.update = function () { // };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
collectedFootballs: []
});
/****
* Classes
****/
//Library for using the camera (the background becomes the user's camera video feed) and the microphone. It can access face coordinates for interactive play, as well detect microphone volume / voice interactions
// var facekit = LK.import('@upit/facekit.v1');
//Classes can only be defined here. You cannot create inline classes in the games code.
var Football = Container.expand(function (id) {
var self = Container.call(this);
self.id = id; // Unique ID for the football
// Use the correct asset for each football type
var assetId = id;
// Defensive: fallback to generic if asset not found
var validAssets = {
'Tropical': true,
'Cave': true,
'Crystal': true,
'Fire': true,
'Galaxy': true,
'Magic': true,
'Snow': true,
'Gold': true,
'Honey': true,
'Ocean': true,
'Plant': true,
'Rainbow': true,
'Regular': true,
'Slime': true,
'Night': true,
'Sky': true,
'Cheese': true,
'Popcorn': true,
'Mismi': true,
'Volcano': true,
'Soapy': true,
'Ice': true,
'Neon': true,
'Nuclear': true,
'Coral': true,
'Astronaut': true,
'Icecream': true,
'Medival': true,
'Star': true,
'Coconut': true,
'Clock': true,
'Jellyfish': true,
'Airplane': true,
'Bacon': true,
'Potato': true,
'Money': true,
'Pickle': true,
'Pumpkin': true,
'Rock': true,
'Gummy': true,
'Wizard': true,
'Polka': true
};
if (!validAssets[assetId]) assetId = 'football';
self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var InventorySlot = Container.expand(function (footballId) {
var self = Container.call(this);
self.footballId = footballId;
self.attachAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5
});
// Display the football if it has been collected
if (isFootballCollected(footballId)) {
var football = new Football(footballId);
football.scale.set(1.75); // Scale up to fit in slot
football.x = self.width / 2;
football.y = self.height / 2;
self.addChild(football);
} else {
// Display a placeholder or question mark for uncollected footballs
var placeholder = new Text2('?', {
size: 150,
fill: 0xFFFFFF
});
placeholder.anchor.set(0.5);
placeholder.x = self.width / 2;
placeholder.y = self.height / 2;
self.addChild(placeholder);
}
return self;
});
var Pack = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('pack', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
// Open the pack when pressed
openPack();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a // Dark background
});
/****
* Game Code
****/
//Storage library which should be used for persistent game data
//Minimalistic tween library which should be used for animations over time, including tinting / colouring an object, scaling, rotating, or changing any game object property.
//Only include the plugins you need to create the game.
//We have access to the following plugins. (Note that the variable names used are mandetory for each plugin)
// Initialize music
// Placeholder football graphic
// Initialize assets used in this game. Scale them according to what is needed for the game.
// or via static code analysis based on their usage in the code.
// Assets are automatically created and loaded either dynamically during gameplay
/*
Supported Types:
1. Shape:
- Simple geometric figures with these properties:
* width: (required) pixel width of the shape.
* height: (required) pixel height of the shape.
* color: (required) color of the shape.
* shape: (required) type of shape. Valid options: 'box', 'ellipse'.
2. Image:
- Imported images with these properties:
* width: (required) pixel resolution width.
* height: (required) pixel resolution height.
* id: (required) identifier for the image.
* flipX: (optional) horizontal flip. Valid values: 0 (no flip), 1 (flip).
* flipY: (optional) vertical flip. Valid values: 0 (no flip), 1 (flip).
* orientation: (optional) rotation in multiples of 90 degrees, clockwise. Valid values:
- 0: No rotation.
- 1: Rotate 90 degrees.
- 2: Rotate 180 degrees.
- 3: Rotate 270 degrees.
Note: Width and height remain unchanged upon flipping.
3. Sound:
- Sound effects with these properties:
* id: (required) identifier for the sound.
* volume: (optional) custom volume. Valid values are a float from 0 to 1.
4. Music:
- In contract to sound effects, only one music can be played at a time
- Music is using the same API to initilize just like sound.
- Music loops by default
- Music with these config options:
* id: (required) identifier for the sound.
* volume: (optional) custom volume. Valid values are a float from 0 to 1.
* start: (optional) a float from 0 to 1 used for cropping and indicates the start of the cropping
* end: (optional) a float from 0 to 1 used for cropping and indicates the end of the cropping
*/
var allFootballs = []; // Array of all possible football IDs
var packNode = null; // The visual representation of the pack
var inventoryContainer = null; // Container for inventory slots
var scoreTxt = null; // Text display for collection progress
// Define all possible football IDs (actual asset names)
allFootballs = ['Tropical', 'Cave', 'Crystal', 'Fire', 'Galaxy', 'Magic', 'Snow', 'Gold', 'Honey', 'Ocean', 'Plant', 'Rainbow', 'Regular', 'Slime', 'Night', 'Sky', 'Cheese', 'Popcorn', 'Mismi', 'Volcano', 'Soapy', 'Ice', 'Neon', 'Nuclear', 'Coral', 'Astronaut', 'Icecream', 'Medival', 'Star', 'Coconut', 'Clock', 'Jellyfish', 'Airplane', 'Bacon', 'Potato', 'Money', 'Pickle', 'Pumpkin', 'Rock', 'Gummy', 'Wizard', 'Polka'];
// Function to check if a football ID is in the player's collection
function isFootballCollected(footballId) {
return storage.collectedFootballs.indexOf(footballId) !== -1;
}
// Function to get a random uncollected football ID
function getRandomUncollectedFootballId() {
var uncollected = allFootballs.filter(function (id) {
return !isFootballCollected(id);
});
if (uncollected.length === 0) {
return null; // All footballs collected
}
var randomIndex = Math.floor(Math.random() * uncollected.length);
return uncollected[randomIndex];
}
// Function to get a random football ID (collected or uncollected)
function getRandomFootballId() {
var randomIndex = Math.floor(Math.random() * allFootballs.length);
return allFootballs[randomIndex];
}
// Function to open a pack
function openPack() {
// Remove the pack node
if (packNode) {
packNode.destroy();
packNode = null;
}
LK.getSound('openPack').play();
var revealedFootballs = [];
// Generate 4 footballs. Allow duplicates, but if not all collected, bias toward uncollected for at least one slot
var guaranteedUncollected = !allFootballs.every(isFootballCollected);
var uncollectedGiven = false;
for (var i = 0; i < 4; i++) {
var footballId;
// Guarantee at least one uncollected if possible
if (guaranteedUncollected && !uncollectedGiven) {
footballId = getRandomUncollectedFootballId();
if (footballId !== null) {
uncollectedGiven = true;
} else {
footballId = getRandomFootballId();
}
} else {
footballId = getRandomFootballId();
}
revealedFootballs.push(footballId);
// Add to collection if not already collected
if (!isFootballCollected(footballId)) {
storage.collectedFootballs.push(footballId);
LK.getSound('collectFootball').play();
}
}
// Update storage immediately (ensure persistence)
storage.collectedFootballs = storage.collectedFootballs;
// Display the revealed footballs
var startX = (game.width - (revealedFootballs.length * 300 + (revealedFootballs.length - 1) * 50)) / 2 + 150;
var startY = game.height / 2;
for (var j = 0; j < revealedFootballs.length; j++) {
var football = new Football(revealedFootballs[j]);
football.scale.set(1.75); // Increase scale for visibility
football.x = startX + j * 350;
football.y = startY;
game.addChild(football);
// Simple animation
tween(football, {
y: football.y - 200
}, {
duration: 500,
easing: tween.easeOut
});
tween(football, {
rotation: Math.PI * 2
}, {
duration: 1000,
easing: tween.linear
});
// Delete football after animation is done (after 1000ms)
// Delete football after animation is done (after 1000ms)
(function (footballRef) {
var thisJ = j; // capture the current value of j for this closure
LK.setTimeout(function () {
// Always destroy the football after animation, do not leave it visible
if (footballRef && footballRef.parent) {
// Optionally, you could play a quick scale-down animation before destroy
tween(footballRef, {
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeOut,
complete: function complete() {
if (footballRef && footballRef.parent) {
footballRef.destroy();
}
}
});
}
}, 1000);
})(football);
}
// Update collection progress display
updateCollectionProgress();
// After a delay, show the inventory again
LK.setTimeout(showInventory, 3000); // Show inventory after 3 seconds
}
// Function to update the collection progress display
function updateCollectionProgress() {
var collectedCount = storage.collectedFootballs.length;
var totalCount = allFootballs.length;
scoreTxt.setText('Collected: ' + collectedCount + '/' + totalCount);
// Check for win condition
if (collectedCount === totalCount) {
LK.showYouWin();
}
}
// Function to show the inventory
function showInventory() {
// Remove any revealed footballs from pack opening
game.children.forEach(function (child) {
if (child instanceof Football) {
child.destroy();
}
});
// Create or show the inventory container
if (!inventoryContainer) {
inventoryContainer = new Container();
// Configure for horizontal scrolling
inventoryContainer.interactive = true;
inventoryContainer.overflow = 'scroll';
inventoryContainer.scrollDirection = 'horizontal';
// Add drag functionality for manual horizontal scrolling
var dragging = false;
var lastMouseX = 0;
var scrollOffset = 0;
var minScroll = 0;
var slotWidth = 300;
var slotHeight = 300;
var padding = 50;
var totalContentWidth = allFootballs.length * (slotWidth + padding) - padding;
var maxScroll = Math.max(0, totalContentWidth - game.width);
inventoryContainer.down = function (x, y, obj) {
dragging = true;
lastMouseX = x;
};
inventoryContainer.move = function (x, y, obj) {
if (dragging) {
var deltaX = x - lastMouseX;
scrollOffset += deltaX;
// Clamp scrollOffset to bounds
if (scrollOffset > minScroll) scrollOffset = minScroll;
if (scrollOffset < -maxScroll) scrollOffset = -maxScroll;
// Move all slots accordingly
for (var i = 0; i < inventoryContainer.children.length; i++) {
var child = inventoryContainer.children[i];
// Only move InventorySlot, not buttons
if (child instanceof InventorySlot) {
child.x = i * (slotWidth + padding) + slotWidth / 2 + scrollOffset;
}
}
lastMouseX = x;
}
};
inventoryContainer.up = function (x, y, obj) {
dragging = false;
};
inventoryContainer.upoutside = function (x, y, obj) {
dragging = false;
};
inventoryContainer.width = game.width; // Set the visible width
inventoryContainer.height = game.height - 400; // Set the visible height, leaving space for buttons
// Position the inventory container (example positioning)
inventoryContainer.x = 0; // Align to the left edge
inventoryContainer.y = 300; // Offset from top, moved down by 100 pixels
game.addChild(inventoryContainer);
// Arrange inventory slots in a single row
var slotWidth = 300;
var slotHeight = 300;
var padding = 50;
// Calculate the total width needed for the single row
var totalContentWidth = allFootballs.length * (slotWidth + padding) - padding;
inventoryContainer.contentWidth = totalContentWidth; // Set the scrollable width
for (var i = 0; i < allFootballs.length; i++) {
var footballId = allFootballs[i];
var slot = new InventorySlot(footballId);
slot.x = i * (slotWidth + padding) + slotWidth / 2;
slot.y = slotHeight / 2; // Position vertically relative to the slot's height, keeping it in a straight line at the top of the container.
inventoryContainer.addChild(slot);
}
// Add a button to open a pack
var openPackButton = new Container();
var buttonGraphic = openPackButton.attachAsset('pack', {
anchorX: 0.5,
anchorY: 0.5
}); // Use pack graphic for button
buttonGraphic.width = 300;
buttonGraphic.height = 400;
var buttonText = new Text2('Open Pack', {
size: 60,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5);
buttonText.x = buttonGraphic.width / 2;
buttonText.y = buttonGraphic.height / 2;
openPackButton.addChild(buttonText);
openPackButton.x = game.width / 2;
openPackButton.y = game.height - 150; // Position at the bottom, adjusted for larger inventory area
openPackButton.down = function () {
// Remove the inventory and show the pack
if (inventoryContainer) {
// Destroy children first
inventoryContainer.children.forEach(function (child) {
child.destroy();
});
inventoryContainer.destroy();
inventoryContainer = null;
}
showPack();
};
game.addChild(openPackButton);
// Add a reset progress button at the bottom left (avoid top left 100x100 for menu)
var resetButton = new Container();
var resetButtonGraphic = resetButton.attachAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5
});
resetButtonGraphic.width = 220;
resetButtonGraphic.height = 120;
var resetText = new Text2('Reset', {
size: 60,
fill: 0xFFFFFF
});
resetText.anchor.set(0.5);
resetText.x = resetButtonGraphic.width / 2;
resetText.y = resetButtonGraphic.height / 2;
resetButton.addChild(resetText);
// Place at bottom left, but not in the top left 100x100
resetButton.x = 120;
resetButton.y = game.height - 120; // Keep at the bottom left
resetButton.down = function () {
// Clear collection and restart
storage.collectedFootballs = [];
// Remove inventory and pack if present
if (inventoryContainer) {
inventoryContainer.children.forEach(function (child) {
child.destroy();
});
inventoryContainer.destroy();
inventoryContainer = null;
}
if (packNode) {
packNode.destroy();
packNode = null;
}
// Reset progress display
updateCollectionProgress();
// Show inventory again
showInventory();
};
game.addChild(resetButton);
} else {
inventoryContainer.visible = true;
}
// Update the content of the inventory slots based on collected footballs
inventoryContainer.children.forEach(function (child) {
if (child instanceof InventorySlot) {
// Clear existing content in the slot
child.children.forEach(function (slotChild) {
slotChild.destroy();
});
child.children = []; // Clear children array
// Add appropriate graphic based on collection status
if (isFootballCollected(child.footballId)) {
var football = new Football(child.footballId);
football.scale.set(1.75); // Ensure scale is correct on update
football.x = child.width / 2;
football.y = child.height / 2;
child.addChild(football);
} else {
var placeholder = new Text2('?', {
size: 150,
fill: 0xFFFFFF
});
placeholder.anchor.set(0.5);
placeholder.x = child.width / 2;
placeholder.y = child.height / 2;
child.addChild(placeholder);
}
}
});
}
// Function to show the pack
function showPack() {
// Remove inventory if visible
if (inventoryContainer) {
inventoryContainer.visible = false;
}
if (!packNode) {
packNode = new Pack();
packNode.x = game.width / 2;
packNode.y = game.height / 2;
game.addChild(packNode);
} else {
packNode.visible = true;
}
}
// Initial setup
scoreTxt = new Text2('Collected: 0/0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = LK.gui.top.width / 2;
scoreTxt.y = 100; // Offset from the very top to avoid the menu icon
LK.gui.top.addChild(scoreTxt);
updateCollectionProgress(); // Initialize the score display
showInventory(); // Start by showing the inventory
// Play background music
LK.playMusic('backgroundMusic');
// Main game loop (not needed for this simple UI game)
// game.update = function () {
// };