User prompt
commander assetlerini biraz daha büyütüp yukarı alalım ve shadow ekleyelim. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
commander assettlerinin boyutunu büyütelim ve yanındaki enemy commande your commander yazısını kaldıralım.
User prompt
commander göselleride hangi oyun alanı gözüküyorsa sadece onun commander asseti gözükmeli yerleri aynı olmalı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bir commander asseti ekleyelim enemy ve my commander şeklince oyun penceresinin sol alt köşesine koyalım görsellik önemli
User prompt
oyun alanını birz daha büyütürmüsün ekrana oranla biraz küçük duruyor.
User prompt
oyun alanları arasında geçiş yaparken biraz efekt eklermisin. birde kalan süreyi görebilmem adına sağ üst tarafa sayaç eklermisin. Start game yazısını biraz alta alalım. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
rakip gemi batırılınca hitmarker iconları biraz koyu hale gelmeliki geminin battığını anlasınlar. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
hit marker oyuncu rakibi vurunca onun gemisine denk gelirse hitmarker asseti üstüne gelmeli. beni vursa bile hitmarker iconu sol üst köşede gözüküyor. bir hata olmalı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
hitmarker asseti ship assetinin üzerinde gözükmeli.
User prompt
hit yaptığımız yerler kırmızı oluyor bu gayet güzel buraya bu kırmızılık için bir asset eklermisin onu ben seçeceğim. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
vurma assetinin rengi değil vurduktan sonra grip üzerinde vurduğumuz miss yerleri gösteren kısım yeşil olmalı
User prompt
bizim vurduğumuz miss yerlerini gösteren yerde mavi değil yeşil olmalı. Eğer bir hit yaparsak 5 saniye beklememize gerek yok sadece miss vurursak 5 saniye sistemi çalışmalı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
biz eğer düşmanı vurursak hit asseti bizdede gözüksün şuan düşmanı biz vurusak miss asseti çalışıyor. miss olanlar düşmanın vurdukları yeşil olarak gözüküyor bizimkilerde yeşil renkle gözüksün miss olarak vuruduğumuz yerler. Ship için koyduğumuz asset gridin üstünde gözükmeli. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
her tur için 30 saniye vermeliyiz oynaması için total olarak değil. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
oyuncunun ve rakibin ateş etmesi için 30 saniye verelim. ateş ettikten sonra ateş edilen yere bir vurma efekti eklemek istiyorum hit için ayrı efekt miss için ayrı efekt. patlama ve suya düşme efekti gibi olmalı. her atıştan sonra ekranı görmek için bir 5 saniye beklemeli ve diğer tura geçmeli. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
rakip biraz daha zeki olmalı bir hit yaparsa onun sağı solu yukarısı yada aşağısını tahmin ederek ateş etmeli. gemiler oyuna yerleştirmeden bekledikleri yerde küçük gözükmeli çok yer kaplıyorlar. sürüklerken gerçek boyutunda gözükmeli ve yerleşmeli. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
gemilerin yerleştirmeden önce beklediği kısım alt kısıma alalım. gemileri yerleştirden sonra start game yazısı yukarıda olsun.şuanda gözükmüyor. oyun alanını daha büyük yapalım hala biraz küçük duruyor.
User prompt
start game yazısı biraz daha yukarda olmalı ve oyun alanı daha büyük gözüksün şuanda çok küçük görünüyor.
User prompt
gemileri yerleştirmeden kendi alanımı göremiyorum önce kendi alanıma gemilerimi yerleştirmek istiyorum daha sonra rakip tahta ekrana gelmeli. kendi ekranımda rakip ekranımda ekranın tam ortasına gelmeli sırası gelince ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
rakip oyun alanını ben saldırı yaparken görmeliyim rakip saldırı yaparken ben kendi alanımı görmeliyim. rakip biraz daha yavaş saldırı yapmalı düşünmeli ve ona göre vurmalı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
düşman ekranı görme sıralaması değiştir sürekli gözüküyor. Ayrıca miss geçen yerler farklı renkte olsun asset olarak ekleme yaparım ben. gemiler kutulara sürüklerken tam oturmalı tam olarak istediğim yere koyamıyorum. ayrıca koyduğum gemiyi hareket ettiremiyorum. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kendi oyun alanımda rakibin oyun alanıda oyunun ortasında gözükmeli. miss vurduğumuz yerler rakip alanda ve rakibin miss vurduğu alanlar kendi alanımda görünmeli
User prompt
oyun alanında kutular gözükmeli. her iki oyuncunun tahtasınıda aynı anda görmemeliyiz sıra bendeyse karşı tarafın alanı ekrana gelmeli sıra rakipteyse kendi oyun alanımı görmeliyim. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'hit')' in or related to this line: 'var sunk = ship.hit();' Line Number: 459
User prompt
gemiler ekranın sağ tarafında dursun ayrıca yerleştirdiğimiz gemileride tut sürükle olarak yer değiştirebilmeliyiz. Start game yazısı ekranın ortasında olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var DraggableShip = Container.expand(function (length, id) { var self = Container.call(this); self.length = length; self.shipId = id; self.isHorizontal = true; self.isBeingDragged = false; self.isPlaced = false; self.shipCells = []; self.smallScale = 0.5; // Scale for when ship is waiting // Create visual representation of ship for (var i = 0; i < length; i++) { var shipCell = self.attachAsset('ship', { anchorX: 0, anchorY: 0 }); shipCell.x = i * CELL_SIZE; shipCell.y = 0; self.shipCells.push(shipCell); } // Start ships at smaller scale self.scaleX = self.smallScale; self.scaleY = self.smallScale; self.rotate = function () { self.isHorizontal = !self.isHorizontal; for (var i = 0; i < self.shipCells.length; i++) { if (self.isHorizontal) { self.shipCells[i].x = i * CELL_SIZE; self.shipCells[i].y = 0; } else { self.shipCells[i].x = 0; self.shipCells[i].y = i * CELL_SIZE; } } }; self.canBePlacedAt = function (gridX, gridY) { for (var i = 0; i < self.length; i++) { var x = self.isHorizontal ? gridX + i : gridX; var y = self.isHorizontal ? gridY : gridY + i; if (x >= GRID_SIZE || y >= GRID_SIZE || x < 0 || y < 0) { return false; } if (playerGrid[x][y].hasShip) { return false; } } return true; }; self.placeOnGrid = function (gridX, gridY) { if (self.canBePlacedAt(gridX, gridY)) { for (var i = 0; i < self.length; i++) { var x = self.isHorizontal ? gridX + i : gridX; var y = self.isHorizontal ? gridY : gridY + i; playerGrid[x][y].setShip(self.shipId); } self.isPlaced = true; self.visible = false; return true; } return false; }; self.down = function (x, y, obj) { if (gameState === 'placement') { if (self.isPlaced) { // Remove ship from grid for repositioning removeShipFromGrid(self); self.isPlaced = false; self.visible = true; placedShipsCount--; statusText.setText('Place remaining ships (' + (shipLengths.length - placedShipsCount) + ' left)'); startButton.visible = false; // Position ship at current grid location for smooth dragging var currentGridX = -1, currentGridY = -1; for (var gx = 0; gx < GRID_SIZE; gx++) { for (var gy = 0; gy < GRID_SIZE; gy++) { if (playerGrid[gx][gy].shipId === self.shipId) { currentGridX = gx; currentGridY = gy; break; } } if (currentGridX !== -1) break; } if (currentGridX !== -1) { self.x = CENTER_GRID_X + currentGridX * CELL_SIZE; self.y = CENTER_GRID_Y + currentGridY * CELL_SIZE; } } self.isBeingDragged = true; draggedShip = self; // Scale up to full size when dragging tween(self, { alpha: 0.7, scaleX: 1, scaleY: 1 }, { duration: 200 }); } }; self.up = function (x, y, obj) { if (self.isBeingDragged && !self.isPlaced) { self.isBeingDragged = false; // Try to place ship on grid with better snapping var gridX = Math.round((self.x - CENTER_GRID_X) / CELL_SIZE); var gridY = Math.round((self.y - CENTER_GRID_Y) / CELL_SIZE); // Snap to grid position var snapX = CENTER_GRID_X + gridX * CELL_SIZE; var snapY = CENTER_GRID_Y + gridY * CELL_SIZE; if (self.placeOnGrid(gridX, gridY)) { // Snap ship to exact grid position before hiding self.x = snapX; self.y = snapY; tween(self, { alpha: 1 }, { duration: 200 }); placedShipsCount++; if (placedShipsCount >= shipLengths.length) { statusText.setText('All ships placed! Press START GAME to begin'); startButton.visible = true; } else { statusText.setText('Place remaining ships (' + (shipLengths.length - placedShipsCount) + ' left)'); } } else { // Return to original position and scale down if can't place tween(self, { x: self.originalX, y: self.originalY, alpha: 1, scaleX: self.smallScale, scaleY: self.smallScale }, { duration: 300, easing: tween.easeOut }); } } }; return self; }); var GridCell = Container.expand(function (x, y, isPlayer) { var self = Container.call(this); self.gridX = x; self.gridY = y; self.isPlayer = isPlayer; self.hasShip = false; self.isHit = false; self.isMiss = false; self.shipId = -1; var cellGraphics = self.attachAsset('gridBox', { anchorX: 0, anchorY: 0 }); self.setShip = function (shipId) { self.hasShip = true; self.shipId = shipId; if (self.isPlayer) { cellGraphics.tint = 0x808080; } }; self.markHit = function () { self.isHit = true; cellGraphics.tint = 0xFF0000; }; self.markMiss = function (isEnemyMiss) { self.isMiss = true; if (isEnemyMiss) { // Enemy missed on player's grid - use orange color cellGraphics.tint = 0xffaa00; } else { // Player missed on enemy's grid - use light blue color cellGraphics.tint = 0x87CEEB; } }; self.markSunk = function () { cellGraphics.tint = 0x2F2F2F; }; self.down = function (x, y, obj) { if (gameState === 'playing' && !self.isPlayer && !self.isHit && !self.isMiss) { playerShoot(self.gridX, self.gridY); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var Ship = function Ship(length, id) { this.length = length; this.id = id; this.hits = 0; this.cells = []; this.isSunk = false; this.addCell = function (x, y) { this.cells.push({ x: x, y: y }); }; this.hit = function () { this.hits++; if (this.hits >= this.length) { this.isSunk = true; return true; } return false; }; }; var GRID_SIZE = 10; var CELL_SIZE = 120; // Increased from 100 to 120 for larger game area var GRID_OFFSET_X = 200; var PLAYER_GRID_Y = 1200; var AI_GRID_Y = 200; // Calculate center positions for single grid display var CENTER_GRID_X = (2048 - GRID_SIZE * CELL_SIZE) / 2; var CENTER_GRID_Y = (2732 - GRID_SIZE * CELL_SIZE) / 2 - 100; // Move grid up slightly var GRID_SPACING = 1000; // Distance between the two grids var playerGrid = []; var aiGrid = []; var playerShips = []; var aiShips = []; var gameState = 'placement'; // 'placement', 'playing', 'gameOver' var currentPlayer = 'player'; // 'player', 'ai' var selectedX = -1; var selectedY = -1; var currentShipToPlace = 0; var isHorizontalPlacement = true; var shipLengths = [5, 4, 3, 3, 2]; var draggableShips = []; var placedShipsCount = 0; var draggedShip = null; // AI hunting variables var aiLastHitX = -1; var aiLastHitY = -1; var aiHuntingDirections = []; var aiCurrentDirection = 0; var aiHuntingMode = false; // Timer and effect variables var turnTimer = null; var turnTimeRemaining = 30; var isWaitingAfterShot = false; // Timer text var timerText = new Text2('30', { size: 50, fill: 0xFF0000 }); timerText.anchor.set(0.5, 0.5); timerText.x = 2048 / 2; timerText.y = 150; LK.gui.top.addChild(timerText); var playerGridContainer = new Container(); var aiGridContainer = new Container(); // UI Elements var statusText = new Text2('Drag ships to your grid', { size: 60, fill: 0x000000 }); statusText.anchor.set(0.5, 0); LK.gui.top.addChild(statusText); var instructionText = new Text2('Double tap ships to rotate, drag to reposition', { size: 40, fill: 0x000000 }); instructionText.anchor.set(0.5, 0); instructionText.y = 100; LK.gui.top.addChild(instructionText); var startButton = new Text2('START GAME', { size: 60, fill: 0x00FF00 }); startButton.anchor.set(0.5, 0.5); startButton.x = 2048 / 2; startButton.y = 200; // Move button much higher up startButton.visible = false; game.addChild(startButton); startButton.down = function (x, y, obj) { if (gameState === 'placement' && placedShipsCount >= shipLengths.length) { gameState = 'playing'; statusText.setText('Fire at enemy positions!'); instructionText.setText('Tap enemy grid to shoot'); startButton.visible = false; placeAIShips(); // Switch to AI grid for player's turn to attack playerGridContainer.visible = false; aiGridContainer.visible = true; } }; // Initialize grids function initializeGrids() { // Add containers to game game.addChild(playerGridContainer); game.addChild(aiGridContainer); // Player grid (center during placement, left side during game) for (var x = 0; x < GRID_SIZE; x++) { playerGrid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { var cell = new GridCell(x, y, true); cell.x = CENTER_GRID_X + x * CELL_SIZE; cell.y = CENTER_GRID_Y + y * CELL_SIZE; playerGrid[x][y] = cell; playerGridContainer.addChild(cell); } } // AI grid (center during game) for (var x = 0; x < GRID_SIZE; x++) { aiGrid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { var cell = new GridCell(x, y, false); cell.x = CENTER_GRID_X + x * CELL_SIZE; cell.y = CENTER_GRID_Y + y * CELL_SIZE; aiGrid[x][y] = cell; aiGridContainer.addChild(cell); } } // Initialize grid visibility - show player grid during placement phase playerGridContainer.visible = true; aiGridContainer.visible = false; // Add grid labels var playerLabel = new Text2('Your Fleet', { size: 40, fill: 0x000000 }); playerLabel.anchor.set(0.5, 0.5); playerLabel.x = CENTER_GRID_X + GRID_SIZE * CELL_SIZE / 2; playerLabel.y = CENTER_GRID_Y - 50; playerGridContainer.addChild(playerLabel); var aiLabel = new Text2('Enemy Waters', { size: 40, fill: 0x000000 }); aiLabel.anchor.set(0.5, 0.5); aiLabel.x = CENTER_GRID_X + GRID_SIZE * CELL_SIZE / 2; aiLabel.y = CENTER_GRID_Y - 50; aiGridContainer.addChild(aiLabel); // Add coordinate labels for player grid for (var i = 0; i < GRID_SIZE; i++) { // Letters A-J on the left side var letterLabel = new Text2(String.fromCharCode(65 + i), { size: 20, fill: 0x000000 }); letterLabel.anchor.set(0.5, 0.5); letterLabel.x = CENTER_GRID_X - 30; letterLabel.y = CENTER_GRID_Y + i * CELL_SIZE + CELL_SIZE / 2; playerGridContainer.addChild(letterLabel); // Numbers 1-10 on the top var numberLabel = new Text2((i + 1).toString(), { size: 20, fill: 0x000000 }); numberLabel.anchor.set(0.5, 0.5); numberLabel.x = CENTER_GRID_X + i * CELL_SIZE + CELL_SIZE / 2; numberLabel.y = CENTER_GRID_Y - 60; playerGridContainer.addChild(numberLabel); } // Add coordinate labels for AI grid for (var i = 0; i < GRID_SIZE; i++) { // Letters A-J on the left side var letterLabel = new Text2(String.fromCharCode(65 + i), { size: 20, fill: 0x000000 }); letterLabel.anchor.set(0.5, 0.5); letterLabel.x = CENTER_GRID_X - 30; letterLabel.y = CENTER_GRID_Y + i * CELL_SIZE + CELL_SIZE / 2; aiGridContainer.addChild(letterLabel); // Numbers 1-10 on the top var numberLabel = new Text2((i + 1).toString(), { size: 20, fill: 0x000000 }); numberLabel.anchor.set(0.5, 0.5); numberLabel.x = CENTER_GRID_X + i * CELL_SIZE + CELL_SIZE / 2; numberLabel.y = CENTER_GRID_Y - 60; aiGridContainer.addChild(numberLabel); } // Create draggable ships at bottom of screen var shipStartY = 2400; // Move ships to bottom area var shipStartX = 200; // Start from left side for (var i = 0; i < shipLengths.length; i++) { var ship = new DraggableShip(shipLengths[i], i); ship.x = shipStartX + i * 350; // Space ships horizontally ship.y = shipStartY; ship.originalX = ship.x; ship.originalY = ship.y; draggableShips.push(ship); game.addChild(ship); } } function selectCellForPlacement(x, y) { selectedX = x; selectedY = y; if (canPlaceShip(x, y, shipLengths[currentShipToPlace], isHorizontalPlacement, true)) { placeShip(x, y, shipLengths[currentShipToPlace], isHorizontalPlacement, true, currentShipToPlace); currentShipToPlace++; if (currentShipToPlace >= shipLengths.length) { gameState = 'playing'; statusText.setText('Fire at enemy positions!'); instructionText.setText('Tap enemy grid to shoot'); placeAIShips(); } else { statusText.setText('Place ship ' + (currentShipToPlace + 1) + ' (length: ' + shipLengths[currentShipToPlace] + ')'); } } } function canPlaceShip(startX, startY, length, horizontal, isPlayer) { var grid = isPlayer ? playerGrid : aiGrid; for (var i = 0; i < length; i++) { var x = horizontal ? startX + i : startX; var y = horizontal ? startY : startY + i; if (x >= GRID_SIZE || y >= GRID_SIZE || x < 0 || y < 0) { return false; } if (grid[x][y].hasShip) { return false; } } return true; } function placeShip(startX, startY, length, horizontal, isPlayer, shipId) { var grid = isPlayer ? playerGrid : aiGrid; var ships = isPlayer ? playerShips : aiShips; var ship = new Ship(length, shipId); for (var i = 0; i < length; i++) { var x = horizontal ? startX + i : startX; var y = horizontal ? startY : startY + i; grid[x][y].setShip(shipId); ship.addCell(x, y); } ships.push(ship); } function placeAIShips() { for (var i = 0; i < shipLengths.length; i++) { var placed = false; var attempts = 0; while (!placed && attempts < 100) { var x = Math.floor(Math.random() * GRID_SIZE); var y = Math.floor(Math.random() * GRID_SIZE); var horizontal = Math.random() < 0.5; if (canPlaceShip(x, y, shipLengths[i], horizontal, false)) { placeShip(x, y, shipLengths[i], horizontal, false, i); placed = true; } attempts++; } } } function playerShoot(x, y) { if (currentPlayer !== 'player' || isWaitingAfterShot) return; // Stop the timer if (turnTimer) { LK.clearInterval(turnTimer); turnTimer = null; } var cell = aiGrid[x][y]; var hit = false; // Create visual effect var effectAsset = hit ? 'hit' : 'miss'; var effect = LK.getAsset(effectAsset, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1 }); effect.x = CENTER_GRID_X + x * CELL_SIZE + CELL_SIZE / 2; effect.y = CENTER_GRID_Y + y * CELL_SIZE + CELL_SIZE / 2; aiGridContainer.addChild(effect); if (cell.hasShip) { cell.markHit(); hit = true; LK.getSound('hit').play(); // Explosion effect for hit tween(effect, { scaleX: 2, scaleY: 2, alpha: 0.8 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(effect, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 500, onFinish: function onFinish() { effect.destroy(); } }); } }); var ship = null; // Find the ship by ID in the aiShips array for (var i = 0; i < aiShips.length; i++) { if (aiShips[i].id === cell.shipId) { ship = aiShips[i]; break; } } if (ship) { var sunk = ship.hit(); if (sunk) { LK.getSound('sunk').play(); markShipAsSunk(ship, false); if (checkVictory(false)) { gameState = 'gameOver'; statusText.setText('Victory! You sank all enemy ships!'); instructionText.setText(''); LK.showYouWin(); return; } } } statusText.setText('Hit! Fire again!'); // 5-second delay before continuing isWaitingAfterShot = true; LK.setTimeout(function () { isWaitingAfterShot = false; startPlayerTurn(); }, 5000); } else { cell.markMiss(false); LK.getSound('miss').play(); // Water splash effect for miss effect.tint = 0x87CEEB; tween(effect, { scaleX: 1.5, scaleY: 1.5, alpha: 0.6 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(effect, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 600, onFinish: function onFinish() { effect.destroy(); } }); } }); currentPlayer = 'ai'; statusText.setText('Miss! Enemy is thinking...'); // 5-second delay before AI turn isWaitingAfterShot = true; LK.setTimeout(function () { isWaitingAfterShot = false; // Switch to player grid when AI attacks playerGridContainer.visible = true; aiGridContainer.visible = false; startAiTurn(); }, 5000); } } function aiTurn() { if (currentPlayer !== 'ai' || isWaitingAfterShot) return; // Stop the timer if (turnTimer) { LK.clearInterval(turnTimer); turnTimer = null; } var x, y; var attempts = 0; // Smart AI: If in hunting mode, try adjacent cells to last hit if (aiHuntingMode && aiLastHitX !== -1 && aiLastHitY !== -1) { var found = false; // Try directions: up, right, down, left var directions = [{ x: 0, y: -1 }, // up { x: 1, y: 0 }, // right { x: 0, y: 1 }, // down { x: -1, y: 0 } // left ]; // Try each direction from the last hit for (var d = 0; d < directions.length && !found; d++) { var testX = aiLastHitX + directions[d].x; var testY = aiLastHitY + directions[d].y; // Check if position is valid and not already attacked if (testX >= 0 && testX < GRID_SIZE && testY >= 0 && testY < GRID_SIZE && !playerGrid[testX][testY].isHit && !playerGrid[testX][testY].isMiss) { x = testX; y = testY; found = true; } } // If no adjacent cells available, exit hunting mode if (!found) { aiHuntingMode = false; aiLastHitX = -1; aiLastHitY = -1; } } // If not in hunting mode or no valid adjacent cells, shoot randomly if (!aiHuntingMode || aiLastHitX === -1 && aiLastHitY === -1) { do { x = Math.floor(Math.random() * GRID_SIZE); y = Math.floor(Math.random() * GRID_SIZE); attempts++; } while ((playerGrid[x][y].isHit || playerGrid[x][y].isMiss) && attempts < 100); } var cell = playerGrid[x][y]; var hit = cell.hasShip; // Create visual effect var effectAsset = hit ? 'hit' : 'miss'; var effect = LK.getAsset(effectAsset, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1 }); effect.x = CENTER_GRID_X + x * CELL_SIZE + CELL_SIZE / 2; effect.y = CENTER_GRID_Y + y * CELL_SIZE + CELL_SIZE / 2; playerGridContainer.addChild(effect); if (cell.hasShip) { cell.markHit(); LK.getSound('hit').play(); // Explosion effect for hit tween(effect, { scaleX: 2, scaleY: 2, alpha: 0.8 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(effect, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 500, onFinish: function onFinish() { effect.destroy(); } }); } }); // Enter hunting mode and remember this hit position aiHuntingMode = true; aiLastHitX = x; aiLastHitY = y; var ship = null; // Find the ship by ID in the playerShips array for (var i = 0; i < playerShips.length; i++) { if (playerShips[i].id === cell.shipId) { ship = playerShips[i]; break; } } if (ship) { var sunk = ship.hit(); if (sunk) { LK.getSound('sunk').play(); markShipAsSunk(ship, true); // Exit hunting mode when ship is sunk aiHuntingMode = false; aiLastHitX = -1; aiLastHitY = -1; if (checkVictory(true)) { gameState = 'gameOver'; statusText.setText('Defeat! Enemy sank all your ships!'); instructionText.setText(''); LK.showGameOver(); return; } } } statusText.setText('Enemy hit your ship!'); // 5-second delay before AI continues isWaitingAfterShot = true; LK.setTimeout(function () { isWaitingAfterShot = false; startAiTurn(); }, 5000); } else { cell.markMiss(true); LK.getSound('miss').play(); // Water splash effect for miss effect.tint = 0xFFAA00; tween(effect, { scaleX: 1.5, scaleY: 1.5, alpha: 0.6 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(effect, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 600, onFinish: function onFinish() { effect.destroy(); } }); } }); currentPlayer = 'player'; statusText.setText('Enemy missed! Your turn!'); // 5-second delay before player turn isWaitingAfterShot = true; LK.setTimeout(function () { isWaitingAfterShot = false; // Switch to AI grid for player's turn to attack playerGridContainer.visible = false; aiGridContainer.visible = true; startPlayerTurn(); startPlayerTurn(); }, 5000); } } function markShipAsSunk(ship, isPlayer) { var grid = isPlayer ? playerGrid : aiGrid; for (var i = 0; i < ship.cells.length; i++) { var cellPos = ship.cells[i]; grid[cellPos.x][cellPos.y].markSunk(); } } function removeShipFromGrid(ship) { for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (playerGrid[x][y].shipId === ship.shipId) { playerGrid[x][y].hasShip = false; playerGrid[x][y].shipId = -1; var cellGraphics = playerGrid[x][y].children[0]; cellGraphics.tint = 0xFFFFFF; } } } } function checkVictory(playerLost) { var ships = playerLost ? playerShips : aiShips; for (var i = 0; i < ships.length; i++) { if (!ships[i].isSunk) { return false; } } return true; } // Double tap to rotate ship during placement var lastTapTime = 0; game.down = function (x, y, obj) { if (gameState === 'placement') { var currentTime = Date.now(); if (currentTime - lastTapTime < 300) { // Find ship being rotated - check both unplaced and placed ships for (var i = 0; i < draggableShips.length; i++) { var ship = draggableShips[i]; var shipBounds = { x: ship.x, y: ship.y, width: ship.isHorizontal ? ship.length * CELL_SIZE : CELL_SIZE, height: ship.isHorizontal ? CELL_SIZE : ship.length * CELL_SIZE }; if (x >= shipBounds.x && x <= shipBounds.x + shipBounds.width && y >= shipBounds.y && y <= shipBounds.y + shipBounds.height) { if (ship.isPlaced) { // Remove ship from grid removeShipFromGrid(ship); ship.isPlaced = false; ship.visible = true; placedShipsCount--; } ship.rotate(); break; } } instructionText.setText('Double tap ships to rotate, drag to reposition'); } lastTapTime = currentTime; } }; game.move = function (x, y, obj) { if (gameState === 'placement' && draggedShip) { draggedShip.x = x - draggedShip.width / 2; draggedShip.y = y - draggedShip.height / 2; } }; game.up = function (x, y, obj) { draggedShip = null; }; function startPlayerTurn() { currentPlayer = 'player'; turnTimeRemaining = 30; timerText.setText(turnTimeRemaining.toString()); timerText.visible = true; turnTimer = LK.setInterval(function () { turnTimeRemaining--; timerText.setText(turnTimeRemaining.toString()); if (turnTimeRemaining <= 0) { LK.clearInterval(turnTimer); turnTimer = null; timerText.visible = false; // Auto-switch to AI turn on timeout currentPlayer = 'ai'; statusText.setText('Time up! Enemy is thinking...'); playerGridContainer.visible = true; aiGridContainer.visible = false; startAiTurn(); } }, 1000); } function startAiTurn() { currentPlayer = 'ai'; turnTimeRemaining = 30; timerText.setText(turnTimeRemaining.toString()); timerText.visible = true; // AI thinks for 2-5 seconds before shooting var thinkTime = 2000 + Math.random() * 3000; turnTimer = LK.setInterval(function () { turnTimeRemaining--; timerText.setText(turnTimeRemaining.toString()); if (turnTimeRemaining <= 0) { LK.clearInterval(turnTimer); turnTimer = null; timerText.visible = false; aiTurn(); } }, 1000); LK.setTimeout(function () { if (currentPlayer === 'ai' && !isWaitingAfterShot) { aiTurn(); } }, thinkTime); } // Initialize the game initializeGrids(); ;
===================================================================
--- original.js
+++ change.js
@@ -252,8 +252,21 @@
var aiLastHitY = -1;
var aiHuntingDirections = [];
var aiCurrentDirection = 0;
var aiHuntingMode = false;
+// Timer and effect variables
+var turnTimer = null;
+var turnTimeRemaining = 30;
+var isWaitingAfterShot = false;
+// Timer text
+var timerText = new Text2('30', {
+ size: 50,
+ fill: 0xFF0000
+});
+timerText.anchor.set(0.5, 0.5);
+timerText.x = 2048 / 2;
+timerText.y = 150;
+LK.gui.top.addChild(timerText);
var playerGridContainer = new Container();
var aiGridContainer = new Container();
// UI Elements
var statusText = new Text2('Drag ships to your grid', {
@@ -450,15 +463,52 @@
}
}
}
function playerShoot(x, y) {
- if (currentPlayer !== 'player') return;
+ if (currentPlayer !== 'player' || isWaitingAfterShot) return;
+ // Stop the timer
+ if (turnTimer) {
+ LK.clearInterval(turnTimer);
+ turnTimer = null;
+ }
var cell = aiGrid[x][y];
var hit = false;
+ // Create visual effect
+ var effectAsset = hit ? 'hit' : 'miss';
+ var effect = LK.getAsset(effectAsset, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.1,
+ scaleY: 0.1
+ });
+ effect.x = CENTER_GRID_X + x * CELL_SIZE + CELL_SIZE / 2;
+ effect.y = CENTER_GRID_Y + y * CELL_SIZE + CELL_SIZE / 2;
+ aiGridContainer.addChild(effect);
if (cell.hasShip) {
cell.markHit();
hit = true;
LK.getSound('hit').play();
+ // Explosion effect for hit
+ tween(effect, {
+ scaleX: 2,
+ scaleY: 2,
+ alpha: 0.8
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(effect, {
+ scaleX: 0.1,
+ scaleY: 0.1,
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ effect.destroy();
+ }
+ });
+ }
+ });
var ship = null;
// Find the ship by ID in the aiShips array
for (var i = 0; i < aiShips.length; i++) {
if (aiShips[i].id === cell.shipId) {
@@ -480,23 +530,59 @@
}
}
}
statusText.setText('Hit! Fire again!');
+ // 5-second delay before continuing
+ isWaitingAfterShot = true;
+ LK.setTimeout(function () {
+ isWaitingAfterShot = false;
+ startPlayerTurn();
+ }, 5000);
} else {
cell.markMiss(false);
LK.getSound('miss').play();
+ // Water splash effect for miss
+ effect.tint = 0x87CEEB;
+ tween(effect, {
+ scaleX: 1.5,
+ scaleY: 1.5,
+ alpha: 0.6
+ }, {
+ duration: 400,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(effect, {
+ scaleX: 0.1,
+ scaleY: 0.1,
+ alpha: 0
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ effect.destroy();
+ }
+ });
+ }
+ });
currentPlayer = 'ai';
statusText.setText('Miss! Enemy is thinking...');
- // Switch to player grid when AI attacks
- playerGridContainer.visible = true;
- aiGridContainer.visible = false;
+ // 5-second delay before AI turn
+ isWaitingAfterShot = true;
LK.setTimeout(function () {
- aiTurn();
- }, 2500);
+ isWaitingAfterShot = false;
+ // Switch to player grid when AI attacks
+ playerGridContainer.visible = true;
+ aiGridContainer.visible = false;
+ startAiTurn();
+ }, 5000);
}
}
function aiTurn() {
- if (currentPlayer !== 'ai') return;
+ if (currentPlayer !== 'ai' || isWaitingAfterShot) return;
+ // Stop the timer
+ if (turnTimer) {
+ LK.clearInterval(turnTimer);
+ turnTimer = null;
+ }
var x, y;
var attempts = 0;
// Smart AI: If in hunting mode, try adjacent cells to last hit
if (aiHuntingMode && aiLastHitX !== -1 && aiLastHitY !== -1) {
@@ -548,13 +634,44 @@
attempts++;
} while ((playerGrid[x][y].isHit || playerGrid[x][y].isMiss) && attempts < 100);
}
var cell = playerGrid[x][y];
- var hit = false;
+ var hit = cell.hasShip;
+ // Create visual effect
+ var effectAsset = hit ? 'hit' : 'miss';
+ var effect = LK.getAsset(effectAsset, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.1,
+ scaleY: 0.1
+ });
+ effect.x = CENTER_GRID_X + x * CELL_SIZE + CELL_SIZE / 2;
+ effect.y = CENTER_GRID_Y + y * CELL_SIZE + CELL_SIZE / 2;
+ playerGridContainer.addChild(effect);
if (cell.hasShip) {
cell.markHit();
- hit = true;
LK.getSound('hit').play();
+ // Explosion effect for hit
+ tween(effect, {
+ scaleX: 2,
+ scaleY: 2,
+ alpha: 0.8
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(effect, {
+ scaleX: 0.1,
+ scaleY: 0.1,
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ effect.destroy();
+ }
+ });
+ }
+ });
// Enter hunting mode and remember this hit position
aiHuntingMode = true;
aiLastHitX = x;
aiLastHitY = y;
@@ -584,19 +701,51 @@
}
}
}
statusText.setText('Enemy hit your ship!');
+ // 5-second delay before AI continues
+ isWaitingAfterShot = true;
LK.setTimeout(function () {
- aiTurn();
- }, 2000);
+ isWaitingAfterShot = false;
+ startAiTurn();
+ }, 5000);
} else {
cell.markMiss(true);
LK.getSound('miss').play();
+ // Water splash effect for miss
+ effect.tint = 0xFFAA00;
+ tween(effect, {
+ scaleX: 1.5,
+ scaleY: 1.5,
+ alpha: 0.6
+ }, {
+ duration: 400,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(effect, {
+ scaleX: 0.1,
+ scaleY: 0.1,
+ alpha: 0
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ effect.destroy();
+ }
+ });
+ }
+ });
currentPlayer = 'player';
statusText.setText('Enemy missed! Your turn!');
- // Switch back to AI grid for player's turn
- playerGridContainer.visible = false;
- aiGridContainer.visible = true;
+ // 5-second delay before player turn
+ isWaitingAfterShot = true;
+ LK.setTimeout(function () {
+ isWaitingAfterShot = false;
+ // Switch to AI grid for player's turn to attack
+ playerGridContainer.visible = false;
+ aiGridContainer.visible = true;
+ startPlayerTurn();
+ startPlayerTurn();
+ }, 5000);
}
}
function markShipAsSunk(ship, isPlayer) {
var grid = isPlayer ? playerGrid : aiGrid;
@@ -666,6 +815,51 @@
};
game.up = function (x, y, obj) {
draggedShip = null;
};
+function startPlayerTurn() {
+ currentPlayer = 'player';
+ turnTimeRemaining = 30;
+ timerText.setText(turnTimeRemaining.toString());
+ timerText.visible = true;
+ turnTimer = LK.setInterval(function () {
+ turnTimeRemaining--;
+ timerText.setText(turnTimeRemaining.toString());
+ if (turnTimeRemaining <= 0) {
+ LK.clearInterval(turnTimer);
+ turnTimer = null;
+ timerText.visible = false;
+ // Auto-switch to AI turn on timeout
+ currentPlayer = 'ai';
+ statusText.setText('Time up! Enemy is thinking...');
+ playerGridContainer.visible = true;
+ aiGridContainer.visible = false;
+ startAiTurn();
+ }
+ }, 1000);
+}
+function startAiTurn() {
+ currentPlayer = 'ai';
+ turnTimeRemaining = 30;
+ timerText.setText(turnTimeRemaining.toString());
+ timerText.visible = true;
+ // AI thinks for 2-5 seconds before shooting
+ var thinkTime = 2000 + Math.random() * 3000;
+ turnTimer = LK.setInterval(function () {
+ turnTimeRemaining--;
+ timerText.setText(turnTimeRemaining.toString());
+ if (turnTimeRemaining <= 0) {
+ LK.clearInterval(turnTimer);
+ turnTimer = null;
+ timerText.visible = false;
+ aiTurn();
+ }
+ }, 1000);
+ LK.setTimeout(function () {
+ if (currentPlayer === 'ai' && !isWaitingAfterShot) {
+ aiTurn();
+ }
+ }, thinkTime);
+}
// Initialize the game
-initializeGrids();
\ No newline at end of file
+initializeGrids();
+;
\ No newline at end of file
water look on top. In-Game asset. 2d. High contrast. No shadows
white location icon look on top. In-Game asset. 2d. High contrast. No shadows
explosion look on top. In-Game asset. 2d. High contrast. No shadows
white smoke look on top. In-Game asset. 2d. High contrast. No shadows
red point icon. In-Game asset. 2d. High contrast. No shadows
2d sea mine In-Game asset. 2d. High contrast. No shadows
warship commander head looking right in game asset. In-Game asset. 2d. High contrast. No shadows
warship commander head looking left in game asset. In-Game asset. 2d. High contrast. No shadows
speech bubble 2d. In-Game asset. 2d. High contrast. No shadows
metal border. In-Game asset. 2d. High contrast. No shadows
metal line. In-Game asset. 2d. High contrast. No shadows