/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currentBattle: 0, battlesWon: 0, totalUnits: 12 }); /**** * Classes ****/ var Bullet = Container.expand(function (startX, startY, targetX, targetY, owner) { var self = Container.call(this); self.owner = owner; self.speed = 8; self.active = true; var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.x = startX; self.y = startY; // Calculate direction var dx = targetX - startX; var dy = targetY - startY; var distance = Math.sqrt(dx * dx + dy * dy); self.velocityX = dx / distance * self.speed; self.velocityY = dy / distance * self.speed; self.update = function () { if (!self.active) return; self.x += self.velocityX; self.y += self.velocityY; // Remove if out of bounds (with safer margins) if (self.x < -100 || self.x > 1950 || self.y < -100 || self.y > 1350) { self.active = false; self.destroy(); } }; return self; }); var DialogSystem = Container.expand(function () { var self = Container.call(this); self.visible = false; self.currentDialogIndex = 0; self.dialogData = []; var dialogBg = self.attachAsset('dialogBox', { anchorX: 0.5, anchorY: 0 }); self.commanderText = new Text2('', { size: 40, fill: '#ffffff' }); self.commanderText.anchor.set(0, 0); self.addChild(self.commanderText); self.continueText = new Text2('TAP TO CONTINUE', { size: 30, fill: '#ffff00' }); self.continueText.anchor.set(0.5, 1); self.addChild(self.continueText); self.x = 2048 / 2; self.y = 2732 - 450; self.commanderText.x = -900; self.commanderText.y = 50; self.continueText.x = 0; self.continueText.y = -50; self.showDialog = function (dialogArray) { self.dialogData = dialogArray; self.currentDialogIndex = 0; self.visible = true; self.continueText.setText(t('tapToContinue')); self.displayCurrentDialog(); }; self.displayCurrentDialog = function () { if (self.currentDialogIndex < self.dialogData.length) { var currentText = self.dialogData[self.currentDialogIndex]; self.commanderText.setText(currentText); } }; self.nextDialog = function () { self.currentDialogIndex++; if (self.currentDialogIndex < self.dialogData.length) { self.displayCurrentDialog(); } else { self.hideDialog(); } }; self.hideDialog = function () { self.visible = false; if (currentGameState === 'briefing') { startBattle(); } else if (currentGameState === 'victory') { nextBattle(); } }; self.down = function (x, y, obj) { if (self.visible) { self.nextDialog(); } }; return self; }); var Unit = Container.expand(function (type, subType, unitX, unitY) { var self = Container.call(this); self.unitType = type || 'soldier'; self.subType = subType || 'soldier'; // 'soldier', 'tank', 'aircraft' self.health = self.subType === 'tank' ? 5 : self.subType === 'aircraft' ? 2 : 3; self.maxHealth = self.health; self.selected = false; self.hasMoved = false; self.hasFired = false; self.range = self.subType === 'tank' ? 300 : self.subType === 'aircraft' ? 400 : 150; // Choose appropriate asset based on type and subtype var assetName; if (type === 'enemy') { assetName = subType === 'tank' ? 'enemyTank' : subType === 'aircraft' ? 'enemyAircraft' : 'enemyUnit'; } else { assetName = subType === 'tank' ? 'tankUnit' : subType === 'aircraft' ? 'aircraftUnit' : 'soldierUnit'; } var unitGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.x = unitX || 0; self.y = unitY || 0; self.select = function () { // Simplified selection - no complex logic self.selected = true; unitGraphics.tint = 0x00ff00; }; self.deselect = function () { self.selected = false; unitGraphics.tint = 0xffffff; }; self.moveTo = function (targetX, targetY) { if (self.selected && !self.hasMoved) { tween(self, { x: targetX, y: targetY }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { self.hasMoved = true; if (self.hasFired) { self.deselect(); checkTurnComplete(); } } }); LK.getSound('unitMove').play(); } }; self.fireAt = function (targetX, targetY) { if (self.selected && !self.hasFired) { var distance = Math.sqrt(Math.pow(targetX - self.x, 2) + Math.pow(targetY - self.y, 2)); if (distance <= self.range) { var bullet = new Bullet(self.x, self.y, targetX, targetY, self); bullets.push(bullet); battlefieldContainer.addChild(bullet); LK.getSound('bulletFire').play(); // Visual feedback for firing LK.effects.flashObject(self, 0xffff00, 200); self.hasFired = true; if (self.hasMoved) { self.deselect(); checkTurnComplete(); } } else { // Out of range feedback LK.effects.flashObject(self, 0xff0000, 300); } } }; self.takeDamage = function () { self.health--; if (self.health <= 0) { self.destroy(); return true; } return false; }; self.down = function (x, y, obj) { if (self.unitType !== 'enemy' && currentGameState === 'battle') { // Clear previous selections first clearAllSelections(); // Select this unit self.select(); selectedUnit = self; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c5234 }); /**** * Game Code ****/ var currentGameState = 'language_selection'; // 'language_selection', 'briefing', 'battle', 'victory', 'complete' var currentBattle = storage.currentBattle || 0; var battlesWon = storage.battlesWon || 0; var playerHealth = 100; var languageSelectionContainer; var selectedUnit = null; var playerUnits = []; var enemyUnits = []; var objectives = []; var bullets = []; var trees = []; var turnComplete = false; var currentLanguage = storage.language || 'en'; // 'en' or 'tr' // Translation system var translations = { en: { battlesWon: 'Battles Won: ', tapToContinue: 'TAP TO CONTINUE', beachLanding: 'Beach Landing', forestPatrol: 'Forest Patrol', urbanWarfare: 'Urban Warfare', battle: 'Battle', languageButton: 'TR' }, tr: { battlesWon: 'Kazanılan Savaşlar: ', tapToContinue: 'DEVAM İÇİN DOKUN', beachLanding: 'Sahil Çıkarması', forestPatrol: 'Orman Devriyesi', urbanWarfare: 'Şehir Savaşı', battle: 'Savaş', languageButton: 'EN' } }; function t(key) { return translations[currentLanguage][key] || translations.en[key] || key; } // Battle configurations var battleConfigs = [{ name: { en: "Beach Landing", tr: "Sahil Çıkarması" }, briefing: { en: ["Commander: Welcome to Operation Overlord, soldier!", "Your mission: Secure the beach and eliminate enemy resistance.", "Move your units carefully - the enemy has defensive positions.", "TAP units to select, then TAP destination to move or fire. Good luck!"], tr: ["Komutan: Overlord Harekâtına hoş geldin asker!", "Görevin: Sahili ele geçir ve düşman direncini yok et.", "Birliklerini dikkatli hareket ettir - düşmanın savunma mevzileri var.", "Birlikleri seçmek için DOKUN, hareket veya ateş etmek için tekrar DOKUN. İyi şanslar!"] }, playerStartPositions: [[200, 800, 'soldier'], [200, 900, 'soldier'], [200, 1000, 'tank']], enemyPositions: [[1600, 400, 'soldier'], [1600, 600, 'tank']], objectivePos: [1600, 500] }, { name: { en: "Tank Assault", tr: "Tank Saldırısı" }, briefing: { en: ["Heavy armor engagement ahead!", "Use your tanks to break enemy lines.", "Coordinate infantry and armor for maximum effect!"], tr: ["Ağır zırhlı çatışma yaklaşıyor!", "Düşman hatlarını kırmak için tanklarını kullan.", "Maksimum etki için piyade ve zırhı koordine et!"] }, playerStartPositions: [[300, 1000, 'tank'], [400, 1000, 'soldier'], [500, 1000, 'tank']], enemyPositions: [[1400, 300, 'tank'], [1500, 500, 'soldier'], [1300, 700, 'tank']], objectivePos: [1450, 400] }, { name: { en: "Air Superiority", tr: "Hava Üstünlüğü" }, briefing: { en: ["Control the skies soldier!", "Aircraft have superior range but less armor.", "Use hit and run tactics with air units!"], tr: ["Gökleri kontrol et asker!", "Uçakların menzili üstün ama zırhı az.", "Hava birlikleriyle vur-kaç taktiği kullan!"] }, playerStartPositions: [[150, 1100, 'aircraft'], [250, 1100, 'soldier'], [350, 1100, 'aircraft']], enemyPositions: [[1500, 200, 'aircraft'], [1400, 400, 'tank'], [1600, 600, 'aircraft']], objectivePos: [1500, 350] }, { name: { en: "Combined Arms", tr: "Birleşik Kuvvetler" }, briefing: { en: ["All unit types in action!", "Coordinate soldiers, tanks, and aircraft.", "Each unit has unique strengths - use them wisely!"], tr: ["Tüm birlik türleri harekete geçiyor!", "Asker, tank ve uçakları koordine et.", "Her birliğin benzersiz gücü var - akıllıca kullan!"] }, playerStartPositions: [[200, 1000, 'soldier'], [300, 1000, 'tank'], [400, 1000, 'aircraft'], [500, 1000, 'soldier']], enemyPositions: [[1400, 300, 'tank'], [1500, 400, 'aircraft'], [1600, 500, 'soldier'], [1300, 600, 'tank']], objectivePos: [1500, 400] }]; // Extend battle configs to 10 battles for (var i = 3; i < 10; i++) { var baseConfig = battleConfigs[i % 3]; battleConfigs.push({ name: { en: "Battle " + (i + 1), tr: "Savaş " + (i + 1) }, briefing: { en: ["Commander: Battle " + (i + 1) + " awaits!", "The enemy grows stronger with each encounter.", "Use everything you've learned so far!"], tr: ["Komutan: Savaş " + (i + 1) + " seni bekliyor!", "Düşman her karşılaşmada daha da güçleniyor.", "Şimdiye kadar öğrendiğin her şeyi kullan!"] }, playerStartPositions: baseConfig.playerStartPositions, enemyPositions: baseConfig.enemyPositions, objectivePos: baseConfig.objectivePos }); } // UI Elements var battlefieldContainer = game.addChild(new Container()); var battlefield = battlefieldContainer.attachAsset('battlefield', { anchorX: 0.5, anchorY: 0.5 }); battlefieldContainer.x = 2048 / 2; battlefieldContainer.y = (2732 - 400) / 2; var dialogSystem = game.addChild(new DialogSystem()); var battleTitle = new Text2('', { size: 60, fill: '#ffffff' }); battleTitle.anchor.set(0.5, 0); LK.gui.top.addChild(battleTitle); battleTitle.y = 100; var scoreText = new Text2('Battles Won: 0/10', { size: 40, fill: '#ffffff' }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); scoreText.x = -20; scoreText.y = 20; var healthText = new Text2('Health: 100', { size: 40, fill: '#ff0000' }); healthText.anchor.set(0, 0); LK.gui.topLeft.addChild(healthText); healthText.x = 120; healthText.y = 20; // Language toggle button var langButton = new Text2(t('languageButton'), { size: 40, fill: '#ffffff' }); langButton.anchor.set(0.5, 0); LK.gui.topRight.addChild(langButton); langButton.x = -60; langButton.y = 80; langButton.interactive = true; langButton.buttonMode = true; langButton.on('pointerdown', function () { currentLanguage = currentLanguage === 'en' ? 'tr' : 'en'; storage.language = currentLanguage; langButton.setText(t('languageButton')); updateScoreDisplay(); // Update dialog continue text dialogSystem.continueText.setText(t('tapToContinue')); // Update battle title if currently displayed var config = battleConfigs[currentBattle]; if (config && config.name && config.name[currentLanguage]) { battleTitle.setText(config.name[currentLanguage]); } }); // Game Functions function startGame() { currentGameState = 'briefing'; if (languageSelectionContainer) { languageSelectionContainer.destroy(); } battlefieldContainer.visible = true; battleTitle.visible = true; scoreText.visible = true; langButton.visible = true; dialogSystem.visible = true; healthText.visible = true; // Update UI text with selected language langButton.setText(t('languageButton')); dialogSystem.continueText.setText(t('tapToContinue')); // Initialize first battle setupBattle(); updateScoreDisplay(); var config = battleConfigs[currentBattle]; var firstBriefing = config && config.briefing && config.briefing[currentLanguage] ? config.briefing[currentLanguage] : ["Mission briefing not available"]; dialogSystem.showDialog(firstBriefing); } function clearAllSelections() { selectedUnit = null; for (var i = 0; i < playerUnits.length; i++) { playerUnits[i].deselect(); } } function setupBattle() { // Clear previous battle for (var i = playerUnits.length - 1; i >= 0; i--) { playerUnits[i].destroy(); } for (var i = enemyUnits.length - 1; i >= 0; i--) { enemyUnits[i].destroy(); } for (var i = objectives.length - 1; i >= 0; i--) { objectives[i].destroy(); } for (var i = trees.length - 1; i >= 0; i--) { trees[i].destroy(); } playerUnits = []; enemyUnits = []; objectives = []; trees = []; playerHealth = 100; updateHealthDisplay(); var config = battleConfigs[currentBattle]; if (config && config.name && config.name[currentLanguage]) { battleTitle.setText(config.name[currentLanguage]); } // Create player units - with safety check if (config && config.playerStartPositions && config.playerStartPositions.length > 0) { for (var i = 0; i < config.playerStartPositions.length; i++) { var pos = config.playerStartPositions[i]; var unitSubType = pos[2] || 'soldier'; var unit = new Unit('player', unitSubType, pos[0], pos[1]); playerUnits.push(unit); battlefieldContainer.addChild(unit); } } // Create enemy units at top of screen - with safety check if (config && config.enemyPositions && config.enemyPositions.length > 0) { for (var i = 0; i < config.enemyPositions.length; i++) { var pos = config.enemyPositions[i]; var unitSubType = pos[2] || 'soldier'; // Position enemies at top edge with spread positions var enemyX = 300 + i * 400 + Math.random() * 200; var enemyY = -100; // Start from above screen var enemy = new Unit('enemy', unitSubType, enemyX, enemyY); enemyUnits.push(enemy); battlefieldContainer.addChild(enemy); // Use tween to move enemy down into battlefield area tween(enemy, { y: 200 + Math.random() * 200 }, { duration: 2000, easing: tween.easeOut }); } } // Create objective - with safety check if (config && config.objectivePos && config.objectivePos.length >= 2) { var objPos = config.objectivePos; var objective = battlefieldContainer.attachAsset('objective', { anchorX: 0.5, anchorY: 0.5, x: objPos[0], y: objPos[1] }); objectives.push(objective); } // Create trees only at battlefield edges for decoration for (var i = 0; i < 8; i++) { // Left edge trees - at the very edge var leftTree = battlefieldContainer.attachAsset('tree', { anchorX: 0.5, anchorY: 1, x: 50 + Math.random() * 30, y: 200 + i * 120 + Math.random() * 50 }); leftTree.visible = true; trees.push(leftTree); // Right edge trees - at the very edge var rightTree = battlefieldContainer.attachAsset('tree', { anchorX: 0.5, anchorY: 1, x: 1720 + Math.random() * 30, y: 200 + i * 120 + Math.random() * 50 }); rightTree.visible = true; trees.push(rightTree); } // Add top edge trees for (var i = 0; i < 6; i++) { var topTree = battlefieldContainer.attachAsset('tree', { anchorX: 0.5, anchorY: 1, x: 300 + i * 200 + Math.random() * 100, y: 50 + Math.random() * 30 }); topTree.visible = true; trees.push(topTree); } // Add bottom edge trees for (var i = 0; i < 6; i++) { var bottomTree = battlefieldContainer.attachAsset('tree', { anchorX: 0.5, anchorY: 1, x: 300 + i * 200 + Math.random() * 100, y: 1150 + Math.random() * 30 }); bottomTree.visible = true; trees.push(bottomTree); } } function checkTurnComplete() { // Simplified - just check victory condition if (checkVictoryCondition()) { handleVictory(); } } function checkVictoryCondition() { if (enemyUnits.length === 0) return true; // Check if any player unit is near objective for (var i = 0; i < playerUnits.length; i++) { var unit = playerUnits[i]; var objective = objectives[0]; var distance = Math.sqrt(Math.pow(unit.x - objective.x, 2) + Math.pow(unit.y - objective.y, 2)); if (distance < 120) { return true; } } return false; } function handleVictory() { battlesWon++; storage.battlesWon = battlesWon; storage.currentBattle = currentBattle + 1; LK.getSound('battleWin').play(); updateScoreDisplay(); if (currentBattle >= 9) { // Won all 10 battles - reset game to start over currentGameState = 'complete'; var completeMessages = currentLanguage === 'en' ? ["Commander: Outstanding work, soldier!", "You have successfully completed all 10 battles!", "The war is won thanks to your strategic brilliance!", "Starting new campaign..."] : ["Komutan: Olağanüstü iş başardın asker!", "10 savaşın tamamını başarıyla tamamladın!", "Savaş senin stratejik dehanla kazanıldı!", "Yeni kampanya başlıyor..."]; dialogSystem.showDialog(completeMessages); // Reset game progress currentBattle = 0; battlesWon = 0; storage.currentBattle = 0; storage.battlesWon = 0; updateScoreDisplay(); // Start over from first battle LK.setTimeout(function () { currentGameState = 'briefing'; setupBattle(); var config = battleConfigs[currentBattle]; var firstBriefing = config && config.briefing && config.briefing[currentLanguage] ? config.briefing[currentLanguage] : ["Mission briefing not available"]; dialogSystem.showDialog(firstBriefing); }, 2000); return; } else { currentGameState = 'victory'; var victoryMessages = currentLanguage === 'en' ? ["Commander: Excellent work! Battle won!", "Your tactical skills are improving with each victory.", "Prepare for the next engagement, soldier."] : ["Komutan: Mükemmel iş! Savaş kazanıldı!", "Taktik yeteneklerin her zaferle gelişiyor.", "Bir sonraki çatışmaya hazırlan asker."]; dialogSystem.showDialog(victoryMessages); } } function nextBattle() { currentBattle++; if (currentBattle < 10) { currentGameState = 'briefing'; setupBattle(); var config = battleConfigs[currentBattle]; var briefingText = config && config.briefing && config.briefing[currentLanguage] ? config.briefing[currentLanguage] : ["Mission briefing not available"]; dialogSystem.showDialog(briefingText); } } function startBattle() { currentGameState = 'battle'; } function updateScoreDisplay() { scoreText.setText(t('battlesWon') + battlesWon + '/10'); } function updateHealthDisplay() { healthText.setText('Health: ' + playerHealth); if (playerHealth <= 0) { LK.showGameOver(); } } function takeDamageFromEnemy(damage) { playerHealth -= damage; if (playerHealth < 0) playerHealth = 0; updateHealthDisplay(); LK.effects.flashScreen(0xff0000, 500); } // Mouse/Touch handling - simplified battlefieldContainer.down = function (x, y, obj) { if (currentGameState !== 'battle') return; // If we have a selected unit, move it to clicked position if (selectedUnit) { // Convert click position to battlefield coordinates safely var localPos; if (obj && obj.parent && obj.position) { localPos = battlefieldContainer.toLocal(obj.parent.toGlobal(obj.position)); } else { // Fallback to using x, y directly as local coordinates localPos = { x: x, y: y }; } selectedUnit.moveTo(localPos.x, localPos.y); } }; function initializeLanguageSelection() { // Hide main game UI battlefieldContainer.visible = false; battleTitle.visible = false; scoreText.visible = false; langButton.visible = false; dialogSystem.visible = false; healthText.visible = false; // Setup selection screen languageSelectionContainer = new Container(); languageSelectionContainer.x = 2048 / 2; languageSelectionContainer.y = 2732 / 2; game.addChild(languageSelectionContainer); var title = new Text2('Select Language / Dil Seçiniz', { size: 70, fill: '#ffffff', align: 'center' }); title.anchor.set(0.5, 0.5); title.y = -350; languageSelectionContainer.addChild(title); var btnEn = LK.getAsset('flag_en', { anchorX: 0.5, anchorY: 0.5 }); btnEn.y = -100; btnEn.interactive = true; btnEn.buttonMode = true; btnEn.down = function () { currentLanguage = 'en'; storage.language = 'en'; startGame(); }; languageSelectionContainer.addChild(btnEn); var btnTr = LK.getAsset('flag_tr', { anchorX: 0.5, anchorY: 0.5 }); btnTr.y = 200; btnTr.interactive = true; btnTr.buttonMode = true; btnTr.down = function () { currentLanguage = 'tr'; storage.language = 'tr'; startGame(); }; languageSelectionContainer.addChild(btnTr); } initializeLanguageSelection(); game.update = function () { if (currentGameState === 'language_selection') return; // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet && bullet.active) { // Check bullet collisions with enemy units (player bullets) if (bullet.owner && bullet.owner.unitType !== 'enemy') { for (var j = 0; j < enemyUnits.length; j++) { var enemy = enemyUnits[j]; if (enemy) { var distance = Math.sqrt(Math.pow(bullet.x - enemy.x, 2) + Math.pow(bullet.y - enemy.y, 2)); if (distance < 50) { if (enemy.takeDamage()) { enemy.destroy(); enemyUnits.splice(j, 1); } bullet.active = false; bullet.destroy(); bullets.splice(i, 1); LK.getSound('unitAttack').play(); break; } } } } // Check bullet collisions with player units (enemy bullets) if (bullet && bullet.active && bullet.owner && bullet.owner.unitType === 'enemy') { for (var j = 0; j < playerUnits.length; j++) { var player = playerUnits[j]; if (player) { var distance = Math.sqrt(Math.pow(bullet.x - player.x, 2) + Math.pow(bullet.y - player.y, 2)); if (distance < 50) { // Calculate damage based on enemy type var damage = bullet.owner.subType === 'tank' ? 15 : 10; takeDamageFromEnemy(damage); if (player.takeDamage()) { player.destroy(); playerUnits.splice(j, 1); } bullet.active = false; bullet.destroy(); bullets.splice(i, 1); LK.getSound('unitAttack').play(); break; } } } } } else if (bullet && !bullet.active) { bullets.splice(i, 1); } } // Simplified auto-fire - no restrictions if (currentGameState === 'battle' && LK.ticks % 90 === 0) { for (var i = 0; i < playerUnits.length; i++) { var unit = playerUnits[i]; if (unit) { // Find closest enemy to auto-fire at var closestEnemy = null; var closestDistance = Infinity; for (var j = 0; j < enemyUnits.length; j++) { var enemy = enemyUnits[j]; if (enemy) { var distance = Math.sqrt(Math.pow(unit.x - enemy.x, 2) + Math.pow(unit.y - enemy.y, 2)); if (distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } } // Auto-fire at closest enemy if (closestEnemy) { var bullet = new Bullet(unit.x, unit.y, closestEnemy.x, closestEnemy.y, unit); bullets.push(bullet); battlefieldContainer.addChild(bullet); LK.getSound('bulletFire').play(); LK.effects.flashObject(unit, 0xffff00, 200); } } } } // Enhanced AI for enemies - enemy tanks fire from distance at player units if (currentGameState === 'battle' && enemyUnits.length > 0) { for (var i = 0; i < enemyUnits.length; i++) { var enemy = enemyUnits[i]; if (enemy && playerUnits.length > 0) { // Tank enemies fire faster and from longer distance var actualFireRate = enemy.subType === 'tank' ? 40 : 120; if (LK.ticks % actualFireRate === 0) { var targetPlayer = playerUnits[Math.floor(Math.random() * playerUnits.length)]; var distance = Math.sqrt(Math.pow(targetPlayer.x - enemy.x, 2) + Math.pow(targetPlayer.y - enemy.y, 2)); // Tanks fire from much longer range - up to 600 pixels away var effectiveRange = enemy.subType === 'tank' ? 600 : enemy.range; if (distance <= effectiveRange) { var bullet = new Bullet(enemy.x, enemy.y, targetPlayer.x, targetPlayer.y, enemy); bullets.push(bullet); battlefieldContainer.addChild(bullet); LK.getSound('bulletFire').play(); LK.effects.flashObject(enemy, 0xff0000, 200); } } // Move primarily down from top with some horizontal movement var moveDirection = Math.random() > 0.5 ? 1 : -1; var moveX = enemy.x + moveDirection * 60; // Reduced horizontal movement // Keep within battlefield bounds horizontally (with safety margins) if (moveX < 300) moveX = 300; if (moveX > 1500) moveX = 1500; // Move down into battlefield area but stop before player area var targetY = Math.min(500, enemy.y + 80); tween(enemy, { x: moveX, y: targetY }, { duration: 1500, easing: tween.easeOut }); } } } // Check victory condition regularly if (currentGameState === 'battle' && LK.ticks % 60 === 0) { if (checkVictoryCondition()) { handleVictory(); } } // Check for close combat (melee when units are very close) if (currentGameState === 'battle' && LK.ticks % 60 === 0) { for (var i = playerUnits.length - 1; i >= 0; i--) { for (var j = enemyUnits.length - 1; j >= 0; j--) { if (playerUnits[i] && enemyUnits[j]) { var player = playerUnits[i]; var enemy = enemyUnits[j]; var distance = Math.sqrt(Math.pow(player.x - enemy.x, 2) + Math.pow(player.y - enemy.y, 2)); if (distance < 80) { LK.getSound('unitAttack').play(); if (Math.random() > 0.5) { if (enemy.takeDamage()) { enemyUnits.splice(j, 1); } } else { if (player.takeDamage()) { playerUnits.splice(i, 1); } } // Check game over condition if (playerUnits.length === 0) { LK.showGameOver(); } } } } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
currentBattle: 0,
battlesWon: 0,
totalUnits: 12
});
/****
* Classes
****/
var Bullet = Container.expand(function (startX, startY, targetX, targetY, owner) {
var self = Container.call(this);
self.owner = owner;
self.speed = 8;
self.active = true;
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = startX;
self.y = startY;
// Calculate direction
var dx = targetX - startX;
var dy = targetY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
self.update = function () {
if (!self.active) return;
self.x += self.velocityX;
self.y += self.velocityY;
// Remove if out of bounds (with safer margins)
if (self.x < -100 || self.x > 1950 || self.y < -100 || self.y > 1350) {
self.active = false;
self.destroy();
}
};
return self;
});
var DialogSystem = Container.expand(function () {
var self = Container.call(this);
self.visible = false;
self.currentDialogIndex = 0;
self.dialogData = [];
var dialogBg = self.attachAsset('dialogBox', {
anchorX: 0.5,
anchorY: 0
});
self.commanderText = new Text2('', {
size: 40,
fill: '#ffffff'
});
self.commanderText.anchor.set(0, 0);
self.addChild(self.commanderText);
self.continueText = new Text2('TAP TO CONTINUE', {
size: 30,
fill: '#ffff00'
});
self.continueText.anchor.set(0.5, 1);
self.addChild(self.continueText);
self.x = 2048 / 2;
self.y = 2732 - 450;
self.commanderText.x = -900;
self.commanderText.y = 50;
self.continueText.x = 0;
self.continueText.y = -50;
self.showDialog = function (dialogArray) {
self.dialogData = dialogArray;
self.currentDialogIndex = 0;
self.visible = true;
self.continueText.setText(t('tapToContinue'));
self.displayCurrentDialog();
};
self.displayCurrentDialog = function () {
if (self.currentDialogIndex < self.dialogData.length) {
var currentText = self.dialogData[self.currentDialogIndex];
self.commanderText.setText(currentText);
}
};
self.nextDialog = function () {
self.currentDialogIndex++;
if (self.currentDialogIndex < self.dialogData.length) {
self.displayCurrentDialog();
} else {
self.hideDialog();
}
};
self.hideDialog = function () {
self.visible = false;
if (currentGameState === 'briefing') {
startBattle();
} else if (currentGameState === 'victory') {
nextBattle();
}
};
self.down = function (x, y, obj) {
if (self.visible) {
self.nextDialog();
}
};
return self;
});
var Unit = Container.expand(function (type, subType, unitX, unitY) {
var self = Container.call(this);
self.unitType = type || 'soldier';
self.subType = subType || 'soldier'; // 'soldier', 'tank', 'aircraft'
self.health = self.subType === 'tank' ? 5 : self.subType === 'aircraft' ? 2 : 3;
self.maxHealth = self.health;
self.selected = false;
self.hasMoved = false;
self.hasFired = false;
self.range = self.subType === 'tank' ? 300 : self.subType === 'aircraft' ? 400 : 150;
// Choose appropriate asset based on type and subtype
var assetName;
if (type === 'enemy') {
assetName = subType === 'tank' ? 'enemyTank' : subType === 'aircraft' ? 'enemyAircraft' : 'enemyUnit';
} else {
assetName = subType === 'tank' ? 'tankUnit' : subType === 'aircraft' ? 'aircraftUnit' : 'soldierUnit';
}
var unitGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.x = unitX || 0;
self.y = unitY || 0;
self.select = function () {
// Simplified selection - no complex logic
self.selected = true;
unitGraphics.tint = 0x00ff00;
};
self.deselect = function () {
self.selected = false;
unitGraphics.tint = 0xffffff;
};
self.moveTo = function (targetX, targetY) {
if (self.selected && !self.hasMoved) {
tween(self, {
x: targetX,
y: targetY
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
self.hasMoved = true;
if (self.hasFired) {
self.deselect();
checkTurnComplete();
}
}
});
LK.getSound('unitMove').play();
}
};
self.fireAt = function (targetX, targetY) {
if (self.selected && !self.hasFired) {
var distance = Math.sqrt(Math.pow(targetX - self.x, 2) + Math.pow(targetY - self.y, 2));
if (distance <= self.range) {
var bullet = new Bullet(self.x, self.y, targetX, targetY, self);
bullets.push(bullet);
battlefieldContainer.addChild(bullet);
LK.getSound('bulletFire').play();
// Visual feedback for firing
LK.effects.flashObject(self, 0xffff00, 200);
self.hasFired = true;
if (self.hasMoved) {
self.deselect();
checkTurnComplete();
}
} else {
// Out of range feedback
LK.effects.flashObject(self, 0xff0000, 300);
}
}
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
self.destroy();
return true;
}
return false;
};
self.down = function (x, y, obj) {
if (self.unitType !== 'enemy' && currentGameState === 'battle') {
// Clear previous selections first
clearAllSelections();
// Select this unit
self.select();
selectedUnit = self;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c5234
});
/****
* Game Code
****/
var currentGameState = 'language_selection'; // 'language_selection', 'briefing', 'battle', 'victory', 'complete'
var currentBattle = storage.currentBattle || 0;
var battlesWon = storage.battlesWon || 0;
var playerHealth = 100;
var languageSelectionContainer;
var selectedUnit = null;
var playerUnits = [];
var enemyUnits = [];
var objectives = [];
var bullets = [];
var trees = [];
var turnComplete = false;
var currentLanguage = storage.language || 'en'; // 'en' or 'tr'
// Translation system
var translations = {
en: {
battlesWon: 'Battles Won: ',
tapToContinue: 'TAP TO CONTINUE',
beachLanding: 'Beach Landing',
forestPatrol: 'Forest Patrol',
urbanWarfare: 'Urban Warfare',
battle: 'Battle',
languageButton: 'TR'
},
tr: {
battlesWon: 'Kazanılan Savaşlar: ',
tapToContinue: 'DEVAM İÇİN DOKUN',
beachLanding: 'Sahil Çıkarması',
forestPatrol: 'Orman Devriyesi',
urbanWarfare: 'Şehir Savaşı',
battle: 'Savaş',
languageButton: 'EN'
}
};
function t(key) {
return translations[currentLanguage][key] || translations.en[key] || key;
}
// Battle configurations
var battleConfigs = [{
name: {
en: "Beach Landing",
tr: "Sahil Çıkarması"
},
briefing: {
en: ["Commander: Welcome to Operation Overlord, soldier!", "Your mission: Secure the beach and eliminate enemy resistance.", "Move your units carefully - the enemy has defensive positions.", "TAP units to select, then TAP destination to move or fire. Good luck!"],
tr: ["Komutan: Overlord Harekâtına hoş geldin asker!", "Görevin: Sahili ele geçir ve düşman direncini yok et.", "Birliklerini dikkatli hareket ettir - düşmanın savunma mevzileri var.", "Birlikleri seçmek için DOKUN, hareket veya ateş etmek için tekrar DOKUN. İyi şanslar!"]
},
playerStartPositions: [[200, 800, 'soldier'], [200, 900, 'soldier'], [200, 1000, 'tank']],
enemyPositions: [[1600, 400, 'soldier'], [1600, 600, 'tank']],
objectivePos: [1600, 500]
}, {
name: {
en: "Tank Assault",
tr: "Tank Saldırısı"
},
briefing: {
en: ["Heavy armor engagement ahead!", "Use your tanks to break enemy lines.", "Coordinate infantry and armor for maximum effect!"],
tr: ["Ağır zırhlı çatışma yaklaşıyor!", "Düşman hatlarını kırmak için tanklarını kullan.", "Maksimum etki için piyade ve zırhı koordine et!"]
},
playerStartPositions: [[300, 1000, 'tank'], [400, 1000, 'soldier'], [500, 1000, 'tank']],
enemyPositions: [[1400, 300, 'tank'], [1500, 500, 'soldier'], [1300, 700, 'tank']],
objectivePos: [1450, 400]
}, {
name: {
en: "Air Superiority",
tr: "Hava Üstünlüğü"
},
briefing: {
en: ["Control the skies soldier!", "Aircraft have superior range but less armor.", "Use hit and run tactics with air units!"],
tr: ["Gökleri kontrol et asker!", "Uçakların menzili üstün ama zırhı az.", "Hava birlikleriyle vur-kaç taktiği kullan!"]
},
playerStartPositions: [[150, 1100, 'aircraft'], [250, 1100, 'soldier'], [350, 1100, 'aircraft']],
enemyPositions: [[1500, 200, 'aircraft'], [1400, 400, 'tank'], [1600, 600, 'aircraft']],
objectivePos: [1500, 350]
}, {
name: {
en: "Combined Arms",
tr: "Birleşik Kuvvetler"
},
briefing: {
en: ["All unit types in action!", "Coordinate soldiers, tanks, and aircraft.", "Each unit has unique strengths - use them wisely!"],
tr: ["Tüm birlik türleri harekete geçiyor!", "Asker, tank ve uçakları koordine et.", "Her birliğin benzersiz gücü var - akıllıca kullan!"]
},
playerStartPositions: [[200, 1000, 'soldier'], [300, 1000, 'tank'], [400, 1000, 'aircraft'], [500, 1000, 'soldier']],
enemyPositions: [[1400, 300, 'tank'], [1500, 400, 'aircraft'], [1600, 500, 'soldier'], [1300, 600, 'tank']],
objectivePos: [1500, 400]
}];
// Extend battle configs to 10 battles
for (var i = 3; i < 10; i++) {
var baseConfig = battleConfigs[i % 3];
battleConfigs.push({
name: {
en: "Battle " + (i + 1),
tr: "Savaş " + (i + 1)
},
briefing: {
en: ["Commander: Battle " + (i + 1) + " awaits!", "The enemy grows stronger with each encounter.", "Use everything you've learned so far!"],
tr: ["Komutan: Savaş " + (i + 1) + " seni bekliyor!", "Düşman her karşılaşmada daha da güçleniyor.", "Şimdiye kadar öğrendiğin her şeyi kullan!"]
},
playerStartPositions: baseConfig.playerStartPositions,
enemyPositions: baseConfig.enemyPositions,
objectivePos: baseConfig.objectivePos
});
}
// UI Elements
var battlefieldContainer = game.addChild(new Container());
var battlefield = battlefieldContainer.attachAsset('battlefield', {
anchorX: 0.5,
anchorY: 0.5
});
battlefieldContainer.x = 2048 / 2;
battlefieldContainer.y = (2732 - 400) / 2;
var dialogSystem = game.addChild(new DialogSystem());
var battleTitle = new Text2('', {
size: 60,
fill: '#ffffff'
});
battleTitle.anchor.set(0.5, 0);
LK.gui.top.addChild(battleTitle);
battleTitle.y = 100;
var scoreText = new Text2('Battles Won: 0/10', {
size: 40,
fill: '#ffffff'
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -20;
scoreText.y = 20;
var healthText = new Text2('Health: 100', {
size: 40,
fill: '#ff0000'
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120;
healthText.y = 20;
// Language toggle button
var langButton = new Text2(t('languageButton'), {
size: 40,
fill: '#ffffff'
});
langButton.anchor.set(0.5, 0);
LK.gui.topRight.addChild(langButton);
langButton.x = -60;
langButton.y = 80;
langButton.interactive = true;
langButton.buttonMode = true;
langButton.on('pointerdown', function () {
currentLanguage = currentLanguage === 'en' ? 'tr' : 'en';
storage.language = currentLanguage;
langButton.setText(t('languageButton'));
updateScoreDisplay();
// Update dialog continue text
dialogSystem.continueText.setText(t('tapToContinue'));
// Update battle title if currently displayed
var config = battleConfigs[currentBattle];
if (config && config.name && config.name[currentLanguage]) {
battleTitle.setText(config.name[currentLanguage]);
}
});
// Game Functions
function startGame() {
currentGameState = 'briefing';
if (languageSelectionContainer) {
languageSelectionContainer.destroy();
}
battlefieldContainer.visible = true;
battleTitle.visible = true;
scoreText.visible = true;
langButton.visible = true;
dialogSystem.visible = true;
healthText.visible = true;
// Update UI text with selected language
langButton.setText(t('languageButton'));
dialogSystem.continueText.setText(t('tapToContinue'));
// Initialize first battle
setupBattle();
updateScoreDisplay();
var config = battleConfigs[currentBattle];
var firstBriefing = config && config.briefing && config.briefing[currentLanguage] ? config.briefing[currentLanguage] : ["Mission briefing not available"];
dialogSystem.showDialog(firstBriefing);
}
function clearAllSelections() {
selectedUnit = null;
for (var i = 0; i < playerUnits.length; i++) {
playerUnits[i].deselect();
}
}
function setupBattle() {
// Clear previous battle
for (var i = playerUnits.length - 1; i >= 0; i--) {
playerUnits[i].destroy();
}
for (var i = enemyUnits.length - 1; i >= 0; i--) {
enemyUnits[i].destroy();
}
for (var i = objectives.length - 1; i >= 0; i--) {
objectives[i].destroy();
}
for (var i = trees.length - 1; i >= 0; i--) {
trees[i].destroy();
}
playerUnits = [];
enemyUnits = [];
objectives = [];
trees = [];
playerHealth = 100;
updateHealthDisplay();
var config = battleConfigs[currentBattle];
if (config && config.name && config.name[currentLanguage]) {
battleTitle.setText(config.name[currentLanguage]);
}
// Create player units - with safety check
if (config && config.playerStartPositions && config.playerStartPositions.length > 0) {
for (var i = 0; i < config.playerStartPositions.length; i++) {
var pos = config.playerStartPositions[i];
var unitSubType = pos[2] || 'soldier';
var unit = new Unit('player', unitSubType, pos[0], pos[1]);
playerUnits.push(unit);
battlefieldContainer.addChild(unit);
}
}
// Create enemy units at top of screen - with safety check
if (config && config.enemyPositions && config.enemyPositions.length > 0) {
for (var i = 0; i < config.enemyPositions.length; i++) {
var pos = config.enemyPositions[i];
var unitSubType = pos[2] || 'soldier';
// Position enemies at top edge with spread positions
var enemyX = 300 + i * 400 + Math.random() * 200;
var enemyY = -100; // Start from above screen
var enemy = new Unit('enemy', unitSubType, enemyX, enemyY);
enemyUnits.push(enemy);
battlefieldContainer.addChild(enemy);
// Use tween to move enemy down into battlefield area
tween(enemy, {
y: 200 + Math.random() * 200
}, {
duration: 2000,
easing: tween.easeOut
});
}
}
// Create objective - with safety check
if (config && config.objectivePos && config.objectivePos.length >= 2) {
var objPos = config.objectivePos;
var objective = battlefieldContainer.attachAsset('objective', {
anchorX: 0.5,
anchorY: 0.5,
x: objPos[0],
y: objPos[1]
});
objectives.push(objective);
}
// Create trees only at battlefield edges for decoration
for (var i = 0; i < 8; i++) {
// Left edge trees - at the very edge
var leftTree = battlefieldContainer.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1,
x: 50 + Math.random() * 30,
y: 200 + i * 120 + Math.random() * 50
});
leftTree.visible = true;
trees.push(leftTree);
// Right edge trees - at the very edge
var rightTree = battlefieldContainer.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1,
x: 1720 + Math.random() * 30,
y: 200 + i * 120 + Math.random() * 50
});
rightTree.visible = true;
trees.push(rightTree);
}
// Add top edge trees
for (var i = 0; i < 6; i++) {
var topTree = battlefieldContainer.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1,
x: 300 + i * 200 + Math.random() * 100,
y: 50 + Math.random() * 30
});
topTree.visible = true;
trees.push(topTree);
}
// Add bottom edge trees
for (var i = 0; i < 6; i++) {
var bottomTree = battlefieldContainer.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1,
x: 300 + i * 200 + Math.random() * 100,
y: 1150 + Math.random() * 30
});
bottomTree.visible = true;
trees.push(bottomTree);
}
}
function checkTurnComplete() {
// Simplified - just check victory condition
if (checkVictoryCondition()) {
handleVictory();
}
}
function checkVictoryCondition() {
if (enemyUnits.length === 0) return true;
// Check if any player unit is near objective
for (var i = 0; i < playerUnits.length; i++) {
var unit = playerUnits[i];
var objective = objectives[0];
var distance = Math.sqrt(Math.pow(unit.x - objective.x, 2) + Math.pow(unit.y - objective.y, 2));
if (distance < 120) {
return true;
}
}
return false;
}
function handleVictory() {
battlesWon++;
storage.battlesWon = battlesWon;
storage.currentBattle = currentBattle + 1;
LK.getSound('battleWin').play();
updateScoreDisplay();
if (currentBattle >= 9) {
// Won all 10 battles - reset game to start over
currentGameState = 'complete';
var completeMessages = currentLanguage === 'en' ? ["Commander: Outstanding work, soldier!", "You have successfully completed all 10 battles!", "The war is won thanks to your strategic brilliance!", "Starting new campaign..."] : ["Komutan: Olağanüstü iş başardın asker!", "10 savaşın tamamını başarıyla tamamladın!", "Savaş senin stratejik dehanla kazanıldı!", "Yeni kampanya başlıyor..."];
dialogSystem.showDialog(completeMessages);
// Reset game progress
currentBattle = 0;
battlesWon = 0;
storage.currentBattle = 0;
storage.battlesWon = 0;
updateScoreDisplay();
// Start over from first battle
LK.setTimeout(function () {
currentGameState = 'briefing';
setupBattle();
var config = battleConfigs[currentBattle];
var firstBriefing = config && config.briefing && config.briefing[currentLanguage] ? config.briefing[currentLanguage] : ["Mission briefing not available"];
dialogSystem.showDialog(firstBriefing);
}, 2000);
return;
} else {
currentGameState = 'victory';
var victoryMessages = currentLanguage === 'en' ? ["Commander: Excellent work! Battle won!", "Your tactical skills are improving with each victory.", "Prepare for the next engagement, soldier."] : ["Komutan: Mükemmel iş! Savaş kazanıldı!", "Taktik yeteneklerin her zaferle gelişiyor.", "Bir sonraki çatışmaya hazırlan asker."];
dialogSystem.showDialog(victoryMessages);
}
}
function nextBattle() {
currentBattle++;
if (currentBattle < 10) {
currentGameState = 'briefing';
setupBattle();
var config = battleConfigs[currentBattle];
var briefingText = config && config.briefing && config.briefing[currentLanguage] ? config.briefing[currentLanguage] : ["Mission briefing not available"];
dialogSystem.showDialog(briefingText);
}
}
function startBattle() {
currentGameState = 'battle';
}
function updateScoreDisplay() {
scoreText.setText(t('battlesWon') + battlesWon + '/10');
}
function updateHealthDisplay() {
healthText.setText('Health: ' + playerHealth);
if (playerHealth <= 0) {
LK.showGameOver();
}
}
function takeDamageFromEnemy(damage) {
playerHealth -= damage;
if (playerHealth < 0) playerHealth = 0;
updateHealthDisplay();
LK.effects.flashScreen(0xff0000, 500);
}
// Mouse/Touch handling - simplified
battlefieldContainer.down = function (x, y, obj) {
if (currentGameState !== 'battle') return;
// If we have a selected unit, move it to clicked position
if (selectedUnit) {
// Convert click position to battlefield coordinates safely
var localPos;
if (obj && obj.parent && obj.position) {
localPos = battlefieldContainer.toLocal(obj.parent.toGlobal(obj.position));
} else {
// Fallback to using x, y directly as local coordinates
localPos = {
x: x,
y: y
};
}
selectedUnit.moveTo(localPos.x, localPos.y);
}
};
function initializeLanguageSelection() {
// Hide main game UI
battlefieldContainer.visible = false;
battleTitle.visible = false;
scoreText.visible = false;
langButton.visible = false;
dialogSystem.visible = false;
healthText.visible = false;
// Setup selection screen
languageSelectionContainer = new Container();
languageSelectionContainer.x = 2048 / 2;
languageSelectionContainer.y = 2732 / 2;
game.addChild(languageSelectionContainer);
var title = new Text2('Select Language / Dil Seçiniz', {
size: 70,
fill: '#ffffff',
align: 'center'
});
title.anchor.set(0.5, 0.5);
title.y = -350;
languageSelectionContainer.addChild(title);
var btnEn = LK.getAsset('flag_en', {
anchorX: 0.5,
anchorY: 0.5
});
btnEn.y = -100;
btnEn.interactive = true;
btnEn.buttonMode = true;
btnEn.down = function () {
currentLanguage = 'en';
storage.language = 'en';
startGame();
};
languageSelectionContainer.addChild(btnEn);
var btnTr = LK.getAsset('flag_tr', {
anchorX: 0.5,
anchorY: 0.5
});
btnTr.y = 200;
btnTr.interactive = true;
btnTr.buttonMode = true;
btnTr.down = function () {
currentLanguage = 'tr';
storage.language = 'tr';
startGame();
};
languageSelectionContainer.addChild(btnTr);
}
initializeLanguageSelection();
game.update = function () {
if (currentGameState === 'language_selection') return;
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet && bullet.active) {
// Check bullet collisions with enemy units (player bullets)
if (bullet.owner && bullet.owner.unitType !== 'enemy') {
for (var j = 0; j < enemyUnits.length; j++) {
var enemy = enemyUnits[j];
if (enemy) {
var distance = Math.sqrt(Math.pow(bullet.x - enemy.x, 2) + Math.pow(bullet.y - enemy.y, 2));
if (distance < 50) {
if (enemy.takeDamage()) {
enemy.destroy();
enemyUnits.splice(j, 1);
}
bullet.active = false;
bullet.destroy();
bullets.splice(i, 1);
LK.getSound('unitAttack').play();
break;
}
}
}
}
// Check bullet collisions with player units (enemy bullets)
if (bullet && bullet.active && bullet.owner && bullet.owner.unitType === 'enemy') {
for (var j = 0; j < playerUnits.length; j++) {
var player = playerUnits[j];
if (player) {
var distance = Math.sqrt(Math.pow(bullet.x - player.x, 2) + Math.pow(bullet.y - player.y, 2));
if (distance < 50) {
// Calculate damage based on enemy type
var damage = bullet.owner.subType === 'tank' ? 15 : 10;
takeDamageFromEnemy(damage);
if (player.takeDamage()) {
player.destroy();
playerUnits.splice(j, 1);
}
bullet.active = false;
bullet.destroy();
bullets.splice(i, 1);
LK.getSound('unitAttack').play();
break;
}
}
}
}
} else if (bullet && !bullet.active) {
bullets.splice(i, 1);
}
}
// Simplified auto-fire - no restrictions
if (currentGameState === 'battle' && LK.ticks % 90 === 0) {
for (var i = 0; i < playerUnits.length; i++) {
var unit = playerUnits[i];
if (unit) {
// Find closest enemy to auto-fire at
var closestEnemy = null;
var closestDistance = Infinity;
for (var j = 0; j < enemyUnits.length; j++) {
var enemy = enemyUnits[j];
if (enemy) {
var distance = Math.sqrt(Math.pow(unit.x - enemy.x, 2) + Math.pow(unit.y - enemy.y, 2));
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
}
// Auto-fire at closest enemy
if (closestEnemy) {
var bullet = new Bullet(unit.x, unit.y, closestEnemy.x, closestEnemy.y, unit);
bullets.push(bullet);
battlefieldContainer.addChild(bullet);
LK.getSound('bulletFire').play();
LK.effects.flashObject(unit, 0xffff00, 200);
}
}
}
}
// Enhanced AI for enemies - enemy tanks fire from distance at player units
if (currentGameState === 'battle' && enemyUnits.length > 0) {
for (var i = 0; i < enemyUnits.length; i++) {
var enemy = enemyUnits[i];
if (enemy && playerUnits.length > 0) {
// Tank enemies fire faster and from longer distance
var actualFireRate = enemy.subType === 'tank' ? 40 : 120;
if (LK.ticks % actualFireRate === 0) {
var targetPlayer = playerUnits[Math.floor(Math.random() * playerUnits.length)];
var distance = Math.sqrt(Math.pow(targetPlayer.x - enemy.x, 2) + Math.pow(targetPlayer.y - enemy.y, 2));
// Tanks fire from much longer range - up to 600 pixels away
var effectiveRange = enemy.subType === 'tank' ? 600 : enemy.range;
if (distance <= effectiveRange) {
var bullet = new Bullet(enemy.x, enemy.y, targetPlayer.x, targetPlayer.y, enemy);
bullets.push(bullet);
battlefieldContainer.addChild(bullet);
LK.getSound('bulletFire').play();
LK.effects.flashObject(enemy, 0xff0000, 200);
}
}
// Move primarily down from top with some horizontal movement
var moveDirection = Math.random() > 0.5 ? 1 : -1;
var moveX = enemy.x + moveDirection * 60; // Reduced horizontal movement
// Keep within battlefield bounds horizontally (with safety margins)
if (moveX < 300) moveX = 300;
if (moveX > 1500) moveX = 1500;
// Move down into battlefield area but stop before player area
var targetY = Math.min(500, enemy.y + 80);
tween(enemy, {
x: moveX,
y: targetY
}, {
duration: 1500,
easing: tween.easeOut
});
}
}
}
// Check victory condition regularly
if (currentGameState === 'battle' && LK.ticks % 60 === 0) {
if (checkVictoryCondition()) {
handleVictory();
}
}
// Check for close combat (melee when units are very close)
if (currentGameState === 'battle' && LK.ticks % 60 === 0) {
for (var i = playerUnits.length - 1; i >= 0; i--) {
for (var j = enemyUnits.length - 1; j >= 0; j--) {
if (playerUnits[i] && enemyUnits[j]) {
var player = playerUnits[i];
var enemy = enemyUnits[j];
var distance = Math.sqrt(Math.pow(player.x - enemy.x, 2) + Math.pow(player.y - enemy.y, 2));
if (distance < 80) {
LK.getSound('unitAttack').play();
if (Math.random() > 0.5) {
if (enemy.takeDamage()) {
enemyUnits.splice(j, 1);
}
} else {
if (player.takeDamage()) {
playerUnits.splice(i, 1);
}
}
// Check game over condition
if (playerUnits.length === 0) {
LK.showGameOver();
}
}
}
}
}
}
};