User prompt
Daha da sağa
User prompt
Ateşi padin sağına taşı
User prompt
Özel saldırılar basılı tutunca çalışsın
User prompt
Özel saldırıları ve düz atak saldırısını padin etrafına yerleştir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Padin hedef seçme olayı bozuldu optimize et
User prompt
Pad saldırı için progress bar olarak çalışsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Padin ortası basılı tuttuğunda dolan saldırı butonu olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Padin hassasiyetini default ayara getir
User prompt
Padin hassasiyetini optimize et
User prompt
Padi 2 kat büyüt ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Padin hassasiyetini düşür
User prompt
İmlec sadece bulunduğu hücreye etki edebilsin boyutunu buna göre ayarla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
İmleçlerş optimize et sade düşman alanında hedef belirlemek için kullanacağım ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
2. İmleci kaldır
User prompt
Optimize et düşman alanında hedefleme yapmayı iyileştir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
2. İmleci pasif yap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
1. Ana imleci pasif yap
User prompt
İmleci küçült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Kontrol padini büyüt biraz yukarı taşı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
İmleç sadece düşman alanında gezebilsin
User prompt
İmleç sadece düşman alanının içinde gezinebilsin
User prompt
Düşman alanında belli olmuyor imleç alanın önünde olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Düşman alanındaki seçili hücreyi gösteren imleç ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Hedef seçiciyi kaldır
User prompt
Hedef seçiçiyi ortaya taşı ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var GameGrid = Container.expand(function (isPlayerGrid) { var self = Container.call(this); self.isPlayerGrid = isPlayerGrid; self.cells = []; self.ships = []; var currentGridSize = gridSize; // Use global gridSize variable var cellSize = 60; // Initialize grid cells for (var row = 0; row < currentGridSize; row++) { self.cells[row] = []; for (var col = 0; col < currentGridSize; col++) { var cell = new GridCell(row, col, isPlayerGrid); cell.x = col * cellSize; cell.y = row * cellSize; self.cells[row][col] = cell; self.addChild(cell); } } // Draw grid lines for (var i = 0; i <= currentGridSize; i++) { // Vertical lines var vLine = self.attachAsset('gridLine', { width: 2, height: currentGridSize * cellSize, x: i * cellSize, y: 0 }); // Horizontal lines var hLine = self.attachAsset('gridLine', { width: currentGridSize * cellSize, height: 2, x: 0, y: i * cellSize }); } self.placeShip = function (startRow, startCol, length, isHorizontal, shipType) { var shipCells = []; // Check if placement is valid for (var i = 0; i < length; i++) { var row = isHorizontal ? startRow : startRow + i; var col = isHorizontal ? startCol + i : startCol; if (row >= currentGridSize || col >= currentGridSize || self.cells[row][col].hasShip) { return false; } shipCells.push({ row: row, col: col }); } // Place ship var ship = { cells: shipCells, hits: 0, sunk: false, type: shipType || 'cruiser', length: length, isHorizontal: isHorizontal, shipGraphic: null }; // Create unified ship graphic that spans all cells if (self.isPlayerGrid) { var cellSize = 60; var shipWidth = isHorizontal ? length * cellSize - 8 : cellSize - 8; var shipHeight = isHorizontal ? cellSize - 8 : length * cellSize - 8; var shipX = startCol * cellSize + 4; var shipY = startRow * cellSize + 4; ship.shipGraphic = self.attachAsset(shipType || 'cruiser', { width: shipWidth, height: shipHeight, x: shipX, y: shipY }); } // Mark cells as having ship but don't create individual graphics for (var j = 0; j < shipCells.length; j++) { var cellPos = shipCells[j]; var cell = self.cells[cellPos.row][cellPos.col]; cell.hasShip = true; } self.ships.push(ship); return true; }; self.checkHit = function (row, col) { var cell = self.cells[row][col]; if (cell.hasShip) { cell.markHit(); // Find which ship was hit for (var i = 0; i < self.ships.length; i++) { var ship = self.ships[i]; for (var j = 0; j < ship.cells.length; j++) { if (ship.cells[j].row === row && ship.cells[j].col === col) { ship.hits++; if (ship.hits === ship.cells.length && !ship.sunk) { ship.sunk = true; LK.getSound('sunk').play(); // Add fireworks effect for sunk ship self.createFireworks(ship.cells); updateFleetStatus(); return 'sunk'; } return 'hit'; } } } } else { cell.markMiss(); return 'miss'; } }; self.allShipsSunk = function () { for (var i = 0; i < self.ships.length; i++) { if (!self.ships[i].sunk) { return false; } } return true; }; self.createFireworks = function (shipCells) { var cellSize = 60; for (var i = 0; i < shipCells.length; i++) { var cellPos = shipCells[i]; var centerX = cellPos.col * cellSize + cellSize / 2; var centerY = cellPos.row * cellSize + cellSize / 2; // Create multiple firework particles for (var f = 0; f < 5; f++) { var firework = self.attachAsset('firework', { anchorX: 0.5, anchorY: 0.5, x: centerX, y: centerY, alpha: 1, scaleX: 0.5, scaleY: 0.5 }); var angle = f / 5 * Math.PI * 2; var distance = 50 + Math.random() * 30; var targetX = centerX + Math.cos(angle) * distance; var targetY = centerY + Math.sin(angle) * distance; tween(firework, { x: targetX, y: targetY, scaleX: 1.2, scaleY: 1.2, alpha: 0 }, { duration: 800 + Math.random() * 400, easing: tween.easeOut, onFinish: function onFinish() { firework.destroy(); } }); } } }; return self; }); var GridCell = Container.expand(function (row, col, isPlayerGrid) { var self = Container.call(this); self.row = row; self.col = col; self.isPlayerGrid = isPlayerGrid; self.hasShip = false; self.isHit = false; self.isMiss = false; var cellSize = 60; var waterTile = self.attachAsset('water', { width: cellSize, height: cellSize, x: 0, y: 0, color: 0xffffff }); var shipGraphic = null; var hitMarker = null; var missMarker = null; self.placeShip = function (shipType, segmentIndex, totalLength, isHorizontal) { // Only show ship graphics on player's own grid, hide enemy ships if (!shipGraphic && self.isPlayerGrid) { shipType = shipType || 'cruiser'; // Create single unified ship graphic that spans the entire ship length var shipWidth = isHorizontal ? totalLength * cellSize - 8 : cellSize - 8; var shipHeight = isHorizontal ? cellSize - 8 : totalLength * cellSize - 8; // Calculate position to center the ship across all its cells var shipX = isHorizontal ? segmentIndex * cellSize + 4 - segmentIndex * cellSize : 4; var shipY = isHorizontal ? 4 : segmentIndex * cellSize + 4 - segmentIndex * cellSize; // Only create the ship graphic on the first segment (bow) if (segmentIndex === 0) { shipGraphic = self.attachAsset(shipType, { width: shipWidth, height: shipHeight, x: shipX, y: shipY }); } } self.hasShip = true; }; self.removeShip = function () { // Ship graphics are now handled at the GameGrid level // Just mark the cell as not having a ship self.hasShip = false; }; self.markHit = function () { if (!self.isHit) { hitMarker = self.attachAsset('hit', { anchorX: 0.5, anchorY: 0.5, x: cellSize / 2, y: cellSize / 2 }); self.isHit = true; LK.getSound('hit').play(); LK.getSound('shoot').play(); // Add explosion effect var explosion = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, x: cellSize / 2, y: cellSize / 2, alpha: 0 }); tween(explosion, { alpha: 1, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, onFinish: function onFinish() { tween(explosion, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { explosion.destroy(); } }); } }); } }; self.markMiss = function () { if (!self.isMiss) { missMarker = self.attachAsset('miss', { anchorX: 0.5, anchorY: 0.5, x: cellSize / 2, y: cellSize / 2 }); self.isMiss = true; LK.getSound('miss').play(); // Add missile effect for miss var missile = self.attachAsset('missile', { anchorX: 0.5, anchorY: 1, x: cellSize / 2, y: -50, alpha: 0.8 }); LK.getSound('shoot').play(); tween(missile, { y: cellSize / 2, alpha: 0.3 }, { duration: 400, onFinish: function onFinish() { missile.destroy(); } }); } }; self.down = function (x, y, obj) { if (gamePhase === 'placement' && self.isPlayerGrid) { handleShipPlacement(self.row, self.col); } else if (gamePhase === 'battle' && !self.isPlayerGrid && !self.isHit && !self.isMiss) { handlePlayerShot(self.row, self.col); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x001122 }); /**** * Game Code ****/ // Gun turrets // Deck details // Hull details // Submarine - smallest // Destroyer - smaller // Cruiser - medium // Battleship - large // Aircraft Carrier - long and wide // Game state var gamePhase = 'placement'; // 'placement', 'battle', 'gameOver' var currentShipIndex = 0; var isHorizontal = true; var playerTurn = true; var aiTargets = []; var aiLastHit = null; var aiHuntMode = false; var airBombardmentUsed = false; var airBombardmentInProgress = false; var submarineAttackUsed = false; var submarineAttackInProgress = false; var sihaAttackUsed = false; var sihaAttackInProgress = false; var lastAttackType = null; // Track the last attack type to prevent consecutive use var aiAttackOptions = ['air', 'submarine', 'siha']; // Available AI attack options var aiLastAttackType = null; // Track AI's last attack type var aiAttackCooldowns = { air: false, submarine: false, siha: false }; // Track which AI attacks have been used // Attack rights tracking var playerAttackRights = { air: 2, submarine: 2, siha: 2 }; var aiAttackRights = { air: 2, submarine: 2, siha: 2 }; // Ship sizes to place - realistic naval fleet var shipSizes = [5, 4, 3, 3, 2]; // Carrier, Battleship, Cruiser, Cruiser, Destroyer var shipTypes = ['Uçak Gemisi', 'Savaş Gemisi', 'Kruvazör', 'Kruvazör', 'Muhrip']; var shipAssets = ['carrier', 'battleship', 'cruiser', 'cruiser', 'destroyer']; // Create grids var playerGrid = new GameGrid(true); var enemyGrid = new GameGrid(false); // Scale up grids for better visibility - increased for closer view playerGrid.scaleX = 2.0; playerGrid.scaleY = 2.0; enemyGrid.scaleX = 2.0; enemyGrid.scaleY = 2.0; // Center grids on screen var gridWidth = 8 * 60 * 2.0; // 8 cells * 60px * scale var screenCenterX = 2048 / 2; var gridCenterX = gridWidth / 2; playerGrid.x = screenCenterX - gridCenterX; playerGrid.y = 1300; enemyGrid.x = screenCenterX - gridCenterX; enemyGrid.y = 300; game.addChild(playerGrid); game.addChild(enemyGrid); // Hide enemy grid during placement phase enemyGrid.visible = false; // UI Elements var statusText = new Text2('Gemilerinizi yerleştirin. ' + shipSizes[0] + ' uzunluğunda gemi yerleştirmek için dokunun', { size: 40, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0); LK.gui.top.addChild(statusText); var turnText = new Text2('', { size: 35, fill: 0xFFFF00 }); turnText.anchor.set(0.5, 0); turnText.y = 80; LK.gui.top.addChild(turnText); // Labels for grids var enemyLabel = new Text2('Düşman Suları', { size: 45, fill: 0xFF6666 }); enemyLabel.anchor.set(0.5, 0.5); enemyLabel.x = enemyGrid.x + 8 * 60 * 1.5 / 2; enemyLabel.y = enemyGrid.y - 60; game.addChild(enemyLabel); var playerLabel = new Text2('Filonuz', { size: 45, fill: 0x66FF66 }); playerLabel.anchor.set(0.5, 0.5); playerLabel.x = playerGrid.x + 8 * 60 * 1.5 / 2; playerLabel.y = playerGrid.y - 60; game.addChild(playerLabel); // Rotation button for ship placement var rotateButton = new Text2('Gemiyi Çevir', { size: 60, fill: 0xFFFF00 }); rotateButton.anchor.set(0.5, 0.5); rotateButton.x = 300; rotateButton.y = 1200; game.addChild(rotateButton); rotateButton.down = function (x, y, obj) { if (gamePhase === 'placement') { isHorizontal = !isHorizontal; updateStatusText(); updateShipPreview(); } }; // Auto-placement button var autoPlaceButton = new Text2('Otomatik Yerleştir', { size: 60, fill: 0x00FF00 }); autoPlaceButton.anchor.set(0.5, 0.5); autoPlaceButton.x = 300; autoPlaceButton.y = 1300; game.addChild(autoPlaceButton); autoPlaceButton.down = function (x, y, obj) { if (gamePhase === 'placement') { autoPlacePlayerShips(); } }; // Start battle button var startBattleButton = new Text2('Savaşı Başlat', { size: 60, fill: 0xFF0000 }); startBattleButton.anchor.set(0.5, 0.5); startBattleButton.x = 300; startBattleButton.y = 1400; game.addChild(startBattleButton); startBattleButton.down = function (x, y, obj) { if (gamePhase === 'placement' && currentShipIndex >= shipSizes.length) { placeAIShips(); gamePhase = 'battle'; rotateButton.visible = false; autoPlaceButton.visible = false; startBattleButton.visible = false; enemyGrid.visible = true; airBombardmentButton.visible = true; submarineAttackButton.visible = true; sihaAttackButton.visible = true; // Move and scale down player grid to bottom left tween(playerGrid, { x: 50, y: 2150, scaleX: playerGrid.originalScaleX * 0.6, scaleY: playerGrid.originalScaleY * 0.6 }, { duration: 1000, easing: tween.easeInOut }); // Update player label position tween(playerLabel, { x: 50 + gridSize * 60 * playerGrid.originalScaleX * 0.6 / 2, y: 2150 - 60 }, { duration: 1000, easing: tween.easeInOut }); updateStatusText(); } }; // Air bombardment button var airBombardmentButton = new Container(); airBombardmentButton.x = 50; airBombardmentButton.y = 700; airBombardmentButton.visible = false; game.addChild(airBombardmentButton); // Button background var airButtonBg = airBombardmentButton.attachAsset('water', { width: 420, height: 90, x: -10, y: -45, color: 0xFF6600 }); airButtonBg.alpha = 0.9; // Button border var airButtonBorder = airBombardmentButton.attachAsset('gridLine', { width: 424, height: 94, x: -12, y: -47, color: 0xFFFFFF }); airButtonBorder.alpha = 0.8; // Button text var airButtonText = new Text2('🚁 Hava Bombardımanı', { size: 42, fill: 0xFFFFFF }); airButtonText.anchor.set(0, 0.5); airButtonText.x = 15; airButtonText.y = 0; airBombardmentButton.addChild(airButtonText); // Button press effect airBombardmentButton.down = function (x, y, obj) { if (gamePhase === 'battle' && playerTurn && !airBombardmentUsed && !airBombardmentInProgress && lastAttackType !== 'air') { // Press effect tween(airBombardmentButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(airBombardmentButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); executeAirBombardment(); } }; // Submarine attack button var submarineAttackButton = new Container(); submarineAttackButton.x = 50; submarineAttackButton.y = 1000; submarineAttackButton.visible = false; game.addChild(submarineAttackButton); // Button background var subButtonBg = submarineAttackButton.attachAsset('water', { width: 420, height: 90, x: -10, y: -45, color: 0x0066CC }); subButtonBg.alpha = 0.9; // Button border var subButtonBorder = submarineAttackButton.attachAsset('gridLine', { width: 424, height: 94, x: -12, y: -47, color: 0xFFFFFF }); subButtonBorder.alpha = 0.8; // Button text var subButtonText = new Text2('🚢 Denizaltı Saldırısı', { size: 42, fill: 0xFFFFFF }); subButtonText.anchor.set(0, 0.5); subButtonText.x = 15; subButtonText.y = 0; submarineAttackButton.addChild(subButtonText); // Button press effect submarineAttackButton.down = function (x, y, obj) { if (gamePhase === 'battle' && playerTurn && !submarineAttackUsed && !submarineAttackInProgress && lastAttackType !== 'submarine') { // Press effect tween(submarineAttackButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(submarineAttackButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); executeSubmarineAttack(); } }; // SIHA attack button var sihaAttackButton = new Container(); sihaAttackButton.x = 50; sihaAttackButton.y = 1300; sihaAttackButton.visible = false; game.addChild(sihaAttackButton); // Button background var sihaButtonBg = sihaAttackButton.attachAsset('water', { width: 420, height: 90, x: -10, y: -45, color: 0x9900FF }); sihaButtonBg.alpha = 0.9; // Button border var sihaButtonBorder = sihaAttackButton.attachAsset('gridLine', { width: 424, height: 94, x: -12, y: -47, color: 0xFFFFFF }); sihaButtonBorder.alpha = 0.8; // Button text var sihaButtonText = new Text2('🛩️ SİHA Saldırısı', { size: 42, fill: 0xFFFFFF }); sihaButtonText.anchor.set(0, 0.5); sihaButtonText.x = 15; sihaButtonText.y = 0; sihaAttackButton.addChild(sihaButtonText); // Target selector button var targetSelectorButton = new Container(); targetSelectorButton.x = 2048 / 2; targetSelectorButton.y = 1600; targetSelectorButton.visible = false; game.addChild(targetSelectorButton); // Button background var targetButtonBg = targetSelectorButton.attachAsset('water', { width: 420, height: 90, x: -210, y: -45, color: 0x00CCFF }); targetButtonBg.alpha = 0.9; // Button border var targetButtonBorder = targetSelectorButton.attachAsset('gridLine', { width: 424, height: 94, x: -212, y: -47, color: 0xFFFFFF }); targetButtonBorder.alpha = 0.8; // Button text var targetButtonText = new Text2('🎯 Hedef Seçici', { size: 42, fill: 0xFFFFFF }); targetButtonText.anchor.set(0.5, 0.5); targetButtonText.x = 0; targetButtonText.y = 0; targetSelectorButton.addChild(targetButtonText); // Button press effect targetSelectorButton.down = function (x, y, obj) { if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) { // Press effect tween(targetSelectorButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(targetSelectorButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); activateTargetSelector(); } }; // Button press effect sihaAttackButton.down = function (x, y, obj) { if (gamePhase === 'battle' && playerTurn && !sihaAttackUsed && !sihaAttackInProgress && lastAttackType !== 'siha') { // Press effect tween(sihaAttackButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(sihaAttackButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); executeSihaAttack(); } }; // Attack rights display var attackRightsContainer = new Container(); attackRightsContainer.x = 50; attackRightsContainer.y = playerGrid.y + 200; game.addChild(attackRightsContainer); var attackRightsTitle = new Text2('Saldırı Hakları', { size: 60, fill: 0xFFFFFF }); attackRightsTitle.anchor.set(0, 0); attackRightsTitle.x = 0; attackRightsTitle.y = 0; attackRightsContainer.addChild(attackRightsTitle); // Player attack rights var playerRightsTitle = new Text2('Oyuncu:', { size: 50, fill: 0x00FF00 }); playerRightsTitle.anchor.set(0, 0); playerRightsTitle.x = 0; playerRightsTitle.y = 60; attackRightsContainer.addChild(playerRightsTitle); var playerAirRightsText = new Text2('Hava: 2', { size: 45, fill: 0x00FF00 }); playerAirRightsText.anchor.set(0, 0); playerAirRightsText.x = 0; playerAirRightsText.y = 110; attackRightsContainer.addChild(playerAirRightsText); var playerSubRightsText = new Text2('Denizaltı: 2', { size: 45, fill: 0x00FF00 }); playerSubRightsText.anchor.set(0, 0); playerSubRightsText.x = 0; playerSubRightsText.y = 160; attackRightsContainer.addChild(playerSubRightsText); var playerSihaRightsText = new Text2('SİHA: 2', { size: 45, fill: 0x00FF00 }); playerSihaRightsText.anchor.set(0, 0); playerSihaRightsText.x = 0; playerSihaRightsText.y = 210; attackRightsContainer.addChild(playerSihaRightsText); // AI attack rights var aiRightsTitle = new Text2('Düşman:', { size: 50, fill: 0xFF0000 }); aiRightsTitle.anchor.set(0, 0); aiRightsTitle.x = 0; aiRightsTitle.y = 280; attackRightsContainer.addChild(aiRightsTitle); var aiAirRightsText = new Text2('Hava: 2', { size: 45, fill: 0xFF0000 }); aiAirRightsText.anchor.set(0, 0); aiAirRightsText.x = 0; aiAirRightsText.y = 330; attackRightsContainer.addChild(aiAirRightsText); var aiSubRightsText = new Text2('Denizaltı: 2', { size: 45, fill: 0xFF0000 }); aiSubRightsText.anchor.set(0, 0); aiSubRightsText.x = 0; aiSubRightsText.y = 380; attackRightsContainer.addChild(aiSubRightsText); var aiSihaRightsText = new Text2('SİHA: 2', { size: 45, fill: 0xFF0000 }); aiSihaRightsText.anchor.set(0, 0); aiSihaRightsText.x = 0; aiSihaRightsText.y = 430; attackRightsContainer.addChild(aiSihaRightsText); function activateTargetSelector() { if (!enemyGrid.visible || targetSelectorActive) return; targetSelectorActive = true; availableTargets = []; currentTargetIndex = 0; // Find all valid targets on enemy grid for (var row = 0; row < gridSize; row++) { for (var col = 0; col < gridSize; col++) { var cell = enemyGrid.cells[row][col]; if (!cell.isHit && !cell.isMiss) { availableTargets.push({ row: row, col: col, cell: cell }); } } } if (availableTargets.length === 0) { targetSelectorActive = false; return; } // Start with first available target selectTarget(0); // Update status text statusText.setText('Hedef seçici aktif - Hedefleri geçmek için ekrana dokunun'); } function selectTarget(index) { if (availableTargets.length === 0) return; currentTargetIndex = index % availableTargets.length; selectedTarget = availableTargets[currentTargetIndex]; // Move cursor to selected target var cellSize = 60 * enemyGrid.scaleX; var targetX = enemyGrid.x + selectedTarget.col * cellSize + cellSize / 2; var targetY = enemyGrid.y + selectedTarget.row * cellSize + cellSize / 2; // Animate cursor to target with smooth movement tween(cursorContainer, { x: targetX, y: targetY }, { duration: 400, easing: tween.easeInOut }); // Enhanced target highlighting with pulsing effect tween(crosshairCenter, { scaleX: 5.0, scaleY: 5.0, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); tween(crosshairOuter, { scaleX: 4.5, scaleY: 4.5, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); // Color code for target selection crosshairHorizontal.tint = 0x00ffff; crosshairVertical.tint = 0x00ffff; crosshairCenter.tint = 0xffff00; crosshairOuter.tint = 0x00ff88; crosshairInner.tint = 0xffff00; targetSelectionActive = true; } function cycleToNextTarget() { if (!targetSelectorActive || availableTargets.length === 0) return; selectTarget(currentTargetIndex + 1); } function fireAtSelectedTarget() { if (!targetSelectorActive || !selectedTarget) return; targetSelectorActive = false; targetSelectionActive = false; // Enhanced firing confirmation effect tween(crosshairCenter, { scaleX: 8.0, scaleY: 8.0, alpha: 0.3 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { handlePlayerShot(selectedTarget.row, selectedTarget.col); } }); tween(crosshairOuter, { scaleX: 6.0, scaleY: 6.0, alpha: 0.2 }, { duration: 200, easing: tween.easeIn }); } function updateAttackRightsDisplay() { playerAirRightsText.setText('Hava: ' + playerAttackRights.air); playerSubRightsText.setText('Denizaltı: ' + playerAttackRights.submarine); playerSihaRightsText.setText('SİHA: ' + playerAttackRights.siha); aiAirRightsText.setText('Hava: ' + aiAttackRights.air); aiSubRightsText.setText('Denizaltı: ' + aiAttackRights.submarine); aiSihaRightsText.setText('SİHA: ' + aiAttackRights.siha); // Update button visibility based on available rights if (gamePhase === 'battle') { attackRightsContainer.visible = true; airBombardmentButton.visible = playerAttackRights.air > 0 && lastAttackType !== 'air' && playerTurn; submarineAttackButton.visible = playerAttackRights.submarine > 0 && lastAttackType !== 'submarine' && playerTurn; sihaAttackButton.visible = playerAttackRights.siha > 0 && lastAttackType !== 'siha' && playerTurn; targetSelectorButton.visible = playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress; } else { attackRightsContainer.visible = false; targetSelectorButton.visible = false; } } // Ship preview container for placement phase var shipPreviewContainer = new Container(); shipPreviewContainer.x = 2048 / 2; shipPreviewContainer.y = 1050; // Position above player grid (player grid is at y=1300) game.addChild(shipPreviewContainer); function updateShipPreview() { // Clear existing preview for (var i = shipPreviewContainer.children.length - 1; i >= 0; i--) { shipPreviewContainer.children[i].destroy(); } if (gamePhase === 'placement' && currentShipIndex < shipSizes.length) { var shipLength = shipSizes[currentShipIndex]; var shipType = shipAssets[currentShipIndex]; var cellSize = 60; // Create preview ship graphic var previewWidth = isHorizontal ? shipLength * cellSize - 8 : cellSize - 8; var previewHeight = isHorizontal ? cellSize - 8 : shipLength * cellSize - 8; var previewX = isHorizontal ? -(previewWidth / 2) : -(previewWidth / 2); var previewY = isHorizontal ? -(previewHeight / 2) : -(previewHeight / 2); var shipPreview = shipPreviewContainer.attachAsset(shipType, { width: previewWidth, height: previewHeight, x: previewX, y: previewY, alpha: 0.8 }); // Add ship name label var shipNameText = new Text2(shipTypes[currentShipIndex], { size: 35, fill: 0xFFFFFF }); shipNameText.anchor.set(0.5, 0.5); shipNameText.x = 0; shipNameText.y = previewHeight / 2 + 50; shipPreviewContainer.addChild(shipNameText); // Add orientation label var orientationText = new Text2(isHorizontal ? 'Yatay' : 'Dikey', { size: 30, fill: 0xFFFF00 }); orientationText.anchor.set(0.5, 0.5); orientationText.x = 0; orientationText.y = previewHeight / 2 + 90; shipPreviewContainer.addChild(orientationText); } } function updateStatusText() { if (gamePhase === 'placement') { if (currentShipIndex < shipSizes.length) { var orientation = isHorizontal ? 'yatay' : 'dikey'; var shipName = shipTypes[currentShipIndex]; statusText.setText(shipName + ' yerleştirin (' + shipSizes[currentShipIndex] + ' kare, ' + orientation + ')'); updateShipPreview(); } else { statusText.setText('Tüm gemiler yerleştirildi! Savaşı başlatmak için butona tıklayın.'); shipPreviewContainer.visible = false; } } else if (gamePhase === 'battle') { shipPreviewContainer.visible = false; if (playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) { var bombardmentText = playerAttackRights.air > 0 && lastAttackType !== 'air' ? ' | Hava bombardımanı mevcut!' : ''; var submarineText = playerAttackRights.submarine > 0 && lastAttackType !== 'submarine' ? ' | Denizaltı saldırısı mevcut!' : ''; var sihaText = playerAttackRights.siha > 0 && lastAttackType !== 'siha' ? ' | SİHA saldırısı mevcut!' : ''; statusText.setText('Sıra sizde - Düşman ızgarasına ateş edin!' + bombardmentText + submarineText + sihaText); turnText.setText('SİZİN SIRANIZ'); } else if (airBombardmentInProgress) { statusText.setText('Hava bombardımanı devam ediyor...'); turnText.setText('HAVA SALDIRISI'); airBombardmentButton.visible = false; submarineAttackButton.visible = false; sihaAttackButton.visible = false; } else if (submarineAttackInProgress) { statusText.setText('Denizaltı saldırısı devam ediyor...'); turnText.setText('DENİZALTI SALDIRISI'); airBombardmentButton.visible = false; submarineAttackButton.visible = false; sihaAttackButton.visible = false; } else if (sihaAttackInProgress) { statusText.setText('SİHA saldırısı devam ediyor...'); turnText.setText('SİHA SALDIRISI'); airBombardmentButton.visible = false; submarineAttackButton.visible = false; sihaAttackButton.visible = false; } else { var aiHasAttacks = aiAttackRights.air > 0 || aiAttackRights.submarine > 0 || aiAttackRights.siha > 0; var aiAttackText = aiHasAttacks && aiLastAttackType !== 'regular' ? ' (Özel saldırı hazırlanıyor...)' : ''; statusText.setText('Düşman düşünüyor...' + aiAttackText); turnText.setText('DÜŞMAN SIRASI'); } } updateAttackRightsDisplay(); } function handleShipPlacement(row, col) { if (currentShipIndex >= shipSizes.length) return; var shipLength = shipSizes[currentShipIndex]; var shipType = shipAssets[currentShipIndex]; if (playerGrid.placeShip(row, col, shipLength, isHorizontal, shipType)) { currentShipIndex++; updateFleetStatus(); if (currentShipIndex >= shipSizes.length) { // All ships placed, start AI placement placeAIShips(); gamePhase = 'battle'; rotateButton.visible = false; autoPlaceButton.visible = false; enemyGrid.visible = true; updateStatusText(); } else { updateStatusText(); } } } function autoPlacePlayerShips() { // Clear existing ships and their graphics for (var i = 0; i < playerGrid.ships.length; i++) { var ship = playerGrid.ships[i]; if (ship.shipGraphic) { ship.shipGraphic.destroy(); ship.shipGraphic = null; } for (var j = 0; j < ship.cells.length; j++) { var cellPos = ship.cells[j]; playerGrid.cells[cellPos.row][cellPos.col].removeShip(); } } playerGrid.ships = []; // Clear all hit and miss markers from the board for (var row = 0; row < gridSize; row++) { for (var col = 0; col < gridSize; col++) { var cell = playerGrid.cells[row][col]; cell.isHit = false; cell.isMiss = false; // Remove any visual markers that might exist if (cell.hitMarker) { cell.hitMarker.destroy(); cell.hitMarker = null; } if (cell.missMarker) { cell.missMarker.destroy(); cell.missMarker = null; } } } // Reset ship placement index currentShipIndex = 0; var playerShipSizes = [5, 4, 3, 3, 2]; var playerShipTypes = ['carrier', 'battleship', 'cruiser', 'cruiser', 'destroyer']; for (var i = 0; i < playerShipSizes.length; i++) { var placed = false; var attempts = 0; while (!placed && attempts < 100) { var row = Math.floor(Math.random() * gridSize); var col = Math.floor(Math.random() * gridSize); var horizontal = Math.random() < 0.5; if (playerGrid.placeShip(row, col, playerShipSizes[i], horizontal, playerShipTypes[i])) { placed = true; currentShipIndex++; } attempts++; } } // Update status text to show current placement state updateStatusText(); updateFleetStatus(); } function placeAIShips() { var aiShipSizes = [5, 4, 3, 3, 2]; var aiShipTypes = ['carrier', 'battleship', 'cruiser', 'cruiser', 'destroyer']; for (var i = 0; i < aiShipSizes.length; i++) { var placed = false; var attempts = 0; while (!placed && attempts < 100) { var row = Math.floor(Math.random() * gridSize); var col = Math.floor(Math.random() * gridSize); var horizontal = Math.random() < 0.5; if (enemyGrid.placeShip(row, col, aiShipSizes[i], horizontal, aiShipTypes[i])) { placed = true; } attempts++; } } } updateFleetStatus(); function handlePlayerShot(row, col) { if (!playerTurn) return; lastAttackType = 'regular'; // Set last attack type for regular shots // Clear target selection after firing selectedTarget = null; targetSelectionActive = false; lastSelectedCell = null; targetSelectorActive = false; availableTargets = []; // Play enhanced shooting sound effect with target confirmation LK.getSound('shoot').play(); var result = enemyGrid.checkHit(row, col); if (result === 'hit' || result === 'sunk') { LK.setScore(LK.getScore() + (result === 'sunk' ? 100 : 50)); if (enemyGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Zafer! Tüm düşman gemileri yok edildi!'); turnText.setText('KAZANDINIZ!'); LK.showYouWin(); return; } } playerTurn = false; airBombardmentButton.visible = false; submarineAttackButton.visible = false; sihaAttackButton.visible = false; updateStatusText(); // AI turn after delay LK.setTimeout(function () { aiTurn(); }, 1000); } function executeAirBombardment() { if (playerAttackRights.air <= 0 || airBombardmentInProgress) return; playerAttackRights.air--; airBombardmentInProgress = true; lastAttackType = 'air'; // Set last attack type playerTurn = false; updateAttackRightsDisplay(); statusText.setText('Hava bombardımanı başlatıldı! Uçaklar hedefe yaklaşıyor...'); turnText.setText('HAVA SALDIRISI'); // Generate 5 random target positions var targets = []; var attempts = 0; while (targets.length < 5 && attempts < 100) { var row = Math.floor(Math.random() * gridSize); var col = Math.floor(Math.random() * gridSize); var duplicate = false; for (var i = 0; i < targets.length; i++) { if (targets[i].row === row && targets[i].col === col) { duplicate = true; break; } } if (!duplicate) { targets.push({ row: row, col: col }); } attempts++; } // Create aircraft animation var aircraft = game.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, x: -100, y: 200, scaleX: 2, scaleY: 2, rotation: Math.PI / 4 }); // Animate aircraft flying across screen tween(aircraft, { x: 2148, y: 300 }, { duration: 2000, easing: tween.linear, onFinish: function onFinish() { aircraft.destroy(); // Execute bombardment hits with delays executeTargetHits(targets, 0); } }); } function executeTargetHits(targets, currentIndex) { if (currentIndex >= targets.length) { // All hits completed LK.setTimeout(function () { airBombardmentInProgress = false; if (enemyGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Zafer! Tüm düşman gemileri yok edildi!'); turnText.setText('KAZANDINIZ!'); LK.showYouWin(); return; } // AI turn after air bombardment aiLastAttackType = null; // Reset AI attack type to allow AI special attacks LK.setTimeout(function () { aiTurn(); }, 1000); }, 1000); return; } var target = targets[currentIndex]; // Create bomb falling animation var bomb = game.attachAsset('missile', { anchorX: 0.5, anchorY: 1, x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: 100, alpha: 0.8 }); tween(bomb, { y: enemyGrid.y + target.row * 60 * 1.5 + 30 * 1.5, alpha: 0.3 }, { duration: 600, onFinish: function onFinish() { bomb.destroy(); // Check hit result var result = enemyGrid.checkHit(target.row, target.col); if (result === 'hit' || result === 'sunk') { LK.setScore(LK.getScore() + (result === 'sunk' ? 100 : 50)); } // Continue with next target after short delay LK.setTimeout(function () { executeTargetHits(targets, currentIndex + 1); }, 300); } }); } function executeSubmarineAttack() { if (playerAttackRights.submarine <= 0 || submarineAttackInProgress) return; playerAttackRights.submarine--; submarineAttackInProgress = true; lastAttackType = 'submarine'; // Set last attack type playerTurn = false; updateAttackRightsDisplay(); statusText.setText('Denizaltı saldırısı başlatıldı! Torpido hazırlanıyor...'); turnText.setText('DENİZALTI SALDIRISI'); // Find all enemy ships that are not yet sunk var availableTargets = []; for (var i = 0; i < enemyGrid.ships.length; i++) { var ship = enemyGrid.ships[i]; if (!ship.sunk) { // Add all unhit cells of this ship as potential targets for (var j = 0; j < ship.cells.length; j++) { var cellPos = ship.cells[j]; var cell = enemyGrid.cells[cellPos.row][cellPos.col]; if (!cell.isHit) { availableTargets.push({ row: cellPos.row, col: cellPos.col }); } } } } // If no available targets (all ships sunk or all remaining cells hit), just end if (availableTargets.length === 0) { submarineAttackInProgress = false; playerTurn = true; updateStatusText(); return; } // Select random target from available unhit ship cells var target = availableTargets[Math.floor(Math.random() * availableTargets.length)]; // Create submarine animation from bottom of screen var submarine = game.attachAsset('submarine', { anchorX: 0.5, anchorY: 0.5, x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: 2732 + 100, scaleX: 2, scaleY: 2, alpha: 0.7 }); // Animate submarine rising tween(submarine, { y: enemyGrid.y + target.row * 60 * 1.5 + 200, alpha: 1 }, { duration: 1500, easing: tween.easeOut, onFinish: function onFinish() { // Create torpedo var torpedo = game.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, x: submarine.x, y: submarine.y, scaleX: 1.5, scaleY: 1.5, rotation: -Math.PI / 2, alpha: 0.9 }); // Animate torpedo to target tween(torpedo, { x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: enemyGrid.y + target.row * 60 * 1.5 + 30 * 1.5, alpha: 0.5 }, { duration: 800, easing: tween.linear, onFinish: function onFinish() { torpedo.destroy(); // Guaranteed hit on ship var result = enemyGrid.checkHit(target.row, target.col); LK.setScore(LK.getScore() + (result === 'sunk' ? 150 : 75)); // Submarine disappears tween(submarine, { y: 2732 + 100, alpha: 0 }, { duration: 1000, easing: tween.easeIn, onFinish: function onFinish() { submarine.destroy(); submarineAttackInProgress = false; if (enemyGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Zafer! Tüm düşman gemileri yok edildi!'); turnText.setText('KAZANDINIZ!'); LK.showYouWin(); return; } // AI turn after submarine attack aiLastAttackType = null; // Reset AI attack type to allow AI special attacks LK.setTimeout(function () { aiTurn(); }, 1000); } }); } }); } }); } function executeSihaAttack() { if (playerAttackRights.siha <= 0 || sihaAttackInProgress) return; playerAttackRights.siha--; sihaAttackInProgress = true; lastAttackType = 'siha'; // Set last attack type playerTurn = false; updateAttackRightsDisplay(); statusText.setText('SİHA saldırısı başlatıldı! Hedef aranıyor...'); turnText.setText('SİHA SALDIRISI'); // Find all enemy ships that are not yet sunk var availableShips = []; for (var i = 0; i < enemyGrid.ships.length; i++) { var ship = enemyGrid.ships[i]; if (!ship.sunk) { availableShips.push(ship); } } // If no available ships, just end if (availableShips.length === 0) { sihaAttackInProgress = false; playerTurn = true; updateStatusText(); return; } // Select random ship to completely destroy var targetShip = availableShips[Math.floor(Math.random() * availableShips.length)]; var targetCells = []; // Get all cells of the target ship for (var j = 0; j < targetShip.cells.length; j++) { targetCells.push(targetShip.cells[j]); } // Create SIHA drone animation from top of screen var siha = game.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, x: -100, y: -100, scaleX: 1.8, scaleY: 1.8, rotation: Math.PI / 6, alpha: 0.9 }); // Animate SIHA flying to target area var targetCenterX = enemyGrid.x + targetCells[0].col * 60 * 1.5 + 30 * 1.5; var targetCenterY = enemyGrid.y + targetCells[0].row * 60 * 1.5 + 30 * 1.5; tween(siha, { x: targetCenterX, y: targetCenterY - 150, rotation: 0 }, { duration: 2500, easing: tween.easeInOut, onFinish: function onFinish() { // Hover for targeting tween(siha, { y: targetCenterY - 100, alpha: 1 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { // Execute precision strike - hit all cells of the ship executeShipDestruction(targetCells, 0, siha); } }); } }); } function executeShipDestruction(targetCells, currentIndex, siha) { if (currentIndex >= targetCells.length) { // All cells destroyed, SIHA returns tween(siha, { x: 2200, y: -100, alpha: 0.5 }, { duration: 2000, easing: tween.easeIn, onFinish: function onFinish() { siha.destroy(); sihaAttackInProgress = false; if (enemyGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Zafer! Tüm düşman gemileri yok edildi!'); turnText.setText('KAZANDINIZ!'); LK.showYouWin(); return; } // AI turn after SIHA attack aiLastAttackType = null; // Reset AI attack type to allow AI special attacks LK.setTimeout(function () { aiTurn(); }, 1000); } }); return; } var target = targetCells[currentIndex]; // Create precision missile var missile = game.attachAsset('missile', { anchorX: 0.5, anchorY: 1, x: siha.x, y: siha.y, scaleX: 0.8, scaleY: 0.8, alpha: 0.9 }); tween(missile, { x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: enemyGrid.y + target.row * 60 * 1.5 + 30 * 1.5, alpha: 0.4 }, { duration: 400, easing: tween.linear, onFinish: function onFinish() { missile.destroy(); // Guaranteed hit var result = enemyGrid.checkHit(target.row, target.col); if (result === 'hit' || result === 'sunk') { LK.setScore(LK.getScore() + (result === 'sunk' ? 200 : 100)); } // Continue with next target after short delay LK.setTimeout(function () { executeShipDestruction(targetCells, currentIndex + 1, siha); }, 200); } }); } function executeAIAirBombardment() { aiAttackRights.air--; aiLastAttackType = 'air'; updateAttackRightsDisplay(); statusText.setText('Düşman hava bombardımanı başlattı!'); turnText.setText('DÜŞMAN HAVA SALDIRISI'); // Generate 5 random target positions on player grid var targets = []; var attempts = 0; while (targets.length < 5 && attempts < 100) { var row = Math.floor(Math.random() * gridSize); var col = Math.floor(Math.random() * gridSize); var cell = playerGrid.cells[row][col]; // Only target untouched cells if (!cell.isHit && !cell.isMiss) { var duplicate = false; for (var i = 0; i < targets.length; i++) { if (targets[i].row === row && targets[i].col === col) { duplicate = true; break; } } if (!duplicate) { targets.push({ row: row, col: col }); } } attempts++; } // Create AI aircraft animation var aircraft = game.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, x: 2148, y: 200, scaleX: 2, scaleY: 2, rotation: -Math.PI * 3 / 4, tint: 0xFF0000 }); // Animate aircraft flying across screen tween(aircraft, { x: -100, y: 300 }, { duration: 2000, easing: tween.linear, onFinish: function onFinish() { aircraft.destroy(); executeAITargetHits(targets, 0); } }); } function executeAITargetHits(targets, currentIndex) { if (currentIndex >= targets.length) { // All hits completed LK.setTimeout(function () { if (playerGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Yenilgi! Filonuz yok edildi!'); turnText.setText('KAYBETTİNİZ!'); LK.showGameOver(); return; } playerTurn = true; lastAttackType = null; updateStatusText(); }, 1000); return; } var target = targets[currentIndex]; // Create bomb falling animation var bomb = game.attachAsset('missile', { anchorX: 0.5, anchorY: 1, x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: 100, alpha: 0.8, tint: 0xFF0000 }); tween(bomb, { y: playerGrid.y + target.row * 60 * 1.5 + 30 * 1.5, alpha: 0.3 }, { duration: 600, onFinish: function onFinish() { bomb.destroy(); var result = playerGrid.checkHit(target.row, target.col); LK.setTimeout(function () { executeAITargetHits(targets, currentIndex + 1); }, 300); } }); } function executeAISubmarineAttack() { aiAttackRights.submarine--; aiLastAttackType = 'submarine'; updateAttackRightsDisplay(); statusText.setText('Düşman denizaltı saldırısı başlattı!'); turnText.setText('DÜŞMAN DENİZALTI SALDIRISI'); // Find player ships that are not yet sunk var availableTargets = []; for (var i = 0; i < playerGrid.ships.length; i++) { var ship = playerGrid.ships[i]; if (!ship.sunk) { for (var j = 0; j < ship.cells.length; j++) { var cellPos = ship.cells[j]; var cell = playerGrid.cells[cellPos.row][cellPos.col]; if (!cell.isHit) { availableTargets.push({ row: cellPos.row, col: cellPos.col }); } } } } if (availableTargets.length === 0) { playerTurn = true; lastAttackType = null; updateStatusText(); return; } // Select random target from available unhit ship cells var target = availableTargets[Math.floor(Math.random() * availableTargets.length)]; // Create submarine animation var submarine = game.attachAsset('submarine', { anchorX: 0.5, anchorY: 0.5, x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: 2732 + 100, scaleX: 2, scaleY: 2, alpha: 0.7, tint: 0xFF0000 }); // Animate submarine rising tween(submarine, { y: playerGrid.y + target.row * 60 * 1.5 + 200, alpha: 1 }, { duration: 1500, easing: tween.easeOut, onFinish: function onFinish() { // Create torpedo var torpedo = game.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, x: submarine.x, y: submarine.y, scaleX: 1.5, scaleY: 1.5, rotation: -Math.PI / 2, alpha: 0.9, tint: 0xFF0000 }); // Animate torpedo to target tween(torpedo, { x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: playerGrid.y + target.row * 60 * 1.5 + 30 * 1.5, alpha: 0.5 }, { duration: 800, easing: tween.linear, onFinish: function onFinish() { torpedo.destroy(); var result = playerGrid.checkHit(target.row, target.col); // Submarine disappears tween(submarine, { y: 2732 + 100, alpha: 0 }, { duration: 1000, easing: tween.easeIn, onFinish: function onFinish() { submarine.destroy(); if (playerGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Yenilgi! Filonuz yok edildi!'); turnText.setText('KAYBETTİNİZ!'); LK.showGameOver(); return; } playerTurn = true; lastAttackType = null; updateStatusText(); } }); } }); } }); } function executeAISihaAttack() { aiAttackRights.siha--; aiLastAttackType = 'siha'; updateAttackRightsDisplay(); statusText.setText('Düşman SİHA saldırısı başlattı!'); turnText.setText('DÜŞMAN SİHA SALDIRISI'); // Find all player ships that are not yet sunk var availableShips = []; for (var i = 0; i < playerGrid.ships.length; i++) { var ship = playerGrid.ships[i]; if (!ship.sunk) { availableShips.push(ship); } } if (availableShips.length === 0) { playerTurn = true; lastAttackType = null; updateStatusText(); return; } // Select random ship to completely destroy var targetShip = availableShips[Math.floor(Math.random() * availableShips.length)]; var targetCells = []; for (var j = 0; j < targetShip.cells.length; j++) { targetCells.push(targetShip.cells[j]); } // Create AI SIHA drone animation var siha = game.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, x: 2148, y: -100, scaleX: 1.8, scaleY: 1.8, rotation: -Math.PI / 6, alpha: 0.9, tint: 0xFF0000 }); // Animate SIHA flying to target area var targetCenterX = playerGrid.x + targetCells[0].col * 60 * 1.5 + 30 * 1.5; var targetCenterY = playerGrid.y + targetCells[0].row * 60 * 1.5 + 30 * 1.5; tween(siha, { x: targetCenterX, y: targetCenterY - 150, rotation: 0 }, { duration: 2500, easing: tween.easeInOut, onFinish: function onFinish() { tween(siha, { y: targetCenterY - 100, alpha: 1 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { executeAIShipDestruction(targetCells, 0, siha); } }); } }); } function executeAIShipDestruction(targetCells, currentIndex, siha) { if (currentIndex >= targetCells.length) { // All cells destroyed, SIHA returns tween(siha, { x: 2200, y: -100, alpha: 0.5 }, { duration: 2000, easing: tween.easeIn, onFinish: function onFinish() { siha.destroy(); if (playerGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Yenilgi! Filonuz yok edildi!'); turnText.setText('KAYBETTİNİZ!'); LK.showGameOver(); return; } playerTurn = true; lastAttackType = null; updateStatusText(); } }); return; } var target = targetCells[currentIndex]; // Create precision missile var missile = game.attachAsset('missile', { anchorX: 0.5, anchorY: 1, x: siha.x, y: siha.y, scaleX: 0.8, scaleY: 0.8, alpha: 0.9, tint: 0xFF0000 }); tween(missile, { x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5, y: playerGrid.y + target.row * 60 * 1.5 + 30 * 1.5, alpha: 0.4 }, { duration: 400, easing: tween.linear, onFinish: function onFinish() { missile.destroy(); var result = playerGrid.checkHit(target.row, target.col); LK.setTimeout(function () { executeAIShipDestruction(targetCells, currentIndex + 1, siha); }, 200); } }); } function aiTurn() { // Check if AI should use a special attack (30% chance if available and not consecutive) var shouldUseSpecialAttack = Math.random() < 0.3; var availableAttacks = []; // Check which attacks are available (have rights remaining and not the last attack type) if (aiAttackRights.air > 0 && aiLastAttackType !== 'air') { availableAttacks.push('air'); } if (aiAttackRights.submarine > 0 && aiLastAttackType !== 'submarine') { availableAttacks.push('submarine'); } if (aiAttackRights.siha > 0 && aiLastAttackType !== 'siha') { availableAttacks.push('siha'); } // Use special attack if conditions are met if (shouldUseSpecialAttack && availableAttacks.length > 0) { var selectedAttack = availableAttacks[Math.floor(Math.random() * availableAttacks.length)]; if (selectedAttack === 'air') { executeAIAirBombardment(); return; } else if (selectedAttack === 'submarine') { executeAISubmarineAttack(); return; } else if (selectedAttack === 'siha') { executeAISihaAttack(); return; } } // Regular attack logic var row, col; var attempts = 0; var targetFound = false; if (aiHuntMode && aiLastHit) { // First priority: Try adjacent cells to last hit var adjacents = [{ row: aiLastHit.row - 1, col: aiLastHit.col }, { row: aiLastHit.row + 1, col: aiLastHit.col }, { row: aiLastHit.row, col: aiLastHit.col - 1 }, { row: aiLastHit.row, col: aiLastHit.col + 1 }]; var validTargets = []; for (var i = 0; i < adjacents.length; i++) { var target = adjacents[i]; if (target.row >= 0 && target.row < gridSize && target.col >= 0 && target.col < gridSize) { var cell = playerGrid.cells[target.row][target.col]; if (!cell.isHit && !cell.isMiss) { validTargets.push(target); } } } if (validTargets.length > 0) { var chosen = validTargets[Math.floor(Math.random() * validTargets.length)]; row = chosen.row; col = chosen.col; targetFound = true; } else { // Second priority: Look for any hit cells that still have adjacent untested cells var allHitCells = []; for (var r = 0; r < gridSize; r++) { for (var c = 0; c < gridSize; c++) { var cell = playerGrid.cells[r][c]; if (cell.isHit && cell.hasShip) { // Check if this hit cell's ship is not sunk var shipNotSunk = false; for (var s = 0; s < playerGrid.ships.length; s++) { var ship = playerGrid.ships[s]; if (!ship.sunk) { for (var sc = 0; sc < ship.cells.length; sc++) { if (ship.cells[sc].row === r && ship.cells[sc].col === c) { shipNotSunk = true; break; } } } if (shipNotSunk) break; } if (shipNotSunk) { allHitCells.push({ row: r, col: c }); } } } } // Find hit cells that still have adjacent untested targets var validHitCells = []; for (var h = 0; h < allHitCells.length; h++) { var hitCell = allHitCells[h]; var hitAdjacents = [{ row: hitCell.row - 1, col: hitCell.col }, { row: hitCell.row + 1, col: hitCell.col }, { row: hitCell.row, col: hitCell.col - 1 }, { row: hitCell.row, col: hitCell.col + 1 }]; for (var ha = 0; ha < hitAdjacents.length; ha++) { var adj = hitAdjacents[ha]; if (adj.row >= 0 && adj.row < gridSize && adj.col >= 0 && adj.col < gridSize) { var adjCell = playerGrid.cells[adj.row][adj.col]; if (!adjCell.isHit && !adjCell.isMiss) { validHitCells.push(adj); } } } } if (validHitCells.length > 0) { var chosen = validHitCells[Math.floor(Math.random() * validHitCells.length)]; row = chosen.row; col = chosen.col; targetFound = true; } else { aiHuntMode = false; aiLastHit = null; } } } if (!targetFound) { // Random targeting do { row = Math.floor(Math.random() * gridSize); col = Math.floor(Math.random() * gridSize); attempts++; } while ((playerGrid.cells[row][col].isHit || playerGrid.cells[row][col].isMiss) && attempts < 100); } var result = playerGrid.checkHit(row, col); if (result === 'hit' || result === 'sunk') { aiLastHit = { row: row, col: col }; aiHuntMode = true; if (result === 'sunk') { aiHuntMode = false; aiLastHit = null; } else if (result === 'hit') { // Ship was hit but not sunk, continue attacking surrounding area LK.setTimeout(function () { aiTurn(); // Continue attacking immediately }, 1500); return; } if (playerGrid.allShipsSunk()) { gamePhase = 'gameOver'; statusText.setText('Yenilgi! Filonuz yok edildi!'); turnText.setText('KAYBETTİNİZ!'); LK.showGameOver(); return; } } playerTurn = true; lastAttackType = null; // Reset attack type after AI turn to allow alternating attacks aiLastAttackType = 'regular'; // Set AI's last attack as regular updateStatusText(); } // Fleet status displays var playerFleetStatus = new Container(); playerFleetStatus.x = 1700; playerFleetStatus.y = 1500; game.addChild(playerFleetStatus); var enemyFleetStatus = new Container(); enemyFleetStatus.x = 1700; enemyFleetStatus.y = 900; game.addChild(enemyFleetStatus); // Fleet status title texts var playerFleetTitle = new Text2('Filonuz', { size: 40, fill: 0x66FF66 }); playerFleetTitle.anchor.set(0.5, 0); playerFleetTitle.x = 0; playerFleetTitle.y = -60; playerFleetStatus.addChild(playerFleetTitle); var enemyFleetTitle = new Text2('Düşman Filosu', { size: 40, fill: 0xFF6666 }); enemyFleetTitle.anchor.set(0.5, 0); enemyFleetTitle.x = 0; enemyFleetTitle.y = -60; enemyFleetStatus.addChild(enemyFleetTitle); // Fleet status arrays var playerFleetDisplay = []; var enemyFleetDisplay = []; function updateFleetStatus() { // Initialize arrays if they don't exist if (!playerFleetDisplay) playerFleetDisplay = []; if (!enemyFleetDisplay) enemyFleetDisplay = []; // Clear existing displays for (var i = 0; i < playerFleetDisplay.length; i++) { playerFleetDisplay[i].destroy(); } for (var i = 0; i < enemyFleetDisplay.length; i++) { enemyFleetDisplay[i].destroy(); } playerFleetDisplay = []; enemyFleetDisplay = []; // Create player fleet status createFleetStatusDisplay(playerGrid, playerFleetStatus, playerFleetDisplay, true); // Create enemy fleet status createFleetStatusDisplay(enemyGrid, enemyFleetStatus, enemyFleetDisplay, false); } function createFleetStatusDisplay(grid, statusContainer, displayArray, isPlayerFleet) { for (var i = 0; i < grid.ships.length; i++) { var ship = grid.ships[i]; // Create main ship container var shipContainer = new Container(); shipContainer.x = 0; shipContainer.y = i * 50; // Reduced spacing for text-only statusContainer.addChild(shipContainer); displayArray.push(shipContainer); // Create ship info display (text only) createShipTextDisplay(ship, shipContainer, i, isPlayerFleet); } } function createShipTextDisplay(ship, container, shipIndex, isPlayerFleet) { // Ship name and status var shipName = shipTypes[shipIndex]; var statusText = shipName; var statusColor = 0xCCCCCC; // Determine status and color if (isPlayerFleet) { if (ship.sunk) { statusColor = 0xFF4444; statusText += ' - BATIK (' + ship.hits + '/' + ship.length + ')'; } else if (ship.hits > 0) { statusColor = 0xFFAA00; statusText += ' - Hasarlı (' + ship.hits + '/' + ship.length + ')'; } else { statusColor = 0x66FF99; statusText += ' - Sağlam (' + ship.hits + '/' + ship.length + ')'; } } else { // Enemy fleet - only show detailed status if damaged or sunk if (ship.sunk) { statusColor = 0xFF4444; statusText += ' - BATIK (' + ship.hits + '/' + ship.length + ')'; } else if (ship.hits > 0) { statusColor = 0xFFAA00; statusText += ' - Hasarlı (' + ship.hits + '/' + ship.length + ')'; } else { statusColor = 0x888888; statusText += ' - Bilinmiyor'; } } var nameText = new Text2(statusText, { size: 28, fill: statusColor }); nameText.anchor.set(0, 0); nameText.x = 0; nameText.y = 0; container.addChild(nameText); } // Removed - no longer needed for text-only display // Removed - no longer needed for text-only display // Game info page variables var gameInfoShown = false; var currentInfoPage = 0; var totalInfoPages = 3; // Difficulty selection variables var difficultySelected = false; var selectedDifficulty = 'easy'; // default var gridSize = 8; // will be updated based on difficulty // Game information page UI var gameInfoContainer = new Container(); gameInfoContainer.x = 2048 / 2; gameInfoContainer.y = 2732 / 2; game.addChild(gameInfoContainer); // Info page background var infoBg = LK.getAsset('water', { width: 1800, height: 2400, x: -900, y: -1200, color: 0x001122 }); infoBg.alpha = 0.95; gameInfoContainer.addChild(infoBg); // Info page title var infoTitle = new Text2('AMİRAL BATTI', { size: 80, fill: 0xFFD700 }); infoTitle.anchor.set(0.5, 0.5); infoTitle.x = 0; infoTitle.y = -1000; gameInfoContainer.addChild(infoTitle); // Page indicator var pageIndicator = new Text2('Sayfa 1 / 3', { size: 50, fill: 0xCCCCCC }); pageIndicator.anchor.set(0.5, 0.5); pageIndicator.x = 0; pageIndicator.y = -900; gameInfoContainer.addChild(pageIndicator); // Info content container var infoContentContainer = new Container(); infoContentContainer.x = 0; infoContentContainer.y = -400; gameInfoContainer.addChild(infoContentContainer); // Navigation buttons var prevButton = new Text2('← ÖNCEKİ', { size: 60, fill: 0x888888 }); prevButton.anchor.set(0.5, 0.5); prevButton.x = -300; prevButton.y = 1000; gameInfoContainer.addChild(prevButton); var nextButton = new Text2('SONRAKİ →', { size: 60, fill: 0x00FF00 }); nextButton.anchor.set(0.5, 0.5); nextButton.x = 300; nextButton.y = 1000; gameInfoContainer.addChild(nextButton); var startGameButton = new Text2('OYUNA BAŞLA', { size: 70, fill: 0xFF0000 }); startGameButton.anchor.set(0.5, 0.5); startGameButton.x = 0; startGameButton.y = 900; startGameButton.visible = false; gameInfoContainer.addChild(startGameButton); // Info page content arrays var infoPages = [ // Page 1: Basic Rules ['OYUN KURALLARI', '', '• Deniz savaşı oyununda amacınız düşman', ' filosunu tamamen yok etmektir', '', '• Filonuzda 5 farklı gemi türü bulunur:', ' - Uçak Gemisi (5 kare)', ' - Savaş Gemisi (4 kare)', ' - Kruvazör x2 (3 kare)', ' - Muhrip (2 kare)', '', '• Gemiler yatay veya dikey olarak', ' yerleştirilebilir', '', '• Düşman ızgarasına tıklayarak ateş edin', '• İsabet: Kırmızı, Kaçan: Mavi'], // Page 2: Special Attacks ['ÖZEL SALDIRILAR', '', '🛩️ HAVA BOMBARDIMANI (2 Hak)', '• 5 rastgele hedefe eş zamanlı saldırı', '• Geniş alan hasarı', '• Ardışık kullanılamaz', '', '🚢 DENİZALTI SALDIRISI (2 Hak)', '• Düşman gemisine garantili isabet', '• Hedef otomatik seçilir', '• Yüksek hasar', '', '🛸 SİHA SALDIRISI (2 Hak)', '• Seçilen gemiyi tamamen yok eder', '• Hassas hedefleme', '• En güçlü saldırı türü'], // Page 3: Game Tips ['OYUN İPUÇLARI', '', '⚡ STRATEJİ TAVSİYELERİ:', '', '• Gemilerinizi rastgele yerleştirin', '• Özel saldırıları akıllıca kullanın', '• Düşman vuruşlarından kalıp çıkarın', '• Isabet aldığınız bölgelerin etrafını', ' sistematik olarak tarayın', '', '🎯 ZORLUK SEVİYELERİ:', '• Kolay: Yavaş yapay zeka', '• Orta: Dengeli yapay zeka', '• Zor: Agresif yapay zeka', '', '• Düşman da özel saldırılara sahiptir!', '• Savunmanızı güçlü tutun!']]; // Button event handlers prevButton.down = function (x, y, obj) { if (currentInfoPage > 0) { currentInfoPage--; updateInfoPage(); } }; nextButton.down = function (x, y, obj) { if (currentInfoPage < totalInfoPages - 1) { currentInfoPage++; updateInfoPage(); } }; startGameButton.down = function (x, y, obj) { gameInfoShown = true; gameInfoContainer.visible = false; difficultyContainer.visible = true; }; function updateInfoPage() { // Clear existing content for (var i = infoContentContainer.children.length - 1; i >= 0; i--) { infoContentContainer.children[i].destroy(); } // Update page indicator pageIndicator.setText('Sayfa ' + (currentInfoPage + 1) + ' / ' + totalInfoPages); // Add new content var content = infoPages[currentInfoPage]; for (var i = 0; i < content.length; i++) { var line = content[i]; var isTitle = i === 0; var isEmpty = line === ''; if (!isEmpty) { var textSize = isTitle ? 80 : 55; var textColor = isTitle ? 0xFFD700 : line.startsWith('•') ? 0xCCCCCC : line.startsWith('🛩️') || line.startsWith('🚢') || line.startsWith('🛸') ? 0x00FFFF : line.startsWith('⚡') || line.startsWith('🎯') ? 0xFFAA00 : 0xFFFFFF; var lineText = new Text2(line, { size: textSize, fill: textColor }); lineText.anchor.set(0.5, 0); lineText.x = 0; lineText.y = i * 60 - 200; infoContentContainer.addChild(lineText); } } // Update button visibility prevButton.visible = currentInfoPage > 0; prevButton.fill = currentInfoPage > 0 ? 0xFFFFFF : 0x888888; nextButton.visible = currentInfoPage < totalInfoPages - 1; nextButton.fill = currentInfoPage < totalInfoPages - 1 ? 0x00FF00 : 0x888888; startGameButton.visible = currentInfoPage === totalInfoPages - 1; } // Initialize first page updateInfoPage(); // Difficulty selection UI var difficultyContainer = new Container(); difficultyContainer.x = 2048 / 2; difficultyContainer.y = 2732 / 2; difficultyContainer.visible = false; game.addChild(difficultyContainer); var difficultyTitle = new Text2('Zorluk Seviyesi Seçin', { size: 80, fill: 0xFFFFFF }); difficultyTitle.anchor.set(0.5, 0.5); difficultyTitle.x = 0; difficultyTitle.y = -200; difficultyContainer.addChild(difficultyTitle); // Easy button var easyButton = new Text2('KOLAY (8x8)', { size: 65, fill: 0x00FF00 }); easyButton.anchor.set(0.5, 0.5); easyButton.x = -400; easyButton.y = 0; difficultyContainer.addChild(easyButton); easyButton.down = function (x, y, obj) { selectedDifficulty = 'easy'; gridSize = 8; startGameWithDifficulty(); }; // Medium button var mediumButton = new Text2('ORTA (8x8)', { size: 65, fill: 0xFFFF00 }); mediumButton.anchor.set(0.5, 0.5); mediumButton.x = 0; mediumButton.y = 0; difficultyContainer.addChild(mediumButton); mediumButton.down = function (x, y, obj) { selectedDifficulty = 'medium'; gridSize = 8; startGameWithDifficulty(); }; // Hard button var hardButton = new Text2('ZOR (8x8)', { size: 65, fill: 0xFF0000 }); hardButton.anchor.set(0.5, 0.5); hardButton.x = 400; hardButton.y = 0; difficultyContainer.addChild(hardButton); hardButton.down = function (x, y, obj) { selectedDifficulty = 'hard'; gridSize = 8; startGameWithDifficulty(); }; function startGameWithDifficulty() { difficultySelected = true; difficultyContainer.visible = false; // Recreate grids with new size playerGrid.destroy(); enemyGrid.destroy(); playerGrid = new GameGrid(true); enemyGrid = new GameGrid(false); // Scale grids based on difficulty to fit screen - increased for closer view var baseScale = selectedDifficulty === 'easy' ? 2.0 : selectedDifficulty === 'medium' ? 1.8 : 1.5; playerGrid.scaleX = baseScale; playerGrid.scaleY = baseScale; enemyGrid.scaleX = baseScale; enemyGrid.scaleY = baseScale; // Center grids on screen var gridWidth = gridSize * 60 * baseScale; var screenCenterX = 2048 / 2; var gridCenterX = gridWidth / 2; playerGrid.x = screenCenterX - gridCenterX; playerGrid.y = 1400; enemyGrid.x = screenCenterX - gridCenterX; enemyGrid.y = 400; // Store original positions for battle phase repositioning playerGrid.originalX = playerGrid.x; playerGrid.originalY = playerGrid.y; playerGrid.originalScaleX = playerGrid.scaleX; playerGrid.originalScaleY = playerGrid.scaleY; game.addChild(playerGrid); game.addChild(enemyGrid); // Hide enemy grid during placement phase enemyGrid.visible = false; // Update labels position enemyLabel.x = enemyGrid.x + gridSize * 60 * baseScale / 2; enemyLabel.y = enemyGrid.y - 60; playerLabel.x = playerGrid.x + gridSize * 60 * baseScale / 2; playerLabel.y = playerGrid.y - 60; // Add separator line between player and enemy grids var separatorLine = game.attachAsset('gridLine', { width: 2048, height: 4, x: 0, y: (enemyGrid.y + gridSize * 60 * baseScale + playerGrid.y) / 2, color: 0xFFFFFF }); // Reset game state gamePhase = 'placement'; currentShipIndex = 0; // Initial setup updateStatusText(); updateAttackRightsDisplay(); } // Control pad variables var controlPadActive = false; var controlPadContainer = new Container(); var controlPadKnob = null; var controlPadBaseCenter = { x: 0, y: 0 }; var controlPadMaxDistance = 120; var cursorSpeed = 12; var lastControlPadUpdate = 0; // Create cursor/crosshair system var cursorContainer = new Container(); game.addChild(cursorContainer); // Create control pad controlPadContainer.x = 2048 / 2; controlPadContainer.y = 2732 - 450; controlPadContainer.scaleX = 1.5; controlPadContainer.scaleY = 1.5; controlPadContainer.visible = false; game.addChild(controlPadContainer); // Control pad border var controlPadBorder = controlPadContainer.attachAsset('controlPadBorder', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); // Control pad base var controlPadBase = controlPadContainer.attachAsset('controlPadBase', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6 }); // Control pad knob controlPadKnob = controlPadContainer.attachAsset('controlPadKnob', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); // Store base center position controlPadBaseCenter.x = 0; controlPadBaseCenter.y = 0; // Create crosshair targeting system for better aiming var crosshairOuter = cursorContainer.attachAsset('cursorRing', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8, scaleX: 1.5, scaleY: 1.5 }); var crosshairHorizontal = cursorContainer.attachAsset('crosshairH', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 1.2, scaleY: 1.2 }); var crosshairVertical = cursorContainer.attachAsset('crosshairV', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 1.2, scaleY: 1.2 }); var crosshairCenter = cursorContainer.attachAsset('cursorCenter', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0, scaleX: 2.0, scaleY: 2.0 }); // Add crosshair inner ring for precision targeting var crosshairInner = cursorContainer.attachAsset('cursorRing', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6, scaleX: 0.7, scaleY: 0.7 }); // Initialize cursor position cursorContainer.x = 2048 / 2; cursorContainer.y = 2732 / 2; cursorContainer.visible = false; // Initially hidden // Add subtle pulse animation to cursor ring for better visibility var cursorPulseDirection = 1; var cursorPulseTimer = 0; function updateCursorPulse() { cursorPulseTimer++; if (cursorPulseTimer % 40 === 0) { // Every 0.67 seconds at 60fps for smoother targeting pulse if (cursorPulseDirection === 1) { // Pulse outer crosshair ring tween(crosshairOuter, { scaleX: 1.8, scaleY: 1.8, alpha: 0.4 }, { duration: 600, easing: tween.easeInOut }); // Pulse crosshair center for precision feedback tween(crosshairCenter, { scaleX: 2.5, scaleY: 2.5, alpha: 0.7 }, { duration: 600, easing: tween.easeInOut }); cursorPulseDirection = -1; } else { tween(crosshairOuter, { scaleX: 1.5, scaleY: 1.5, alpha: 0.8 }, { duration: 600, easing: tween.easeInOut }); tween(crosshairCenter, { scaleX: 2.0, scaleY: 2.0, alpha: 1.0 }, { duration: 600, easing: tween.easeInOut }); cursorPulseDirection = 1; } } } // Hide all game elements initially playerGrid.visible = false; enemyGrid.visible = false; statusText.visible = false; turnText.visible = false; enemyLabel.visible = false; playerLabel.visible = false; rotateButton.visible = false; autoPlaceButton.visible = false; startBattleButton.visible = false; airBombardmentButton.visible = false; submarineAttackButton.visible = false; sihaAttackButton.visible = false; attackRightsContainer.visible = false; playerFleetStatus.visible = false; enemyFleetStatus.visible = false; shipPreviewContainer.visible = false; // Control pad event handlers controlPadContainer.down = function (x, y, obj) { if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) { controlPadActive = true; // Use local coordinates for better control var localPos = { x: x, y: y }; // Calculate distance and constrain properly var distance = Math.sqrt(localPos.x * localPos.x + localPos.y * localPos.y); if (distance > controlPadMaxDistance) { var angle = Math.atan2(localPos.y, localPos.x); localPos.x = Math.cos(angle) * controlPadMaxDistance; localPos.y = Math.sin(angle) * controlPadMaxDistance; } controlPadKnob.x = localPos.x; controlPadKnob.y = localPos.y; } }; controlPadContainer.up = function (x, y, obj) { // If this was a quick tap (not a drag), try to fire at selected target if (controlPadActive && gamePhase === 'battle' && playerTurn) { var tapDistance = Math.sqrt(controlPadKnob.x * controlPadKnob.x + controlPadKnob.y * controlPadKnob.y); if (tapDistance < 20) { // Quick tap threshold - fire at selected target if valid if (selectedTarget && targetSelectionActive && !selectedTarget.cell.isHit && !selectedTarget.cell.isMiss) { // Enhanced target confirmation feedback tween(crosshairCenter, { scaleX: 4.0, scaleY: 4.0, alpha: 0.8 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { // Fire at the selected target handlePlayerShot(selectedTarget.row, selectedTarget.col); } }); // Add visual confirmation flash tween(crosshairOuter, { scaleX: 3.5, scaleY: 3.5, alpha: 0.3 }, { duration: 150, easing: tween.easeIn }); } else { // Try to fire at current cursor position as fallback if (enemyGrid.visible) { var localX = cursorContainer.x - enemyGrid.x; var localY = cursorContainer.y - enemyGrid.y; var cellSize = 60 * enemyGrid.scaleX; if (localX >= 0 && localX < gridSize * cellSize && localY >= 0 && localY < gridSize * cellSize) { var gridCol = Math.floor(localX / cellSize); var gridRow = Math.floor(localY / cellSize); if (gridRow >= 0 && gridRow < gridSize && gridCol >= 0 && gridCol < gridSize) { var targetCell = enemyGrid.cells[gridRow][gridCol]; if (!targetCell.isHit && !targetCell.isMiss) { handlePlayerShot(gridRow, gridCol); } } } } } } } controlPadActive = false; // Animate knob back to center tween(controlPadKnob, { x: 0, y: 0 }, { duration: 200, easing: tween.easeOut }); }; controlPadContainer.move = function (x, y, obj) { if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) { // Convert coordinates to local space properly var localPos = { x: x, y: y }; // Calculate distance from center var distance = Math.sqrt(localPos.x * localPos.x + localPos.y * localPos.y); // Constrain knob within the control pad with smooth movement if (distance > controlPadMaxDistance) { var angle = Math.atan2(localPos.y, localPos.x); localPos.x = Math.cos(angle) * controlPadMaxDistance; localPos.y = Math.sin(angle) * controlPadMaxDistance; } // Smooth knob movement for better responsiveness controlPadKnob.x = localPos.x; controlPadKnob.y = localPos.y; // Move cursor directly based on knob position var knobOffsetX = controlPadKnob.x / controlPadMaxDistance; var knobOffsetY = controlPadKnob.y / controlPadMaxDistance; var dynamicSpeed = cursorSpeed * 2; // Increased responsiveness cursorContainer.x += knobOffsetX * dynamicSpeed; cursorContainer.y += knobOffsetY * dynamicSpeed; // Keep cursor within screen bounds cursorContainer.x = Math.max(20, Math.min(2028, cursorContainer.x)); cursorContainer.y = Math.max(20, Math.min(2712, cursorContainer.y)); // Set control pad as active when moving controlPadActive = true; } }; // Target selection variables var selectedTarget = null; var targetSelectionActive = false; var lastSelectedCell = null; var availableTargets = []; var currentTargetIndex = 0; var targetSelectorActive = false; // Add target selector down handler for firing at selected target game.down = function (x, y, obj) { if (targetSelectorActive && gamePhase === 'battle' && playerTurn) { fireAtSelectedTarget(); return; } }; // Add cursor movement handler with enhanced aiming for enemy waters game.move = function (x, y, obj) { // Handle target selector cycling on screen touch/click if (targetSelectorActive && gamePhase === 'battle' && playerTurn) { cycleToNextTarget(); return; } // Update cursor position based on control pad if active, otherwise use mouse/touch if (!controlPadActive) { cursorContainer.x = x; cursorContainer.y = y; } // Show cursor during battle phase if (gamePhase === 'battle') { cursorContainer.visible = true; // Enhanced targeting for enemy waters if (enemyGrid.visible) { // Convert screen coordinates to grid coordinates var localX = cursorContainer.x - enemyGrid.x; var localY = cursorContainer.y - enemyGrid.y; var cellSize = 60 * enemyGrid.scaleX; // Check if cursor is over enemy grid if (localX >= 0 && localX < gridSize * cellSize && localY >= 0 && localY < gridSize * cellSize) { var gridCol = Math.floor(localX / cellSize); var gridRow = Math.floor(localY / cellSize); // Check if valid target if (gridRow >= 0 && gridRow < gridSize && gridCol >= 0 && gridCol < gridSize) { var targetCell = enemyGrid.cells[gridRow][gridCol]; var currentCellKey = gridRow + '_' + gridCol; // Check if we've moved to a new cell for target selection if (lastSelectedCell !== currentCellKey) { lastSelectedCell = currentCellKey; selectedTarget = { row: gridRow, col: gridCol, cell: targetCell }; targetSelectionActive = true; // Stop any ongoing crosshair animations tween.stop(crosshairCenter); tween.stop(crosshairOuter); tween.stop(crosshairHorizontal); tween.stop(crosshairVertical); tween.stop(crosshairInner); } if (!targetCell.isHit && !targetCell.isMiss) { // Enhanced aiming for enemy waters - bright targeting crosshair with pulsing effect crosshairHorizontal.tint = 0x00ffff; crosshairVertical.tint = 0x00ffff; crosshairCenter.tint = 0xff4444; crosshairOuter.tint = 0x00ff88; crosshairInner.tint = 0xffff00; // Enhanced aiming animation with prominent scaling tween(crosshairCenter, { scaleX: 4.0, scaleY: 4.0, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); tween(crosshairOuter, { scaleX: 3.5, scaleY: 3.5, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); tween(crosshairHorizontal, { scaleX: 3.0, scaleY: 3.0, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); tween(crosshairVertical, { scaleX: 3.0, scaleY: 3.0, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); tween(crosshairInner, { scaleX: 1.8, scaleY: 1.8, alpha: 1.0 }, { duration: 300, easing: tween.easeOut }); } else { // Already targeted - red crosshair with warning colors crosshairHorizontal.tint = 0xff0000; crosshairVertical.tint = 0xff0000; crosshairCenter.tint = 0xff0000; crosshairOuter.tint = 0xff0000; crosshairInner.tint = 0xff0000; // Scale up but reduce opacity for invalid targets tween(crosshairCenter, { scaleX: 2.5, scaleY: 2.5, alpha: 0.8 }, { duration: 200, easing: tween.easeOut }); tween(crosshairOuter, { scaleX: 1.8, scaleY: 1.8, alpha: 0.7 }, { duration: 200, easing: tween.easeOut }); } } else { // Outside enemy grid targeting area - neutral visibility crosshairHorizontal.tint = 0x888888; crosshairVertical.tint = 0x888888; crosshairCenter.tint = 0x888888; crosshairOuter.tint = 0x888888; crosshairInner.tint = 0x888888; selectedTarget = null; targetSelectionActive = false; lastSelectedCell = null; tween(crosshairCenter, { scaleX: 1.8, scaleY: 1.8, alpha: 0.7 }, { duration: 200, easing: tween.easeOut }); tween(crosshairOuter, { scaleX: 1.3, scaleY: 1.3, alpha: 0.6 }, { duration: 200, easing: tween.easeOut }); } } else { // Outside enemy waters - dim targeting crosshair crosshairHorizontal.tint = 0x666666; crosshairVertical.tint = 0x666666; crosshairCenter.tint = 0x666666; crosshairOuter.tint = 0x666666; crosshairInner.tint = 0x666666; selectedTarget = null; targetSelectionActive = false; lastSelectedCell = null; tween(crosshairCenter, { scaleX: 1.5, scaleY: 1.5, alpha: 0.4 }, { duration: 200, easing: tween.easeOut }); tween(crosshairOuter, { scaleX: 1.2, scaleY: 1.2, alpha: 0.3 }, { duration: 200, easing: tween.easeOut }); tween(crosshairHorizontal, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 200, easing: tween.easeOut }); tween(crosshairVertical, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 200, easing: tween.easeOut }); } } } else { // Hide cursor during other phases cursorContainer.visible = false; selectedTarget = null; targetSelectionActive = false; lastSelectedCell = null; } }; // Play background music from game start LK.playMusic('deniz'); // Show info page initially gameInfoContainer.visible = true; game.update = function () { if (!gameInfoShown) { // Show info page gameInfoContainer.visible = true; difficultyContainer.visible = false; } else if (!difficultySelected) { // Show difficulty selection gameInfoContainer.visible = false; difficultyContainer.visible = true; } else if (difficultySelected) { // Show game elements once difficulty is selected gameInfoContainer.visible = false; difficultyContainer.visible = false; playerGrid.visible = true; enemyGrid.visible = gamePhase === 'battle'; statusText.visible = true; turnText.visible = true; enemyLabel.visible = gamePhase === 'battle'; playerLabel.visible = true; rotateButton.visible = gamePhase === 'placement'; autoPlaceButton.visible = gamePhase === 'placement'; startBattleButton.visible = gamePhase === 'placement' && currentShipIndex >= shipSizes.length; shipPreviewContainer.visible = gamePhase === 'placement' && currentShipIndex < shipSizes.length; playerFleetStatus.visible = true; enemyFleetStatus.visible = true; // Update cursor visibility and animation if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) { cursorContainer.visible = true; controlPadContainer.visible = true; updateCursorPulse(); // Continuous cursor movement based on control pad position if (controlPadContainer.visible) { var knobOffsetX = controlPadKnob.x / controlPadMaxDistance; var knobOffsetY = controlPadKnob.y / controlPadMaxDistance; // Calculate movement speed based on knob distance for variable sensitivity var knobDistance = Math.sqrt(knobOffsetX * knobOffsetX + knobOffsetY * knobOffsetY); // Only move cursor if knob is displaced significantly if (knobDistance > 0.05) { var dynamicSpeed = cursorSpeed * (0.5 + knobDistance * 1.0); // Smooth speed scaling // Move cursor based on knob position cursorContainer.x += knobOffsetX * dynamicSpeed; cursorContainer.y += knobOffsetY * dynamicSpeed; // Keep cursor within screen bounds cursorContainer.x = Math.max(20, Math.min(2028, cursorContainer.x)); cursorContainer.y = Math.max(20, Math.min(2712, cursorContainer.y)); } } } else { cursorContainer.visible = false; controlPadContainer.visible = false; } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var GameGrid = Container.expand(function (isPlayerGrid) {
var self = Container.call(this);
self.isPlayerGrid = isPlayerGrid;
self.cells = [];
self.ships = [];
var currentGridSize = gridSize; // Use global gridSize variable
var cellSize = 60;
// Initialize grid cells
for (var row = 0; row < currentGridSize; row++) {
self.cells[row] = [];
for (var col = 0; col < currentGridSize; col++) {
var cell = new GridCell(row, col, isPlayerGrid);
cell.x = col * cellSize;
cell.y = row * cellSize;
self.cells[row][col] = cell;
self.addChild(cell);
}
}
// Draw grid lines
for (var i = 0; i <= currentGridSize; i++) {
// Vertical lines
var vLine = self.attachAsset('gridLine', {
width: 2,
height: currentGridSize * cellSize,
x: i * cellSize,
y: 0
});
// Horizontal lines
var hLine = self.attachAsset('gridLine', {
width: currentGridSize * cellSize,
height: 2,
x: 0,
y: i * cellSize
});
}
self.placeShip = function (startRow, startCol, length, isHorizontal, shipType) {
var shipCells = [];
// Check if placement is valid
for (var i = 0; i < length; i++) {
var row = isHorizontal ? startRow : startRow + i;
var col = isHorizontal ? startCol + i : startCol;
if (row >= currentGridSize || col >= currentGridSize || self.cells[row][col].hasShip) {
return false;
}
shipCells.push({
row: row,
col: col
});
}
// Place ship
var ship = {
cells: shipCells,
hits: 0,
sunk: false,
type: shipType || 'cruiser',
length: length,
isHorizontal: isHorizontal,
shipGraphic: null
};
// Create unified ship graphic that spans all cells
if (self.isPlayerGrid) {
var cellSize = 60;
var shipWidth = isHorizontal ? length * cellSize - 8 : cellSize - 8;
var shipHeight = isHorizontal ? cellSize - 8 : length * cellSize - 8;
var shipX = startCol * cellSize + 4;
var shipY = startRow * cellSize + 4;
ship.shipGraphic = self.attachAsset(shipType || 'cruiser', {
width: shipWidth,
height: shipHeight,
x: shipX,
y: shipY
});
}
// Mark cells as having ship but don't create individual graphics
for (var j = 0; j < shipCells.length; j++) {
var cellPos = shipCells[j];
var cell = self.cells[cellPos.row][cellPos.col];
cell.hasShip = true;
}
self.ships.push(ship);
return true;
};
self.checkHit = function (row, col) {
var cell = self.cells[row][col];
if (cell.hasShip) {
cell.markHit();
// Find which ship was hit
for (var i = 0; i < self.ships.length; i++) {
var ship = self.ships[i];
for (var j = 0; j < ship.cells.length; j++) {
if (ship.cells[j].row === row && ship.cells[j].col === col) {
ship.hits++;
if (ship.hits === ship.cells.length && !ship.sunk) {
ship.sunk = true;
LK.getSound('sunk').play();
// Add fireworks effect for sunk ship
self.createFireworks(ship.cells);
updateFleetStatus();
return 'sunk';
}
return 'hit';
}
}
}
} else {
cell.markMiss();
return 'miss';
}
};
self.allShipsSunk = function () {
for (var i = 0; i < self.ships.length; i++) {
if (!self.ships[i].sunk) {
return false;
}
}
return true;
};
self.createFireworks = function (shipCells) {
var cellSize = 60;
for (var i = 0; i < shipCells.length; i++) {
var cellPos = shipCells[i];
var centerX = cellPos.col * cellSize + cellSize / 2;
var centerY = cellPos.row * cellSize + cellSize / 2;
// Create multiple firework particles
for (var f = 0; f < 5; f++) {
var firework = self.attachAsset('firework', {
anchorX: 0.5,
anchorY: 0.5,
x: centerX,
y: centerY,
alpha: 1,
scaleX: 0.5,
scaleY: 0.5
});
var angle = f / 5 * Math.PI * 2;
var distance = 50 + Math.random() * 30;
var targetX = centerX + Math.cos(angle) * distance;
var targetY = centerY + Math.sin(angle) * distance;
tween(firework, {
x: targetX,
y: targetY,
scaleX: 1.2,
scaleY: 1.2,
alpha: 0
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
firework.destroy();
}
});
}
}
};
return self;
});
var GridCell = Container.expand(function (row, col, isPlayerGrid) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.isPlayerGrid = isPlayerGrid;
self.hasShip = false;
self.isHit = false;
self.isMiss = false;
var cellSize = 60;
var waterTile = self.attachAsset('water', {
width: cellSize,
height: cellSize,
x: 0,
y: 0,
color: 0xffffff
});
var shipGraphic = null;
var hitMarker = null;
var missMarker = null;
self.placeShip = function (shipType, segmentIndex, totalLength, isHorizontal) {
// Only show ship graphics on player's own grid, hide enemy ships
if (!shipGraphic && self.isPlayerGrid) {
shipType = shipType || 'cruiser';
// Create single unified ship graphic that spans the entire ship length
var shipWidth = isHorizontal ? totalLength * cellSize - 8 : cellSize - 8;
var shipHeight = isHorizontal ? cellSize - 8 : totalLength * cellSize - 8;
// Calculate position to center the ship across all its cells
var shipX = isHorizontal ? segmentIndex * cellSize + 4 - segmentIndex * cellSize : 4;
var shipY = isHorizontal ? 4 : segmentIndex * cellSize + 4 - segmentIndex * cellSize;
// Only create the ship graphic on the first segment (bow)
if (segmentIndex === 0) {
shipGraphic = self.attachAsset(shipType, {
width: shipWidth,
height: shipHeight,
x: shipX,
y: shipY
});
}
}
self.hasShip = true;
};
self.removeShip = function () {
// Ship graphics are now handled at the GameGrid level
// Just mark the cell as not having a ship
self.hasShip = false;
};
self.markHit = function () {
if (!self.isHit) {
hitMarker = self.attachAsset('hit', {
anchorX: 0.5,
anchorY: 0.5,
x: cellSize / 2,
y: cellSize / 2
});
self.isHit = true;
LK.getSound('hit').play();
LK.getSound('shoot').play();
// Add explosion effect
var explosion = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: cellSize / 2,
y: cellSize / 2,
alpha: 0
});
tween(explosion, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
tween(explosion, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
explosion.destroy();
}
});
}
});
}
};
self.markMiss = function () {
if (!self.isMiss) {
missMarker = self.attachAsset('miss', {
anchorX: 0.5,
anchorY: 0.5,
x: cellSize / 2,
y: cellSize / 2
});
self.isMiss = true;
LK.getSound('miss').play();
// Add missile effect for miss
var missile = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 1,
x: cellSize / 2,
y: -50,
alpha: 0.8
});
LK.getSound('shoot').play();
tween(missile, {
y: cellSize / 2,
alpha: 0.3
}, {
duration: 400,
onFinish: function onFinish() {
missile.destroy();
}
});
}
};
self.down = function (x, y, obj) {
if (gamePhase === 'placement' && self.isPlayerGrid) {
handleShipPlacement(self.row, self.col);
} else if (gamePhase === 'battle' && !self.isPlayerGrid && !self.isHit && !self.isMiss) {
handlePlayerShot(self.row, self.col);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Gun turrets
// Deck details
// Hull details
// Submarine - smallest
// Destroyer - smaller
// Cruiser - medium
// Battleship - large
// Aircraft Carrier - long and wide
// Game state
var gamePhase = 'placement'; // 'placement', 'battle', 'gameOver'
var currentShipIndex = 0;
var isHorizontal = true;
var playerTurn = true;
var aiTargets = [];
var aiLastHit = null;
var aiHuntMode = false;
var airBombardmentUsed = false;
var airBombardmentInProgress = false;
var submarineAttackUsed = false;
var submarineAttackInProgress = false;
var sihaAttackUsed = false;
var sihaAttackInProgress = false;
var lastAttackType = null; // Track the last attack type to prevent consecutive use
var aiAttackOptions = ['air', 'submarine', 'siha']; // Available AI attack options
var aiLastAttackType = null; // Track AI's last attack type
var aiAttackCooldowns = {
air: false,
submarine: false,
siha: false
}; // Track which AI attacks have been used
// Attack rights tracking
var playerAttackRights = {
air: 2,
submarine: 2,
siha: 2
};
var aiAttackRights = {
air: 2,
submarine: 2,
siha: 2
};
// Ship sizes to place - realistic naval fleet
var shipSizes = [5, 4, 3, 3, 2]; // Carrier, Battleship, Cruiser, Cruiser, Destroyer
var shipTypes = ['Uçak Gemisi', 'Savaş Gemisi', 'Kruvazör', 'Kruvazör', 'Muhrip'];
var shipAssets = ['carrier', 'battleship', 'cruiser', 'cruiser', 'destroyer'];
// Create grids
var playerGrid = new GameGrid(true);
var enemyGrid = new GameGrid(false);
// Scale up grids for better visibility - increased for closer view
playerGrid.scaleX = 2.0;
playerGrid.scaleY = 2.0;
enemyGrid.scaleX = 2.0;
enemyGrid.scaleY = 2.0;
// Center grids on screen
var gridWidth = 8 * 60 * 2.0; // 8 cells * 60px * scale
var screenCenterX = 2048 / 2;
var gridCenterX = gridWidth / 2;
playerGrid.x = screenCenterX - gridCenterX;
playerGrid.y = 1300;
enemyGrid.x = screenCenterX - gridCenterX;
enemyGrid.y = 300;
game.addChild(playerGrid);
game.addChild(enemyGrid);
// Hide enemy grid during placement phase
enemyGrid.visible = false;
// UI Elements
var statusText = new Text2('Gemilerinizi yerleştirin. ' + shipSizes[0] + ' uzunluğunda gemi yerleştirmek için dokunun', {
size: 40,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0);
LK.gui.top.addChild(statusText);
var turnText = new Text2('', {
size: 35,
fill: 0xFFFF00
});
turnText.anchor.set(0.5, 0);
turnText.y = 80;
LK.gui.top.addChild(turnText);
// Labels for grids
var enemyLabel = new Text2('Düşman Suları', {
size: 45,
fill: 0xFF6666
});
enemyLabel.anchor.set(0.5, 0.5);
enemyLabel.x = enemyGrid.x + 8 * 60 * 1.5 / 2;
enemyLabel.y = enemyGrid.y - 60;
game.addChild(enemyLabel);
var playerLabel = new Text2('Filonuz', {
size: 45,
fill: 0x66FF66
});
playerLabel.anchor.set(0.5, 0.5);
playerLabel.x = playerGrid.x + 8 * 60 * 1.5 / 2;
playerLabel.y = playerGrid.y - 60;
game.addChild(playerLabel);
// Rotation button for ship placement
var rotateButton = new Text2('Gemiyi Çevir', {
size: 60,
fill: 0xFFFF00
});
rotateButton.anchor.set(0.5, 0.5);
rotateButton.x = 300;
rotateButton.y = 1200;
game.addChild(rotateButton);
rotateButton.down = function (x, y, obj) {
if (gamePhase === 'placement') {
isHorizontal = !isHorizontal;
updateStatusText();
updateShipPreview();
}
};
// Auto-placement button
var autoPlaceButton = new Text2('Otomatik Yerleştir', {
size: 60,
fill: 0x00FF00
});
autoPlaceButton.anchor.set(0.5, 0.5);
autoPlaceButton.x = 300;
autoPlaceButton.y = 1300;
game.addChild(autoPlaceButton);
autoPlaceButton.down = function (x, y, obj) {
if (gamePhase === 'placement') {
autoPlacePlayerShips();
}
};
// Start battle button
var startBattleButton = new Text2('Savaşı Başlat', {
size: 60,
fill: 0xFF0000
});
startBattleButton.anchor.set(0.5, 0.5);
startBattleButton.x = 300;
startBattleButton.y = 1400;
game.addChild(startBattleButton);
startBattleButton.down = function (x, y, obj) {
if (gamePhase === 'placement' && currentShipIndex >= shipSizes.length) {
placeAIShips();
gamePhase = 'battle';
rotateButton.visible = false;
autoPlaceButton.visible = false;
startBattleButton.visible = false;
enemyGrid.visible = true;
airBombardmentButton.visible = true;
submarineAttackButton.visible = true;
sihaAttackButton.visible = true;
// Move and scale down player grid to bottom left
tween(playerGrid, {
x: 50,
y: 2150,
scaleX: playerGrid.originalScaleX * 0.6,
scaleY: playerGrid.originalScaleY * 0.6
}, {
duration: 1000,
easing: tween.easeInOut
});
// Update player label position
tween(playerLabel, {
x: 50 + gridSize * 60 * playerGrid.originalScaleX * 0.6 / 2,
y: 2150 - 60
}, {
duration: 1000,
easing: tween.easeInOut
});
updateStatusText();
}
};
// Air bombardment button
var airBombardmentButton = new Container();
airBombardmentButton.x = 50;
airBombardmentButton.y = 700;
airBombardmentButton.visible = false;
game.addChild(airBombardmentButton);
// Button background
var airButtonBg = airBombardmentButton.attachAsset('water', {
width: 420,
height: 90,
x: -10,
y: -45,
color: 0xFF6600
});
airButtonBg.alpha = 0.9;
// Button border
var airButtonBorder = airBombardmentButton.attachAsset('gridLine', {
width: 424,
height: 94,
x: -12,
y: -47,
color: 0xFFFFFF
});
airButtonBorder.alpha = 0.8;
// Button text
var airButtonText = new Text2('🚁 Hava Bombardımanı', {
size: 42,
fill: 0xFFFFFF
});
airButtonText.anchor.set(0, 0.5);
airButtonText.x = 15;
airButtonText.y = 0;
airBombardmentButton.addChild(airButtonText);
// Button press effect
airBombardmentButton.down = function (x, y, obj) {
if (gamePhase === 'battle' && playerTurn && !airBombardmentUsed && !airBombardmentInProgress && lastAttackType !== 'air') {
// Press effect
tween(airBombardmentButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(airBombardmentButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
executeAirBombardment();
}
};
// Submarine attack button
var submarineAttackButton = new Container();
submarineAttackButton.x = 50;
submarineAttackButton.y = 1000;
submarineAttackButton.visible = false;
game.addChild(submarineAttackButton);
// Button background
var subButtonBg = submarineAttackButton.attachAsset('water', {
width: 420,
height: 90,
x: -10,
y: -45,
color: 0x0066CC
});
subButtonBg.alpha = 0.9;
// Button border
var subButtonBorder = submarineAttackButton.attachAsset('gridLine', {
width: 424,
height: 94,
x: -12,
y: -47,
color: 0xFFFFFF
});
subButtonBorder.alpha = 0.8;
// Button text
var subButtonText = new Text2('🚢 Denizaltı Saldırısı', {
size: 42,
fill: 0xFFFFFF
});
subButtonText.anchor.set(0, 0.5);
subButtonText.x = 15;
subButtonText.y = 0;
submarineAttackButton.addChild(subButtonText);
// Button press effect
submarineAttackButton.down = function (x, y, obj) {
if (gamePhase === 'battle' && playerTurn && !submarineAttackUsed && !submarineAttackInProgress && lastAttackType !== 'submarine') {
// Press effect
tween(submarineAttackButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(submarineAttackButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
executeSubmarineAttack();
}
};
// SIHA attack button
var sihaAttackButton = new Container();
sihaAttackButton.x = 50;
sihaAttackButton.y = 1300;
sihaAttackButton.visible = false;
game.addChild(sihaAttackButton);
// Button background
var sihaButtonBg = sihaAttackButton.attachAsset('water', {
width: 420,
height: 90,
x: -10,
y: -45,
color: 0x9900FF
});
sihaButtonBg.alpha = 0.9;
// Button border
var sihaButtonBorder = sihaAttackButton.attachAsset('gridLine', {
width: 424,
height: 94,
x: -12,
y: -47,
color: 0xFFFFFF
});
sihaButtonBorder.alpha = 0.8;
// Button text
var sihaButtonText = new Text2('🛩️ SİHA Saldırısı', {
size: 42,
fill: 0xFFFFFF
});
sihaButtonText.anchor.set(0, 0.5);
sihaButtonText.x = 15;
sihaButtonText.y = 0;
sihaAttackButton.addChild(sihaButtonText);
// Target selector button
var targetSelectorButton = new Container();
targetSelectorButton.x = 2048 / 2;
targetSelectorButton.y = 1600;
targetSelectorButton.visible = false;
game.addChild(targetSelectorButton);
// Button background
var targetButtonBg = targetSelectorButton.attachAsset('water', {
width: 420,
height: 90,
x: -210,
y: -45,
color: 0x00CCFF
});
targetButtonBg.alpha = 0.9;
// Button border
var targetButtonBorder = targetSelectorButton.attachAsset('gridLine', {
width: 424,
height: 94,
x: -212,
y: -47,
color: 0xFFFFFF
});
targetButtonBorder.alpha = 0.8;
// Button text
var targetButtonText = new Text2('🎯 Hedef Seçici', {
size: 42,
fill: 0xFFFFFF
});
targetButtonText.anchor.set(0.5, 0.5);
targetButtonText.x = 0;
targetButtonText.y = 0;
targetSelectorButton.addChild(targetButtonText);
// Button press effect
targetSelectorButton.down = function (x, y, obj) {
if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) {
// Press effect
tween(targetSelectorButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(targetSelectorButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
activateTargetSelector();
}
};
// Button press effect
sihaAttackButton.down = function (x, y, obj) {
if (gamePhase === 'battle' && playerTurn && !sihaAttackUsed && !sihaAttackInProgress && lastAttackType !== 'siha') {
// Press effect
tween(sihaAttackButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(sihaAttackButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
executeSihaAttack();
}
};
// Attack rights display
var attackRightsContainer = new Container();
attackRightsContainer.x = 50;
attackRightsContainer.y = playerGrid.y + 200;
game.addChild(attackRightsContainer);
var attackRightsTitle = new Text2('Saldırı Hakları', {
size: 60,
fill: 0xFFFFFF
});
attackRightsTitle.anchor.set(0, 0);
attackRightsTitle.x = 0;
attackRightsTitle.y = 0;
attackRightsContainer.addChild(attackRightsTitle);
// Player attack rights
var playerRightsTitle = new Text2('Oyuncu:', {
size: 50,
fill: 0x00FF00
});
playerRightsTitle.anchor.set(0, 0);
playerRightsTitle.x = 0;
playerRightsTitle.y = 60;
attackRightsContainer.addChild(playerRightsTitle);
var playerAirRightsText = new Text2('Hava: 2', {
size: 45,
fill: 0x00FF00
});
playerAirRightsText.anchor.set(0, 0);
playerAirRightsText.x = 0;
playerAirRightsText.y = 110;
attackRightsContainer.addChild(playerAirRightsText);
var playerSubRightsText = new Text2('Denizaltı: 2', {
size: 45,
fill: 0x00FF00
});
playerSubRightsText.anchor.set(0, 0);
playerSubRightsText.x = 0;
playerSubRightsText.y = 160;
attackRightsContainer.addChild(playerSubRightsText);
var playerSihaRightsText = new Text2('SİHA: 2', {
size: 45,
fill: 0x00FF00
});
playerSihaRightsText.anchor.set(0, 0);
playerSihaRightsText.x = 0;
playerSihaRightsText.y = 210;
attackRightsContainer.addChild(playerSihaRightsText);
// AI attack rights
var aiRightsTitle = new Text2('Düşman:', {
size: 50,
fill: 0xFF0000
});
aiRightsTitle.anchor.set(0, 0);
aiRightsTitle.x = 0;
aiRightsTitle.y = 280;
attackRightsContainer.addChild(aiRightsTitle);
var aiAirRightsText = new Text2('Hava: 2', {
size: 45,
fill: 0xFF0000
});
aiAirRightsText.anchor.set(0, 0);
aiAirRightsText.x = 0;
aiAirRightsText.y = 330;
attackRightsContainer.addChild(aiAirRightsText);
var aiSubRightsText = new Text2('Denizaltı: 2', {
size: 45,
fill: 0xFF0000
});
aiSubRightsText.anchor.set(0, 0);
aiSubRightsText.x = 0;
aiSubRightsText.y = 380;
attackRightsContainer.addChild(aiSubRightsText);
var aiSihaRightsText = new Text2('SİHA: 2', {
size: 45,
fill: 0xFF0000
});
aiSihaRightsText.anchor.set(0, 0);
aiSihaRightsText.x = 0;
aiSihaRightsText.y = 430;
attackRightsContainer.addChild(aiSihaRightsText);
function activateTargetSelector() {
if (!enemyGrid.visible || targetSelectorActive) return;
targetSelectorActive = true;
availableTargets = [];
currentTargetIndex = 0;
// Find all valid targets on enemy grid
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
var cell = enemyGrid.cells[row][col];
if (!cell.isHit && !cell.isMiss) {
availableTargets.push({
row: row,
col: col,
cell: cell
});
}
}
}
if (availableTargets.length === 0) {
targetSelectorActive = false;
return;
}
// Start with first available target
selectTarget(0);
// Update status text
statusText.setText('Hedef seçici aktif - Hedefleri geçmek için ekrana dokunun');
}
function selectTarget(index) {
if (availableTargets.length === 0) return;
currentTargetIndex = index % availableTargets.length;
selectedTarget = availableTargets[currentTargetIndex];
// Move cursor to selected target
var cellSize = 60 * enemyGrid.scaleX;
var targetX = enemyGrid.x + selectedTarget.col * cellSize + cellSize / 2;
var targetY = enemyGrid.y + selectedTarget.row * cellSize + cellSize / 2;
// Animate cursor to target with smooth movement
tween(cursorContainer, {
x: targetX,
y: targetY
}, {
duration: 400,
easing: tween.easeInOut
});
// Enhanced target highlighting with pulsing effect
tween(crosshairCenter, {
scaleX: 5.0,
scaleY: 5.0,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
tween(crosshairOuter, {
scaleX: 4.5,
scaleY: 4.5,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
// Color code for target selection
crosshairHorizontal.tint = 0x00ffff;
crosshairVertical.tint = 0x00ffff;
crosshairCenter.tint = 0xffff00;
crosshairOuter.tint = 0x00ff88;
crosshairInner.tint = 0xffff00;
targetSelectionActive = true;
}
function cycleToNextTarget() {
if (!targetSelectorActive || availableTargets.length === 0) return;
selectTarget(currentTargetIndex + 1);
}
function fireAtSelectedTarget() {
if (!targetSelectorActive || !selectedTarget) return;
targetSelectorActive = false;
targetSelectionActive = false;
// Enhanced firing confirmation effect
tween(crosshairCenter, {
scaleX: 8.0,
scaleY: 8.0,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
handlePlayerShot(selectedTarget.row, selectedTarget.col);
}
});
tween(crosshairOuter, {
scaleX: 6.0,
scaleY: 6.0,
alpha: 0.2
}, {
duration: 200,
easing: tween.easeIn
});
}
function updateAttackRightsDisplay() {
playerAirRightsText.setText('Hava: ' + playerAttackRights.air);
playerSubRightsText.setText('Denizaltı: ' + playerAttackRights.submarine);
playerSihaRightsText.setText('SİHA: ' + playerAttackRights.siha);
aiAirRightsText.setText('Hava: ' + aiAttackRights.air);
aiSubRightsText.setText('Denizaltı: ' + aiAttackRights.submarine);
aiSihaRightsText.setText('SİHA: ' + aiAttackRights.siha);
// Update button visibility based on available rights
if (gamePhase === 'battle') {
attackRightsContainer.visible = true;
airBombardmentButton.visible = playerAttackRights.air > 0 && lastAttackType !== 'air' && playerTurn;
submarineAttackButton.visible = playerAttackRights.submarine > 0 && lastAttackType !== 'submarine' && playerTurn;
sihaAttackButton.visible = playerAttackRights.siha > 0 && lastAttackType !== 'siha' && playerTurn;
targetSelectorButton.visible = playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress;
} else {
attackRightsContainer.visible = false;
targetSelectorButton.visible = false;
}
}
// Ship preview container for placement phase
var shipPreviewContainer = new Container();
shipPreviewContainer.x = 2048 / 2;
shipPreviewContainer.y = 1050; // Position above player grid (player grid is at y=1300)
game.addChild(shipPreviewContainer);
function updateShipPreview() {
// Clear existing preview
for (var i = shipPreviewContainer.children.length - 1; i >= 0; i--) {
shipPreviewContainer.children[i].destroy();
}
if (gamePhase === 'placement' && currentShipIndex < shipSizes.length) {
var shipLength = shipSizes[currentShipIndex];
var shipType = shipAssets[currentShipIndex];
var cellSize = 60;
// Create preview ship graphic
var previewWidth = isHorizontal ? shipLength * cellSize - 8 : cellSize - 8;
var previewHeight = isHorizontal ? cellSize - 8 : shipLength * cellSize - 8;
var previewX = isHorizontal ? -(previewWidth / 2) : -(previewWidth / 2);
var previewY = isHorizontal ? -(previewHeight / 2) : -(previewHeight / 2);
var shipPreview = shipPreviewContainer.attachAsset(shipType, {
width: previewWidth,
height: previewHeight,
x: previewX,
y: previewY,
alpha: 0.8
});
// Add ship name label
var shipNameText = new Text2(shipTypes[currentShipIndex], {
size: 35,
fill: 0xFFFFFF
});
shipNameText.anchor.set(0.5, 0.5);
shipNameText.x = 0;
shipNameText.y = previewHeight / 2 + 50;
shipPreviewContainer.addChild(shipNameText);
// Add orientation label
var orientationText = new Text2(isHorizontal ? 'Yatay' : 'Dikey', {
size: 30,
fill: 0xFFFF00
});
orientationText.anchor.set(0.5, 0.5);
orientationText.x = 0;
orientationText.y = previewHeight / 2 + 90;
shipPreviewContainer.addChild(orientationText);
}
}
function updateStatusText() {
if (gamePhase === 'placement') {
if (currentShipIndex < shipSizes.length) {
var orientation = isHorizontal ? 'yatay' : 'dikey';
var shipName = shipTypes[currentShipIndex];
statusText.setText(shipName + ' yerleştirin (' + shipSizes[currentShipIndex] + ' kare, ' + orientation + ')');
updateShipPreview();
} else {
statusText.setText('Tüm gemiler yerleştirildi! Savaşı başlatmak için butona tıklayın.');
shipPreviewContainer.visible = false;
}
} else if (gamePhase === 'battle') {
shipPreviewContainer.visible = false;
if (playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) {
var bombardmentText = playerAttackRights.air > 0 && lastAttackType !== 'air' ? ' | Hava bombardımanı mevcut!' : '';
var submarineText = playerAttackRights.submarine > 0 && lastAttackType !== 'submarine' ? ' | Denizaltı saldırısı mevcut!' : '';
var sihaText = playerAttackRights.siha > 0 && lastAttackType !== 'siha' ? ' | SİHA saldırısı mevcut!' : '';
statusText.setText('Sıra sizde - Düşman ızgarasına ateş edin!' + bombardmentText + submarineText + sihaText);
turnText.setText('SİZİN SIRANIZ');
} else if (airBombardmentInProgress) {
statusText.setText('Hava bombardımanı devam ediyor...');
turnText.setText('HAVA SALDIRISI');
airBombardmentButton.visible = false;
submarineAttackButton.visible = false;
sihaAttackButton.visible = false;
} else if (submarineAttackInProgress) {
statusText.setText('Denizaltı saldırısı devam ediyor...');
turnText.setText('DENİZALTI SALDIRISI');
airBombardmentButton.visible = false;
submarineAttackButton.visible = false;
sihaAttackButton.visible = false;
} else if (sihaAttackInProgress) {
statusText.setText('SİHA saldırısı devam ediyor...');
turnText.setText('SİHA SALDIRISI');
airBombardmentButton.visible = false;
submarineAttackButton.visible = false;
sihaAttackButton.visible = false;
} else {
var aiHasAttacks = aiAttackRights.air > 0 || aiAttackRights.submarine > 0 || aiAttackRights.siha > 0;
var aiAttackText = aiHasAttacks && aiLastAttackType !== 'regular' ? ' (Özel saldırı hazırlanıyor...)' : '';
statusText.setText('Düşman düşünüyor...' + aiAttackText);
turnText.setText('DÜŞMAN SIRASI');
}
}
updateAttackRightsDisplay();
}
function handleShipPlacement(row, col) {
if (currentShipIndex >= shipSizes.length) return;
var shipLength = shipSizes[currentShipIndex];
var shipType = shipAssets[currentShipIndex];
if (playerGrid.placeShip(row, col, shipLength, isHorizontal, shipType)) {
currentShipIndex++;
updateFleetStatus();
if (currentShipIndex >= shipSizes.length) {
// All ships placed, start AI placement
placeAIShips();
gamePhase = 'battle';
rotateButton.visible = false;
autoPlaceButton.visible = false;
enemyGrid.visible = true;
updateStatusText();
} else {
updateStatusText();
}
}
}
function autoPlacePlayerShips() {
// Clear existing ships and their graphics
for (var i = 0; i < playerGrid.ships.length; i++) {
var ship = playerGrid.ships[i];
if (ship.shipGraphic) {
ship.shipGraphic.destroy();
ship.shipGraphic = null;
}
for (var j = 0; j < ship.cells.length; j++) {
var cellPos = ship.cells[j];
playerGrid.cells[cellPos.row][cellPos.col].removeShip();
}
}
playerGrid.ships = [];
// Clear all hit and miss markers from the board
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
var cell = playerGrid.cells[row][col];
cell.isHit = false;
cell.isMiss = false;
// Remove any visual markers that might exist
if (cell.hitMarker) {
cell.hitMarker.destroy();
cell.hitMarker = null;
}
if (cell.missMarker) {
cell.missMarker.destroy();
cell.missMarker = null;
}
}
}
// Reset ship placement index
currentShipIndex = 0;
var playerShipSizes = [5, 4, 3, 3, 2];
var playerShipTypes = ['carrier', 'battleship', 'cruiser', 'cruiser', 'destroyer'];
for (var i = 0; i < playerShipSizes.length; i++) {
var placed = false;
var attempts = 0;
while (!placed && attempts < 100) {
var row = Math.floor(Math.random() * gridSize);
var col = Math.floor(Math.random() * gridSize);
var horizontal = Math.random() < 0.5;
if (playerGrid.placeShip(row, col, playerShipSizes[i], horizontal, playerShipTypes[i])) {
placed = true;
currentShipIndex++;
}
attempts++;
}
}
// Update status text to show current placement state
updateStatusText();
updateFleetStatus();
}
function placeAIShips() {
var aiShipSizes = [5, 4, 3, 3, 2];
var aiShipTypes = ['carrier', 'battleship', 'cruiser', 'cruiser', 'destroyer'];
for (var i = 0; i < aiShipSizes.length; i++) {
var placed = false;
var attempts = 0;
while (!placed && attempts < 100) {
var row = Math.floor(Math.random() * gridSize);
var col = Math.floor(Math.random() * gridSize);
var horizontal = Math.random() < 0.5;
if (enemyGrid.placeShip(row, col, aiShipSizes[i], horizontal, aiShipTypes[i])) {
placed = true;
}
attempts++;
}
}
}
updateFleetStatus();
function handlePlayerShot(row, col) {
if (!playerTurn) return;
lastAttackType = 'regular'; // Set last attack type for regular shots
// Clear target selection after firing
selectedTarget = null;
targetSelectionActive = false;
lastSelectedCell = null;
targetSelectorActive = false;
availableTargets = [];
// Play enhanced shooting sound effect with target confirmation
LK.getSound('shoot').play();
var result = enemyGrid.checkHit(row, col);
if (result === 'hit' || result === 'sunk') {
LK.setScore(LK.getScore() + (result === 'sunk' ? 100 : 50));
if (enemyGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Zafer! Tüm düşman gemileri yok edildi!');
turnText.setText('KAZANDINIZ!');
LK.showYouWin();
return;
}
}
playerTurn = false;
airBombardmentButton.visible = false;
submarineAttackButton.visible = false;
sihaAttackButton.visible = false;
updateStatusText();
// AI turn after delay
LK.setTimeout(function () {
aiTurn();
}, 1000);
}
function executeAirBombardment() {
if (playerAttackRights.air <= 0 || airBombardmentInProgress) return;
playerAttackRights.air--;
airBombardmentInProgress = true;
lastAttackType = 'air'; // Set last attack type
playerTurn = false;
updateAttackRightsDisplay();
statusText.setText('Hava bombardımanı başlatıldı! Uçaklar hedefe yaklaşıyor...');
turnText.setText('HAVA SALDIRISI');
// Generate 5 random target positions
var targets = [];
var attempts = 0;
while (targets.length < 5 && attempts < 100) {
var row = Math.floor(Math.random() * gridSize);
var col = Math.floor(Math.random() * gridSize);
var duplicate = false;
for (var i = 0; i < targets.length; i++) {
if (targets[i].row === row && targets[i].col === col) {
duplicate = true;
break;
}
}
if (!duplicate) {
targets.push({
row: row,
col: col
});
}
attempts++;
}
// Create aircraft animation
var aircraft = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
x: -100,
y: 200,
scaleX: 2,
scaleY: 2,
rotation: Math.PI / 4
});
// Animate aircraft flying across screen
tween(aircraft, {
x: 2148,
y: 300
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
aircraft.destroy();
// Execute bombardment hits with delays
executeTargetHits(targets, 0);
}
});
}
function executeTargetHits(targets, currentIndex) {
if (currentIndex >= targets.length) {
// All hits completed
LK.setTimeout(function () {
airBombardmentInProgress = false;
if (enemyGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Zafer! Tüm düşman gemileri yok edildi!');
turnText.setText('KAZANDINIZ!');
LK.showYouWin();
return;
}
// AI turn after air bombardment
aiLastAttackType = null; // Reset AI attack type to allow AI special attacks
LK.setTimeout(function () {
aiTurn();
}, 1000);
}, 1000);
return;
}
var target = targets[currentIndex];
// Create bomb falling animation
var bomb = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 1,
x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: 100,
alpha: 0.8
});
tween(bomb, {
y: enemyGrid.y + target.row * 60 * 1.5 + 30 * 1.5,
alpha: 0.3
}, {
duration: 600,
onFinish: function onFinish() {
bomb.destroy();
// Check hit result
var result = enemyGrid.checkHit(target.row, target.col);
if (result === 'hit' || result === 'sunk') {
LK.setScore(LK.getScore() + (result === 'sunk' ? 100 : 50));
}
// Continue with next target after short delay
LK.setTimeout(function () {
executeTargetHits(targets, currentIndex + 1);
}, 300);
}
});
}
function executeSubmarineAttack() {
if (playerAttackRights.submarine <= 0 || submarineAttackInProgress) return;
playerAttackRights.submarine--;
submarineAttackInProgress = true;
lastAttackType = 'submarine'; // Set last attack type
playerTurn = false;
updateAttackRightsDisplay();
statusText.setText('Denizaltı saldırısı başlatıldı! Torpido hazırlanıyor...');
turnText.setText('DENİZALTI SALDIRISI');
// Find all enemy ships that are not yet sunk
var availableTargets = [];
for (var i = 0; i < enemyGrid.ships.length; i++) {
var ship = enemyGrid.ships[i];
if (!ship.sunk) {
// Add all unhit cells of this ship as potential targets
for (var j = 0; j < ship.cells.length; j++) {
var cellPos = ship.cells[j];
var cell = enemyGrid.cells[cellPos.row][cellPos.col];
if (!cell.isHit) {
availableTargets.push({
row: cellPos.row,
col: cellPos.col
});
}
}
}
}
// If no available targets (all ships sunk or all remaining cells hit), just end
if (availableTargets.length === 0) {
submarineAttackInProgress = false;
playerTurn = true;
updateStatusText();
return;
}
// Select random target from available unhit ship cells
var target = availableTargets[Math.floor(Math.random() * availableTargets.length)];
// Create submarine animation from bottom of screen
var submarine = game.attachAsset('submarine', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: 2732 + 100,
scaleX: 2,
scaleY: 2,
alpha: 0.7
});
// Animate submarine rising
tween(submarine, {
y: enemyGrid.y + target.row * 60 * 1.5 + 200,
alpha: 1
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create torpedo
var torpedo = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
x: submarine.x,
y: submarine.y,
scaleX: 1.5,
scaleY: 1.5,
rotation: -Math.PI / 2,
alpha: 0.9
});
// Animate torpedo to target
tween(torpedo, {
x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: enemyGrid.y + target.row * 60 * 1.5 + 30 * 1.5,
alpha: 0.5
}, {
duration: 800,
easing: tween.linear,
onFinish: function onFinish() {
torpedo.destroy();
// Guaranteed hit on ship
var result = enemyGrid.checkHit(target.row, target.col);
LK.setScore(LK.getScore() + (result === 'sunk' ? 150 : 75));
// Submarine disappears
tween(submarine, {
y: 2732 + 100,
alpha: 0
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
submarine.destroy();
submarineAttackInProgress = false;
if (enemyGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Zafer! Tüm düşman gemileri yok edildi!');
turnText.setText('KAZANDINIZ!');
LK.showYouWin();
return;
}
// AI turn after submarine attack
aiLastAttackType = null; // Reset AI attack type to allow AI special attacks
LK.setTimeout(function () {
aiTurn();
}, 1000);
}
});
}
});
}
});
}
function executeSihaAttack() {
if (playerAttackRights.siha <= 0 || sihaAttackInProgress) return;
playerAttackRights.siha--;
sihaAttackInProgress = true;
lastAttackType = 'siha'; // Set last attack type
playerTurn = false;
updateAttackRightsDisplay();
statusText.setText('SİHA saldırısı başlatıldı! Hedef aranıyor...');
turnText.setText('SİHA SALDIRISI');
// Find all enemy ships that are not yet sunk
var availableShips = [];
for (var i = 0; i < enemyGrid.ships.length; i++) {
var ship = enemyGrid.ships[i];
if (!ship.sunk) {
availableShips.push(ship);
}
}
// If no available ships, just end
if (availableShips.length === 0) {
sihaAttackInProgress = false;
playerTurn = true;
updateStatusText();
return;
}
// Select random ship to completely destroy
var targetShip = availableShips[Math.floor(Math.random() * availableShips.length)];
var targetCells = [];
// Get all cells of the target ship
for (var j = 0; j < targetShip.cells.length; j++) {
targetCells.push(targetShip.cells[j]);
}
// Create SIHA drone animation from top of screen
var siha = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
x: -100,
y: -100,
scaleX: 1.8,
scaleY: 1.8,
rotation: Math.PI / 6,
alpha: 0.9
});
// Animate SIHA flying to target area
var targetCenterX = enemyGrid.x + targetCells[0].col * 60 * 1.5 + 30 * 1.5;
var targetCenterY = enemyGrid.y + targetCells[0].row * 60 * 1.5 + 30 * 1.5;
tween(siha, {
x: targetCenterX,
y: targetCenterY - 150,
rotation: 0
}, {
duration: 2500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Hover for targeting
tween(siha, {
y: targetCenterY - 100,
alpha: 1
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Execute precision strike - hit all cells of the ship
executeShipDestruction(targetCells, 0, siha);
}
});
}
});
}
function executeShipDestruction(targetCells, currentIndex, siha) {
if (currentIndex >= targetCells.length) {
// All cells destroyed, SIHA returns
tween(siha, {
x: 2200,
y: -100,
alpha: 0.5
}, {
duration: 2000,
easing: tween.easeIn,
onFinish: function onFinish() {
siha.destroy();
sihaAttackInProgress = false;
if (enemyGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Zafer! Tüm düşman gemileri yok edildi!');
turnText.setText('KAZANDINIZ!');
LK.showYouWin();
return;
}
// AI turn after SIHA attack
aiLastAttackType = null; // Reset AI attack type to allow AI special attacks
LK.setTimeout(function () {
aiTurn();
}, 1000);
}
});
return;
}
var target = targetCells[currentIndex];
// Create precision missile
var missile = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 1,
x: siha.x,
y: siha.y,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.9
});
tween(missile, {
x: enemyGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: enemyGrid.y + target.row * 60 * 1.5 + 30 * 1.5,
alpha: 0.4
}, {
duration: 400,
easing: tween.linear,
onFinish: function onFinish() {
missile.destroy();
// Guaranteed hit
var result = enemyGrid.checkHit(target.row, target.col);
if (result === 'hit' || result === 'sunk') {
LK.setScore(LK.getScore() + (result === 'sunk' ? 200 : 100));
}
// Continue with next target after short delay
LK.setTimeout(function () {
executeShipDestruction(targetCells, currentIndex + 1, siha);
}, 200);
}
});
}
function executeAIAirBombardment() {
aiAttackRights.air--;
aiLastAttackType = 'air';
updateAttackRightsDisplay();
statusText.setText('Düşman hava bombardımanı başlattı!');
turnText.setText('DÜŞMAN HAVA SALDIRISI');
// Generate 5 random target positions on player grid
var targets = [];
var attempts = 0;
while (targets.length < 5 && attempts < 100) {
var row = Math.floor(Math.random() * gridSize);
var col = Math.floor(Math.random() * gridSize);
var cell = playerGrid.cells[row][col];
// Only target untouched cells
if (!cell.isHit && !cell.isMiss) {
var duplicate = false;
for (var i = 0; i < targets.length; i++) {
if (targets[i].row === row && targets[i].col === col) {
duplicate = true;
break;
}
}
if (!duplicate) {
targets.push({
row: row,
col: col
});
}
}
attempts++;
}
// Create AI aircraft animation
var aircraft = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
x: 2148,
y: 200,
scaleX: 2,
scaleY: 2,
rotation: -Math.PI * 3 / 4,
tint: 0xFF0000
});
// Animate aircraft flying across screen
tween(aircraft, {
x: -100,
y: 300
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
aircraft.destroy();
executeAITargetHits(targets, 0);
}
});
}
function executeAITargetHits(targets, currentIndex) {
if (currentIndex >= targets.length) {
// All hits completed
LK.setTimeout(function () {
if (playerGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Yenilgi! Filonuz yok edildi!');
turnText.setText('KAYBETTİNİZ!');
LK.showGameOver();
return;
}
playerTurn = true;
lastAttackType = null;
updateStatusText();
}, 1000);
return;
}
var target = targets[currentIndex];
// Create bomb falling animation
var bomb = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 1,
x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: 100,
alpha: 0.8,
tint: 0xFF0000
});
tween(bomb, {
y: playerGrid.y + target.row * 60 * 1.5 + 30 * 1.5,
alpha: 0.3
}, {
duration: 600,
onFinish: function onFinish() {
bomb.destroy();
var result = playerGrid.checkHit(target.row, target.col);
LK.setTimeout(function () {
executeAITargetHits(targets, currentIndex + 1);
}, 300);
}
});
}
function executeAISubmarineAttack() {
aiAttackRights.submarine--;
aiLastAttackType = 'submarine';
updateAttackRightsDisplay();
statusText.setText('Düşman denizaltı saldırısı başlattı!');
turnText.setText('DÜŞMAN DENİZALTI SALDIRISI');
// Find player ships that are not yet sunk
var availableTargets = [];
for (var i = 0; i < playerGrid.ships.length; i++) {
var ship = playerGrid.ships[i];
if (!ship.sunk) {
for (var j = 0; j < ship.cells.length; j++) {
var cellPos = ship.cells[j];
var cell = playerGrid.cells[cellPos.row][cellPos.col];
if (!cell.isHit) {
availableTargets.push({
row: cellPos.row,
col: cellPos.col
});
}
}
}
}
if (availableTargets.length === 0) {
playerTurn = true;
lastAttackType = null;
updateStatusText();
return;
}
// Select random target from available unhit ship cells
var target = availableTargets[Math.floor(Math.random() * availableTargets.length)];
// Create submarine animation
var submarine = game.attachAsset('submarine', {
anchorX: 0.5,
anchorY: 0.5,
x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: 2732 + 100,
scaleX: 2,
scaleY: 2,
alpha: 0.7,
tint: 0xFF0000
});
// Animate submarine rising
tween(submarine, {
y: playerGrid.y + target.row * 60 * 1.5 + 200,
alpha: 1
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create torpedo
var torpedo = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
x: submarine.x,
y: submarine.y,
scaleX: 1.5,
scaleY: 1.5,
rotation: -Math.PI / 2,
alpha: 0.9,
tint: 0xFF0000
});
// Animate torpedo to target
tween(torpedo, {
x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: playerGrid.y + target.row * 60 * 1.5 + 30 * 1.5,
alpha: 0.5
}, {
duration: 800,
easing: tween.linear,
onFinish: function onFinish() {
torpedo.destroy();
var result = playerGrid.checkHit(target.row, target.col);
// Submarine disappears
tween(submarine, {
y: 2732 + 100,
alpha: 0
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
submarine.destroy();
if (playerGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Yenilgi! Filonuz yok edildi!');
turnText.setText('KAYBETTİNİZ!');
LK.showGameOver();
return;
}
playerTurn = true;
lastAttackType = null;
updateStatusText();
}
});
}
});
}
});
}
function executeAISihaAttack() {
aiAttackRights.siha--;
aiLastAttackType = 'siha';
updateAttackRightsDisplay();
statusText.setText('Düşman SİHA saldırısı başlattı!');
turnText.setText('DÜŞMAN SİHA SALDIRISI');
// Find all player ships that are not yet sunk
var availableShips = [];
for (var i = 0; i < playerGrid.ships.length; i++) {
var ship = playerGrid.ships[i];
if (!ship.sunk) {
availableShips.push(ship);
}
}
if (availableShips.length === 0) {
playerTurn = true;
lastAttackType = null;
updateStatusText();
return;
}
// Select random ship to completely destroy
var targetShip = availableShips[Math.floor(Math.random() * availableShips.length)];
var targetCells = [];
for (var j = 0; j < targetShip.cells.length; j++) {
targetCells.push(targetShip.cells[j]);
}
// Create AI SIHA drone animation
var siha = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
x: 2148,
y: -100,
scaleX: 1.8,
scaleY: 1.8,
rotation: -Math.PI / 6,
alpha: 0.9,
tint: 0xFF0000
});
// Animate SIHA flying to target area
var targetCenterX = playerGrid.x + targetCells[0].col * 60 * 1.5 + 30 * 1.5;
var targetCenterY = playerGrid.y + targetCells[0].row * 60 * 1.5 + 30 * 1.5;
tween(siha, {
x: targetCenterX,
y: targetCenterY - 150,
rotation: 0
}, {
duration: 2500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(siha, {
y: targetCenterY - 100,
alpha: 1
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
executeAIShipDestruction(targetCells, 0, siha);
}
});
}
});
}
function executeAIShipDestruction(targetCells, currentIndex, siha) {
if (currentIndex >= targetCells.length) {
// All cells destroyed, SIHA returns
tween(siha, {
x: 2200,
y: -100,
alpha: 0.5
}, {
duration: 2000,
easing: tween.easeIn,
onFinish: function onFinish() {
siha.destroy();
if (playerGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Yenilgi! Filonuz yok edildi!');
turnText.setText('KAYBETTİNİZ!');
LK.showGameOver();
return;
}
playerTurn = true;
lastAttackType = null;
updateStatusText();
}
});
return;
}
var target = targetCells[currentIndex];
// Create precision missile
var missile = game.attachAsset('missile', {
anchorX: 0.5,
anchorY: 1,
x: siha.x,
y: siha.y,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.9,
tint: 0xFF0000
});
tween(missile, {
x: playerGrid.x + target.col * 60 * 1.5 + 30 * 1.5,
y: playerGrid.y + target.row * 60 * 1.5 + 30 * 1.5,
alpha: 0.4
}, {
duration: 400,
easing: tween.linear,
onFinish: function onFinish() {
missile.destroy();
var result = playerGrid.checkHit(target.row, target.col);
LK.setTimeout(function () {
executeAIShipDestruction(targetCells, currentIndex + 1, siha);
}, 200);
}
});
}
function aiTurn() {
// Check if AI should use a special attack (30% chance if available and not consecutive)
var shouldUseSpecialAttack = Math.random() < 0.3;
var availableAttacks = [];
// Check which attacks are available (have rights remaining and not the last attack type)
if (aiAttackRights.air > 0 && aiLastAttackType !== 'air') {
availableAttacks.push('air');
}
if (aiAttackRights.submarine > 0 && aiLastAttackType !== 'submarine') {
availableAttacks.push('submarine');
}
if (aiAttackRights.siha > 0 && aiLastAttackType !== 'siha') {
availableAttacks.push('siha');
}
// Use special attack if conditions are met
if (shouldUseSpecialAttack && availableAttacks.length > 0) {
var selectedAttack = availableAttacks[Math.floor(Math.random() * availableAttacks.length)];
if (selectedAttack === 'air') {
executeAIAirBombardment();
return;
} else if (selectedAttack === 'submarine') {
executeAISubmarineAttack();
return;
} else if (selectedAttack === 'siha') {
executeAISihaAttack();
return;
}
}
// Regular attack logic
var row, col;
var attempts = 0;
var targetFound = false;
if (aiHuntMode && aiLastHit) {
// First priority: Try adjacent cells to last hit
var adjacents = [{
row: aiLastHit.row - 1,
col: aiLastHit.col
}, {
row: aiLastHit.row + 1,
col: aiLastHit.col
}, {
row: aiLastHit.row,
col: aiLastHit.col - 1
}, {
row: aiLastHit.row,
col: aiLastHit.col + 1
}];
var validTargets = [];
for (var i = 0; i < adjacents.length; i++) {
var target = adjacents[i];
if (target.row >= 0 && target.row < gridSize && target.col >= 0 && target.col < gridSize) {
var cell = playerGrid.cells[target.row][target.col];
if (!cell.isHit && !cell.isMiss) {
validTargets.push(target);
}
}
}
if (validTargets.length > 0) {
var chosen = validTargets[Math.floor(Math.random() * validTargets.length)];
row = chosen.row;
col = chosen.col;
targetFound = true;
} else {
// Second priority: Look for any hit cells that still have adjacent untested cells
var allHitCells = [];
for (var r = 0; r < gridSize; r++) {
for (var c = 0; c < gridSize; c++) {
var cell = playerGrid.cells[r][c];
if (cell.isHit && cell.hasShip) {
// Check if this hit cell's ship is not sunk
var shipNotSunk = false;
for (var s = 0; s < playerGrid.ships.length; s++) {
var ship = playerGrid.ships[s];
if (!ship.sunk) {
for (var sc = 0; sc < ship.cells.length; sc++) {
if (ship.cells[sc].row === r && ship.cells[sc].col === c) {
shipNotSunk = true;
break;
}
}
}
if (shipNotSunk) break;
}
if (shipNotSunk) {
allHitCells.push({
row: r,
col: c
});
}
}
}
}
// Find hit cells that still have adjacent untested targets
var validHitCells = [];
for (var h = 0; h < allHitCells.length; h++) {
var hitCell = allHitCells[h];
var hitAdjacents = [{
row: hitCell.row - 1,
col: hitCell.col
}, {
row: hitCell.row + 1,
col: hitCell.col
}, {
row: hitCell.row,
col: hitCell.col - 1
}, {
row: hitCell.row,
col: hitCell.col + 1
}];
for (var ha = 0; ha < hitAdjacents.length; ha++) {
var adj = hitAdjacents[ha];
if (adj.row >= 0 && adj.row < gridSize && adj.col >= 0 && adj.col < gridSize) {
var adjCell = playerGrid.cells[adj.row][adj.col];
if (!adjCell.isHit && !adjCell.isMiss) {
validHitCells.push(adj);
}
}
}
}
if (validHitCells.length > 0) {
var chosen = validHitCells[Math.floor(Math.random() * validHitCells.length)];
row = chosen.row;
col = chosen.col;
targetFound = true;
} else {
aiHuntMode = false;
aiLastHit = null;
}
}
}
if (!targetFound) {
// Random targeting
do {
row = Math.floor(Math.random() * gridSize);
col = Math.floor(Math.random() * gridSize);
attempts++;
} while ((playerGrid.cells[row][col].isHit || playerGrid.cells[row][col].isMiss) && attempts < 100);
}
var result = playerGrid.checkHit(row, col);
if (result === 'hit' || result === 'sunk') {
aiLastHit = {
row: row,
col: col
};
aiHuntMode = true;
if (result === 'sunk') {
aiHuntMode = false;
aiLastHit = null;
} else if (result === 'hit') {
// Ship was hit but not sunk, continue attacking surrounding area
LK.setTimeout(function () {
aiTurn(); // Continue attacking immediately
}, 1500);
return;
}
if (playerGrid.allShipsSunk()) {
gamePhase = 'gameOver';
statusText.setText('Yenilgi! Filonuz yok edildi!');
turnText.setText('KAYBETTİNİZ!');
LK.showGameOver();
return;
}
}
playerTurn = true;
lastAttackType = null; // Reset attack type after AI turn to allow alternating attacks
aiLastAttackType = 'regular'; // Set AI's last attack as regular
updateStatusText();
}
// Fleet status displays
var playerFleetStatus = new Container();
playerFleetStatus.x = 1700;
playerFleetStatus.y = 1500;
game.addChild(playerFleetStatus);
var enemyFleetStatus = new Container();
enemyFleetStatus.x = 1700;
enemyFleetStatus.y = 900;
game.addChild(enemyFleetStatus);
// Fleet status title texts
var playerFleetTitle = new Text2('Filonuz', {
size: 40,
fill: 0x66FF66
});
playerFleetTitle.anchor.set(0.5, 0);
playerFleetTitle.x = 0;
playerFleetTitle.y = -60;
playerFleetStatus.addChild(playerFleetTitle);
var enemyFleetTitle = new Text2('Düşman Filosu', {
size: 40,
fill: 0xFF6666
});
enemyFleetTitle.anchor.set(0.5, 0);
enemyFleetTitle.x = 0;
enemyFleetTitle.y = -60;
enemyFleetStatus.addChild(enemyFleetTitle);
// Fleet status arrays
var playerFleetDisplay = [];
var enemyFleetDisplay = [];
function updateFleetStatus() {
// Initialize arrays if they don't exist
if (!playerFleetDisplay) playerFleetDisplay = [];
if (!enemyFleetDisplay) enemyFleetDisplay = [];
// Clear existing displays
for (var i = 0; i < playerFleetDisplay.length; i++) {
playerFleetDisplay[i].destroy();
}
for (var i = 0; i < enemyFleetDisplay.length; i++) {
enemyFleetDisplay[i].destroy();
}
playerFleetDisplay = [];
enemyFleetDisplay = [];
// Create player fleet status
createFleetStatusDisplay(playerGrid, playerFleetStatus, playerFleetDisplay, true);
// Create enemy fleet status
createFleetStatusDisplay(enemyGrid, enemyFleetStatus, enemyFleetDisplay, false);
}
function createFleetStatusDisplay(grid, statusContainer, displayArray, isPlayerFleet) {
for (var i = 0; i < grid.ships.length; i++) {
var ship = grid.ships[i];
// Create main ship container
var shipContainer = new Container();
shipContainer.x = 0;
shipContainer.y = i * 50; // Reduced spacing for text-only
statusContainer.addChild(shipContainer);
displayArray.push(shipContainer);
// Create ship info display (text only)
createShipTextDisplay(ship, shipContainer, i, isPlayerFleet);
}
}
function createShipTextDisplay(ship, container, shipIndex, isPlayerFleet) {
// Ship name and status
var shipName = shipTypes[shipIndex];
var statusText = shipName;
var statusColor = 0xCCCCCC;
// Determine status and color
if (isPlayerFleet) {
if (ship.sunk) {
statusColor = 0xFF4444;
statusText += ' - BATIK (' + ship.hits + '/' + ship.length + ')';
} else if (ship.hits > 0) {
statusColor = 0xFFAA00;
statusText += ' - Hasarlı (' + ship.hits + '/' + ship.length + ')';
} else {
statusColor = 0x66FF99;
statusText += ' - Sağlam (' + ship.hits + '/' + ship.length + ')';
}
} else {
// Enemy fleet - only show detailed status if damaged or sunk
if (ship.sunk) {
statusColor = 0xFF4444;
statusText += ' - BATIK (' + ship.hits + '/' + ship.length + ')';
} else if (ship.hits > 0) {
statusColor = 0xFFAA00;
statusText += ' - Hasarlı (' + ship.hits + '/' + ship.length + ')';
} else {
statusColor = 0x888888;
statusText += ' - Bilinmiyor';
}
}
var nameText = new Text2(statusText, {
size: 28,
fill: statusColor
});
nameText.anchor.set(0, 0);
nameText.x = 0;
nameText.y = 0;
container.addChild(nameText);
}
// Removed - no longer needed for text-only display
// Removed - no longer needed for text-only display
// Game info page variables
var gameInfoShown = false;
var currentInfoPage = 0;
var totalInfoPages = 3;
// Difficulty selection variables
var difficultySelected = false;
var selectedDifficulty = 'easy'; // default
var gridSize = 8; // will be updated based on difficulty
// Game information page UI
var gameInfoContainer = new Container();
gameInfoContainer.x = 2048 / 2;
gameInfoContainer.y = 2732 / 2;
game.addChild(gameInfoContainer);
// Info page background
var infoBg = LK.getAsset('water', {
width: 1800,
height: 2400,
x: -900,
y: -1200,
color: 0x001122
});
infoBg.alpha = 0.95;
gameInfoContainer.addChild(infoBg);
// Info page title
var infoTitle = new Text2('AMİRAL BATTI', {
size: 80,
fill: 0xFFD700
});
infoTitle.anchor.set(0.5, 0.5);
infoTitle.x = 0;
infoTitle.y = -1000;
gameInfoContainer.addChild(infoTitle);
// Page indicator
var pageIndicator = new Text2('Sayfa 1 / 3', {
size: 50,
fill: 0xCCCCCC
});
pageIndicator.anchor.set(0.5, 0.5);
pageIndicator.x = 0;
pageIndicator.y = -900;
gameInfoContainer.addChild(pageIndicator);
// Info content container
var infoContentContainer = new Container();
infoContentContainer.x = 0;
infoContentContainer.y = -400;
gameInfoContainer.addChild(infoContentContainer);
// Navigation buttons
var prevButton = new Text2('← ÖNCEKİ', {
size: 60,
fill: 0x888888
});
prevButton.anchor.set(0.5, 0.5);
prevButton.x = -300;
prevButton.y = 1000;
gameInfoContainer.addChild(prevButton);
var nextButton = new Text2('SONRAKİ →', {
size: 60,
fill: 0x00FF00
});
nextButton.anchor.set(0.5, 0.5);
nextButton.x = 300;
nextButton.y = 1000;
gameInfoContainer.addChild(nextButton);
var startGameButton = new Text2('OYUNA BAŞLA', {
size: 70,
fill: 0xFF0000
});
startGameButton.anchor.set(0.5, 0.5);
startGameButton.x = 0;
startGameButton.y = 900;
startGameButton.visible = false;
gameInfoContainer.addChild(startGameButton);
// Info page content arrays
var infoPages = [
// Page 1: Basic Rules
['OYUN KURALLARI', '', '• Deniz savaşı oyununda amacınız düşman', ' filosunu tamamen yok etmektir', '', '• Filonuzda 5 farklı gemi türü bulunur:', ' - Uçak Gemisi (5 kare)', ' - Savaş Gemisi (4 kare)', ' - Kruvazör x2 (3 kare)', ' - Muhrip (2 kare)', '', '• Gemiler yatay veya dikey olarak', ' yerleştirilebilir', '', '• Düşman ızgarasına tıklayarak ateş edin', '• İsabet: Kırmızı, Kaçan: Mavi'],
// Page 2: Special Attacks
['ÖZEL SALDIRILAR', '', '🛩️ HAVA BOMBARDIMANI (2 Hak)', '• 5 rastgele hedefe eş zamanlı saldırı', '• Geniş alan hasarı', '• Ardışık kullanılamaz', '', '🚢 DENİZALTI SALDIRISI (2 Hak)', '• Düşman gemisine garantili isabet', '• Hedef otomatik seçilir', '• Yüksek hasar', '', '🛸 SİHA SALDIRISI (2 Hak)', '• Seçilen gemiyi tamamen yok eder', '• Hassas hedefleme', '• En güçlü saldırı türü'],
// Page 3: Game Tips
['OYUN İPUÇLARI', '', '⚡ STRATEJİ TAVSİYELERİ:', '', '• Gemilerinizi rastgele yerleştirin', '• Özel saldırıları akıllıca kullanın', '• Düşman vuruşlarından kalıp çıkarın', '• Isabet aldığınız bölgelerin etrafını', ' sistematik olarak tarayın', '', '🎯 ZORLUK SEVİYELERİ:', '• Kolay: Yavaş yapay zeka', '• Orta: Dengeli yapay zeka', '• Zor: Agresif yapay zeka', '', '• Düşman da özel saldırılara sahiptir!', '• Savunmanızı güçlü tutun!']];
// Button event handlers
prevButton.down = function (x, y, obj) {
if (currentInfoPage > 0) {
currentInfoPage--;
updateInfoPage();
}
};
nextButton.down = function (x, y, obj) {
if (currentInfoPage < totalInfoPages - 1) {
currentInfoPage++;
updateInfoPage();
}
};
startGameButton.down = function (x, y, obj) {
gameInfoShown = true;
gameInfoContainer.visible = false;
difficultyContainer.visible = true;
};
function updateInfoPage() {
// Clear existing content
for (var i = infoContentContainer.children.length - 1; i >= 0; i--) {
infoContentContainer.children[i].destroy();
}
// Update page indicator
pageIndicator.setText('Sayfa ' + (currentInfoPage + 1) + ' / ' + totalInfoPages);
// Add new content
var content = infoPages[currentInfoPage];
for (var i = 0; i < content.length; i++) {
var line = content[i];
var isTitle = i === 0;
var isEmpty = line === '';
if (!isEmpty) {
var textSize = isTitle ? 80 : 55;
var textColor = isTitle ? 0xFFD700 : line.startsWith('•') ? 0xCCCCCC : line.startsWith('🛩️') || line.startsWith('🚢') || line.startsWith('🛸') ? 0x00FFFF : line.startsWith('⚡') || line.startsWith('🎯') ? 0xFFAA00 : 0xFFFFFF;
var lineText = new Text2(line, {
size: textSize,
fill: textColor
});
lineText.anchor.set(0.5, 0);
lineText.x = 0;
lineText.y = i * 60 - 200;
infoContentContainer.addChild(lineText);
}
}
// Update button visibility
prevButton.visible = currentInfoPage > 0;
prevButton.fill = currentInfoPage > 0 ? 0xFFFFFF : 0x888888;
nextButton.visible = currentInfoPage < totalInfoPages - 1;
nextButton.fill = currentInfoPage < totalInfoPages - 1 ? 0x00FF00 : 0x888888;
startGameButton.visible = currentInfoPage === totalInfoPages - 1;
}
// Initialize first page
updateInfoPage();
// Difficulty selection UI
var difficultyContainer = new Container();
difficultyContainer.x = 2048 / 2;
difficultyContainer.y = 2732 / 2;
difficultyContainer.visible = false;
game.addChild(difficultyContainer);
var difficultyTitle = new Text2('Zorluk Seviyesi Seçin', {
size: 80,
fill: 0xFFFFFF
});
difficultyTitle.anchor.set(0.5, 0.5);
difficultyTitle.x = 0;
difficultyTitle.y = -200;
difficultyContainer.addChild(difficultyTitle);
// Easy button
var easyButton = new Text2('KOLAY (8x8)', {
size: 65,
fill: 0x00FF00
});
easyButton.anchor.set(0.5, 0.5);
easyButton.x = -400;
easyButton.y = 0;
difficultyContainer.addChild(easyButton);
easyButton.down = function (x, y, obj) {
selectedDifficulty = 'easy';
gridSize = 8;
startGameWithDifficulty();
};
// Medium button
var mediumButton = new Text2('ORTA (8x8)', {
size: 65,
fill: 0xFFFF00
});
mediumButton.anchor.set(0.5, 0.5);
mediumButton.x = 0;
mediumButton.y = 0;
difficultyContainer.addChild(mediumButton);
mediumButton.down = function (x, y, obj) {
selectedDifficulty = 'medium';
gridSize = 8;
startGameWithDifficulty();
};
// Hard button
var hardButton = new Text2('ZOR (8x8)', {
size: 65,
fill: 0xFF0000
});
hardButton.anchor.set(0.5, 0.5);
hardButton.x = 400;
hardButton.y = 0;
difficultyContainer.addChild(hardButton);
hardButton.down = function (x, y, obj) {
selectedDifficulty = 'hard';
gridSize = 8;
startGameWithDifficulty();
};
function startGameWithDifficulty() {
difficultySelected = true;
difficultyContainer.visible = false;
// Recreate grids with new size
playerGrid.destroy();
enemyGrid.destroy();
playerGrid = new GameGrid(true);
enemyGrid = new GameGrid(false);
// Scale grids based on difficulty to fit screen - increased for closer view
var baseScale = selectedDifficulty === 'easy' ? 2.0 : selectedDifficulty === 'medium' ? 1.8 : 1.5;
playerGrid.scaleX = baseScale;
playerGrid.scaleY = baseScale;
enemyGrid.scaleX = baseScale;
enemyGrid.scaleY = baseScale;
// Center grids on screen
var gridWidth = gridSize * 60 * baseScale;
var screenCenterX = 2048 / 2;
var gridCenterX = gridWidth / 2;
playerGrid.x = screenCenterX - gridCenterX;
playerGrid.y = 1400;
enemyGrid.x = screenCenterX - gridCenterX;
enemyGrid.y = 400;
// Store original positions for battle phase repositioning
playerGrid.originalX = playerGrid.x;
playerGrid.originalY = playerGrid.y;
playerGrid.originalScaleX = playerGrid.scaleX;
playerGrid.originalScaleY = playerGrid.scaleY;
game.addChild(playerGrid);
game.addChild(enemyGrid);
// Hide enemy grid during placement phase
enemyGrid.visible = false;
// Update labels position
enemyLabel.x = enemyGrid.x + gridSize * 60 * baseScale / 2;
enemyLabel.y = enemyGrid.y - 60;
playerLabel.x = playerGrid.x + gridSize * 60 * baseScale / 2;
playerLabel.y = playerGrid.y - 60;
// Add separator line between player and enemy grids
var separatorLine = game.attachAsset('gridLine', {
width: 2048,
height: 4,
x: 0,
y: (enemyGrid.y + gridSize * 60 * baseScale + playerGrid.y) / 2,
color: 0xFFFFFF
});
// Reset game state
gamePhase = 'placement';
currentShipIndex = 0;
// Initial setup
updateStatusText();
updateAttackRightsDisplay();
}
// Control pad variables
var controlPadActive = false;
var controlPadContainer = new Container();
var controlPadKnob = null;
var controlPadBaseCenter = {
x: 0,
y: 0
};
var controlPadMaxDistance = 120;
var cursorSpeed = 12;
var lastControlPadUpdate = 0;
// Create cursor/crosshair system
var cursorContainer = new Container();
game.addChild(cursorContainer);
// Create control pad
controlPadContainer.x = 2048 / 2;
controlPadContainer.y = 2732 - 450;
controlPadContainer.scaleX = 1.5;
controlPadContainer.scaleY = 1.5;
controlPadContainer.visible = false;
game.addChild(controlPadContainer);
// Control pad border
var controlPadBorder = controlPadContainer.attachAsset('controlPadBorder', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
// Control pad base
var controlPadBase = controlPadContainer.attachAsset('controlPadBase', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6
});
// Control pad knob
controlPadKnob = controlPadContainer.attachAsset('controlPadKnob', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Store base center position
controlPadBaseCenter.x = 0;
controlPadBaseCenter.y = 0;
// Create crosshair targeting system for better aiming
var crosshairOuter = cursorContainer.attachAsset('cursorRing', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8,
scaleX: 1.5,
scaleY: 1.5
});
var crosshairHorizontal = cursorContainer.attachAsset('crosshairH', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 1.2,
scaleY: 1.2
});
var crosshairVertical = cursorContainer.attachAsset('crosshairV', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 1.2,
scaleY: 1.2
});
var crosshairCenter = cursorContainer.attachAsset('cursorCenter', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0,
scaleX: 2.0,
scaleY: 2.0
});
// Add crosshair inner ring for precision targeting
var crosshairInner = cursorContainer.attachAsset('cursorRing', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6,
scaleX: 0.7,
scaleY: 0.7
});
// Initialize cursor position
cursorContainer.x = 2048 / 2;
cursorContainer.y = 2732 / 2;
cursorContainer.visible = false; // Initially hidden
// Add subtle pulse animation to cursor ring for better visibility
var cursorPulseDirection = 1;
var cursorPulseTimer = 0;
function updateCursorPulse() {
cursorPulseTimer++;
if (cursorPulseTimer % 40 === 0) {
// Every 0.67 seconds at 60fps for smoother targeting pulse
if (cursorPulseDirection === 1) {
// Pulse outer crosshair ring
tween(crosshairOuter, {
scaleX: 1.8,
scaleY: 1.8,
alpha: 0.4
}, {
duration: 600,
easing: tween.easeInOut
});
// Pulse crosshair center for precision feedback
tween(crosshairCenter, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0.7
}, {
duration: 600,
easing: tween.easeInOut
});
cursorPulseDirection = -1;
} else {
tween(crosshairOuter, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.8
}, {
duration: 600,
easing: tween.easeInOut
});
tween(crosshairCenter, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 1.0
}, {
duration: 600,
easing: tween.easeInOut
});
cursorPulseDirection = 1;
}
}
}
// Hide all game elements initially
playerGrid.visible = false;
enemyGrid.visible = false;
statusText.visible = false;
turnText.visible = false;
enemyLabel.visible = false;
playerLabel.visible = false;
rotateButton.visible = false;
autoPlaceButton.visible = false;
startBattleButton.visible = false;
airBombardmentButton.visible = false;
submarineAttackButton.visible = false;
sihaAttackButton.visible = false;
attackRightsContainer.visible = false;
playerFleetStatus.visible = false;
enemyFleetStatus.visible = false;
shipPreviewContainer.visible = false;
// Control pad event handlers
controlPadContainer.down = function (x, y, obj) {
if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) {
controlPadActive = true;
// Use local coordinates for better control
var localPos = {
x: x,
y: y
};
// Calculate distance and constrain properly
var distance = Math.sqrt(localPos.x * localPos.x + localPos.y * localPos.y);
if (distance > controlPadMaxDistance) {
var angle = Math.atan2(localPos.y, localPos.x);
localPos.x = Math.cos(angle) * controlPadMaxDistance;
localPos.y = Math.sin(angle) * controlPadMaxDistance;
}
controlPadKnob.x = localPos.x;
controlPadKnob.y = localPos.y;
}
};
controlPadContainer.up = function (x, y, obj) {
// If this was a quick tap (not a drag), try to fire at selected target
if (controlPadActive && gamePhase === 'battle' && playerTurn) {
var tapDistance = Math.sqrt(controlPadKnob.x * controlPadKnob.x + controlPadKnob.y * controlPadKnob.y);
if (tapDistance < 20) {
// Quick tap threshold - fire at selected target if valid
if (selectedTarget && targetSelectionActive && !selectedTarget.cell.isHit && !selectedTarget.cell.isMiss) {
// Enhanced target confirmation feedback
tween(crosshairCenter, {
scaleX: 4.0,
scaleY: 4.0,
alpha: 0.8
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
// Fire at the selected target
handlePlayerShot(selectedTarget.row, selectedTarget.col);
}
});
// Add visual confirmation flash
tween(crosshairOuter, {
scaleX: 3.5,
scaleY: 3.5,
alpha: 0.3
}, {
duration: 150,
easing: tween.easeIn
});
} else {
// Try to fire at current cursor position as fallback
if (enemyGrid.visible) {
var localX = cursorContainer.x - enemyGrid.x;
var localY = cursorContainer.y - enemyGrid.y;
var cellSize = 60 * enemyGrid.scaleX;
if (localX >= 0 && localX < gridSize * cellSize && localY >= 0 && localY < gridSize * cellSize) {
var gridCol = Math.floor(localX / cellSize);
var gridRow = Math.floor(localY / cellSize);
if (gridRow >= 0 && gridRow < gridSize && gridCol >= 0 && gridCol < gridSize) {
var targetCell = enemyGrid.cells[gridRow][gridCol];
if (!targetCell.isHit && !targetCell.isMiss) {
handlePlayerShot(gridRow, gridCol);
}
}
}
}
}
}
}
controlPadActive = false;
// Animate knob back to center
tween(controlPadKnob, {
x: 0,
y: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
controlPadContainer.move = function (x, y, obj) {
if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) {
// Convert coordinates to local space properly
var localPos = {
x: x,
y: y
};
// Calculate distance from center
var distance = Math.sqrt(localPos.x * localPos.x + localPos.y * localPos.y);
// Constrain knob within the control pad with smooth movement
if (distance > controlPadMaxDistance) {
var angle = Math.atan2(localPos.y, localPos.x);
localPos.x = Math.cos(angle) * controlPadMaxDistance;
localPos.y = Math.sin(angle) * controlPadMaxDistance;
}
// Smooth knob movement for better responsiveness
controlPadKnob.x = localPos.x;
controlPadKnob.y = localPos.y;
// Move cursor directly based on knob position
var knobOffsetX = controlPadKnob.x / controlPadMaxDistance;
var knobOffsetY = controlPadKnob.y / controlPadMaxDistance;
var dynamicSpeed = cursorSpeed * 2; // Increased responsiveness
cursorContainer.x += knobOffsetX * dynamicSpeed;
cursorContainer.y += knobOffsetY * dynamicSpeed;
// Keep cursor within screen bounds
cursorContainer.x = Math.max(20, Math.min(2028, cursorContainer.x));
cursorContainer.y = Math.max(20, Math.min(2712, cursorContainer.y));
// Set control pad as active when moving
controlPadActive = true;
}
};
// Target selection variables
var selectedTarget = null;
var targetSelectionActive = false;
var lastSelectedCell = null;
var availableTargets = [];
var currentTargetIndex = 0;
var targetSelectorActive = false;
// Add target selector down handler for firing at selected target
game.down = function (x, y, obj) {
if (targetSelectorActive && gamePhase === 'battle' && playerTurn) {
fireAtSelectedTarget();
return;
}
};
// Add cursor movement handler with enhanced aiming for enemy waters
game.move = function (x, y, obj) {
// Handle target selector cycling on screen touch/click
if (targetSelectorActive && gamePhase === 'battle' && playerTurn) {
cycleToNextTarget();
return;
}
// Update cursor position based on control pad if active, otherwise use mouse/touch
if (!controlPadActive) {
cursorContainer.x = x;
cursorContainer.y = y;
}
// Show cursor during battle phase
if (gamePhase === 'battle') {
cursorContainer.visible = true;
// Enhanced targeting for enemy waters
if (enemyGrid.visible) {
// Convert screen coordinates to grid coordinates
var localX = cursorContainer.x - enemyGrid.x;
var localY = cursorContainer.y - enemyGrid.y;
var cellSize = 60 * enemyGrid.scaleX;
// Check if cursor is over enemy grid
if (localX >= 0 && localX < gridSize * cellSize && localY >= 0 && localY < gridSize * cellSize) {
var gridCol = Math.floor(localX / cellSize);
var gridRow = Math.floor(localY / cellSize);
// Check if valid target
if (gridRow >= 0 && gridRow < gridSize && gridCol >= 0 && gridCol < gridSize) {
var targetCell = enemyGrid.cells[gridRow][gridCol];
var currentCellKey = gridRow + '_' + gridCol;
// Check if we've moved to a new cell for target selection
if (lastSelectedCell !== currentCellKey) {
lastSelectedCell = currentCellKey;
selectedTarget = {
row: gridRow,
col: gridCol,
cell: targetCell
};
targetSelectionActive = true;
// Stop any ongoing crosshair animations
tween.stop(crosshairCenter);
tween.stop(crosshairOuter);
tween.stop(crosshairHorizontal);
tween.stop(crosshairVertical);
tween.stop(crosshairInner);
}
if (!targetCell.isHit && !targetCell.isMiss) {
// Enhanced aiming for enemy waters - bright targeting crosshair with pulsing effect
crosshairHorizontal.tint = 0x00ffff;
crosshairVertical.tint = 0x00ffff;
crosshairCenter.tint = 0xff4444;
crosshairOuter.tint = 0x00ff88;
crosshairInner.tint = 0xffff00;
// Enhanced aiming animation with prominent scaling
tween(crosshairCenter, {
scaleX: 4.0,
scaleY: 4.0,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
tween(crosshairOuter, {
scaleX: 3.5,
scaleY: 3.5,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
tween(crosshairHorizontal, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
tween(crosshairVertical, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
tween(crosshairInner, {
scaleX: 1.8,
scaleY: 1.8,
alpha: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Already targeted - red crosshair with warning colors
crosshairHorizontal.tint = 0xff0000;
crosshairVertical.tint = 0xff0000;
crosshairCenter.tint = 0xff0000;
crosshairOuter.tint = 0xff0000;
crosshairInner.tint = 0xff0000;
// Scale up but reduce opacity for invalid targets
tween(crosshairCenter, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0.8
}, {
duration: 200,
easing: tween.easeOut
});
tween(crosshairOuter, {
scaleX: 1.8,
scaleY: 1.8,
alpha: 0.7
}, {
duration: 200,
easing: tween.easeOut
});
}
} else {
// Outside enemy grid targeting area - neutral visibility
crosshairHorizontal.tint = 0x888888;
crosshairVertical.tint = 0x888888;
crosshairCenter.tint = 0x888888;
crosshairOuter.tint = 0x888888;
crosshairInner.tint = 0x888888;
selectedTarget = null;
targetSelectionActive = false;
lastSelectedCell = null;
tween(crosshairCenter, {
scaleX: 1.8,
scaleY: 1.8,
alpha: 0.7
}, {
duration: 200,
easing: tween.easeOut
});
tween(crosshairOuter, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 0.6
}, {
duration: 200,
easing: tween.easeOut
});
}
} else {
// Outside enemy waters - dim targeting crosshair
crosshairHorizontal.tint = 0x666666;
crosshairVertical.tint = 0x666666;
crosshairCenter.tint = 0x666666;
crosshairOuter.tint = 0x666666;
crosshairInner.tint = 0x666666;
selectedTarget = null;
targetSelectionActive = false;
lastSelectedCell = null;
tween(crosshairCenter, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.4
}, {
duration: 200,
easing: tween.easeOut
});
tween(crosshairOuter, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
tween(crosshairHorizontal, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
tween(crosshairVertical, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
}
}
} else {
// Hide cursor during other phases
cursorContainer.visible = false;
selectedTarget = null;
targetSelectionActive = false;
lastSelectedCell = null;
}
};
// Play background music from game start
LK.playMusic('deniz');
// Show info page initially
gameInfoContainer.visible = true;
game.update = function () {
if (!gameInfoShown) {
// Show info page
gameInfoContainer.visible = true;
difficultyContainer.visible = false;
} else if (!difficultySelected) {
// Show difficulty selection
gameInfoContainer.visible = false;
difficultyContainer.visible = true;
} else if (difficultySelected) {
// Show game elements once difficulty is selected
gameInfoContainer.visible = false;
difficultyContainer.visible = false;
playerGrid.visible = true;
enemyGrid.visible = gamePhase === 'battle';
statusText.visible = true;
turnText.visible = true;
enemyLabel.visible = gamePhase === 'battle';
playerLabel.visible = true;
rotateButton.visible = gamePhase === 'placement';
autoPlaceButton.visible = gamePhase === 'placement';
startBattleButton.visible = gamePhase === 'placement' && currentShipIndex >= shipSizes.length;
shipPreviewContainer.visible = gamePhase === 'placement' && currentShipIndex < shipSizes.length;
playerFleetStatus.visible = true;
enemyFleetStatus.visible = true;
// Update cursor visibility and animation
if (gamePhase === 'battle' && playerTurn && !airBombardmentInProgress && !submarineAttackInProgress && !sihaAttackInProgress) {
cursorContainer.visible = true;
controlPadContainer.visible = true;
updateCursorPulse();
// Continuous cursor movement based on control pad position
if (controlPadContainer.visible) {
var knobOffsetX = controlPadKnob.x / controlPadMaxDistance;
var knobOffsetY = controlPadKnob.y / controlPadMaxDistance;
// Calculate movement speed based on knob distance for variable sensitivity
var knobDistance = Math.sqrt(knobOffsetX * knobOffsetX + knobOffsetY * knobOffsetY);
// Only move cursor if knob is displaced significantly
if (knobDistance > 0.05) {
var dynamicSpeed = cursorSpeed * (0.5 + knobDistance * 1.0); // Smooth speed scaling
// Move cursor based on knob position
cursorContainer.x += knobOffsetX * dynamicSpeed;
cursorContainer.y += knobOffsetY * dynamicSpeed;
// Keep cursor within screen bounds
cursorContainer.x = Math.max(20, Math.min(2028, cursorContainer.x));
cursorContainer.y = Math.max(20, Math.min(2712, cursorContainer.y));
}
}
} else {
cursorContainer.visible = false;
controlPadContainer.visible = false;
}
}
};
sketch tarzında carrier gemisi. In-Game asset. 2d. High contrast. No shadows
sketch tarzında cruıser savas gemısı. In-Game asset. 2d. High contrast. No shadows
skecth tarzında destroyer savas gemisi. In-Game asset. 2d. High contrast. No shadows
suya düşen füze. In-Game asset. 2d. High contrast. No shadows
suya düşen nesne sonrası oluşan dalgacıklar. In-Game asset. 2d. High contrast. No shadows
patlama sonrası kıvılcımlar. In-Game asset. 2d. High contrast. No shadows
aşağı yönde giden füze. In-Game asset. 2d. High contrast. No shadows
denizaltı gemisi torpidosundan ateşleme. In-Game asset. 2d. High contrast. No shadows