Code edit (3 edits merged)
Please save this source code
User prompt
bucket should be made visible only from Playing State
Code edit (8 edits merged)
Please save this source code
User prompt
when a sand block isn't dropped above the previous sandblock (or the sandcastle for the 1st one) then it should continue to fall until going out of screen, it should not stop at centralPointY
Code edit (1 edits merged)
Please save this source code
User prompt
move the bucket icons on the center right border, one above the other
Code edit (1 edits merged)
Please save this source code
User prompt
move the logic of checking block alignement and update score and live in a separate function called only once per drop
User prompt
after 1st drop make the bucker move from horizontally between the borders
Code edit (1 edits merged)
Please save this source code
User prompt
add a flag, bucketReady for when bucket reach y=0
Code edit (17 edits merged)
Please save this source code
User prompt
instead of the direct `bucket.y = 0; // Reset bucket position when the camera reaches the target` make the bucket move down progressively
User prompt
bucket should always appear aboce sand blocks (z-index)
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
add a new flag, send block dropped
Code edit (7 edits merged)
Please save this source code
User prompt
Don't allow taps during camera move.
Code edit (1 edits merged)
Please save this source code
User prompt
In handlePlayingLoop, separate the logic in two independent functions
User prompt
séparer la logique de manière de jouer dans plusieurs fonctions
Code edit (20 edits merged)
Please save this source code
User prompt
Lorsque le background 1 n'est plus visible, le déplacer vers le haut après
Code edit (1 edits merged)
Please save this source code
/**** * Classes ****/ var SandBlock = Container.expand(function () { var self = Container.call(this); var sandBlockGraphics = self.attachAsset('sandBlock', { anchorX: 0.5, anchorY: 0 }); self.velocity = 0; // Initial velocity for natural falling speed increase self.update = function () { // SandBlock specific update logic }; }); /***********************************************************************************/ /********************************** SANDCASTLE CLASS ************************************/ /***********************************************************************************/ var Sandcastle = Container.expand(function () { var self = Container.call(this); var sandcastleGraphics = self.attachAsset('sandcastle', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Sandcastle specific update logic }; }); /**** * Initialize Game ****/ // Utility function to draw a polygon using drawLine var game = new LK.Game({ backgroundColor: 0x000050 // Initialize game with a black background }); /**** * Game Code ****/ function initializeBackgrounds() { backgroundImage = LK.getAsset('backgroundImage', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(backgroundImage); background2 = LK.getAsset('background2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 }); background2.y = -background2.height / 2; game.addChild(background2); background3 = LK.getAsset('background3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 }); background3.y = -background2.height - background3.height / 2; background4 = LK.getAsset('background2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 }); background4.y = -background2.height - background3.height - background4.height / 2; game.addChild(background4); background5 = LK.getAsset('background3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 }); background5.y = -background2.height - background3.height - background4.height - background5.height / 2; game.addChild(background5); game.addChild(background3); } // Enumeration for game states /****************************************************************************************** */ /************************************** GLOBAL VARIABLES ********************************** */ /****************************************************************************************** */ var GAME_STATE = { INIT: 'INIT', MENU: 'MENU', NEW_ROUND: 'NEW_ROUND', PLAYING: 'PLAYING', SCORE: 'SCORE' }; var gameState = GAME_STATE.INIT; var score = 0; var scoreTxt; var isDebug = true; var debugText; var debugMarker; var backgroundImage; var bucket; var sandBlocks = []; var lives = 3; var livesIcons = []; var cameraMoved = false; // Flag to track if the camera has moved for the current sandblock fall var sandcastle; var sandBlockSize = 512; var gravity = 2; // Gravity effect for sand block falling /****************************************************************************************** */ /*********************************** UTILITY FUNCTIONS ************************************ */ /****************************************************************************************** */ function moveCamera() { var targetY = backgroundImage.y + sandBlockSize; var moveStep = sandBlockSize / 60; // Move over 1 second (60 frames) function progressiveMove() { if (backgroundImage.y < targetY) { backgroundImage.y += moveStep; background2.y += moveStep; background3.y += moveStep; sandcastle.y += moveStep; background4.y += moveStep; background5.y += moveStep; for (var j = 0; j < sandBlocks.length; j++) { sandBlocks[j].y += moveStep; } if (backgroundImage.y < targetY) { LK.setTimeout(progressiveMove, 1000 / 60); // Call progressiveMove every 1/60th of a second } else { bucket.y = 0; // Reset bucket position when the camera reaches the target } } } progressiveMove(); } function log() { if (isDebug) { var _console; (_console = console).log.apply(_console, arguments); } } /****************************************************************************************** */ /************************************** INPUT HANDLERS ************************************ */ /****************************************************************************************** */ game.on('down', function (x, y, obj) { switch (gameState) { case GAME_STATE.MENU: gameMenuDown(x, y, obj); break; case GAME_STATE.NEW_ROUND: gameNewRoundDown(x, y, obj); break; case GAME_STATE.PLAYING: gamePlayingDown(x, y, obj); break; case GAME_STATE.SCORE: // Handle score display logic here break; } }); function gameMenuDown(x, y, obj) { log("gameMenuDown..."); cleanMenuState(); initNewRoundState(); } function gameNewRoundDown(x, y, obj) { log("gameNewRoundDown..."); cleanNewRoundState(); initPlayingState(); } function gamePlayingDown(x, y, obj) { log("gamePlayingDown..."); var sandBlock = new SandBlock(); sandBlock.x = bucket.x; sandBlock.y = bucket.y - bucket.height / 2; sandBlocks.push(sandBlock); game.addChild(sandBlock); cameraMoved = false; // Reset the flag when a new sandblock is created // Move the bucket vertically to hide over the screen top var bucketMoveStep = 15; // Adjust the step size as needed function moveBucketUp() { if (bucket.y > -bucket.height) { bucket.y -= bucketMoveStep; LK.setTimeout(moveBucketUp, 1000 / 240); // Call moveBucketUp every 1/60th of a second } } moveBucketUp(); } /****************************************************************************************** */ /************************************* GAME FUNCTIONS ************************************* */ /****************************************************************************************** */ /****************************************************************************************** */ /************************************* GAME STATES **************************************** */ /****************************************************************************************** */ function gameInitialize() { log("Game initialize..."); initializeBackgrounds(); sandcastle = new Sandcastle(); sandcastle.x = 2048 / 2; sandcastle.y = 2732 - sandcastle.height / 2 + 300; game.addChild(sandcastle); var banner = LK.getAsset('banner', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 0 }); game.addChild(banner); for (var i = 0; i < lives; i++) { var lifeIcon = LK.getAsset('bucketIcon', { anchorX: 0.5, anchorY: 0.5, x: 300 + i * 100, y: 50 }); livesIcons.push(lifeIcon); LK.gui.top.addChild(lifeIcon); } bucket = LK.getAsset('bucket', { anchorX: 0.5, anchorY: 0.0, x: 2048 / 2, y: 0 }); game.addChild(bucket); score = 0; scoreTxt = new Text2('0', { size: 150, fill: "#ffffff" }); scoreTxt.anchor.set(0.5, 0); scoreTxt.x = 2048 / 2; scoreTxt.y = 50; LK.gui.top.addChild(scoreTxt); if (isDebug) { debugMarker = LK.getAsset('debugMarker', { anchorX: 0.5, anchorY: 0.5, x: 2048 * 0.5, y: 1526 }); game.addChild(debugMarker); debugText = new Text2('Debug Info', { size: 50, fill: "#ffffff" }); debugText.anchor.set(0.5, 1); // Anchor to the bottom-right LK.gui.bottom.addChild(debugText); } initMenuState(); } // GAME MENU function initMenuState() { log("initMenuState..."); gameState = GAME_STATE.MENU; } function handleMenuLoop() { // Menu animations here } function cleanMenuState() { log("cleanMenuState..."); } // NEW ROUND function initNewRoundState() { log("initNewRoundState..."); gameState = GAME_STATE.NEW_ROUND; // Round preparation logic here. } function handleNewRoundLoop() { // New Round animations here } function cleanNewRoundState() { log("cleanNewRoundState..."); } // PLAYING function initPlayingState() { log("initPlayingState..."); gameState = GAME_STATE.PLAYING; } function handlePlayingLoop() { for (var i = sandBlocks.length - 1; i >= 0; i--) { var sandBlock = sandBlocks[i]; if (sandBlock.y < 1526 - sandBlockSize) { sandBlock.velocity += gravity; // Increase velocity due to gravity sandBlock.y += sandBlock.velocity; // Update position based on velocity } if (sandBlock.y >= 1526 - sandBlockSize) { // Move background, sandcastle, and fallen sandblock vertically by sandBlockSize if (!cameraMoved) { cameraMoved = true; LK.setTimeout(function () { moveCamera(); // Set the flag to true after moving the camera //bucket.y = 0; // Reset bucket position when the camera moves }, 512); // Delay of 1 second before moving the camera } // Check if sand block reached the base if (Math.abs(sandBlock.x - 2048 / 2) < 50) { // Check for perfect alignment score += 10; // Bonus points for perfect alignment } else { lives--; if (lives <= 0) { LK.showGameOver(); return; } livesIcons[lives].destroy(); livesIcons.pop(); } } } scoreTxt.setText(score); if (isDebug) { debugText.setText("X: " + bucket.x + " Y: " + bucket.y); } } function cleanPlayingState() { log("cleanPlayingState..."); // TODO Remove elements } // SCORE function initScoreState() { log("initScoreState..."); gameState = GAME_STATE.SCORE; // TODO add score elements // TEMPORAY cleanScoreState(); } function handleScoreLoop() { // Score display logic here } function cleanScoreState() { log("cleanScoreState..."); LK.showGameOver(); } /***********************************************************************************/ /******************************** MAIN GAME LOOP ***********************************/ /***********************************************************************************/ game.update = function () { switch (gameState) { case GAME_STATE.MENU: handleMenuLoop(); break; case GAME_STATE.NEW_ROUND: handleNewRoundLoop(); break; case GAME_STATE.PLAYING: handlePlayingLoop(); break; case GAME_STATE.SCORE: handleScoreLoop(); break; } }; gameInitialize(); // Initialize the game /********************************************************************************/ /**************************** GAME DESCRIPTION *********************************/ /******************************************************************************/ /* **Game Title**: **Sand Tower** **Description**: Build towering sandcastles, perfect your alignment, and climb to the top! Sand Tower awaits! 🏖️🏰 **Objective**: - Players aim to construct the tallest sandcastle tower. - Perfect alignment of sand blocks is crucial for stability and bonus points. **Visuals**: - The game features a sandy beach backdrop. - A basic sandcastle stands in the center, serving as the base. - The central tower is the focal point. **Gameplay Mechanics**: - **Beach Bucket Mechanism**: - Players use an upside-down beach bucket. - When the player taps, the bucket tips over, releasing sand. - **Sand Block Placement**: - Sand falls vertically from the bucket onto the base. - The player must time their taps to stack the sand blocks. - Perfect alignment grants bonus points. - **Lives System**: - The player starts with 3 lives (represented by small bucket icons). - Each time a sand block isn't centered enough and falls, 1 life is lost. - **Scoring**: - Points increase with tower height. - Bonus points for precise alignment. - **Game Over**: - The game ends if the player loses all their lives (buckets). **Audio**: - Gentle beach sounds (waves, distant chatter). - Encouraging music during gameplay. */
/****
* Classes
****/
var SandBlock = Container.expand(function () {
var self = Container.call(this);
var sandBlockGraphics = self.attachAsset('sandBlock', {
anchorX: 0.5,
anchorY: 0
});
self.velocity = 0; // Initial velocity for natural falling speed increase
self.update = function () {
// SandBlock specific update logic
};
});
/***********************************************************************************/
/********************************** SANDCASTLE CLASS ************************************/
/***********************************************************************************/
var Sandcastle = Container.expand(function () {
var self = Container.call(this);
var sandcastleGraphics = self.attachAsset('sandcastle', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Sandcastle specific update logic
};
});
/****
* Initialize Game
****/
// Utility function to draw a polygon using drawLine
var game = new LK.Game({
backgroundColor: 0x000050 // Initialize game with a black background
});
/****
* Game Code
****/
function initializeBackgrounds() {
backgroundImage = LK.getAsset('backgroundImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(backgroundImage);
background2 = LK.getAsset('background2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2
});
background2.y = -background2.height / 2;
game.addChild(background2);
background3 = LK.getAsset('background3', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2
});
background3.y = -background2.height - background3.height / 2;
background4 = LK.getAsset('background2', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2
});
background4.y = -background2.height - background3.height - background4.height / 2;
game.addChild(background4);
background5 = LK.getAsset('background3', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2
});
background5.y = -background2.height - background3.height - background4.height - background5.height / 2;
game.addChild(background5);
game.addChild(background3);
}
// Enumeration for game states
/****************************************************************************************** */
/************************************** GLOBAL VARIABLES ********************************** */
/****************************************************************************************** */
var GAME_STATE = {
INIT: 'INIT',
MENU: 'MENU',
NEW_ROUND: 'NEW_ROUND',
PLAYING: 'PLAYING',
SCORE: 'SCORE'
};
var gameState = GAME_STATE.INIT;
var score = 0;
var scoreTxt;
var isDebug = true;
var debugText;
var debugMarker;
var backgroundImage;
var bucket;
var sandBlocks = [];
var lives = 3;
var livesIcons = [];
var cameraMoved = false; // Flag to track if the camera has moved for the current sandblock fall
var sandcastle;
var sandBlockSize = 512;
var gravity = 2; // Gravity effect for sand block falling
/****************************************************************************************** */
/*********************************** UTILITY FUNCTIONS ************************************ */
/****************************************************************************************** */
function moveCamera() {
var targetY = backgroundImage.y + sandBlockSize;
var moveStep = sandBlockSize / 60; // Move over 1 second (60 frames)
function progressiveMove() {
if (backgroundImage.y < targetY) {
backgroundImage.y += moveStep;
background2.y += moveStep;
background3.y += moveStep;
sandcastle.y += moveStep;
background4.y += moveStep;
background5.y += moveStep;
for (var j = 0; j < sandBlocks.length; j++) {
sandBlocks[j].y += moveStep;
}
if (backgroundImage.y < targetY) {
LK.setTimeout(progressiveMove, 1000 / 60); // Call progressiveMove every 1/60th of a second
} else {
bucket.y = 0; // Reset bucket position when the camera reaches the target
}
}
}
progressiveMove();
}
function log() {
if (isDebug) {
var _console;
(_console = console).log.apply(_console, arguments);
}
}
/****************************************************************************************** */
/************************************** INPUT HANDLERS ************************************ */
/****************************************************************************************** */
game.on('down', function (x, y, obj) {
switch (gameState) {
case GAME_STATE.MENU:
gameMenuDown(x, y, obj);
break;
case GAME_STATE.NEW_ROUND:
gameNewRoundDown(x, y, obj);
break;
case GAME_STATE.PLAYING:
gamePlayingDown(x, y, obj);
break;
case GAME_STATE.SCORE:
// Handle score display logic here
break;
}
});
function gameMenuDown(x, y, obj) {
log("gameMenuDown...");
cleanMenuState();
initNewRoundState();
}
function gameNewRoundDown(x, y, obj) {
log("gameNewRoundDown...");
cleanNewRoundState();
initPlayingState();
}
function gamePlayingDown(x, y, obj) {
log("gamePlayingDown...");
var sandBlock = new SandBlock();
sandBlock.x = bucket.x;
sandBlock.y = bucket.y - bucket.height / 2;
sandBlocks.push(sandBlock);
game.addChild(sandBlock);
cameraMoved = false; // Reset the flag when a new sandblock is created
// Move the bucket vertically to hide over the screen top
var bucketMoveStep = 15; // Adjust the step size as needed
function moveBucketUp() {
if (bucket.y > -bucket.height) {
bucket.y -= bucketMoveStep;
LK.setTimeout(moveBucketUp, 1000 / 240); // Call moveBucketUp every 1/60th of a second
}
}
moveBucketUp();
}
/****************************************************************************************** */
/************************************* GAME FUNCTIONS ************************************* */
/****************************************************************************************** */
/****************************************************************************************** */
/************************************* GAME STATES **************************************** */
/****************************************************************************************** */
function gameInitialize() {
log("Game initialize...");
initializeBackgrounds();
sandcastle = new Sandcastle();
sandcastle.x = 2048 / 2;
sandcastle.y = 2732 - sandcastle.height / 2 + 300;
game.addChild(sandcastle);
var banner = LK.getAsset('banner', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 0
});
game.addChild(banner);
for (var i = 0; i < lives; i++) {
var lifeIcon = LK.getAsset('bucketIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 300 + i * 100,
y: 50
});
livesIcons.push(lifeIcon);
LK.gui.top.addChild(lifeIcon);
}
bucket = LK.getAsset('bucket', {
anchorX: 0.5,
anchorY: 0.0,
x: 2048 / 2,
y: 0
});
game.addChild(bucket);
score = 0;
scoreTxt = new Text2('0', {
size: 150,
fill: "#ffffff"
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = 2048 / 2;
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt);
if (isDebug) {
debugMarker = LK.getAsset('debugMarker', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 * 0.5,
y: 1526
});
game.addChild(debugMarker);
debugText = new Text2('Debug Info', {
size: 50,
fill: "#ffffff"
});
debugText.anchor.set(0.5, 1); // Anchor to the bottom-right
LK.gui.bottom.addChild(debugText);
}
initMenuState();
}
// GAME MENU
function initMenuState() {
log("initMenuState...");
gameState = GAME_STATE.MENU;
}
function handleMenuLoop() {
// Menu animations here
}
function cleanMenuState() {
log("cleanMenuState...");
}
// NEW ROUND
function initNewRoundState() {
log("initNewRoundState...");
gameState = GAME_STATE.NEW_ROUND;
// Round preparation logic here.
}
function handleNewRoundLoop() {
// New Round animations here
}
function cleanNewRoundState() {
log("cleanNewRoundState...");
}
// PLAYING
function initPlayingState() {
log("initPlayingState...");
gameState = GAME_STATE.PLAYING;
}
function handlePlayingLoop() {
for (var i = sandBlocks.length - 1; i >= 0; i--) {
var sandBlock = sandBlocks[i];
if (sandBlock.y < 1526 - sandBlockSize) {
sandBlock.velocity += gravity; // Increase velocity due to gravity
sandBlock.y += sandBlock.velocity; // Update position based on velocity
}
if (sandBlock.y >= 1526 - sandBlockSize) {
// Move background, sandcastle, and fallen sandblock vertically by sandBlockSize
if (!cameraMoved) {
cameraMoved = true;
LK.setTimeout(function () {
moveCamera();
// Set the flag to true after moving the camera
//bucket.y = 0; // Reset bucket position when the camera moves
}, 512); // Delay of 1 second before moving the camera
}
// Check if sand block reached the base
if (Math.abs(sandBlock.x - 2048 / 2) < 50) {
// Check for perfect alignment
score += 10; // Bonus points for perfect alignment
} else {
lives--;
if (lives <= 0) {
LK.showGameOver();
return;
}
livesIcons[lives].destroy();
livesIcons.pop();
}
}
}
scoreTxt.setText(score);
if (isDebug) {
debugText.setText("X: " + bucket.x + " Y: " + bucket.y);
}
}
function cleanPlayingState() {
log("cleanPlayingState...");
// TODO Remove elements
}
// SCORE
function initScoreState() {
log("initScoreState...");
gameState = GAME_STATE.SCORE;
// TODO add score elements
// TEMPORAY
cleanScoreState();
}
function handleScoreLoop() {
// Score display logic here
}
function cleanScoreState() {
log("cleanScoreState...");
LK.showGameOver();
}
/***********************************************************************************/
/******************************** MAIN GAME LOOP ***********************************/
/***********************************************************************************/
game.update = function () {
switch (gameState) {
case GAME_STATE.MENU:
handleMenuLoop();
break;
case GAME_STATE.NEW_ROUND:
handleNewRoundLoop();
break;
case GAME_STATE.PLAYING:
handlePlayingLoop();
break;
case GAME_STATE.SCORE:
handleScoreLoop();
break;
}
};
gameInitialize(); // Initialize the game
/********************************************************************************/
/**************************** GAME DESCRIPTION *********************************/
/******************************************************************************/
/*
**Game Title**: **Sand Tower**
**Description**: Build towering sandcastles, perfect your alignment, and climb to the top! Sand Tower awaits! 🏖️🏰
**Objective**:
- Players aim to construct the tallest sandcastle tower.
- Perfect alignment of sand blocks is crucial for stability and bonus points.
**Visuals**:
- The game features a sandy beach backdrop.
- A basic sandcastle stands in the center, serving as the base.
- The central tower is the focal point.
**Gameplay Mechanics**:
- **Beach Bucket Mechanism**:
- Players use an upside-down beach bucket.
- When the player taps, the bucket tips over, releasing sand.
- **Sand Block Placement**:
- Sand falls vertically from the bucket onto the base.
- The player must time their taps to stack the sand blocks.
- Perfect alignment grants bonus points.
- **Lives System**:
- The player starts with 3 lives (represented by small bucket icons).
- Each time a sand block isn't centered enough and falls, 1 life is lost.
- **Scoring**:
- Points increase with tower height.
- Bonus points for precise alignment.
- **Game Over**:
- The game ends if the player loses all their lives (buckets).
**Audio**:
- Gentle beach sounds (waves, distant chatter).
- Encouraging music during gameplay.
*/
Front close view of a calm sea from the beach. nothing on the beach just flat sand. no sun... photorealistic
Start button. Beach themed
face view of a red beach bucket with a blue handle.. photo
beach toys. photorealistic
beach construction toys. red bucket with blue handle.. photorealistic
an horizontal cloud. photorealistic
an air ballon. photorealistic
simple rectangular white ribon.
a soaring gull. lateral view