User prompt
Place the mounted archer under the normal archer in the deploy panel
User prompt
Add a horseback archer to the game.
User prompt
havana asset ekle
User prompt
oyuna havan ekle ve hareketsiz kalsın ve top fırlatsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a new asset for boostedarrows
User prompt
AFTER LEVEL 5, archers will use other arrows, these are boosted arrows that will hit more than normal arrows.
User prompt
Give more coins after level 4. And increase the health of the trenchs by 20%.
Code edit (1 edits merged)
Please save this source code
User prompt
Make the shield's name a trench. And lower the health of normal guards a little.
User prompt
Add another guard to the Ottoman army, let it be 20 silver coins, let it have a lot of health, but let it not deal any damage to the opponent.
User prompt
Osmanlı ordusuna 30 akçelik bir koruma ekle canı çok olsun ama rakibe hasar vurmasın
User prompt
Zorluk değiştirme olsun ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Deployment phase position yazısı biraz daha yukarıda olsun
User prompt
In the menu, do not write raid number 2 preparation
User prompt
at the menu dont write a akın sayısı
User prompt
Menüdeyken akın sayısı yazısı çıkmaısn
User prompt
Move the raid count text a little higher and add settings to the menu
User prompt
add menu to game
User prompt
Increase Swordsman's range by 3000%
User prompt
Increase Swordsman's range by 1000%
User prompt
Increase the swordsman's price to 15 coins. Increase the swordsman's damage by 80%. Increase the swordsman's health by 50%. Increase the swordsman's speed by 50%.
User prompt
Increase the range of the spearman by 500%. Increase the health of the spearman by 80%. Increase the damage of the spearman by 50%.
User prompt
The archer's price should be 25 coins and the hit damage should be reduced by 9%. The health of the guards should be increased by 40%. The spearman should be able to throw spears.
User prompt
Reduces the number of coins dropped each time we kill an enemy
User prompt
Increase the range of Ottoman archers by 200% and increase their firing speed. Decrease the firing speed of Ottoman artillery. Increase the speed of Timurunfilleri's by 40%.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ArcherEnemy = Container.expand(function () {
var self = Container.call(this);
// Archer enemies have less health but can attack from range
var waveMultiplier = 1 + (currentWave - 1) * 0.3;
self.health = Math.floor(80 * waveMultiplier);
self.maxHealth = Math.floor(80 * waveMultiplier);
self.speed = Math.min(1.5 + (currentWave - 1) * 0.15, 3); // Slower than regular enemies
self.attackPower = Math.floor(25 * waveMultiplier);
self.attackCooldown = 0;
self.maxAttackCooldown = Math.max(80 - (currentWave - 1) * 4, 50); // Slower attacks than regular enemies
self.range = 455; // Archer range (30% increase)
var enemyGraphics = self.attachAsset('enemyArcher', {
anchorX: 0.5,
anchorY: 0.5
});
self.findNearestJanissary = function () {
var nearest = null;
var nearestDistance = Infinity;
for (var i = 0; i < janissaries.length; i++) {
var jan = janissaries[i];
var dx = jan.x - self.x;
var dy = jan.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearest = jan;
nearestDistance = distance;
}
}
return nearest;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = enemyArchers.length - 1; i >= 0; i--) {
if (enemyArchers[i] === self) {
enemyArchers.splice(i, 1);
gold += 8; // Slightly more gold for archer enemies
goldText.setText('Akçe: ' + gold);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var target = self.findNearestJanissary();
if (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.range) {
// Move closer if target is out of range
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
} else if (distance > 120) {
// Stay at range and shoot arrows
if (self.attackCooldown <= 0) {
var enemyArrow = new EnemyArrow();
enemyArrow.x = self.x;
enemyArrow.y = self.y;
enemyArrow.target = target;
enemyArrow.damage = self.attackPower;
enemyArrows.push(enemyArrow);
game.addChild(enemyArrow);
self.attackCooldown = self.maxAttackCooldown;
}
} else {
// Move back if too close (maintain distance)
var angle = Math.atan2(dy, dx);
self.x -= Math.cos(angle) * self.speed;
self.y -= Math.sin(angle) * self.speed;
}
}
};
return self;
});
var Arrow = Container.expand(function () {
var self = Container.call(this);
self.speed = 12;
self.target = null;
self.damage = 30;
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.target.takeDamage(self.damage);
self.destroy();
for (var i = arrows.length - 1; i >= 0; i--) {
if (arrows[i] === self) {
arrows.splice(i, 1);
break;
}
}
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
arrowGraphics.rotation = angle;
}
} else {
self.destroy();
for (var i = arrows.length - 1; i >= 0; i--) {
if (arrows[i] === self) {
arrows.splice(i, 1);
break;
}
}
}
};
return self;
});
var BoostedArrow = Container.expand(function () {
var self = Container.call(this);
self.speed = 15; // Faster than regular arrows
self.target = null;
self.damage = 45; // Higher damage than regular arrows
self.pierceCount = 2; // Can hit multiple enemies
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
// Visual distinction for boosted arrows
arrowGraphics.tint = 0x00FFFF; // Cyan tint for boosted arrows
arrowGraphics.scaleX = 1.3; // Larger size
arrowGraphics.scaleY = 1.3;
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.target.takeDamage(self.damage);
self.pierceCount--;
// If arrow can still pierce, find next target
if (self.pierceCount > 0) {
var nextTarget = self.findNearestEnemyInRange();
if (nextTarget) {
self.target = nextTarget;
} else {
self.destroy();
for (var i = boostedArrows.length - 1; i >= 0; i--) {
if (boostedArrows[i] === self) {
boostedArrows.splice(i, 1);
break;
}
}
}
} else {
self.destroy();
for (var i = boostedArrows.length - 1; i >= 0; i--) {
if (boostedArrows[i] === self) {
boostedArrows.splice(i, 1);
break;
}
}
}
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
arrowGraphics.rotation = angle;
}
} else {
self.destroy();
for (var i = boostedArrows.length - 1; i >= 0; i--) {
if (boostedArrows[i] === self) {
boostedArrows.splice(i, 1);
break;
}
}
}
};
self.findNearestEnemyInRange = function () {
var nearest = null;
var nearestDistance = Infinity;
var maxRange = 200; // Range to find next target for piercing
// Check regular enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy === self.target) continue; // Skip current target
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= maxRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check archer enemies
for (var i = 0; i < enemyArchers.length; i++) {
var enemy = enemyArchers[i];
if (enemy === self.target) continue; // Skip current target
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= maxRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check enemy artillery
for (var i = 0; i < enemyArtillery.length; i++) {
var enemy = enemyArtillery[i];
if (enemy === self.target) continue; // Skip current target
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= maxRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check heavy enemies
for (var i = 0; i < heavyEnemies.length; i++) {
var enemy = heavyEnemies[i];
if (enemy === self.target) continue; // Skip current target
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= maxRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check Timurunfili
for (var i = 0; i < timurunfilis.length; i++) {
var enemy = timurunfilis[i];
if (enemy === self.target) continue; // Skip current target
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= maxRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
return nearest;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.speed = 15;
self.target = null;
self.damage = 60;
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.target.takeDamage(self.damage);
self.destroy();
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
bulletGraphics.rotation = angle;
}
} else {
self.destroy();
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
}
};
return self;
});
var Cannonball = Container.expand(function () {
var self = Container.call(this);
self.speed = 8; // Slower than bullets
self.target = null;
self.damage = 80;
var cannonballGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Visual distinction for cannonballs
cannonballGraphics.tint = 0x444444; // Dark gray for cannonballs
cannonballGraphics.scaleX = 2; // Larger size
cannonballGraphics.scaleY = 2;
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 40) {
// Create explosion effect with tween
tween(cannonballGraphics, {
scaleX: 4,
scaleY: 4,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.target.takeDamage(self.damage);
self.destroy();
for (var i = cannonballs.length - 1; i >= 0; i--) {
if (cannonballs[i] === self) {
cannonballs.splice(i, 1);
break;
}
}
}
});
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
}
} else {
self.destroy();
for (var i = cannonballs.length - 1; i >= 0; i--) {
if (cannonballs[i] === self) {
cannonballs.splice(i, 1);
break;
}
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Scale enemy stats based on current wave for increased difficulty
var waveMultiplier = 1 + (currentWave - 1) * 0.3; // 30% increase per wave
self.health = Math.floor(120 * waveMultiplier);
self.maxHealth = Math.floor(120 * waveMultiplier);
self.speed = Math.min(2 + (currentWave - 1) * 0.2, 4); // Cap speed at 4
self.attackPower = Math.floor(35 * waveMultiplier);
self.attackCooldown = 0;
self.maxAttackCooldown = Math.max(60 - (currentWave - 1) * 3, 30); // Faster attacks, min 30
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.findNearestJanissary = function () {
var nearest = null;
var nearestDistance = Infinity;
for (var i = 0; i < janissaries.length; i++) {
var jan = janissaries[i];
var dx = jan.x - self.x;
var dy = jan.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearest = jan;
nearestDistance = distance;
}
}
return nearest;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
gold += 5;
goldText.setText('Akçe: ' + gold);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var target = self.findNearestJanissary();
if (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 60) {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
} else {
if (self.attackCooldown <= 0) {
target.takeDamage(self.attackPower);
self.attackCooldown = self.maxAttackCooldown;
LK.effects.flashObject(target, 0xff0000, 200);
}
}
}
};
return self;
});
var EnemyArrow = Container.expand(function () {
var self = Container.call(this);
self.speed = 10;
self.target = null;
self.damage = 25;
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
arrowGraphics.tint = 0xff4444; // Red tint for enemy arrows
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.target.takeDamage(self.damage);
self.destroy();
for (var i = enemyArrows.length - 1; i >= 0; i--) {
if (enemyArrows[i] === self) {
enemyArrows.splice(i, 1);
break;
}
}
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
arrowGraphics.rotation = angle;
}
} else {
self.destroy();
for (var i = enemyArrows.length - 1; i >= 0; i--) {
if (enemyArrows[i] === self) {
enemyArrows.splice(i, 1);
break;
}
}
}
};
return self;
});
var EnemyArtillery = Container.expand(function () {
var self = Container.call(this);
// Enemy artillery has high health and long range
var waveMultiplier = 1 + (currentWave - 1) * 0.3;
self.health = Math.floor(200 * waveMultiplier);
self.maxHealth = Math.floor(200 * waveMultiplier);
self.speed = 0.5; // Very slow movement
self.attackPower = Math.floor(72 * waveMultiplier); // Reduced by 10% from 80 to 72
self.attackCooldown = 0;
self.maxAttackCooldown = Math.max(120 - (currentWave - 1) * 5, 80); // Slow but powerful attacks
self.range = 1288; // Double the original range (644 * 2)
var enemyGraphics = self.attachAsset('enemyArtillery', {
anchorX: 0.5,
anchorY: 0.5
});
self.findNearestJanissary = function () {
var nearest = null;
var nearestDistance = Infinity;
for (var i = 0; i < janissaries.length; i++) {
var jan = janissaries[i];
var dx = jan.x - self.x;
var dy = jan.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearest = jan;
nearestDistance = distance;
}
}
return nearest;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = enemyArtillery.length - 1; i >= 0; i--) {
if (enemyArtillery[i] === self) {
enemyArtillery.splice(i, 1);
gold += 12; // High gold reward for destroying artillery
goldText.setText('Akçe: ' + gold);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var target = self.findNearestJanissary();
if (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
// Artillery stays in position and shoots
if (self.attackCooldown <= 0) {
var enemyBullet = new EnemyBullet();
enemyBullet.x = self.x;
enemyBullet.y = self.y;
enemyBullet.target = target;
enemyBullet.damage = self.attackPower;
enemyBullets.push(enemyBullet);
game.addChild(enemyBullet);
self.attackCooldown = self.maxAttackCooldown;
}
} else if (distance > self.range + 100) {
// Only move if target is very far away
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
self.speed = 8; // Slower than regular bullets
self.target = null;
self.damage = 80;
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0xff6666; // Red tint for enemy bullets
bulletGraphics.scaleX = 1.5; // Larger bullets
bulletGraphics.scaleY = 1.5;
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.target.takeDamage(self.damage);
self.destroy();
for (var i = enemyBullets.length - 1; i >= 0; i--) {
if (enemyBullets[i] === self) {
enemyBullets.splice(i, 1);
break;
}
}
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
bulletGraphics.rotation = angle;
}
} else {
self.destroy();
for (var i = enemyBullets.length - 1; i >= 0; i--) {
if (enemyBullets[i] === self) {
enemyBullets.splice(i, 1);
break;
}
}
}
};
return self;
});
var HeavyEnemy = Container.expand(function () {
var self = Container.call(this);
// Heavy enemies have high health and damage but are slow
var waveMultiplier = 1 + (currentWave - 1) * 0.3;
self.health = Math.floor(250 * waveMultiplier);
self.maxHealth = Math.floor(250 * waveMultiplier);
self.speed = Math.min(1 + (currentWave - 1) * 0.1, 2); // Slower than other enemies
self.attackPower = Math.floor(50 * waveMultiplier);
self.attackCooldown = 0;
self.maxAttackCooldown = Math.max(80 - (currentWave - 1) * 3, 40); // Slower attacks
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Make heavy enemies visually distinct
enemyGraphics.tint = 0x666666; // Darker color
enemyGraphics.scaleX = 1.3; // Larger size
enemyGraphics.scaleY = 1.3;
self.findNearestJanissary = function () {
var nearest = null;
var nearestDistance = Infinity;
for (var i = 0; i < janissaries.length; i++) {
var jan = janissaries[i];
var dx = jan.x - self.x;
var dy = jan.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearest = jan;
nearestDistance = distance;
}
}
return nearest;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = heavyEnemies.length - 1; i >= 0; i--) {
if (heavyEnemies[i] === self) {
heavyEnemies.splice(i, 1);
gold += 15; // High gold reward for heavy enemies
goldText.setText('Akçe: ' + gold);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var target = self.findNearestJanissary();
if (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 60) {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
} else {
if (self.attackCooldown <= 0) {
target.takeDamage(self.attackPower);
self.attackCooldown = self.maxAttackCooldown;
LK.effects.flashObject(target, 0xff0000, 200);
}
}
}
};
return self;
});
var Janissary = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
// Apply 20% buff to all Ottoman soldiers
var baseHealth = type === 'shielded' ? 140 : type === 'gunner' ? 150 : type === 'cavalry' ? 150 : type === 'spearman' ? 180 : type === 'swordsman' ? 150 : type === 'guard' ? 264 : type === 'mortar' ? 200 : 100;
var baseAttackPower = type === 'archer' ? 27 : type === 'spearman' ? 60 : type === 'swordsman' ? 117 : type === 'shielded' ? 35 : type === 'gunner' ? 51 : type === 'guard' ? 0 : type === 'mortar' ? 80 : 50;
self.health = Math.floor(baseHealth * 1.2); // 20% buff
self.maxHealth = Math.floor(baseHealth * 1.2); // 20% buff
self.attackPower = Math.floor(baseAttackPower * 1.2); // 20% buff
self.range = type === 'archer' ? 1560 : type === 'spearman' ? 1500 : type === 'swordsman' ? 27280 : type === 'shielded' ? 80 : type === 'gunner' ? 878 : type === 'guard' ? 80 : type === 'mortar' ? 800 : 80;
self.attackCooldown = 0;
self.maxAttackCooldown = type === 'archer' ? 40 : type === 'spearman' ? 70 : type === 'swordsman' ? 40 : type === 'shielded' ? 50 : type === 'gunner' ? 70 : type === 'guard' ? 50 : type === 'mortar' ? 120 : 25;
self.isDragging = false;
self.target = null;
var unitGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
var goldDisplayText = new Text2('', {
size: 30,
fill: 0xFFD700
});
goldDisplayText.anchor.set(0.5, 0);
goldDisplayText.x = -20;
goldDisplayText.y = 80;
self.addChild(goldDisplayText);
self.updateGoldDisplay = function () {
var goldCost = type === 'archer' ? 25 : type === 'spearman' ? 20 : type === 'swordsman' ? 15 : type === 'shielded' ? 10 : type === 'gunner' ? 18 : type === 'guard' ? 20 : type === 'mortar' ? 35 : 30;
var displayText = type === 'guard' ? goldCost + ' akçe (Siper)' : type === 'mortar' ? goldCost + ' akçe (Havan)' : goldCost + ' akçe';
goldDisplayText.setText(displayText);
};
self.updateGoldDisplay();
self.findNearestEnemy = function () {
var nearest = null;
var nearestDistance = Infinity;
// Check regular enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Cavalry and swordsman have extended range for target acquisition to ensure they always charge
// Shielded soldiers use normal range since they stay in position
var effectiveRange = self.type === 'cavalry' || self.type === 'swordsman' ? 800 : self.range;
if (distance <= effectiveRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check archer enemies
for (var i = 0; i < enemyArchers.length; i++) {
var enemy = enemyArchers[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Cavalry and swordsman have extended range for target acquisition to ensure they always charge
// Shielded soldiers use normal range since they stay in position
var effectiveRange = self.type === 'cavalry' || self.type === 'swordsman' ? 800 : self.range;
if (distance <= effectiveRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check enemy artillery
for (var i = 0; i < enemyArtillery.length; i++) {
var enemy = enemyArtillery[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var effectiveRange = self.type === 'cavalry' || self.type === 'swordsman' ? 800 : self.range;
if (distance <= effectiveRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check heavy enemies
for (var i = 0; i < heavyEnemies.length; i++) {
var enemy = heavyEnemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var effectiveRange = self.type === 'cavalry' || self.type === 'swordsman' ? 800 : self.range;
if (distance <= effectiveRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check Timurunfili
for (var i = 0; i < timurunfilis.length; i++) {
var enemy = timurunfilis[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var effectiveRange = self.type === 'cavalry' || self.type === 'swordsman' ? 800 : self.range;
if (distance <= effectiveRange && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
return nearest;
};
self.attack = function (target) {
if (self.attackCooldown <= 0) {
if (self.type === 'archer') {
if (currentWave > 5) {
// Use boosted arrows after level 5
var boostedArrow = new BoostedArrow();
boostedArrow.x = self.x;
boostedArrow.y = self.y;
boostedArrow.target = target;
boostedArrow.damage = self.attackPower;
boostedArrows.push(boostedArrow);
game.addChild(boostedArrow);
} else {
// Use regular arrows for levels 1-5
var arrow = new Arrow();
arrow.x = self.x;
arrow.y = self.y;
arrow.target = target;
arrow.damage = self.attackPower;
arrows.push(arrow);
game.addChild(arrow);
}
LK.getSound('bowRelease').play();
} else if (self.type === 'spearman') {
var spear = new Spear();
spear.x = self.x;
spear.y = self.y;
spear.target = target;
spear.damage = self.attackPower;
spears.push(spear);
game.addChild(spear);
LK.getSound('spearThrow').play();
} else if (self.type === 'cavalry') {
// Cavalry melee attack
target.takeDamage(self.attackPower);
LK.getSound('swordClash').play();
LK.effects.flashObject(target, 0xff0000, 200);
} else if (self.type === 'shielded') {
// Shielded soldier melee attack
target.takeDamage(self.attackPower);
LK.getSound('swordClash').play();
LK.effects.flashObject(target, 0xff0000, 200);
} else if (self.type === 'gunner') {
// Gunner shoots bullets
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.attackPower;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('gunShot').play();
} else if (self.type === 'guard') {
// Guard does not deal any damage - just stands guard
// No attack action, just presence
} else if (self.type === 'mortar') {
// Mortar shoots cannonballs
var cannonball = new Cannonball();
cannonball.x = self.x;
cannonball.y = self.y;
cannonball.target = target;
cannonball.damage = self.attackPower;
cannonballs.push(cannonball);
game.addChild(cannonball);
LK.getSound('gunShot').play();
} else {
// Swordsman melee attack
target.takeDamage(self.attackPower);
LK.getSound('swordClash').play();
LK.effects.flashObject(target, 0xff0000, 200);
}
self.attackCooldown = self.maxAttackCooldown;
}
};
self.takeDamage = function (damage) {
// Shielded soldiers take reduced damage (50% damage reduction)
var actualDamage = self.type === 'shielded' ? Math.ceil(damage * 0.5) : damage;
self.health -= actualDamage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = janissaries.length - 1; i >= 0; i--) {
if (janissaries[i] === self) {
janissaries.splice(i, 1);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (!self.isDragging) {
self.target = self.findNearestEnemy();
if (self.target) {
if (self.type === 'cavalry') {
// Cavalry charges towards enemies
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 60) {
// Move towards enemy - keep charging until very close
var angle = Math.atan2(dy, dx);
var moveSpeed = 7.2; // Cavalry charging speed (reduced by 10%)
self.x += Math.cos(angle) * moveSpeed;
self.y += Math.sin(angle) * moveSpeed;
} else {
// Attack when close enough but keep moving to stay engaged
self.attack(self.target);
// Continue slight movement to maintain engagement
if (distance > 30) {
var angle = Math.atan2(dy, dx);
var moveSpeed = 1.8; // Slower movement when in combat (reduced by 10%)
self.x += Math.cos(angle) * moveSpeed;
self.y += Math.sin(angle) * moveSpeed;
}
}
} else if (self.type === 'swordsman') {
// Swordsmen charge towards enemies like cavalry
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 80) {
// Move towards enemy - keep charging until close enough to attack
var angle = Math.atan2(dy, dx);
var moveSpeed = 6; // Swordsman speed for charging
self.x += Math.cos(angle) * moveSpeed;
self.y += Math.sin(angle) * moveSpeed;
} else {
// Attack when close enough and keep moving to stay engaged
self.attack(self.target);
// Continue movement to maintain engagement and follow the enemy
var angle = Math.atan2(dy, dx);
var moveSpeed = 3; // Moderate movement when in combat to stay close
self.x += Math.cos(angle) * moveSpeed;
self.y += Math.sin(angle) * moveSpeed;
}
} else if (self.type === 'shielded') {
// Shielded soldiers stay in position and attack enemies when they come within range
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 80) {
// Attack when enemy is close enough, but don't move
self.attack(self.target);
}
// Shielded soldiers do not move towards enemies - they stay in their defensive position
} else if (self.type === 'guard') {
// Guards stay in position and do not attack - they are purely defensive
// They just maintain their position and absorb damage
} else if (self.type === 'mortar') {
// Mortars stay in position and attack from range
self.attack(self.target);
} else {
// Other units attack from their position
self.attack(self.target);
}
}
}
};
self.down = function (x, y, obj) {
if (deploymentPhase) {
self.isDragging = true;
draggedUnit = self;
}
};
return self;
});
var Mortar = Container.expand(function () {
var self = Container.call(this);
self.type = 'mortar';
self.health = 200;
self.maxHealth = 200;
self.attackPower = 80;
self.range = 800; // Long range for mortar
self.attackCooldown = 0;
self.maxAttackCooldown = 120; // Slow firing rate
self.isDragging = false;
self.target = null;
var mortarGraphics = self.attachAsset('havan', {
anchorX: 0.5,
anchorY: 0.5
});
var goldDisplayText = new Text2('', {
size: 30,
fill: 0xFFD700
});
goldDisplayText.anchor.set(0.5, 0);
goldDisplayText.x = -20;
goldDisplayText.y = 80;
self.addChild(goldDisplayText);
self.updateGoldDisplay = function () {
goldDisplayText.setText('35 akçe (Havan)');
};
self.updateGoldDisplay();
self.findNearestEnemy = function () {
var nearest = null;
var nearestDistance = Infinity;
// Check regular enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check archer enemies
for (var i = 0; i < enemyArchers.length; i++) {
var enemy = enemyArchers[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check enemy artillery
for (var i = 0; i < enemyArtillery.length; i++) {
var enemy = enemyArtillery[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check heavy enemies
for (var i = 0; i < heavyEnemies.length; i++) {
var enemy = heavyEnemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
// Check Timurunfili
for (var i = 0; i < timurunfilis.length; i++) {
var enemy = timurunfilis[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < nearestDistance) {
nearest = enemy;
nearestDistance = distance;
}
}
return nearest;
};
self.attack = function (target) {
if (self.attackCooldown <= 0) {
var cannonball = new Cannonball();
cannonball.x = self.x;
cannonball.y = self.y;
cannonball.target = target;
cannonball.damage = self.attackPower;
cannonballs.push(cannonball);
game.addChild(cannonball);
LK.getSound('gunShot').play();
self.attackCooldown = self.maxAttackCooldown;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = janissaries.length - 1; i >= 0; i--) {
if (janissaries[i] === self) {
janissaries.splice(i, 1);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (!self.isDragging) {
self.target = self.findNearestEnemy();
if (self.target) {
// Mortar stays stationary and attacks
self.attack(self.target);
}
}
};
self.down = function (x, y, obj) {
if (deploymentPhase) {
self.isDragging = true;
draggedUnit = self;
}
};
return self;
});
var Spear = Container.expand(function () {
var self = Container.call(this);
self.speed = 10;
self.target = null;
self.damage = 40;
var spearGraphics = self.attachAsset('spear', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (self.target && self.target.health > 0) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
self.target.takeDamage(self.damage);
self.destroy();
for (var i = spears.length - 1; i >= 0; i--) {
if (spears[i] === self) {
spears.splice(i, 1);
break;
}
}
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
spearGraphics.rotation = angle;
}
} else {
self.destroy();
for (var i = spears.length - 1; i >= 0; i--) {
if (spears[i] === self) {
spears.splice(i, 1);
break;
}
}
}
};
return self;
});
var Timurunfili = Container.expand(function () {
var self = Container.call(this);
// Timurunfili has the highest health and damage but moves very slowly
var waveMultiplier = 1 + (currentWave - 1) * 0.3;
self.health = Math.floor(400 * waveMultiplier); // Higher health than everyone else
self.maxHealth = Math.floor(400 * waveMultiplier);
self.speed = 1.344; // Slow movement (increased by 40% from original 0.96)
self.attackPower = Math.floor(80 * waveMultiplier); // Higher damage than everyone else
self.attackCooldown = 0;
self.maxAttackCooldown = Math.max(70 - (currentWave - 1) * 3, 50);
var timurunfiliGraphics = self.attachAsset('Timurunfili', {
anchorX: 0.5,
anchorY: 0.5
});
// Make Timurunfili visually distinct with larger size
timurunfiliGraphics.scaleX = 1.5; // Larger than other enemies
timurunfiliGraphics.scaleY = 1.5;
self.findNearestJanissary = function () {
var nearest = null;
var nearestDistance = Infinity;
for (var i = 0; i < janissaries.length; i++) {
var jan = janissaries[i];
var dx = jan.x - self.x;
var dy = jan.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearest = jan;
nearestDistance = distance;
}
}
return nearest;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
self.destroy();
for (var i = timurunfilis.length - 1; i >= 0; i--) {
if (timurunfilis[i] === self) {
timurunfilis.splice(i, 1);
gold += 25; // Highest gold reward for Timurunfili
goldText.setText('Akçe: ' + gold);
break;
}
}
}
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
var target = self.findNearestJanissary();
if (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 60) {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed; // Slow movement
self.y += Math.sin(angle) * self.speed;
} else {
if (self.attackCooldown <= 0) {
target.takeDamage(self.attackPower);
self.attackCooldown = self.maxAttackCooldown;
LK.effects.flashObject(target, 0xff0000, 200);
}
}
}
};
return self;
});
var UnitButton = Container.expand(function (unitType, cost) {
var self = Container.call(this);
self.unitType = unitType;
self.cost = cost;
var buttonGraphics = self.attachAsset(unitType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.down = function (x, y, obj) {
if (deploymentPhase && gold >= self.cost) {
var newUnit = new Janissary(self.unitType);
newUnit.x = x;
newUnit.y = y;
newUnit.isDragging = true;
draggedUnit = newUnit;
janissaries.push(newUnit);
game.addChild(newUnit);
gold -= self.cost;
goldText.setText('Akçe: ' + gold);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F4F2F
});
/****
* Game Code
****/
var battlefield = game.addChild(LK.getAsset('battlefield', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 300
}));
var deployPanel = game.addChild(LK.getAsset('deployPanel', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
var janissaries = [];
var enemies = [];
var enemyArchers = [];
var enemyArtillery = [];
var heavyEnemies = [];
var timurunfilis = [];
var enemyArrows = [];
var enemyBullets = [];
var arrows = [];
var boostedArrows = [];
var spears = [];
var bullets = [];
var cannonballs = [];
var currentWave = 1;
var maxWaves = 10;
var waveTimer = 0;
var deploymentPhase = true;
var draggedUnit = null;
var gold = 100;
var waveText = new Text2('Akın sayısı: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 1);
LK.gui.bottomRight.addChild(waveText);
waveText.x = -20;
waveText.y = -20;
var goldText = new Text2('Akçe: 100', {
size: 60,
fill: 0xFFFF00
});
goldText.anchor.set(0, 0);
LK.gui.topRight.addChild(goldText);
goldText.x = -400;
goldText.y = 20;
var phaseText = new Text2('Deployment Phase - Position Your Units!', {
size: 70,
fill: 0x00FF00
});
phaseText.anchor.set(0.5, 0);
LK.gui.center.addChild(phaseText);
phaseText.y = -200;
var archerButton = new UnitButton('archer', 25);
archerButton.x = 300;
archerButton.y = 150;
game.addChild(archerButton);
var archerGoldText = new Text2('25 akçe', {
size: 30,
fill: 0xFFD700
});
archerGoldText.anchor.set(0.5, 0);
archerGoldText.x = 300;
archerGoldText.y = 220;
game.addChild(archerGoldText);
var spearmanButton = new UnitButton('spearman', 20);
spearmanButton.x = 500;
spearmanButton.y = 150;
game.addChild(spearmanButton);
var spearmanGoldText = new Text2('20 akçe', {
size: 30,
fill: 0xFFD700
});
spearmanGoldText.anchor.set(0.5, 0);
spearmanGoldText.x = 500;
spearmanGoldText.y = 220;
game.addChild(spearmanGoldText);
var cavalryButton = new UnitButton('cavalry', 30);
cavalryButton.x = 700;
cavalryButton.y = 150;
game.addChild(cavalryButton);
var cavalryGoldText = new Text2('30 akçe', {
size: 30,
fill: 0xFFD700
});
cavalryGoldText.anchor.set(0.5, 0);
cavalryGoldText.x = 700;
cavalryGoldText.y = 220;
game.addChild(cavalryGoldText);
var swordsmanButton = new UnitButton('swordsman', 15);
swordsmanButton.x = 900;
swordsmanButton.y = 150;
game.addChild(swordsmanButton);
var swordsmanGoldText = new Text2('15 akçe', {
size: 30,
fill: 0xFFD700
});
swordsmanGoldText.anchor.set(0.5, 0);
swordsmanGoldText.x = 900;
swordsmanGoldText.y = 220;
game.addChild(swordsmanGoldText);
var shieldedButton = new UnitButton('shielded', 10);
shieldedButton.x = 1100;
shieldedButton.y = 150;
game.addChild(shieldedButton);
var shieldedGoldText = new Text2('10 akçe', {
size: 30,
fill: 0xFFD700
});
shieldedGoldText.anchor.set(0.5, 0);
shieldedGoldText.x = 1100;
shieldedGoldText.y = 220;
game.addChild(shieldedGoldText);
var gunnerButton = new UnitButton('gunner', 18);
gunnerButton.x = 1300;
gunnerButton.y = 150;
game.addChild(gunnerButton);
var gunnerGoldText = new Text2('18 akçe', {
size: 30,
fill: 0xFFD700
});
gunnerGoldText.anchor.set(0.5, 0);
gunnerGoldText.x = 1300;
gunnerGoldText.y = 220;
game.addChild(gunnerGoldText);
var guardButton = new UnitButton('guard', 20);
guardButton.x = 1500;
guardButton.y = 150;
game.addChild(guardButton);
var guardGoldText = new Text2('20 akçe (Siper)', {
size: 30,
fill: 0xFFD700
});
guardGoldText.anchor.set(0.5, 0);
guardGoldText.x = 1500;
guardGoldText.y = 220;
game.addChild(guardGoldText);
var mortarButton = new UnitButton('mortar', 35);
mortarButton.x = 1700;
mortarButton.y = 150;
game.addChild(mortarButton);
var mortarGoldText = new Text2('35 akçe (Havan)', {
size: 30,
fill: 0xFFD700
});
mortarGoldText.anchor.set(0.5, 0);
mortarGoldText.x = 1700;
mortarGoldText.y = 220;
game.addChild(mortarGoldText);
var startBattleText = new Text2('Start Battle', {
size: 60,
fill: 0xFF0000
});
startBattleText.anchor.set(0.5, 0.5);
startBattleText.x = 1900;
startBattleText.y = 250;
game.addChild(startBattleText);
startBattleText.down = function (x, y, obj) {
if (deploymentPhase && janissaries.length > 0) {
deploymentPhase = false;
phaseText.setText('Akın sayısı ' + currentWave + ' - Defend!');
phaseText.tint = 0xff0000;
startBattleText.visible = false;
archerButton.visible = false;
spearmanButton.visible = false;
cavalryButton.visible = false;
swordsmanButton.visible = false;
shieldedButton.visible = false;
gunnerButton.visible = false;
guardButton.visible = false;
archerGoldText.visible = false;
spearmanGoldText.visible = false;
cavalryGoldText.visible = false;
swordsmanGoldText.visible = false;
shieldedGoldText.visible = false;
gunnerGoldText.visible = false;
guardGoldText.visible = false;
mortarButton.visible = false;
mortarGoldText.visible = false;
spawnWave();
}
};
function spawnWave() {
// More aggressive scaling for higher waves
var enemyCount = currentWave <= 5 ? currentWave * 3 + 2 : currentWave * 4 + 5;
var archerCount = Math.floor(enemyCount * 0.3); // 30% of enemies are archers
var regularCount = enemyCount - archerCount;
// Spawn regular enemies
for (var i = 0; i < regularCount; i++) {
var enemy = new Enemy();
var side = Math.floor(Math.random() * 2); // Only 2 sides now (left and right)
if (side === 0) {
// Spawn from middle right
enemy.x = 2048;
enemy.y = 300 + 900 + Math.random() * 300; // Middle area (1200-1500 range)
} else {
// Spawn from middle left
enemy.x = 0;
enemy.y = 300 + 900 + Math.random() * 300; // Middle area (1200-1500 range)
}
enemies.push(enemy);
game.addChild(enemy);
}
// Spawn archer enemies
for (var i = 0; i < archerCount; i++) {
var archerEnemy = new ArcherEnemy();
var side = Math.floor(Math.random() * 2);
if (side === 0) {
// Spawn from middle right
archerEnemy.x = 2048;
archerEnemy.y = 300 + 900 + Math.random() * 300;
} else {
// Spawn from middle left
archerEnemy.x = 0;
archerEnemy.y = 300 + 900 + Math.random() * 300;
}
enemyArchers.push(archerEnemy);
game.addChild(archerEnemy);
}
// Spawn enemy artillery in middle of screen (1 per wave starting from wave 2)
if (currentWave >= 2) {
var artilleryCount = Math.floor(currentWave / 2); // 1 artillery every 2 waves
for (var i = 0; i < artilleryCount; i++) {
var enemyArt = new EnemyArtillery();
enemyArt.x = 1024 + (Math.random() - 0.5) * 200; // Center with some variation
enemyArt.y = 300 + 1050 + (Math.random() - 0.5) * 200; // Middle of battlefield
enemyArtillery.push(enemyArt);
game.addChild(enemyArt);
}
}
// Spawn Timurunfili starting from wave 5 (after level 4)
if (currentWave >= 5) {
var timurunfiliCount = Math.floor((currentWave - 4) * 1); // 1 Timurunfili per wave after wave 4
for (var i = 0; i < timurunfiliCount; i++) {
var timurunfili = new Timurunfili();
var side = Math.floor(Math.random() * 2);
if (side === 0) {
// Spawn from middle right
timurunfili.x = 2048;
timurunfili.y = 300 + 900 + Math.random() * 300;
} else {
// Spawn from middle left
timurunfili.x = 0;
timurunfili.y = 300 + 900 + Math.random() * 300;
}
timurunfilis.push(timurunfili);
game.addChild(timurunfili);
}
}
// Spawn heavy enemies starting from wave 6 (after level 5)
if (currentWave >= 6) {
var heavyCount = Math.floor((currentWave - 5) * 2); // 2 heavy enemies per wave after wave 5
for (var i = 0; i < heavyCount; i++) {
var heavyEnemy = new HeavyEnemy();
var side = Math.floor(Math.random() * 2);
if (side === 0) {
// Spawn from middle right
heavyEnemy.x = 2048;
heavyEnemy.y = 300 + 900 + Math.random() * 300;
} else {
// Spawn from middle left
heavyEnemy.x = 0;
heavyEnemy.y = 300 + 900 + Math.random() * 300;
}
heavyEnemies.push(heavyEnemy);
game.addChild(heavyEnemy);
}
}
}
function checkWaveComplete() {
if (enemies.length === 0 && enemyArchers.length === 0 && enemyArtillery.length === 0 && heavyEnemies.length === 0 && timurunfilis.length === 0 && !deploymentPhase) {
currentWave++;
if (currentWave > maxWaves) {
LK.showYouWin();
} else {
deploymentPhase = true;
phaseText.setText('Akın sayısı ' + currentWave + ' Preparation');
phaseText.tint = 0x00ff00;
waveText.setText('Akın sayısı: ' + currentWave);
startBattleText.visible = true;
archerButton.visible = true;
spearmanButton.visible = true;
cavalryButton.visible = true;
swordsmanButton.visible = true;
shieldedButton.visible = true;
gunnerButton.visible = true;
guardButton.visible = true;
archerGoldText.visible = true;
spearmanGoldText.visible = true;
cavalryGoldText.visible = true;
swordsmanGoldText.visible = true;
shieldedGoldText.visible = true;
gunnerGoldText.visible = true;
guardGoldText.visible = true;
mortarButton.visible = true;
mortarGoldText.visible = true;
// Increase gold reward for later waves - more coins after level 4
var goldReward;
if (currentWave > 4) {
goldReward = 50 + (currentWave - 1) * 20; // Double the increase after level 4
} else {
goldReward = 50 + (currentWave - 1) * 10; // Regular increase for first 4 levels
}
gold += goldReward;
goldText.setText('Akçe: ' + gold);
}
}
}
function checkGameOver() {
if (janissaries.length === 0 && !deploymentPhase) {
LK.showGameOver();
}
}
game.move = function (x, y, obj) {
if (draggedUnit && deploymentPhase) {
if (y > 300) {
draggedUnit.x = x;
draggedUnit.y = y;
}
}
};
game.up = function (x, y, obj) {
if (draggedUnit) {
draggedUnit.isDragging = false;
draggedUnit = null;
}
};
var resetButton = new Text2('Reset', {
size: 50,
fill: 0xFF0000
});
resetButton.anchor.set(0, 1);
resetButton.x = 20;
resetButton.y = -20;
LK.gui.bottomLeft.addChild(resetButton);
resetButton.down = function (x, y, obj) {
// Clear all janissaries from battlefield before resetting arrays
for (var i = janissaries.length - 1; i >= 0; i--) {
janissaries[i].destroy();
}
// Reset all game variables to initial state
janissaries = [];
enemies = [];
enemyArchers = [];
enemyArtillery = [];
heavyEnemies = [];
timurunfilis = [];
enemyArrows = [];
enemyBullets = [];
arrows = [];
boostedArrows = [];
spears = [];
bullets = [];
cannonballs = [];
currentWave = 1;
maxWaves = 10;
waveTimer = 0;
deploymentPhase = true;
draggedUnit = null;
gold = 100;
// Clear all units from the game
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.type || child.unitType || child === startBattleText || child === archerButton || child === spearmanButton || child === cavalryButton || child === swordsmanButton || child === shieldedButton || child === gunnerButton || child === guardButton || child === mortarButton || child === archerGoldText || child === spearmanGoldText || child === cavalryGoldText || child === swordsmanGoldText || child === shieldedGoldText || child === gunnerGoldText || child === guardGoldText || child === mortarGoldText) {
continue; // Keep UI elements
}
// Remove projectiles and units
if (child.speed !== undefined || child.health !== undefined) {
child.destroy();
}
}
// Reset UI text
waveText.setText('Akın sayısı: 1');
goldText.setText('Akçe: 100');
phaseText.setText('Deployment Phase - Position Your Units!');
phaseText.tint = 0x00FF00;
// Show deployment UI
startBattleText.visible = true;
archerButton.visible = true;
spearmanButton.visible = true;
cavalryButton.visible = true;
swordsmanButton.visible = true;
shieldedButton.visible = true;
gunnerButton.visible = true;
guardButton.visible = true;
archerGoldText.visible = true;
spearmanGoldText.visible = true;
cavalryGoldText.visible = true;
swordsmanGoldText.visible = true;
shieldedGoldText.visible = true;
gunnerGoldText.visible = true;
guardGoldText.visible = true;
mortarButton.visible = true;
mortarGoldText.visible = true;
};
game.update = function () {
for (var i = janissaries.length - 1; i >= 0; i--) {
if (janissaries[i].health <= 0) {
janissaries[i].destroy();
janissaries.splice(i, 1);
}
}
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].health <= 0) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
for (var i = arrows.length - 1; i >= 0; i--) {
if (!arrows[i].target || arrows[i].target.health <= 0) {
arrows[i].destroy();
arrows.splice(i, 1);
}
}
for (var i = boostedArrows.length - 1; i >= 0; i--) {
if (!boostedArrows[i].target || boostedArrows[i].target.health <= 0) {
boostedArrows[i].destroy();
boostedArrows.splice(i, 1);
}
}
for (var i = spears.length - 1; i >= 0; i--) {
if (!spears[i].target || spears[i].target.health <= 0) {
spears[i].destroy();
spears.splice(i, 1);
}
}
for (var i = bullets.length - 1; i >= 0; i--) {
if (!bullets[i].target || bullets[i].target.health <= 0) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
for (var i = cannonballs.length - 1; i >= 0; i--) {
if (!cannonballs[i].target || cannonballs[i].target.health <= 0) {
cannonballs[i].destroy();
cannonballs.splice(i, 1);
}
}
for (var i = enemyArchers.length - 1; i >= 0; i--) {
if (enemyArchers[i].health <= 0) {
enemyArchers[i].destroy();
enemyArchers.splice(i, 1);
}
}
for (var i = enemyArrows.length - 1; i >= 0; i--) {
if (!enemyArrows[i].target || enemyArrows[i].target.health <= 0) {
enemyArrows[i].destroy();
enemyArrows.splice(i, 1);
}
}
for (var i = enemyArtillery.length - 1; i >= 0; i--) {
if (enemyArtillery[i].health <= 0) {
enemyArtillery[i].destroy();
enemyArtillery.splice(i, 1);
}
}
for (var i = enemyBullets.length - 1; i >= 0; i--) {
if (!enemyBullets[i].target || enemyBullets[i].target.health <= 0) {
enemyBullets[i].destroy();
enemyBullets.splice(i, 1);
}
}
for (var i = heavyEnemies.length - 1; i >= 0; i--) {
if (heavyEnemies[i].health <= 0) {
heavyEnemies[i].destroy();
heavyEnemies.splice(i, 1);
}
}
for (var i = timurunfilis.length - 1; i >= 0; i--) {
if (timurunfilis[i].health <= 0) {
timurunfilis[i].destroy();
timurunfilis.splice(i, 1);
}
}
checkWaveComplete();
checkGameOver();
}; ===================================================================
--- original.js
+++ change.js
@@ -297,8 +297,62 @@
}
};
return self;
});
+var Cannonball = Container.expand(function () {
+ var self = Container.call(this);
+ self.speed = 8; // Slower than bullets
+ self.target = null;
+ self.damage = 80;
+ var cannonballGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Visual distinction for cannonballs
+ cannonballGraphics.tint = 0x444444; // Dark gray for cannonballs
+ cannonballGraphics.scaleX = 2; // Larger size
+ cannonballGraphics.scaleY = 2;
+ self.update = function () {
+ if (self.target && self.target.health > 0) {
+ var dx = self.target.x - self.x;
+ var dy = self.target.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 40) {
+ // Create explosion effect with tween
+ tween(cannonballGraphics, {
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ self.target.takeDamage(self.damage);
+ self.destroy();
+ for (var i = cannonballs.length - 1; i >= 0; i--) {
+ if (cannonballs[i] === self) {
+ cannonballs.splice(i, 1);
+ break;
+ }
+ }
+ }
+ });
+ } else {
+ var angle = Math.atan2(dy, dx);
+ self.x += Math.cos(angle) * self.speed;
+ self.y += Math.sin(angle) * self.speed;
+ }
+ } else {
+ self.destroy();
+ for (var i = cannonballs.length - 1; i >= 0; i--) {
+ if (cannonballs[i] === self) {
+ cannonballs.splice(i, 1);
+ break;
+ }
+ }
+ }
+ };
+ return self;
+});
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Scale enemy stats based on current wave for increased difficulty
var waveMultiplier = 1 + (currentWave - 1) * 0.3; // 30% increase per wave
@@ -603,16 +657,16 @@
var Janissary = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
// Apply 20% buff to all Ottoman soldiers
- var baseHealth = type === 'shielded' ? 140 : type === 'gunner' ? 150 : type === 'cavalry' ? 150 : type === 'spearman' ? 180 : type === 'swordsman' ? 150 : type === 'guard' ? 264 : 100;
- var baseAttackPower = type === 'archer' ? 27 : type === 'spearman' ? 60 : type === 'swordsman' ? 117 : type === 'shielded' ? 35 : type === 'gunner' ? 51 : type === 'guard' ? 0 : 50;
+ var baseHealth = type === 'shielded' ? 140 : type === 'gunner' ? 150 : type === 'cavalry' ? 150 : type === 'spearman' ? 180 : type === 'swordsman' ? 150 : type === 'guard' ? 264 : type === 'mortar' ? 200 : 100;
+ var baseAttackPower = type === 'archer' ? 27 : type === 'spearman' ? 60 : type === 'swordsman' ? 117 : type === 'shielded' ? 35 : type === 'gunner' ? 51 : type === 'guard' ? 0 : type === 'mortar' ? 80 : 50;
self.health = Math.floor(baseHealth * 1.2); // 20% buff
self.maxHealth = Math.floor(baseHealth * 1.2); // 20% buff
self.attackPower = Math.floor(baseAttackPower * 1.2); // 20% buff
- self.range = type === 'archer' ? 1560 : type === 'spearman' ? 1500 : type === 'swordsman' ? 27280 : type === 'shielded' ? 80 : type === 'gunner' ? 878 : type === 'guard' ? 80 : 80;
+ self.range = type === 'archer' ? 1560 : type === 'spearman' ? 1500 : type === 'swordsman' ? 27280 : type === 'shielded' ? 80 : type === 'gunner' ? 878 : type === 'guard' ? 80 : type === 'mortar' ? 800 : 80;
self.attackCooldown = 0;
- self.maxAttackCooldown = type === 'archer' ? 40 : type === 'spearman' ? 70 : type === 'swordsman' ? 40 : type === 'shielded' ? 50 : type === 'gunner' ? 70 : type === 'guard' ? 50 : 25;
+ self.maxAttackCooldown = type === 'archer' ? 40 : type === 'spearman' ? 70 : type === 'swordsman' ? 40 : type === 'shielded' ? 50 : type === 'gunner' ? 70 : type === 'guard' ? 50 : type === 'mortar' ? 120 : 25;
self.isDragging = false;
self.target = null;
var unitGraphics = self.attachAsset(type, {
anchorX: 0.5,
@@ -626,10 +680,10 @@
goldDisplayText.x = -20;
goldDisplayText.y = 80;
self.addChild(goldDisplayText);
self.updateGoldDisplay = function () {
- var goldCost = type === 'archer' ? 25 : type === 'spearman' ? 20 : type === 'swordsman' ? 15 : type === 'shielded' ? 10 : type === 'gunner' ? 18 : type === 'guard' ? 20 : 30;
- var displayText = type === 'guard' ? goldCost + ' akçe (Siper)' : goldCost + ' akçe';
+ var goldCost = type === 'archer' ? 25 : type === 'spearman' ? 20 : type === 'swordsman' ? 15 : type === 'shielded' ? 10 : type === 'gunner' ? 18 : type === 'guard' ? 20 : type === 'mortar' ? 35 : 30;
+ var displayText = type === 'guard' ? goldCost + ' akçe (Siper)' : type === 'mortar' ? goldCost + ' akçe (Havan)' : goldCost + ' akçe';
goldDisplayText.setText(displayText);
};
self.updateGoldDisplay();
self.findNearestEnemy = function () {
@@ -755,8 +809,18 @@
LK.getSound('gunShot').play();
} else if (self.type === 'guard') {
// Guard does not deal any damage - just stands guard
// No attack action, just presence
+ } else if (self.type === 'mortar') {
+ // Mortar shoots cannonballs
+ var cannonball = new Cannonball();
+ cannonball.x = self.x;
+ cannonball.y = self.y;
+ cannonball.target = target;
+ cannonball.damage = self.attackPower;
+ cannonballs.push(cannonball);
+ game.addChild(cannonball);
+ LK.getSound('gunShot').play();
} else {
// Swordsman melee attack
target.takeDamage(self.attackPower);
LK.getSound('swordClash').play();
@@ -841,8 +905,11 @@
// Shielded soldiers do not move towards enemies - they stay in their defensive position
} else if (self.type === 'guard') {
// Guards stay in position and do not attack - they are purely defensive
// They just maintain their position and absorb damage
+ } else if (self.type === 'mortar') {
+ // Mortars stay in position and attack from range
+ self.attack(self.target);
} else {
// Other units attack from their position
self.attack(self.target);
}
@@ -856,8 +923,141 @@
}
};
return self;
});
+var Mortar = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = 'mortar';
+ self.health = 200;
+ self.maxHealth = 200;
+ self.attackPower = 80;
+ self.range = 800; // Long range for mortar
+ self.attackCooldown = 0;
+ self.maxAttackCooldown = 120; // Slow firing rate
+ self.isDragging = false;
+ self.target = null;
+ var mortarGraphics = self.attachAsset('havan', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var goldDisplayText = new Text2('', {
+ size: 30,
+ fill: 0xFFD700
+ });
+ goldDisplayText.anchor.set(0.5, 0);
+ goldDisplayText.x = -20;
+ goldDisplayText.y = 80;
+ self.addChild(goldDisplayText);
+ self.updateGoldDisplay = function () {
+ goldDisplayText.setText('35 akçe (Havan)');
+ };
+ self.updateGoldDisplay();
+ self.findNearestEnemy = function () {
+ var nearest = null;
+ var nearestDistance = Infinity;
+ // Check regular enemies
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ var dx = enemy.x - self.x;
+ var dy = enemy.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range && distance < nearestDistance) {
+ nearest = enemy;
+ nearestDistance = distance;
+ }
+ }
+ // Check archer enemies
+ for (var i = 0; i < enemyArchers.length; i++) {
+ var enemy = enemyArchers[i];
+ var dx = enemy.x - self.x;
+ var dy = enemy.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range && distance < nearestDistance) {
+ nearest = enemy;
+ nearestDistance = distance;
+ }
+ }
+ // Check enemy artillery
+ for (var i = 0; i < enemyArtillery.length; i++) {
+ var enemy = enemyArtillery[i];
+ var dx = enemy.x - self.x;
+ var dy = enemy.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range && distance < nearestDistance) {
+ nearest = enemy;
+ nearestDistance = distance;
+ }
+ }
+ // Check heavy enemies
+ for (var i = 0; i < heavyEnemies.length; i++) {
+ var enemy = heavyEnemies[i];
+ var dx = enemy.x - self.x;
+ var dy = enemy.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range && distance < nearestDistance) {
+ nearest = enemy;
+ nearestDistance = distance;
+ }
+ }
+ // Check Timurunfili
+ for (var i = 0; i < timurunfilis.length; i++) {
+ var enemy = timurunfilis[i];
+ var dx = enemy.x - self.x;
+ var dy = enemy.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range && distance < nearestDistance) {
+ nearest = enemy;
+ nearestDistance = distance;
+ }
+ }
+ return nearest;
+ };
+ self.attack = function (target) {
+ if (self.attackCooldown <= 0) {
+ var cannonball = new Cannonball();
+ cannonball.x = self.x;
+ cannonball.y = self.y;
+ cannonball.target = target;
+ cannonball.damage = self.attackPower;
+ cannonballs.push(cannonball);
+ game.addChild(cannonball);
+ LK.getSound('gunShot').play();
+ self.attackCooldown = self.maxAttackCooldown;
+ }
+ };
+ self.takeDamage = function (damage) {
+ self.health -= damage;
+ if (self.health <= 0) {
+ self.health = 0;
+ self.destroy();
+ for (var i = janissaries.length - 1; i >= 0; i--) {
+ if (janissaries[i] === self) {
+ janissaries.splice(i, 1);
+ break;
+ }
+ }
+ }
+ };
+ self.update = function () {
+ if (self.attackCooldown > 0) {
+ self.attackCooldown--;
+ }
+ if (!self.isDragging) {
+ self.target = self.findNearestEnemy();
+ if (self.target) {
+ // Mortar stays stationary and attacks
+ self.attack(self.target);
+ }
+ }
+ };
+ self.down = function (x, y, obj) {
+ if (deploymentPhase) {
+ self.isDragging = true;
+ draggedUnit = self;
+ }
+ };
+ return self;
+});
var Spear = Container.expand(function () {
var self = Container.call(this);
self.speed = 10;
self.target = null;
@@ -1028,8 +1228,9 @@
var arrows = [];
var boostedArrows = [];
var spears = [];
var bullets = [];
+var cannonballs = [];
var currentWave = 1;
var maxWaves = 10;
var waveTimer = 0;
var deploymentPhase = true;
@@ -1141,14 +1342,26 @@
guardGoldText.anchor.set(0.5, 0);
guardGoldText.x = 1500;
guardGoldText.y = 220;
game.addChild(guardGoldText);
+var mortarButton = new UnitButton('mortar', 35);
+mortarButton.x = 1700;
+mortarButton.y = 150;
+game.addChild(mortarButton);
+var mortarGoldText = new Text2('35 akçe (Havan)', {
+ size: 30,
+ fill: 0xFFD700
+});
+mortarGoldText.anchor.set(0.5, 0);
+mortarGoldText.x = 1700;
+mortarGoldText.y = 220;
+game.addChild(mortarGoldText);
var startBattleText = new Text2('Start Battle', {
size: 60,
fill: 0xFF0000
});
startBattleText.anchor.set(0.5, 0.5);
-startBattleText.x = 1700;
+startBattleText.x = 1900;
startBattleText.y = 250;
game.addChild(startBattleText);
startBattleText.down = function (x, y, obj) {
if (deploymentPhase && janissaries.length > 0) {
@@ -1169,8 +1382,10 @@
swordsmanGoldText.visible = false;
shieldedGoldText.visible = false;
gunnerGoldText.visible = false;
guardGoldText.visible = false;
+ mortarButton.visible = false;
+ mortarGoldText.visible = false;
spawnWave();
}
};
function spawnWave() {
@@ -1284,8 +1499,10 @@
swordsmanGoldText.visible = true;
shieldedGoldText.visible = true;
gunnerGoldText.visible = true;
guardGoldText.visible = true;
+ mortarButton.visible = true;
+ mortarGoldText.visible = true;
// Increase gold reward for later waves - more coins after level 4
var goldReward;
if (currentWave > 4) {
goldReward = 50 + (currentWave - 1) * 20; // Double the increase after level 4
@@ -1341,8 +1558,9 @@
arrows = [];
boostedArrows = [];
spears = [];
bullets = [];
+ cannonballs = [];
currentWave = 1;
maxWaves = 10;
waveTimer = 0;
deploymentPhase = true;
@@ -1350,9 +1568,9 @@
gold = 100;
// Clear all units from the game
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
- if (child.type || child.unitType || child === startBattleText || child === archerButton || child === spearmanButton || child === cavalryButton || child === swordsmanButton || child === shieldedButton || child === gunnerButton || child === guardButton || child === archerGoldText || child === spearmanGoldText || child === cavalryGoldText || child === swordsmanGoldText || child === shieldedGoldText || child === gunnerGoldText || child === guardGoldText) {
+ if (child.type || child.unitType || child === startBattleText || child === archerButton || child === spearmanButton || child === cavalryButton || child === swordsmanButton || child === shieldedButton || child === gunnerButton || child === guardButton || child === mortarButton || child === archerGoldText || child === spearmanGoldText || child === cavalryGoldText || child === swordsmanGoldText || child === shieldedGoldText || child === gunnerGoldText || child === guardGoldText || child === mortarGoldText) {
continue; // Keep UI elements
}
// Remove projectiles and units
if (child.speed !== undefined || child.health !== undefined) {
@@ -1379,8 +1597,10 @@
swordsmanGoldText.visible = true;
shieldedGoldText.visible = true;
gunnerGoldText.visible = true;
guardGoldText.visible = true;
+ mortarButton.visible = true;
+ mortarGoldText.visible = true;
};
game.update = function () {
for (var i = janissaries.length - 1; i >= 0; i--) {
if (janissaries[i].health <= 0) {
@@ -1417,8 +1637,14 @@
bullets[i].destroy();
bullets.splice(i, 1);
}
}
+ for (var i = cannonballs.length - 1; i >= 0; i--) {
+ if (!cannonballs[i].target || cannonballs[i].target.health <= 0) {
+ cannonballs[i].destroy();
+ cannonballs.splice(i, 1);
+ }
+ }
for (var i = enemyArchers.length - 1; i >= 0; i--) {
if (enemyArchers[i].health <= 0) {
enemyArchers[i].destroy();
enemyArchers.splice(i, 1);
animasyon Çizgi dizi tarzında bir Osmanlı okçusu. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında bir At üstünde bir Osmanlı süvarisi. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında bir Osmanlı mızrakçısı. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında Beyaz bir ok. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında bir toprak ama ne ağaç var nede çimen sadece dümdüz kahverengi toprak açık kahverengi olsun toprak. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında bir bizans askeri. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında elinde kılıç olan bir osmanlı yeniçerisi. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında kalkanlı osmanlı askeri.Kalkanları büyük olsun In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında osmanlı topçusu ekle bu askerin yanında savaş topuda olsun. In-Game asset. 2d. High contrast. No shadows
animasyon çizgi dizi tarzında siyah top. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında bizans okçusu. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında bizans topçusu. In-Game asset. 2d. High contrast. No shadows
Mızrak. In-Game asset. 2d. High contrast. No shadows
animasyon çizgi dizi tarzında bir siper. In-Game asset. 2d. High contrast. No shadows
mor bir arrow. In-Game asset. 2d. High contrast. No shadows
at üstünde okçu. In-Game asset. 2d. High contrast. No shadows
Animasyon çizgi dizi tarzında yeniçeri. In-Game asset. 2d. High contrast. No shadows
animasyo çizgi dizi gibi bir osmanlı yeniçerisi ama güçlü. In-Game asset. 2d. High contrast. No shadows