Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (9 edits merged)
Please save this source code
User prompt
Please fix the bug: 'withOffset is not defined' in or related to this line: 'levelText.x = centerX + (withOffset ? 2048 : 0);' Line Number: 230
Code edit (3 edits merged)
Please save this source code
User prompt
when background animate Transition ends, restore initial positions of graphics
Code edit (1 edits merged)
Please save this source code
User prompt
when changing level, call animateTransition on backgroundImage
User prompt
in BackgroundImage add a new function animateTransition() that animates the move of the 4 graphics with a delta of -2048 for x and -2732 for y
Code edit (8 edits merged)
Please save this source code
User prompt
create a class for levelNumberText and use it
Code edit (13 edits merged)
Please save this source code
User prompt
update levelNumberText when changing level
Code edit (1 edits merged)
Please save this source code
User prompt
add a new levelNumberText Text: - declare levelNumberText global - initialize it in initializeGame function, very big and at the screen center. set its text to the current Level number. not visible. - make it visible in initNewRoundState
Code edit (1 edits merged)
Please save this source code
User prompt
play operationSelect when dragNode is set to operation
Code edit (5 edits merged)
Please save this source code
User prompt
rename tileEntrance to tileRemove
Code edit (4 edits merged)
Please save this source code
User prompt
play tile entrance sound once when a tile enters the screen
User prompt
play tick sound once when a tile is highlighted
Code edit (5 edits merged)
Please save this source code
User prompt
rework the lines : ``` // Place tiles randomly out of the screen tile.x = Math.random() * 2300 - 1024; tile.y = Math.random() * 3000 - 1366; ``` To ensure tiles always start out of the screen
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // BackgroundImage class to represent the background image var BackgroundImage = Container.expand(function () { var self = Container.call(this); // Asset Attachments var backgroundGraphics = self.attachAsset('gradientBackground', { anchorX: 0.5, anchorY: 0.5, x: centerX, y: centerY //tint: 0x00FF00 }); var nextBackgroundH = self.attachAsset('gradientBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: -1, scaleY: 1, x: centerX + 2048, y: centerY }); var nextBackgroundV = self.attachAsset('gradientBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: -1, x: centerX, y: centerY + 2732 }); var nextBackgroundC = self.attachAsset('gradientBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: -1, scaleY: -1, x: centerX + 2048, y: centerY + 2732 //tint: 0xFF0000 }); self.animateTransition = function (dirX, dirY) { if (puzzleManager.currentLevel == 1) { // No anim for level 1 return; } self.prepareSideBackgrounds(dirX, dirY); var deltaX = -dirX * 2048; var deltaY = -dirY * 2732; tween(backgroundGraphics, { x: backgroundGraphics.x + deltaX, y: backgroundGraphics.y + deltaY }, { duration: 1000, easing: tween.easeInOut }); tween(nextBackgroundH, { x: nextBackgroundH.x + deltaX, y: nextBackgroundH.y + deltaY }, { duration: 1000, easing: tween.easeInOut }); tween(nextBackgroundV, { x: nextBackgroundV.x + deltaX, y: nextBackgroundV.y + deltaY }, { duration: 1000, easing: tween.easeInOut }); tween(nextBackgroundC, { x: nextBackgroundC.x + deltaX, y: nextBackgroundC.y + deltaY }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Update main background like the transitioned one backgroundGraphics.scale.x = nextBackgroundC.scale.x; backgroundGraphics.scale.y = nextBackgroundC.scale.y; // Switch backgrounds backgroundGraphics.x = centerX; backgroundGraphics.y = centerY; nextBackgroundC.x += 2048; nextBackgroundC.y += 2732; // Restore initial positions of graphics nextBackgroundH.scale.x *= -1; nextBackgroundH.scale.y *= -1; nextBackgroundV.scale.x *= -1; nextBackgroundV.scale.y *= -1; nextBackgroundC.scale.x *= -1; nextBackgroundC.scale.y *= -1; //backgroundGraphics.x -= deltaX; //backgroundGraphics.y -= deltaY; /* nextBackgroundH.x += 2048; nextBackgroundH.y += 2732; nextBackgroundV.x += 2048; nextBackgroundV.y += 2732; nextBackgroundC.x += 2048; nextBackgroundC.y += 2732; */ } }); }; self.prepareSideBackgrounds = function (dirX, dirY) { // Position the next backgrounds depending on the currrent transition direction nextBackgroundH.x = centerX + dirX * 2048; nextBackgroundH.y = centerY; nextBackgroundV.x = centerX; nextBackgroundV.y = centerY + dirY * 2732; nextBackgroundC.x = centerX + dirX * 2048; nextBackgroundC.y = centerY + dirY * 2732; }; return self; }); /***********************************************************************************************/ /******************************************* ASSETS CLASSES ************************************/ /***********************************************************************************************/ // HexTile class to represent each tile on the board var HexTile = Container.expand(function (value, col, row, levelData) { var self = Container.call(this); // Constants var interTileOffsetX = -2; var interTileOffsetY = -4; // relative to interTileOffsetX var tileSize = LK.getAsset('hexTile', {}).width + interTileOffsetX; var tileOffsetX = tileSize; var tileOffsetY = tileSize * 0.75 - interTileOffsetY; // Properties self.value = value; self.originalValue = value; self.visible = false; self.col = col; self.row = row; self.neighbors = []; var tileX = col * tileOffsetX - (levelData ? levelData.tiles.length : 0) * (tileSize / 2) + (row % 2 === 1 ? -tileSize / 2 : 0); var tileY = row * tileOffsetY - (levelData ? levelData.tiles.length : 0) * (tileSize / 2); self.baseX = tileX; self.baseY = tileY; self.x = tileX; self.y = tileY; // Asset Attachments var tileGraphicsShadow = self.attachAsset('hexTile', { anchorX: 0.5, anchorY: 0.5, x: 7, y: 5, tint: 0x000000, alpha: 0.70 }); var tileGraphics = self.attachAsset('hexTile', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, tint: tileColors[self.value], alpha: 0.9 }); // Value text shadow var valueTextShadow = new Text2(self.value.toString(), { size: tileSize * 0.5, fill: 0x000000, //fill: tileColors[self.value], weight: 1000 }); valueTextShadow.anchor.set(0.5, 0.5); valueTextShadow.alpha = 0.1; valueTextShadow.x = tileGraphics.x + 12; valueTextShadow.y = tileGraphics.y - tileSize * 0.01 + 12; self.valueTextShadow = self.addChild(valueTextShadow); // Value Text var valueText = new Text2(self.value.toString(), { size: tileSize * 0.5, fill: 0xEAEEE8, dropShadow: false }); valueText.anchor.set(0.5, 0.5); valueText.x = tileGraphics.x; valueText.y = tileGraphics.y - tileSize * 0.01; self.valueText = self.addChild(valueText); // Functions self.setValue = function (newValue, depth) { LK.setTimeout(function () { // Enclose operation in a timeout log("setValue to ", newValue, depth); self.value = newValue; if (self.value === 0) { self.valueTextShadow.setText(""); self.valueText.setText(""); LK.getSound('tileRemove').play(); tween(tileGraphics, { scaleX: 0, scaleY: 0, rotation: Math.PI / 2 }, { duration: 1000, easing: tween.easeOut }); tween(tileGraphicsShadow, { scaleX: 0, scaleY: 0, rotation: Math.PI / 2 }, { duration: 1000, easing: tween.easeOut }); } else { LK.getSound('tileChangeValue').play(); self.valueText.setText(self.value.toString()); self.valueTextShadow.setText(self.value.toString()); } // Animate color change tween(tileGraphics, { tint: tileColors[self.value] }, { duration: 600, easing: tween.easeOut }); }, depth * 175); // Delay proportional to normalized distance }; return self; }); // LevelNumberText class to represent the level number text var LevelNumberText = Container.expand(function (initialLevel) { var self = Container.call(this); self.displayedLevel = initialLevel; // Initialize level number text var levelText = new Text2(initialLevel.toString(), { size: 600, fill: 0x787878, weight: 1000, dropShadow: true, dropShadowAngle: Math.PI, dropShadowDistance: 10 }); levelText.anchor.set(0.5, 0.5); levelText.alpha = 0.2; levelText.blendMode = 2; levelText.x = centerX; levelText.y = centerY; levelText.visible = false; self.addChild(levelText); // Initialize next level number text var levelText2 = new Text2((initialLevel + 1).toString(), { size: 600, fill: 0x787878, weight: 1000, dropShadow: true, dropShadowAngle: Math.PI, dropShadowDistance: 10 }); levelText2.anchor.set(0.5, 0.5); levelText2.alpha = 0.2; levelText2.blendMode = 2; levelText2.x = centerX + 2048; levelText2.y = centerY + 2732; levelText2.visible = false; self.addChild(levelText2); // Method to update the level number self.updateLevel = function (newLevel) { if (newLevel > 1) { if (newLevel == self.displayedLevel) { // When reseting current level show current level in text2 levelText2.setText(self.displayedLevel.toString()); } tween(levelText, { x: levelText.x - 2048, y: levelText.y - 2732 }, { duration: 1000, easing: tween.easeInOut }); tween(levelText2, { x: levelText2.x - 2048, y: levelText2.y - 2732 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { self.displayedLevel = newLevel; levelText.setText(newLevel.toString()); levelText2.setText((newLevel + 1).toString()); // Restore initial positions levelText.x += 2048; levelText.y += 2732; levelText2.x += 2048; levelText2.y += 2732; } }); } }; // Method to show the level number self.show = function () { levelText.visible = true; levelText2.visible = true; }; // Method to hide the level number self.hide = function () { levelText.visible = false; levelText2.visible = false; }; return self; }); // OperationButton class to represent each operation button var OperationButton = Container.expand(function (type, uses) { var self = Container.call(this); // Properties self.type = type; self.remainingUses = uses; self.baseX = 0; // Initialize baseX to store initial x position self.baseY = 0; // Initialize baseY to store initial y position var buttonSize = LK.getAsset('operationButton', {}).width; // Asset Attachments var buttonGraphicsShadow = self.attachAsset('operationButton', { anchorX: 0.5, anchorY: 0.5, x: 10, y: 10, tint: 0x000000, alpha: 0.7 }); var buttonGraphics = self.attachAsset('operationButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Value Text var valueText = new Text2(self.type, { size: buttonSize * 0.45, fill: tileColors[1], dropShadow: false, weight: 1000 }); valueText.anchor.set(0.5, 0.5); valueText.x = buttonGraphics.x; valueText.y = buttonGraphics.y; self.valueText = self.addChild(valueText); // Functions self.setBasePosition = function (x, y) { self.x = x; self.y = y; self.baseX = x; self.baseY = y; }; self.updateUses = function () { // Update the display or logic related to remaining uses log("Remaining uses updated: ", self.remainingUses); }; return self; }); // ResetButton class to represent the reset button var ResetButton = Container.expand(function () { var self = Container.call(this); // Asset Attachments var buttonShadow = self.attachAsset('resetButton', { anchorX: 0.5, anchorY: 0.5, x: 10, y: 10, tint: 0x000000, alpha: 0.25 }); var buttonGraphics = self.attachAsset('resetButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, tint: 0xEAEEE8 }); self.down = function () { self.disable(); LK.getSound("resetSound").play(); puzzleManager.reset(); // Reset the level puzzle }; self.disable = function () { buttonGraphics.alpha = 0.5; // Dim the button to indicate it's disabled self.interactive = false; // Disable interaction }; self.enable = function () { buttonGraphics.alpha = 1.0; // Restore full opacity to indicate it's enabled self.interactive = true; // Enable interaction }; self.activate = function () { self.visible = true; }; self.deactivate = function () { self.visible = false; }; return self; }); // StartButton class to represent the start button var StartButton = Container.expand(function () { var self = Container.call(this); // Asset Attachments var buttonGraphics = self.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Set game background to black }); /**** * Game Code ****/ var levelNumberText; /************************************* GAME OBJECTS CLASSES ************************************/ /***********************************************************************************************/ // Transition to menu state function PuzzleManager(game) { var self = this; // Properties self.game = game; self.activeTileCount = 0; // Initialize active tile count self.levelBoardOffsetX = 0; // Initialize levelBoardOffsetX self.levelBoardOffsetY = 0; // Initialize levelBoardOffsetY self.currentLevel = 1; self.previousLevelNumber = 1; self.board = []; self.operations = []; self.isAnimating = false; self.selectedOperation = null; self.moveCount = 0; self.levelData = null; // Core Functions self.initPuzzle = function () { self.loadLevel(self.currentLevel); }; self.reset = function () { // Remove all existing tiles self.board.forEach(function (tile) { tile.destroy(); }); self.board = []; // Remove all existing operations self.operations.forEach(function (operation) { operation.destroy(); }); self.operations = []; // Load the current level self.previousLevelNumber = self.currentLevel; self.loadLevel(self.currentLevel); }; self.loadLevel = function (levelNumber) { log("loadLevel...previousLevelNumber", self.previousLevelNumber, " new levelNumber:", levelNumber); // Load level configuration self.levelData = levelConfigs[levelNumber] || { tiles: [], operations: [] }; levelNumberText.updateLevel(levelNumber); currentTransitionDirectionH = levelNumber > self.previousLevelNumber ? 1 : -1; currentTransitionDirectionV = Math.random() < 0.33 ? -1 : Math.random() < 0.33 ? 0 : 1; log("transitions :", currentTransitionDirectionH, currentTransitionDirectionV); backgroundImage.animateTransition(currentTransitionDirectionH, currentTransitionDirectionV); self.createBoard(); self.fillTilesNeighbors(); self.createOperations(); LK.setTimeout(self.animateTilesEntrance, levelNumber == 1 ? 0 : 1000); }; self.createBoard = function () { self.board = []; var maxTilesInRow = 0; // Local variable to track the largest number of tiles in the level rows self.activeTileCount = 0; // Reset active tile count // Update levelBoardOffsets depending on level for (var row = 0; row < self.levelData.tiles.length; row++) { maxTilesInRow = Math.max(maxTilesInRow, self.levelData.tiles[row].length); for (var col = 0; col < self.levelData.tiles[row].length; col++) { var value = self.levelData.tiles[row][col]; if (value !== "") { var tile = new HexTile(value, col, row, self.levelData); self.board.push(tile); boardContainer.addChild(tile); self.activeTileCount++; // Increment active tile count } } } self.levelBoardOffsetX = maxTilesInRow * 100; // largest row * 100 self.levelBoardOffsetY = self.levelData.tiles.length * 30; // nb rows * 30 for (var i = 0; i < self.board.length; i++) { var tile = self.board[i]; tile.x += self.levelBoardOffsetX; tile.y += self.levelBoardOffsetY; } }; self.fillTilesNeighbors = function () { for (var i = 0; i < self.board.length; i++) { var tile = self.board[i]; tile.neighbors = []; for (var j = 0; j < self.board.length; j++) { var potentialNeighbor = self.board[j]; if (tile !== potentialNeighbor && self.areNeighbors(tile, potentialNeighbor)) { tile.neighbors.push(potentialNeighbor); } } } }; self.areNeighbors = function (tile1, tile2) { var dx = Math.abs(tile1.col - tile2.col); var dy = Math.abs(tile1.row - tile2.row); return dx === 1 && dy === 0 || dx === 0 && dy === 1 || dx === 1 && dy === 1; }; self.createOperations = function () { self.operations = []; var baseX = centerX + 900; var baseY = 2620; for (var i = 0; i < self.levelData.operations.length; i++) { var opType = self.levelData.operations[i]; var operation = new OperationButton(opType, 1); // Default uses to 1 as it's no longer needed self.operations.push(operation); var operationX = i < 3 ? baseX - i * 200 : baseX - 100 - (i - 3) * 200; var operationY = i < 3 ? baseY : baseY - 150; operation.setBasePosition(operationX, operationY); // Space buttons evenly and position near the bottom self.game.addChild(operation); } }; self.applyOperation = function (operation, tile) { if (operation.remainingUses > 0) { self.propagateOperation(operation, tile); operation.remainingUses--; operation.updateUses(); self.checkWinCondition(); } }; self.propagateOperation = function (operation, startTile) { var visited = []; var toProcess = [{ tile: startTile, depth: 0 }]; var targetValue = startTile.value; log("Starting propagateOperation with targetValue:", targetValue); while (toProcess.length > 0) { var current = toProcess.pop(); var currentTile = current.tile; var startX = startTile.x; var startY = startTile.y; var dx = Math.abs(currentTile.col - startTile.col); var dy = Math.abs(currentTile.row - startTile.row); var normalizedDistance = Math.max(dx, dy); // Use the maximum of dx and dy to count the distance in tiles log("Processing tile at position:", currentTile.x, currentTile.y, "with value:", currentTile.value, "at normalized distance:", normalizedDistance); if (visited.includes(currentTile)) { log("Tile already visited:", currentTile); continue; } visited.push(currentTile); var newValue = currentTile.value + parseInt(operation.type); if (newValue == 0) { self.activeTileCount--; } resetButton.enable(); currentTile.setValue(newValue, normalizedDistance); log("Applied operation. New value:", currentTile.value); // Check neighbors var _iterator = _createForOfIteratorHelper(currentTile.neighbors), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var neighbor = _step.value; log("Checking neighbor at position:", neighbor.x, neighbor.y, "with value:", neighbor.value); if (neighbor.value === targetValue && !visited.includes(neighbor)) { log("Neighbor matches target value and is not visited. Adding to process list:", neighbor); toProcess.push({ tile: neighbor, depth: normalizedDistance + 1 }); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } log("Finished propagateOperation"); }; self.animateTilesEntrance = function () { self.board.forEach(function (tile, index) { // Place tiles randomly out of the screen tile.x = Math.random() > 0.5 ? -200 - Math.random() * 1000 : 2248 + Math.random() * 1000; tile.y = Math.random() > 0.5 ? -200 - Math.random() * 1000 : 2732 + Math.random() * 1000; ; log("animateTilesEntrance #" + index, tile.x, tile.y); tile.visible = true; // Animate tiles to their base positions tween(tile, { x: tile.baseX + self.levelBoardOffsetX, y: tile.baseY + self.levelBoardOffsetY }, { duration: 800, easing: tween.bounceOut }); }); }; self.checkWinCondition = function () { log("checkWinCondition... Active tiles:", self.activeTileCount); if (self.activeTileCount == 0) { self.playVictoryAnimation(); isPlaying = false; resetButton.disable(); LK.setTimeout(function () { self.previousLevelNumber = self.currentLevel; self.currentLevel++; // Advance to the next level changeGameState(GAME_STATE.NEW_ROUND); // Change state to newRound }, 2000); } }; // Animation Functions self.playVictoryAnimation = function () { log("playVictoryAnimation...previousLevelNumber", self.previousLevelNumber); // Play level complete animation }; } /***********************************************************************************************/ /************************************* UTILITY FUNCTIONS ************************************/ /***********************************************************************************************/ function log() { if (debug) { console.log.apply(console, arguments); } } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) { throw o; } } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } // Business tools function isPointInsideTile(x, y, tile) { var overlapOffsetX = 15; // Offset to prevent multiple tile selection on X-axis var overlapOffsetY = 38; // Offset to prevent multiple tile selection on Y-axis return x >= boardContainer.x + tile.x - tile.width / 2 + overlapOffsetX && x <= boardContainer.x + tile.x + tile.width / 2 - overlapOffsetX && y >= boardContainer.y + tile.y - tile.height / 2 + overlapOffsetY && y <= boardContainer.y + tile.y + tile.height / 2 - overlapOffsetY; } /***********************************************************************************************/ /************************************* GAME STATE MANAGEMENT ************************************/ /***********************************************************************************************/ function initMenuState() { // Initialize the game state for MENU log("Initializing MENU State"); startButton.visible = true; if (debug) { changeGameState(GAME_STATE.NEW_ROUND); } } function handleMenuLoop() { // Handle the game loop for MENU state log("Handling MENU Loop"); } function cleanMenuState() { // Clean up the game state for MENU log("Cleaning MENU State"); startButton.visible = false; } function initNewRoundState() { // Initialize the game state for NEW_ROUND log("Initializing NEW_ROUND State"); puzzleManager.initPuzzle(); levelNumberText.show(); if (debug) { changeGameState(GAME_STATE.PLAYING); } } function handleNewRoundLoop() { // Handle the game loop for NEW_ROUND state log("Handling NEW_ROUND Loop"); } function cleanNewRoundState() { // Clean up the game state for NEW_ROUND log("Cleaning NEW_ROUND State"); } function initPlayingState() { // Initialize the game state for PLAYING log("Initializing PLAYING State"); resetButton.activate(); // Make resetButton visible in PLAYING state } function handlePlayingLoop() { // Handle the game loop for PLAYING state log("Handling PLAYING Loop"); } function cleanPlayingState() { // Clean up the game state for PLAYING log("Cleaning PLAYING State"); resetButton.deactivate(); } function initScoreState() { // Initialize the game state for SCORE log("Initializing SCORE State"); } function handleScoreLoop() { // Handle the game loop for SCORE state log("Handling SCORE Loop"); } function cleanScoreState() { // Clean up the game state for SCORE log("Cleaning SCORE State"); } function changeGameState(newState) { log("Changing game state from", currentState, "to", newState); // Clean up the current state switch (currentState) { case GAME_STATE.INIT: // Do nothing break; case GAME_STATE.MENU: cleanMenuState(); break; case GAME_STATE.NEW_ROUND: cleanNewRoundState(); break; case GAME_STATE.PLAYING: cleanPlayingState(); break; case GAME_STATE.SCORE: cleanScoreState(); break; default: log("Unknown state:", currentState); } // Set the new state currentState = newState; // Initialize the new state switch (newState) { case GAME_STATE.MENU: initMenuState(); break; case GAME_STATE.NEW_ROUND: initNewRoundState(); break; case GAME_STATE.PLAYING: initPlayingState(); break; case GAME_STATE.SCORE: initScoreState(); break; default: log("Unknown state:", newState); } } /***********************************************************************************************/ /****************************************** EVENT HANDLERS *************************************/ /***********************************************************************************************/ game.down = function (x, y, obj) { switch (currentState) { case GAME_STATE.MENU: handleMenuStateDown(x, y, obj); break; case GAME_STATE.PLAYING: handlePlayingStateDown(x, y, obj); break; case GAME_STATE.SCORE: handleScoreStateDown(x, y, obj); break; default: log("Unknown state:", currentState); } }; game.move = function (x, y, obj) { switch (currentState) { case GAME_STATE.MENU: handleMenuStateMove(x, y, obj); break; case GAME_STATE.PLAYING: handlePlayingStateMove(x, y, obj); break; case GAME_STATE.SCORE: handleScoreStateMove(x, y, obj); break; default: log("Unknown state:", currentState); } }; game.up = function (x, y, obj) { switch (currentState) { case GAME_STATE.MENU: handleMenuStateUp(x, y, obj); break; case GAME_STATE.PLAYING: handlePlayingStateUp(x, y, obj); break; case GAME_STATE.SCORE: handleScoreStateUp(x, y, obj); break; default: log("Unknown state:", currentState); } }; // Menu State Handlers function handleMenuStateDown(x, y, obj) { // Implement logic for handling down event in MENU state log("Handling down event in MENU state"); changeGameState(GAME_STATE.NEW_ROUND); } function handleMenuStateMove(x, y, obj) { // Implement logic for handling move event in MENU state //log("Handling move event in MENU state"); } function handleMenuStateUp(x, y, obj) { // Implement logic for handling up event in MENU state log("Handling up event in MENU state"); } // Playing State Handlers function handlePlayingStateDown(x, y, obj) { // Implement logic for handling down event in PLAYING state log("Handling down event in PLAYING state", obj); /*if (x >= resetButton.x - resetButton.width / 2 && x <= resetButton.x + resetButton.width / 2 && y >= resetButton.y - resetButton.height / 2 && y <= resetButton.y + resetButton.height / 2) { log("Reset button pressed"); puzzleManager.reset(); // Reset the level puzzle return; } */ puzzleManager.operations.forEach(function (operation) { if (x >= operation.x - operation.width / 2 && x <= operation.x + operation.width / 2 && y >= operation.y - operation.height / 2 && y <= operation.y + operation.height / 2) { dragNode = operation; LK.getSound('operationSelect').play(); return; } }); } function handlePlayingStateMove(x, y, obj) { //log("Handling move event in PLAYING state", dragNode); if (dragNode) { dragNode.x = x; dragNode.y = y; puzzleManager.board.forEach(function (tile) { if (isPointInsideTile(x, y, tile)) { if (!tile.isHighlighted) { tile.isHighlighted = true; tile.previousZIndex = boardContainer.getChildIndex(tile); // Store previous z-index boardContainer.addChildAt(tile, boardContainer.children.length - 1); // Bring tile to the front tween(tile, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut }); // Play tick sound when a tile is highlighted LK.getSound('tick').play(); } } else if (tile.isHighlighted) { tile.isHighlighted = false; boardContainer.addChildAt(tile, tile.previousZIndex); // Restore tile's original z-index tween(tile, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); } }); } //log("Handling move event in PLAYING state"); } function handlePlayingStateUp(x, y, obj) { // Implement logic for handling up event in PLAYING state log("Handling up event in PLAYING state"); if (dragNode) { // Check if the operation button is above a tile var tileFound = false; log("Operation dropped at ", x, y); log("boardContainer at ", boardContainer.x, boardContainer.y); puzzleManager.board.forEach(function (tile) { log("Checking tile at position:", tile.x, tile.y); // Log tile position if (isPointInsideTile(x, y, tile)) { log("Operation button is above tile at position:", tile.x, tile.y); // Log when operation button is above a tile puzzleManager.applyOperation(dragNode, tile); tileFound = true; boardContainer.addChildAt(tile, tile.previousZIndex); // Restore tile's original z-index tween(tile, { // Restore tile size after operation is applied scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); //{4x.1} tween(dragNode, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { if (dragNode) { dragNode.destroy(); } } }); } else { log("Operation button is NOT above tile at position:", tile.x, tile.y); // Log when operation button is not above a tile } }); if (!tileFound) { log("Operation button not above any tile"); LK.getSound('operationCancel').play(); tween(dragNode, { x: dragNode.baseX, y: dragNode.baseY }, { duration: 500, easing: tween.easeOut }); } dragNode = null; } } // Score State Handlers function handleScoreStateDown(x, y, obj) { // Implement logic for handling down event in SCORE state log("Handling down event in SCORE state"); } function handleScoreStateMove(x, y, obj) { // Implement logic for handling move event in SCORE state //log("Handling move event in SCORE state"); } function handleScoreStateUp(x, y, obj) { // Implement logic for handling up event in SCORE state log("Handling up event in SCORE state"); } // Initialize PuzzleManager //<Assets used in the game will automatically appear here> //<Write imports for supported plugins here> /***********************************************************************************************/ /****************************************** GLOBAL VARIABLES ***********************************/ /***********************************************************************************************/ var debug = true; var isPlaying = false; var GAME_STATE = { INIT: 'INIT', MENU: 'MENU', NEW_ROUND: 'NEW_ROUND', PLAYING: 'PLAYING', SCORE: 'SCORE' }; var currentState = GAME_STATE.INIT; var boardContainer; var puzzleManager; var startButton; var backgroundLayer; var middleLayer; var foregroundLayer; var backgroundImage; var centerX = 1024; var centerY = 1366; var currentTransitionDirectionH = 1; var currentTransitionDirectionV = 1; var dragNode = null; var resetButton; // Declare resetButton as a global variable var tileColors = { 0: 0xEAEEE8, // White / Gray 1: 0x1E90FF, // Blue 2: 0xF93827, // Red 4: 0xFFD65A, // Yellow light 3: 0xFF9D23 // Yellow / Orange }; var levelConfigs = { 1: { tiles: [["", 1, ""], ["", 1, 1], [1, 1, 1], ["", 1, 1], ["", 1, ""]], operations: ['-1'] }, 2: { tiles: [["", 1, ""], ["", 1, 1], [2, 2, 2], ["", 1, 1], ["", 1, ""]], operations: ['-1', '-1'] }, 3: { tiles: [["", "", 1, "", ""], ["", "", 1, 1, ""], ["", 2, 2, 2, ""], ["", 2, 2, 2, 2], [3, 3, 3, 3, 3], ["", 2, 2, 2, 2], ["", 2, 2, 2, ""], ["", "", 1, 1, ""], ["", "", 1, "", ""]], operations: ['-1', '-1', '-1'] } }; // Example configuration for two levels /***********************************************************************************************/ /***************************************** GAME INITIALISATION *********************************/ /***********************************************************************************************/ function initializeGame() { backgroundLayer = new Container(); middleLayer = new Container(); foregroundLayer = new Container(); backgroundImage = new BackgroundImage(); backgroundLayer.addChild(backgroundImage); game.addChild(backgroundLayer); game.addChild(middleLayer); game.addChild(foregroundLayer); boardContainer = new Container(); middleLayer.addChild(boardContainer); boardContainer.x = centerX; boardContainer.y = centerY; puzzleManager = new PuzzleManager(game); startButton = new StartButton(); startButton.x = centerX; // Center horizontally startButton.y = centerY; // Center vertically game.addChild(startButton); startButton.visible = false; resetButton = new ResetButton(); resetButton.x = game.width - 150; // Position at top right resetButton.y = 150; resetButton.visible = false; // Keep it non-visible initially // Initialize levelNumberText using LevelNumberText class levelNumberText = new LevelNumberText(puzzleManager.currentLevel); backgroundLayer.addChild(levelNumberText); foregroundLayer.addChild(resetButton); // Transition to menu state changeGameState(GAME_STATE.MENU); } initializeGame();
===================================================================
--- original.js
+++ change.js
@@ -14,8 +14,9 @@
anchorX: 0.5,
anchorY: 0.5,
x: centerX,
y: centerY
+ //tint: 0x00FF00
});
var nextBackgroundH = self.attachAsset('gradientBackground', {
anchorX: 0.5,
anchorY: 0.5,
@@ -38,61 +39,83 @@
scaleX: -1,
scaleY: -1,
x: centerX + 2048,
y: centerY + 2732
+ //tint: 0xFF0000
});
- self.animateTransition = function () {
+ self.animateTransition = function (dirX, dirY) {
if (puzzleManager.currentLevel == 1) {
+ // No anim for level 1
return;
}
+ self.prepareSideBackgrounds(dirX, dirY);
+ var deltaX = -dirX * 2048;
+ var deltaY = -dirY * 2732;
tween(backgroundGraphics, {
- x: backgroundGraphics.x - 2048,
- y: backgroundGraphics.y - 2732
+ x: backgroundGraphics.x + deltaX,
+ y: backgroundGraphics.y + deltaY
}, {
duration: 1000,
easing: tween.easeInOut
});
tween(nextBackgroundH, {
- x: nextBackgroundH.x - 2048,
- y: nextBackgroundH.y - 2732
+ x: nextBackgroundH.x + deltaX,
+ y: nextBackgroundH.y + deltaY
}, {
duration: 1000,
easing: tween.easeInOut
});
tween(nextBackgroundV, {
- x: nextBackgroundV.x - 2048,
- y: nextBackgroundV.y - 2732
+ x: nextBackgroundV.x + deltaX,
+ y: nextBackgroundV.y + deltaY
}, {
duration: 1000,
easing: tween.easeInOut
});
tween(nextBackgroundC, {
- x: nextBackgroundC.x - 2048,
- y: nextBackgroundC.y - 2732
+ x: nextBackgroundC.x + deltaX,
+ y: nextBackgroundC.y + deltaY
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
+ // Update main background like the transitioned one
+ backgroundGraphics.scale.x = nextBackgroundC.scale.x;
+ backgroundGraphics.scale.y = nextBackgroundC.scale.y;
+ // Switch backgrounds
+ backgroundGraphics.x = centerX;
+ backgroundGraphics.y = centerY;
+ nextBackgroundC.x += 2048;
+ nextBackgroundC.y += 2732;
// Restore initial positions of graphics
- backgroundGraphics.scale.x *= -1;
- backgroundGraphics.scale.y *= -1;
nextBackgroundH.scale.x *= -1;
- //nextBackgroundH.scale.y *= -1;
- //nextBackgroundV.scale.x *= -1;
+ nextBackgroundH.scale.y *= -1;
+ nextBackgroundV.scale.x *= -1;
nextBackgroundV.scale.y *= -1;
nextBackgroundC.scale.x *= -1;
nextBackgroundC.scale.y *= -1;
- backgroundGraphics.x += 2048;
- backgroundGraphics.y += 2732;
+ //backgroundGraphics.x -= deltaX;
+ //backgroundGraphics.y -= deltaY;
+ /*
nextBackgroundH.x += 2048;
nextBackgroundH.y += 2732;
nextBackgroundV.x += 2048;
nextBackgroundV.y += 2732;
nextBackgroundC.x += 2048;
nextBackgroundC.y += 2732;
+ */
}
});
};
+ self.prepareSideBackgrounds = function (dirX, dirY) {
+ // Position the next backgrounds depending on the currrent transition direction
+ nextBackgroundH.x = centerX + dirX * 2048;
+ nextBackgroundH.y = centerY;
+ nextBackgroundV.x = centerX;
+ nextBackgroundV.y = centerY + dirY * 2732;
+ nextBackgroundC.x = centerX + dirX * 2048;
+ nextBackgroundC.y = centerY + dirY * 2732;
+ };
return self;
});
/***********************************************************************************************/
/******************************************* ASSETS CLASSES ************************************/
@@ -403,8 +426,9 @@
self.activeTileCount = 0; // Initialize active tile count
self.levelBoardOffsetX = 0; // Initialize levelBoardOffsetX
self.levelBoardOffsetY = 0; // Initialize levelBoardOffsetY
self.currentLevel = 1;
+ self.previousLevelNumber = 1;
self.board = [];
self.operations = [];
self.isAnimating = false;
self.selectedOperation = null;
@@ -425,18 +449,23 @@
operation.destroy();
});
self.operations = [];
// Load the current level
+ self.previousLevelNumber = self.currentLevel;
self.loadLevel(self.currentLevel);
};
self.loadLevel = function (levelNumber) {
+ log("loadLevel...previousLevelNumber", self.previousLevelNumber, " new levelNumber:", levelNumber);
// Load level configuration
self.levelData = levelConfigs[levelNumber] || {
tiles: [],
operations: []
};
levelNumberText.updateLevel(levelNumber);
- backgroundImage.animateTransition();
+ currentTransitionDirectionH = levelNumber > self.previousLevelNumber ? 1 : -1;
+ currentTransitionDirectionV = Math.random() < 0.33 ? -1 : Math.random() < 0.33 ? 0 : 1;
+ log("transitions :", currentTransitionDirectionH, currentTransitionDirectionV);
+ backgroundImage.animateTransition(currentTransitionDirectionH, currentTransitionDirectionV);
self.createBoard();
self.fillTilesNeighbors();
self.createOperations();
LK.setTimeout(self.animateTilesEntrance, levelNumber == 1 ? 0 : 1000);
@@ -581,16 +610,17 @@
self.playVictoryAnimation();
isPlaying = false;
resetButton.disable();
LK.setTimeout(function () {
+ self.previousLevelNumber = self.currentLevel;
self.currentLevel++; // Advance to the next level
changeGameState(GAME_STATE.NEW_ROUND); // Change state to newRound
}, 2000);
}
};
// Animation Functions
self.playVictoryAnimation = function () {
- log("playVictoryAnimation...");
+ log("playVictoryAnimation...previousLevelNumber", self.previousLevelNumber);
// Play level complete animation
};
}
/***********************************************************************************************/
@@ -848,9 +878,9 @@
log("Reset button pressed");
puzzleManager.reset(); // Reset the level puzzle
return;
}
- */
+ */
puzzleManager.operations.forEach(function (operation) {
if (x >= operation.x - operation.width / 2 && x <= operation.x + operation.width / 2 && y >= operation.y - operation.height / 2 && y <= operation.y + operation.height / 2) {
dragNode = operation;
LK.getSound('operationSelect').play();
@@ -983,8 +1013,10 @@
var foregroundLayer;
var backgroundImage;
var centerX = 1024;
var centerY = 1366;
+var currentTransitionDirectionH = 1;
+var currentTransitionDirectionV = 1;
var dragNode = null;
var resetButton; // Declare resetButton as a global variable
var tileColors = {
0: 0xEAEEE8,
tick
Sound effect
tileEntrance
Sound effect
tileRemove
Sound effect
operationSelect
Sound effect
operationCancel
Sound effect
tileChangeValue
Sound effect
resetSound
Sound effect
levelFailed
Sound effect
menuLevelSelect
Sound effect
menuCellEnter
Sound effect
applause
Sound effect
bgMusic
Music
tada
Sound effect