User prompt
If you come across broken glass, go back to the previous point.
User prompt
horizontally expanding everything except weapons and players
User prompt
hide top text
User prompt
Place a gun image in the middle left of the screen. The gun barrel will show the game order.
User prompt
adjust the grid to the new dimensions and center the screen vertically
User prompt
center everything on the screen vertically
User prompt
creating a starting point for players before the platform
User prompt
Swap player and AI
Code edit (1 edits merged)
Please save this source code
User prompt
Glass Bridge Crossing
Initial prompt
Bridge Crossing Game: AI Briefing This is a turn-based game on a 3x15 grid representing a glass bridge. Your objective is to reach the bottom of the grid, while a human player simultaneously tries to reach the top. The player who makes more vertical progress wins. The Bridge The bridge has 3 columns and 15 rows. Each vertical column contains 0, 1, or 2 broken glass panels. You can't see them initially; they only reveal as broken when a player steps on them. All intact panels look identical. Your Goal Move from the top (row 0) to the bottom (row 14) of the grid. Your score is the number of rows you've advanced vertically. For example, reaching row 5 gives you 5 points. Win by achieving a higher vertical score than the human player. How to Play (Your Turn) You can move to an adjacent square: Down: To any of the three squares in the next row below your current position. Sideways: To an adjacent column within your current row. You cannot move backward (up). Broken Glass Impact: If you step on a broken panel, your current turn ends immediately. You remain on that broken panel until your next turn. Key Information You start above the bridge. The human starts below it. You observe all the human player's moves and any broken panels they reveal. The game ends when one player reaches their target end or neither can move. AI Challenge Focus on strategies for: Pathfinding: Identifying safe routes. Risk vs. Reward: Deciding when to test unknown panels. Information Gathering: Using revealed broken panels (yours and the human's) to inform future moves.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AIPlayer = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('ai', {
anchorX: 0.5,
anchorY: 0.5
});
self.row = -1; // AI starts above the bridge
self.col = 1;
self.isAI = true;
self.moveTo = function (newRow, newCol) {
self.row = newRow;
self.col = newCol;
var targetX = gameStartX + newCol * CELL_SIZE;
var targetY = gameStartY + newRow * CELL_SIZE;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300
});
LK.getSound('move').play();
};
return self;
});
var GridCell = Container.expand(function () {
var self = Container.call(this);
var border = self.attachAsset('gridBorder', {
anchorX: 0.5,
anchorY: 0.5
});
var cell = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5
});
self.isBroken = false;
self.isRevealed = false;
self.row = 0;
self.col = 0;
self.revealBroken = function () {
if (self.isBroken && !self.isRevealed) {
cell.visible = false;
var brokenGraphics = self.attachAsset('brokenGlass', {
anchorX: 0.5,
anchorY: 0.5
});
self.isRevealed = true;
LK.getSound('break').play();
tween(brokenGraphics, {
alpha: 0.8
}, {
duration: 300
});
}
};
self.highlight = function () {
tween(cell, {
tint: 0xFFFFAA
}, {
duration: 200
});
};
self.unhighlight = function () {
tween(cell, {
tint: 0xFFFFFF
}, {
duration: 200
});
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.row = 15; // Player starts below the bridge
self.col = 1;
self.isAI = false;
self.moveTo = function (newRow, newCol) {
self.row = newRow;
self.col = newCol;
var targetX = gameStartX + newCol * CELL_SIZE;
var targetY = gameStartY + newRow * CELL_SIZE;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 300
});
LK.getSound('move').play();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
var GRID_ROWS = 15;
var GRID_COLS = 3;
var CELL_SIZE = 120; // Increased cell size for better mobile experience
var gameStartX = (2048 - GRID_COLS * CELL_SIZE) / 2 + CELL_SIZE / 2;
var totalGameHeight = CELL_SIZE + GRID_ROWS * CELL_SIZE + CELL_SIZE + 100; // AI start area + bridge + player start area + padding
var gameStartY = (2732 - totalGameHeight) / 2 + CELL_SIZE; // Center vertically and account for AI start area
var startingAreaY = gameStartY - CELL_SIZE - 50; // Starting area above bridge for AI
var endingAreaY = gameStartY + GRID_ROWS * CELL_SIZE + 50; // Starting area below bridge for player
var grid = [];
var brokenPanels = [];
var player;
var aiPlayer;
var currentTurn = 'player';
var gameOver = false;
var turnInProgress = false;
// Initialize grid
for (var row = 0; row < GRID_ROWS; row++) {
grid[row] = [];
for (var col = 0; col < GRID_COLS; col++) {
var cell = new GridCell();
cell.row = row;
cell.col = col;
cell.x = gameStartX + col * CELL_SIZE;
cell.y = gameStartY + row * CELL_SIZE;
// Randomly assign broken panels (about 30% chance)
if (Math.random() < 0.3) {
cell.isBroken = true;
brokenPanels.push({
row: row,
col: col
});
}
grid[row][col] = cell;
game.addChild(cell);
}
}
// Create starting areas
var aiStartArea = new GridCell();
aiStartArea.x = gameStartX + 1 * CELL_SIZE; // Center column
aiStartArea.y = startingAreaY;
game.addChild(aiStartArea);
var playerStartArea = new GridCell();
playerStartArea.x = gameStartX + 1 * CELL_SIZE; // Center column
playerStartArea.y = endingAreaY;
game.addChild(playerStartArea);
// Create players
player = new Player();
player.row = 15; // Start below the bridge
player.x = gameStartX + player.col * CELL_SIZE;
player.y = endingAreaY;
game.addChild(player);
aiPlayer = new AIPlayer();
aiPlayer.row = -1; // Start above the bridge
aiPlayer.x = gameStartX + aiPlayer.col * CELL_SIZE;
aiPlayer.y = startingAreaY;
game.addChild(aiPlayer);
// Gun display for game order
var gunDisplay = LK.getAsset('gun', {
anchorX: 0.5,
anchorY: 0.5
});
gunDisplay.x = 200; // Middle left position
gunDisplay.y = 2732 / 2; // Vertically centered
game.addChild(gunDisplay);
// Gun barrel rotation to show turn order
function updateGunDirection() {
if (currentTurn === 'player') {
// Point gun up towards AI
gunDisplay.rotation = -Math.PI / 2;
} else {
// Point gun down towards player
gunDisplay.rotation = Math.PI / 2;
}
}
// Initialize gun direction
updateGunDirection();
// UI Elements
var turnText = new Text2('Your Turn', {
size: 80,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
LK.gui.top.addChild(turnText);
var instructionText = new Text2('Tap adjacent cell to move', {
size: 60,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 100;
LK.gui.top.addChild(instructionText);
var progressText = new Text2('Progress: You 0/15 - AI 0/15', {
size: 50,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(progressText);
function updateProgressText() {
var playerProgress = Math.max(0, 15 - player.row); // Player progress from starting position
var aiProgress = Math.max(0, aiPlayer.row + 1); // AI progress from starting position
progressText.setText('Progress: You ' + playerProgress + '/15 - AI ' + aiProgress + '/15');
}
function isValidMove(fromRow, fromCol, toRow, toCol) {
// Special case: moving from starting areas onto bridge
if (fromRow === -1 && toRow === 0) {
// AI entering bridge from above
return toCol >= 0 && toCol < GRID_COLS && Math.abs(toCol - fromCol) <= 1;
}
if (fromRow === 15 && toRow === 14) {
// Player entering bridge from below
return toCol >= 0 && toCol < GRID_COLS && Math.abs(toCol - fromCol) <= 1;
}
// Check bounds for normal bridge movement
if (toRow < 0 || toRow >= GRID_ROWS || toCol < 0 || toCol >= GRID_COLS) {
return false;
}
// Check if adjacent (including diagonal)
var rowDiff = Math.abs(toRow - fromRow);
var colDiff = Math.abs(toCol - fromCol);
if (rowDiff > 1 || colDiff > 1 || rowDiff === 0 && colDiff === 0) {
return false;
}
return true;
}
function highlightValidMoves(currentPlayer) {
// Unhighlight all cells first
for (var row = 0; row < GRID_ROWS; row++) {
for (var col = 0; col < GRID_COLS; col++) {
grid[row][col].unhighlight();
}
}
// Highlight valid moves
for (var dRow = -1; dRow <= 1; dRow++) {
for (var dCol = -1; dCol <= 1; dCol++) {
if (dRow === 0 && dCol === 0) continue;
var newRow = currentPlayer.row + dRow;
var newCol = currentPlayer.col + dCol;
if (isValidMove(currentPlayer.row, currentPlayer.col, newRow, newCol)) {
grid[newRow][newCol].highlight();
}
}
}
}
function makeAIMove() {
if (gameOver || turnInProgress) return;
var validMoves = [];
// Find all valid moves for AI
for (var dRow = -1; dRow <= 1; dRow++) {
for (var dCol = -1; dCol <= 1; dCol++) {
if (dRow === 0 && dCol === 0) continue;
var newRow = aiPlayer.row + dRow;
var newCol = aiPlayer.col + dCol;
if (isValidMove(aiPlayer.row, aiPlayer.col, newRow, newCol)) {
validMoves.push({
row: newRow,
col: newCol
});
}
}
}
if (validMoves.length === 0) {
endGame();
return;
}
// AI strategy: prioritize moving down (higher row numbers) and avoid known broken panels
validMoves.sort(function (a, b) {
var aIsBroken = grid[a.row][a.col].isRevealed && grid[a.row][a.col].isBroken;
var bIsBroken = grid[b.row][b.col].isRevealed && grid[b.row][b.col].isBroken;
if (aIsBroken && !bIsBroken) return 1;
if (!aIsBroken && bIsBroken) return -1;
return b.row - a.row; // Prefer higher row numbers (moving down)
});
var chosenMove = validMoves[0];
executeMove(aiPlayer, chosenMove.row, chosenMove.col);
}
function executeMove(currentPlayer, newRow, newCol) {
turnInProgress = true;
currentPlayer.moveTo(newRow, newCol);
LK.setTimeout(function () {
var targetCell = grid[newRow][newCol];
if (targetCell.isBroken) {
targetCell.revealBroken();
}
updateProgressText();
checkGameEnd();
if (!gameOver) {
switchTurn();
}
turnInProgress = false;
}, 400);
}
function switchTurn() {
currentTurn = currentTurn === 'player' ? 'ai' : 'player';
updateGunDirection(); // Update gun barrel direction
if (currentTurn === 'player') {
turnText.setText('Your Turn');
highlightValidMoves(player);
} else {
turnText.setText('AI Turn');
// Unhighlight all cells
for (var row = 0; row < GRID_ROWS; row++) {
for (var col = 0; col < GRID_COLS; col++) {
grid[row][col].unhighlight();
}
}
LK.setTimeout(function () {
makeAIMove();
}, 1000);
}
}
function checkGameEnd() {
var playerProgress = Math.max(0, 15 - player.row); // Player progress from starting position
var aiProgress = Math.max(0, aiPlayer.row + 1); // AI progress from starting position
// Check if player reached the end (top of bridge)
if (player.row <= 0) {
LK.showYouWin();
gameOver = true;
return;
}
// Check if AI reached the end (bottom of bridge)
if (aiPlayer.row >= 14) {
LK.showGameOver();
gameOver = true;
return;
}
// Check if no valid moves available
var playerHasMoves = false;
var aiHasMoves = false;
for (var dRow = -1; dRow <= 1; dRow++) {
for (var dCol = -1; dCol <= 1; dCol++) {
if (dRow === 0 && dCol === 0) continue;
var playerNewRow = player.row + dRow;
var playerNewCol = player.col + dCol;
if (isValidMove(player.row, player.col, playerNewRow, playerNewCol)) {
playerHasMoves = true;
}
var aiNewRow = aiPlayer.row + dRow;
var aiNewCol = aiPlayer.col + dCol;
if (isValidMove(aiPlayer.row, aiPlayer.col, aiNewRow, aiNewCol)) {
aiHasMoves = true;
}
}
}
if (!playerHasMoves && !aiHasMoves) {
endGame();
}
}
function endGame() {
gameOver = true;
var playerProgress = Math.max(0, 15 - player.row); // Player progress from starting position
var aiProgress = Math.max(0, aiPlayer.row + 1); // AI progress from starting position
if (playerProgress > aiProgress) {
LK.showYouWin();
} else if (aiProgress > playerProgress) {
LK.showGameOver();
} else {
LK.showGameOver(); // Tie goes to AI
}
}
// Initialize first turn
highlightValidMoves(player);
updateProgressText();
game.down = function (x, y, obj) {
if (gameOver || turnInProgress || currentTurn !== 'player') return;
// Find which cell was clicked
var clickedRow = Math.floor((y - gameStartY + CELL_SIZE / 2) / CELL_SIZE);
var clickedCol = Math.floor((x - gameStartX + CELL_SIZE / 2) / CELL_SIZE);
if (clickedRow < 0 || clickedRow >= GRID_ROWS || clickedCol < 0 || clickedCol >= GRID_COLS) {
return;
}
if (isValidMove(player.row, player.col, clickedRow, clickedCol)) {
executeMove(player, clickedRow, clickedCol);
}
}; ===================================================================
--- original.js
+++ change.js
@@ -166,8 +166,28 @@
aiPlayer.row = -1; // Start above the bridge
aiPlayer.x = gameStartX + aiPlayer.col * CELL_SIZE;
aiPlayer.y = startingAreaY;
game.addChild(aiPlayer);
+// Gun display for game order
+var gunDisplay = LK.getAsset('gun', {
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+gunDisplay.x = 200; // Middle left position
+gunDisplay.y = 2732 / 2; // Vertically centered
+game.addChild(gunDisplay);
+// Gun barrel rotation to show turn order
+function updateGunDirection() {
+ if (currentTurn === 'player') {
+ // Point gun up towards AI
+ gunDisplay.rotation = -Math.PI / 2;
+ } else {
+ // Point gun down towards player
+ gunDisplay.rotation = Math.PI / 2;
+ }
+}
+// Initialize gun direction
+updateGunDirection();
// UI Elements
var turnText = new Text2('Your Turn', {
size: 80,
fill: 0xFFFFFF
@@ -282,8 +302,9 @@
}, 400);
}
function switchTurn() {
currentTurn = currentTurn === 'player' ? 'ai' : 'player';
+ updateGunDirection(); // Update gun barrel direction
if (currentTurn === 'player') {
turnText.setText('Your Turn');
highlightValidMoves(player);
} else {
old 6-shooter pistol. In-Game asset
square glass top view. In-Game asset
broken glass
frog top view. In-Game asset
potato top view. In-Game asset
mushroom top view. In-Game asset
cat top view. In-Game asset
Robot Potato. In-Game asset
street light. In-Game asset
street light. In-Game asset
burst of light in all directions. In-Game asset