Code edit (1 edits merged)
Please save this source code
User prompt
after a life is used, the UI indicator should turn the used life into white color
Code edit (11 edits merged)
Please save this source code
User prompt
after a life is used, turn the UI_Projectile color to white
Code edit (1 edits merged)
Please save this source code
User prompt
move the UI_Projectiles 500 pixels to the right
User prompt
use the UI_Projectile as an UI element indicating the number of available lives the player has. Show 3 of these elements on the screen since the player has 3 lives. When one life is used, turn one of this Lives black, to indicate a life has been used
User prompt
Confirm that lives are only decremented when a domino is directly tipped by a player action and not by subsequent chain reactions caused by projectiles. Lives should be decremented before checking if they have run out.
User prompt
After implementing these changes, thoroughly test the game to ensure that: Lives decrement correctly. The game waits for the last projectile to finish its course after the last life is lost before showing the game over screen. The game over logic functions correctly under various scenarios (e.g., last projectile immediately hitting a domino, last projectile flying off-screen without collisions).
User prompt
the lives system doesnt work. after the player has used it's last (3rd) live and the projectile hits the edge of the screen, the game shouldgo to game over
User prompt
Make sure the game correctly resets all relevant flags and counters (like lives and the "awaiting final projectile" flag) at the start of a new game or when the game is reset.
User prompt
Introduce a global or accessible flag that tracks whether the game is waiting for the last projectile to conclude its path after the last life is lost. Reset this flag appropriately to ensure it's ready for each new game session.
User prompt
Incorporate logic to monitor the state of the game and player actions. Once all lives are used and the final projectile has hit an edge, proceed to display the game over screen or sequence.
User prompt
Ensure that when a domino is tipped via touch, the tipping function is called with the indicator that it's a player action. This way, the game correctly decrements a life only when the player directly causes a domino to tip.
User prompt
In the projectile's movement logic, add a check for when it hits the edge of the screen. If the "awaiting final projectile" flag is set and the projectile hits the screen edge, trigger the game over sequence. Ensure this check is done after the projectile's regular movement and collision checks to avoid prematurely ending the game.
User prompt
Update the domino tipping function to accept an additional parameter indicating whether the tipping was initiated by the player. When a domino is tipped due to a player action, decrement the lives counter. Only after the third life is lost, set a flag indicating that the game is awaiting the final projectile's outcome.
User prompt
Delay Game Over Until Projectile Inactivity: Modify the logic to delay the game over trigger until after the last active projectile has hit the screen edge or has no more dominos to interact with.
User prompt
Ensure Proper Decrement and Check of Lives: Confirm lives are decremented correctly and check for game over only after all lives are used and the last projectile's interaction is complete.
User prompt
The lives variable is decremented each time a domino is tipped, but the check for projectile motion and game over condition seems not to properly account for all 3 lives. The game needs to track not only when the lives run out but also ensure that the game over condition (like showing a game over screen) is triggered after the last projectile has hit an edge or has no more interactions left.
User prompt
the player has 3 lives. right now there's a bug where the game goes to game over after the first tilt. so the sequence should be, player taps a domino, a live is removed, the projectile hits the edge of the screen, the player can then tap another domino, a new life is lost again, then after the projectile hits the edge of the screen the player has 1 final life. after using that, allow the projectile to do it's chain reaction, and only after that 3rd live was used and the projectile hits the edge, go to game over
User prompt
the game should only end after the player used his 3rd tilt.
User prompt
add a lives system. the player can only tilt 3 dominos then it's game over. but after the 3'rd domino the player titlted, don't go straight to game over, instead wait for the projectile to hit one of the screen edges, only then go to game over
User prompt
while a projectile is in motion, disable the player's input so they can't manually tilt a domino. only reenable the input after the projectile hits one of the screen edges
Code edit (2 edits merged)
Please save this source code
User prompt
increase the overall size of the entire grid by 10%
/**** * Classes ****/ // Assets will be automatically generated based on usage in the code. // Domino class var Domino = Container.expand(function () { var self = Container.call(this); // Assuming directionsList is a shuffled array of directions ['U', 'L', 'R', 'D'] repeated to match the number of dominos self.direction = directionsList.shift(); // Updated asset attachment logic based on direction switch (self.direction) { case 'U': dominoGraphics = self.attachAsset('D_Up', { anchorX: 0.5, anchorY: 0.5 }); break; case 'D': dominoGraphics = self.attachAsset('D_Down', { anchorX: 0.5, anchorY: 0.5 }); break; case 'L': dominoGraphics = self.attachAsset('D_Left', { anchorX: 0.5, anchorY: 0.5 }); break; case 'R': dominoGraphics = self.attachAsset('D_Right', { anchorX: 0.5, anchorY: 0.5 }); break; } self.isTipped = false; self.hiddenCoin = false; // Indicates whether a coin is hidden underneath // Direction is already set at the beginning of the constructor. // Direction label code removed as it's no longer necessary with direction-specific assets self.tip = function (projectile) { if (projectile) { projectilePool.put(projectile); // Recycle the projectile immediately var index = projectiles.indexOf(projectile); if (index !== -1) { projectiles.splice(index, 1); // Remove from tracking array } } if (!self.isTipped) { self.isTipped = true; if (self.hiddenCoin) { // Change appearance to a coin and increase score by 10 points self.destroy(); var coin = new Container(); coin.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); game.addChild(coin); coin.x = self.x; coin.y = self.y; score += 10; // Increase score by 10 points for revealing a coin } else { // Destroy original domino before changing to domino_flipped self.destroy(); var flippedDomino = new Domino(); flippedDomino.attachAsset('domino_flipped', { anchorX: 0.5, anchorY: 0.5 }); game.addChild(flippedDomino); flippedDomino.x = self.x; flippedDomino.y = self.y; } // directionLabel removal code has been deprecated // Tip animation logic here LK.effects.flashObject(self, 0xffa500, 500); // Increment score by 1 for regular domino flips score += 1; // Update score display scoreTxt.setText(score.toString()); // Shoot a projectile in the direction specified by the domino's symbol var projectile = projectilePool.get(); projectile.direction = self.direction; projectile.x = self.x; projectile.y = self.y; // Update the projectile's grid position projectile.gridX = Math.floor(projectile.x / 100); projectile.gridY = Math.floor(projectile.y / 100); game.addChild(projectile); projectiles.push(projectile); } // Update the domino's grid position self.gridX = Math.floor(self.x / 100); self.gridY = Math.floor(self.y / 100); }; }); // Factory class var Factory = Container.expand(function () { var self = Container.call(this); self.dominos = []; self.addDomino = function (x, y, hasHiddenCoin) { var domino = new Domino(); domino.x = x; domino.y = y; domino.hiddenCoin = hasHiddenCoin || false; self.addChild(domino); self.dominos.push(domino); }; self.reset = function () { self.dominos.forEach(function (domino) { domino.destroy(); // Destroy domino instance // Remove any event listeners attached to domino here if any }); self.dominos.length = 0; // Clear the array without creating a new one }; }); // Projectile class var Projectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.direction = ''; self.speed = 10; self.move = function () { // Decrease acceleration factor var acceleration = 0.5; // Update speed with decreased acceleration self.speed += acceleration; switch (self.direction) { case 'U': self.y -= self.speed; break; case 'L': self.x -= self.speed; break; case 'R': self.x += self.speed; break; case 'D': self.y += self.speed; break; } // Update the projectile's grid position and check for collisions with dominos self.gridX = Math.floor(self.x / 100); self.gridY = Math.floor(self.y / 100); // Check for domino collisions after moving factory.dominos.forEach(function (domino) { if (!domino.isTipped && self.raycast(domino)) { domino.tip(self); // Pass this projectile to the domino's tip method // Reset projectile's speed to its original value after tipping a domino self.speed = 10; } }); }; self.raycast = function (domino) { // Calculate the distance between the projectile and the domino var dx = domino.x - self.x; var dy = domino.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If the distance is less than the sum of their radii, there is an intersection return distance < self.width / 2 + domino.width / 2; }; }); /**** * Initialize Game ****/ // Initialize a new projectile pool var game = new LK.Game({ backgroundColor: 0xd3d3d3 // Set game background to light grey }); /**** * Game Code ****/ var backgroundAsset = LK.getAsset('background', { anchorX: 0.0, anchorY: 0.0 }); var background = game.addChild(LK.getAsset('background', { x: 0, y: 0, width: game.width, height: game.height })); // Function to shuffle an array function shuffleArray(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var _ref = [array[j], array[i]]; array[i] = _ref[0]; array[j] = _ref[1]; } } // Calculate total number of dominos based on grid size (16 columns * 20 rows) var totalDominos = 16 * 20; // Divide total by 4 to get number of dominos for each direction var dominosPerDirection = totalDominos / 4; // Create a list of directions with an equal number of 'U', 'L', 'R', 'D' var directionsList = []; ['U', 'L', 'R', 'D'].forEach(function (direction) { for (var i = 0; i < dominosPerDirection; i++) { directionsList.push(direction); } }); // Shuffle the directions list shuffleArray(directionsList); // Initialize score variable var score = 0; // Display score var scoreTxt = new Text2(score.toString(), { size: 150, fill: "#ffffff", stroke: "#000000", // Black outline strokeThickness: 8 // Thickness of the outline }); scoreTxt.anchor.set(0.5, 0); // Center the score text horizontally LK.gui.top.addChild(scoreTxt); // Add the score text to the GUI overlay at the top-center of the screen // Custom intersects function for accurate collision detection function intersects(projectile, domino) { var projectileBounds = { left: projectile.x - projectile.width / 2, right: projectile.x + projectile.width / 2, top: projectile.y - projectile.height / 2, bottom: projectile.y + projectile.height / 2 }; var dominoBounds = { left: domino.x - domino.width / 2, right: domino.x + domino.width / 2, top: domino.y - domino.height / 2, bottom: domino.y + domino.height / 2 }; return !(projectileBounds.right < dominoBounds.left || projectileBounds.left > dominoBounds.right || projectileBounds.bottom < dominoBounds.top || projectileBounds.top > dominoBounds.bottom); } // Array to store all projectiles // ProjectilePool class var ProjectilePool = function ProjectilePool() { this.pool = []; this.get = function () { if (this.pool.length > 0) { return this.pool.pop(); } else { return new Projectile(); } }; this.put = function (projectile) { // Assuming projectiles might have event listeners attached // Remove event listeners from projectile here if any this.pool.push(projectile); }; }; // Initialize a new projectile pool var projectilePool = new ProjectilePool(); var projectiles = []; // Game tick function to move all projectiles and check for domino tipping LK.on('tick', function () { projectiles.forEach(function (projectile, i) { // Move the projectile based on its direction projectile.move(); // Check for domino tipping within the same grid cell var tippedDomino = factory.dominos.find(function (domino) { return !domino.isTipped && domino.gridX === projectile.gridX && domino.gridY === projectile.gridY && projectile.intersects(domino); }); if (tippedDomino) { // Recycle the current projectile projectilePool.put(projectile); projectiles.splice(i, 1); // Trigger the projectile of the domino it just hit tippedDomino.tip(); } // Remove projectiles that have moved off screen if (projectile.x < 0 || projectile.x > 2048 || projectile.y < 0 || projectile.y > 2732) { projectile.destroy(); // Destroy the projectile when it hits the edge of the screen projectiles.splice(i, 1); // Remove from tracking array } }); }); var factory = game.addChild(new Factory()); // Function to check and trigger domino tipping function checkAndTipDominos(x, y) { factory.dominos.forEach(function (domino) { if (Math.abs(domino.x - x) < 100 && Math.abs(domino.y - y) < 100) { domino.tip(); } }); } // Populate the factory with dominos and randomly select 10 to have hidden coins var dominoIndexesWithCoins = []; while (dominoIndexesWithCoins.length < 10) { var randomIndex = Math.floor(Math.random() * 320); // 320 is the total number of dominos (16*20) if (dominoIndexesWithCoins.indexOf(randomIndex) === -1) { dominoIndexesWithCoins.push(randomIndex); } } var dominoCounter = 0; for (var i = 0; i < 16; i++) { for (var j = 0; j < 20; j++) { factory.addDomino(2048 / 2 - 15 * 110 / 2 + i * 110, 2732 / 2 - 15 * 110 / 2 + j * 110, dominoIndexesWithCoins.includes(dominoCounter)); dominoCounter++; } } // Handle touch events to tip dominos game.on('down', function (obj) { var pos = obj.event.getLocalPosition(game); // Find the closest domino to the tap position var closestDomino = factory.dominos.reduce(function (closest, domino) { var distance = Math.sqrt(Math.pow(domino.x - pos.x, 2) + Math.pow(domino.y - pos.y, 2)); if (distance < closest.distance) { return { domino: domino, distance: distance }; } else { return closest; } }, { domino: null, distance: Infinity }); // Tip the closest domino if it is within 100 units of the tap position if (closestDomino.distance < 100) { closestDomino.domino.tip(); } });
/****
* Classes
****/
// Assets will be automatically generated based on usage in the code.
// Domino class
var Domino = Container.expand(function () {
var self = Container.call(this);
// Assuming directionsList is a shuffled array of directions ['U', 'L', 'R', 'D'] repeated to match the number of dominos
self.direction = directionsList.shift();
// Updated asset attachment logic based on direction
switch (self.direction) {
case 'U':
dominoGraphics = self.attachAsset('D_Up', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'D':
dominoGraphics = self.attachAsset('D_Down', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'L':
dominoGraphics = self.attachAsset('D_Left', {
anchorX: 0.5,
anchorY: 0.5
});
break;
case 'R':
dominoGraphics = self.attachAsset('D_Right', {
anchorX: 0.5,
anchorY: 0.5
});
break;
}
self.isTipped = false;
self.hiddenCoin = false; // Indicates whether a coin is hidden underneath
// Direction is already set at the beginning of the constructor.
// Direction label code removed as it's no longer necessary with direction-specific assets
self.tip = function (projectile) {
if (projectile) {
projectilePool.put(projectile); // Recycle the projectile immediately
var index = projectiles.indexOf(projectile);
if (index !== -1) {
projectiles.splice(index, 1); // Remove from tracking array
}
}
if (!self.isTipped) {
self.isTipped = true;
if (self.hiddenCoin) {
// Change appearance to a coin and increase score by 10 points
self.destroy();
var coin = new Container();
coin.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(coin);
coin.x = self.x;
coin.y = self.y;
score += 10; // Increase score by 10 points for revealing a coin
} else {
// Destroy original domino before changing to domino_flipped
self.destroy();
var flippedDomino = new Domino();
flippedDomino.attachAsset('domino_flipped', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(flippedDomino);
flippedDomino.x = self.x;
flippedDomino.y = self.y;
}
// directionLabel removal code has been deprecated
// Tip animation logic here
LK.effects.flashObject(self, 0xffa500, 500);
// Increment score by 1 for regular domino flips
score += 1;
// Update score display
scoreTxt.setText(score.toString());
// Shoot a projectile in the direction specified by the domino's symbol
var projectile = projectilePool.get();
projectile.direction = self.direction;
projectile.x = self.x;
projectile.y = self.y;
// Update the projectile's grid position
projectile.gridX = Math.floor(projectile.x / 100);
projectile.gridY = Math.floor(projectile.y / 100);
game.addChild(projectile);
projectiles.push(projectile);
}
// Update the domino's grid position
self.gridX = Math.floor(self.x / 100);
self.gridY = Math.floor(self.y / 100);
};
});
// Factory class
var Factory = Container.expand(function () {
var self = Container.call(this);
self.dominos = [];
self.addDomino = function (x, y, hasHiddenCoin) {
var domino = new Domino();
domino.x = x;
domino.y = y;
domino.hiddenCoin = hasHiddenCoin || false;
self.addChild(domino);
self.dominos.push(domino);
};
self.reset = function () {
self.dominos.forEach(function (domino) {
domino.destroy(); // Destroy domino instance
// Remove any event listeners attached to domino here if any
});
self.dominos.length = 0; // Clear the array without creating a new one
};
});
// Projectile class
var Projectile = Container.expand(function () {
var self = Container.call(this);
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = '';
self.speed = 10;
self.move = function () {
// Decrease acceleration factor
var acceleration = 0.5;
// Update speed with decreased acceleration
self.speed += acceleration;
switch (self.direction) {
case 'U':
self.y -= self.speed;
break;
case 'L':
self.x -= self.speed;
break;
case 'R':
self.x += self.speed;
break;
case 'D':
self.y += self.speed;
break;
}
// Update the projectile's grid position and check for collisions with dominos
self.gridX = Math.floor(self.x / 100);
self.gridY = Math.floor(self.y / 100);
// Check for domino collisions after moving
factory.dominos.forEach(function (domino) {
if (!domino.isTipped && self.raycast(domino)) {
domino.tip(self); // Pass this projectile to the domino's tip method
// Reset projectile's speed to its original value after tipping a domino
self.speed = 10;
}
});
};
self.raycast = function (domino) {
// Calculate the distance between the projectile and the domino
var dx = domino.x - self.x;
var dy = domino.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If the distance is less than the sum of their radii, there is an intersection
return distance < self.width / 2 + domino.width / 2;
};
});
/****
* Initialize Game
****/
// Initialize a new projectile pool
var game = new LK.Game({
backgroundColor: 0xd3d3d3 // Set game background to light grey
});
/****
* Game Code
****/
var backgroundAsset = LK.getAsset('background', {
anchorX: 0.0,
anchorY: 0.0
});
var background = game.addChild(LK.getAsset('background', {
x: 0,
y: 0,
width: game.width,
height: game.height
}));
// Function to shuffle an array
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var _ref = [array[j], array[i]];
array[i] = _ref[0];
array[j] = _ref[1];
}
}
// Calculate total number of dominos based on grid size (16 columns * 20 rows)
var totalDominos = 16 * 20;
// Divide total by 4 to get number of dominos for each direction
var dominosPerDirection = totalDominos / 4;
// Create a list of directions with an equal number of 'U', 'L', 'R', 'D'
var directionsList = [];
['U', 'L', 'R', 'D'].forEach(function (direction) {
for (var i = 0; i < dominosPerDirection; i++) {
directionsList.push(direction);
}
});
// Shuffle the directions list
shuffleArray(directionsList);
// Initialize score variable
var score = 0;
// Display score
var scoreTxt = new Text2(score.toString(), {
size: 150,
fill: "#ffffff",
stroke: "#000000",
// Black outline
strokeThickness: 8 // Thickness of the outline
});
scoreTxt.anchor.set(0.5, 0); // Center the score text horizontally
LK.gui.top.addChild(scoreTxt); // Add the score text to the GUI overlay at the top-center of the screen
// Custom intersects function for accurate collision detection
function intersects(projectile, domino) {
var projectileBounds = {
left: projectile.x - projectile.width / 2,
right: projectile.x + projectile.width / 2,
top: projectile.y - projectile.height / 2,
bottom: projectile.y + projectile.height / 2
};
var dominoBounds = {
left: domino.x - domino.width / 2,
right: domino.x + domino.width / 2,
top: domino.y - domino.height / 2,
bottom: domino.y + domino.height / 2
};
return !(projectileBounds.right < dominoBounds.left || projectileBounds.left > dominoBounds.right || projectileBounds.bottom < dominoBounds.top || projectileBounds.top > dominoBounds.bottom);
}
// Array to store all projectiles
// ProjectilePool class
var ProjectilePool = function ProjectilePool() {
this.pool = [];
this.get = function () {
if (this.pool.length > 0) {
return this.pool.pop();
} else {
return new Projectile();
}
};
this.put = function (projectile) {
// Assuming projectiles might have event listeners attached
// Remove event listeners from projectile here if any
this.pool.push(projectile);
};
};
// Initialize a new projectile pool
var projectilePool = new ProjectilePool();
var projectiles = [];
// Game tick function to move all projectiles and check for domino tipping
LK.on('tick', function () {
projectiles.forEach(function (projectile, i) {
// Move the projectile based on its direction
projectile.move();
// Check for domino tipping within the same grid cell
var tippedDomino = factory.dominos.find(function (domino) {
return !domino.isTipped && domino.gridX === projectile.gridX && domino.gridY === projectile.gridY && projectile.intersects(domino);
});
if (tippedDomino) {
// Recycle the current projectile
projectilePool.put(projectile);
projectiles.splice(i, 1);
// Trigger the projectile of the domino it just hit
tippedDomino.tip();
}
// Remove projectiles that have moved off screen
if (projectile.x < 0 || projectile.x > 2048 || projectile.y < 0 || projectile.y > 2732) {
projectile.destroy(); // Destroy the projectile when it hits the edge of the screen
projectiles.splice(i, 1); // Remove from tracking array
}
});
});
var factory = game.addChild(new Factory());
// Function to check and trigger domino tipping
function checkAndTipDominos(x, y) {
factory.dominos.forEach(function (domino) {
if (Math.abs(domino.x - x) < 100 && Math.abs(domino.y - y) < 100) {
domino.tip();
}
});
}
// Populate the factory with dominos and randomly select 10 to have hidden coins
var dominoIndexesWithCoins = [];
while (dominoIndexesWithCoins.length < 10) {
var randomIndex = Math.floor(Math.random() * 320); // 320 is the total number of dominos (16*20)
if (dominoIndexesWithCoins.indexOf(randomIndex) === -1) {
dominoIndexesWithCoins.push(randomIndex);
}
}
var dominoCounter = 0;
for (var i = 0; i < 16; i++) {
for (var j = 0; j < 20; j++) {
factory.addDomino(2048 / 2 - 15 * 110 / 2 + i * 110, 2732 / 2 - 15 * 110 / 2 + j * 110, dominoIndexesWithCoins.includes(dominoCounter));
dominoCounter++;
}
}
// Handle touch events to tip dominos
game.on('down', function (obj) {
var pos = obj.event.getLocalPosition(game);
// Find the closest domino to the tap position
var closestDomino = factory.dominos.reduce(function (closest, domino) {
var distance = Math.sqrt(Math.pow(domino.x - pos.x, 2) + Math.pow(domino.y - pos.y, 2));
if (distance < closest.distance) {
return {
domino: domino,
distance: distance
};
} else {
return closest;
}
}, {
domino: null,
distance: Infinity
});
// Tip the closest domino if it is within 100 units of the tap position
if (closestDomino.distance < 100) {
closestDomino.domino.tip();
}
});
red projectile rune. pixelated. 8-bit. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
artistic background of the inside the depths of an unlit dark cave filled with a variety of treasures, and a dragon sleeping over a massive pile of treasure chests at its heart. pixelated. 8-bit. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.