User prompt
silahı büyüt tekrar
User prompt
keskin nişancın kendisini küçült silahını biraz büyüt
User prompt
riffle sniper silahı 5 mermi normal riffle silahı 5 mermi otamatik riffle 30 mermi şeklinde şarjorler olsun mermi doldurma animasyonuda olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
silahı büyüt
User prompt
silahların boyutunu biraz büyüt
User prompt
keskin nişancıyı büyüt
User prompt
duvar fazla büyük olmuş biraz küçük
User prompt
Duvar büyüklüğü daha fazla olsun ayrıca duvar kendi assets olsun keskin nişancı ile aynı olmasın
User prompt
karakterimiz biraz daha büyük olsun
User prompt
yaptığımız duvarlar daha büyük olsun ayrıca düşmanlar duvarın içinden geçemesin ve duvarı kırmaya başlar hatta duvarı kırırken animasyon olsun kafasını geriye alıp ileri doğru hızle dönerek duvara hasar veriyormuş gibi yapsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
duvarları bir kez satın aldığımızda tekrar satın ala biliyoruz tek seferliğine satın almıyoruz ayrıca yapı mağazasında sıkıntı var onuda düzelt hit box sıkıtnıs var
User prompt
When we purchase structures, a semi-transparent wall appears in our hands. We can place this wall wherever we want. When a monster comes to the placed wall, it collides with the wall and breaks it. While the wall is breaking, its health is visible with a small bar
User prompt
yapıları satın aldığımızda elimize yarım saydam bir duvar geliyor bu duvarı istediğimiz yere koya biliyoruz ve koyduğumuz yere canavar geldiğinde canvar duvara çarpıyor ve duvarı kırıyor duvar kırlırken duvarın canı gözüküyor küçük bar ile
User prompt
yapılar mağzasını biraz daha sağ ve aşşağa haraket ettir
User prompt
sol üst köşeye yeni yapı mağzası yap içinde 3 tane yapı olsun yapıların fiyatı sırayla 10-20-30 olacak ilk baştaki duvar sonraki daha güçlü duvar diğeri ise keskin nişancı kulesi
User prompt
silah sıktığımızca silahın namlusunda ateş efekti olsun
User prompt
tamam düşmanlar öldükten sonra yan yatsın ve soluklaşarak yok olsun
User prompt
gölgeler çalışmadı düşmanlarda gözükmüyor
User prompt
düşmanların altında gölge olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
etrafta çalılar ve ağaçlar dursun ama etkileşim olmasın
User prompt
score artıkça aynanda doğan düşmanlar artsın
User prompt
etrafa çalıları yerleştir hitbox yok
User prompt
score artıkça düşman çeşidi artsın ve düşman doğmo hızı ona göre artsın
User prompt
kayayı ve keskin nişancının boyutunu artır kayayı daha fazl artır boyunu
User prompt
ilk başta 10 düşman ile başlasın sonra %25 yerine %50 artırılsın sayı istenilen sayıya ulaşıldığında otomatik olarak bütün düşmanlar ölsün
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
currency: 0
});
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15; // Default speed, will be overridden
self.damage = 1; // Default damage, will be overridden
self.active = true;
self.update = function () {
if (!self.active) return;
// Use directional movement if speedX and speedY are defined
if (self.speedX !== undefined && self.speedY !== undefined) {
self.x += self.speedX;
self.y += self.speedY;
} else {
// Fallback to original vertical-only movement
self.y -= self.speed;
}
// Bullet goes off screen (check all edges)
if (self.y < -50 || self.y > 2732 + 50 || self.x < -50 || self.x > 2048 + 50) {
self.active = false;
}
};
self.hit = function () {
self.active = false;
LK.getSound('enemyHit').play();
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
var Bunker = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('bunker', {
anchorX: 0.5,
anchorY: 0.5
});
self.damageIndicator = self.attachAsset('damageIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
self.damageIndicator.alpha = 0;
self.damageIndicator.originalX = 0;
self.damageIndicator.originalY = 0;
self.showDamage = function (percentage) {
// Make indicator more visible as health decreases
self.damageIndicator.alpha = 1 - percentage;
// Move the indicator based on health percentage
// Lower health = more movement
var moveFactor = (1 - percentage) * 10;
self.damageIndicator.x = self.damageIndicator.originalX + (Math.random() * 2 - 1) * moveFactor;
self.damageIndicator.y = self.damageIndicator.originalY + (Math.random() * 2 - 1) * moveFactor;
// Change tint to become redder as health decreases
var healthColor = Math.floor(percentage * 255);
self.damageIndicator.tint = 255 << 16 | healthColor << 8 | healthColor;
};
// Store original position
self.onAddedToStage = function () {
self.damageIndicator.originalX = self.damageIndicator.x;
self.damageIndicator.originalY = self.damageIndicator.y;
};
return self;
});
var Bush = Container.expand(function () {
var self = Container.call(this);
// Random bush appearance with slight variation
var type = Math.floor(Math.random() * 3);
var size = Math.random() * 0.5 + 0.8; // Size between 0.8 and 1.3
var rotation = Math.random() * 0.3 - 0.15; // Slight rotation
// Create the bush using bullet shape with green tint
self.graphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2E8B57,
// Sea green color
scaleX: size,
scaleY: size
});
// Apply random rotation
self.graphics.rotation = rotation;
// Add some details to make bushes look different from each other
if (type === 0) {
// First type - taller bush
self.graphics.scale.y *= 1.3;
self.graphics.tint = 0x228B22; // Forest green
} else if (type === 1) {
// Second type - wider bush
self.graphics.scale.x *= 1.2;
self.graphics.tint = 0x006400; // Dark green
} else {
// Third type - round bush
self.graphics.tint = 0x3CB371; // Medium sea green
}
return self;
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'regular';
// Set properties based on enemy type
switch (self.type) {
case 'fast':
self.graphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
self.speed = 3;
self.hp = 1;
self.damage = 10;
self.points = 15;
self.currency = 2;
break;
case 'tank':
self.graphics = self.attachAsset('tankEnemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
self.speed = 1;
self.hp = 5;
self.damage = 25;
self.points = 30;
self.currency = 5;
break;
default:
// regular
self.graphics = self.attachAsset('regularEnemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
self.speed = 2;
self.hp = 2;
self.damage = 15;
self.points = 10;
self.currency = 1;
}
self.active = true;
self.update = function () {
if (!self.active) return;
// Basic diagonal movement pattern
if (!self.moveDirection) {
self.moveDirection = Math.random() > 0.5 ? 1 : -1; // Random initial direction
self.moveCounter = 0;
self.maxMoveDistance = Math.random() * 30 + 20; // Random move distance
}
// Move diagonally
self.y += self.speed;
self.x += self.moveDirection * (self.speed * 0.5);
// Switch direction after a certain distance
self.moveCounter += self.speed;
if (self.moveCounter >= self.maxMoveDistance) {
self.moveDirection *= -1; // Reverse direction
self.moveCounter = 0;
self.maxMoveDistance = Math.random() * 30 + 20; // New random distance
}
// Add walking animation
if (LK.ticks % 10 === 0) {
// Tilt the enemy slightly in the direction of movement
tween(self.graphics, {
rotation: self.moveDirection * 0.1
}, {
duration: 250,
easing: tween.easeInOut
});
}
// Ensure enemy stays within screen bounds
if (self.x < 50) {
self.x = 50;
self.moveDirection = 1;
} else if (self.x > 2048 - 50) {
self.x = 2048 - 50;
self.moveDirection = -1;
}
// Check if enemy reached the bunker
if (self.y > bunkerY - 50) {
self.attackBunker();
}
};
self.takeDamage = function (amount) {
self.hp -= amount;
if (self.hp <= 0) {
self.die();
} else {
LK.effects.flashObject(self, 0xffffff, 200);
}
};
self.die = function () {
self.active = false;
var currentScore = LK.getScore();
var scoreMultiplier = 1;
// Increase rewards based on score progression
if (currentScore > 300) {
scoreMultiplier = 2.5;
} else if (currentScore > 200) {
scoreMultiplier = 2;
} else if (currentScore > 100) {
scoreMultiplier = 1.5;
}
LK.setScore(currentScore + self.points);
// Set different currency values based on enemy type with score multiplier
if (self.type === 'regular') {
currency += Math.ceil(3 * scoreMultiplier);
} else if (self.type === 'fast') {
currency += Math.ceil(4 * scoreMultiplier);
} else if (self.type === 'tank') {
currency += Math.ceil(6 * scoreMultiplier);
} else {
currency += Math.ceil(self.currency * scoreMultiplier); // Fallback
}
updateUI();
};
self.attackBunker = function () {
bunkerHealth -= self.damage;
updateBunkerHealth();
LK.getSound('bunkerHit').play();
LK.effects.flashObject(bunker, 0xff0000, 500);
// Make damage indicator visible when taking damage
bunker.damageIndicator.alpha = 1;
self.active = false;
// Check if bunker is destroyed
if (bunkerHealth <= 0) {
gameOver();
}
};
return self;
});
var Sniper = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('sniper', {
anchorX: 0.5,
anchorY: 0.5
});
// Add rifle that will rotate toward cursor
self.rifle = self.attachAsset('rifle', {
anchorX: 0,
anchorY: 0.5
});
// Create references to all weapon graphics but only show the active one
self.weapons = {
basic: self.rifle,
sniper: LK.getAsset('sniper_rifle', {
anchorX: 0,
anchorY: 0.5
}),
machine: LK.getAsset('machine_gun', {
anchorX: 0,
anchorY: 0.5
})
};
// Add other weapons but hide them initially
self.weapons.sniper.visible = false;
self.weapons.machine.visible = false;
self.weapons.sniper.x = 10;
self.weapons.machine.x = 10;
self.addChild(self.weapons.sniper);
self.addChild(self.weapons.machine);
// Position rifle to appear like it's being held by the sniper
self.rifle.x = 10;
// Initialize weapon positions
Object.keys(self.weapons).forEach(function (key) {
// Standard positioning
self.weapons[key].x = 10;
self.weapons[key].y = 0;
self.weapons[key].scale.x = 1;
});
self.fireRate = 1000; // ms between shots
self.lastShot = 0;
self.bulletDamage = 1;
self.bulletSpeed = 15; // Default bullet speed
self.currentWeapon = 'basic'; // Track current weapon type
// Method to update rifle rotation based on cursor position
self.updateAim = function (targetX, targetY) {
// Calculate angle to target
var angle = Math.atan2(targetY - self.y, targetX - self.x);
// Determine if target is on left or right side of the screen
var isTargetOnLeftSide = targetX < 2048 / 2;
// Update sniper graphics based on which side target is on
if (isTargetOnLeftSide) {
// Target is on left side - character faces left
self.graphics.scale.x = -1; // Flip character horizontally
// Adjust weapon positions for left-facing stance
Object.keys(self.weapons).forEach(function (key) {
self.weapons[key].x = -10; // Offset for left side
self.weapons[key].scale.x = -1; // Flip weapon horizontally
});
} else {
// Target is on right side - character faces right
self.graphics.scale.x = 1; // Normal orientation
// Adjust weapon positions for right-facing stance
Object.keys(self.weapons).forEach(function (key) {
self.weapons[key].x = 10; // Normal position on right side
self.weapons[key].scale.x = 1; // Normal weapon orientation
});
}
// Set all weapons rotation to aim at target, properly adjusted for direction
if (isTargetOnLeftSide) {
// When facing left, we need to adjust the angle
self.weapons.basic.rotation = angle + Math.PI;
self.weapons.sniper.rotation = angle + Math.PI;
self.weapons.machine.rotation = angle + Math.PI;
} else {
self.weapons.basic.rotation = angle;
self.weapons.sniper.rotation = angle;
self.weapons.machine.rotation = angle;
}
return angle;
};
self.canShoot = function () {
var now = Date.now();
if (now - self.lastShot >= self.fireRate) {
self.lastShot = now;
return true;
}
return false;
};
self.switchWeapon = function (weaponIndex) {
// Hide all weapons first
self.weapons.basic.visible = false;
self.weapons.sniper.visible = false;
self.weapons.machine.visible = false;
// Show selected weapon based on index
switch (weaponIndex) {
case 0:
self.weapons.basic.visible = true;
self.currentWeapon = 'basic';
break;
case 1:
self.weapons.sniper.visible = true;
self.currentWeapon = 'sniper';
break;
case 2:
self.weapons.machine.visible = true;
self.currentWeapon = 'machine';
break;
default:
self.weapons.basic.visible = true;
self.currentWeapon = 'basic';
}
};
self.shoot = function (targetX, targetY) {
if (!self.canShoot()) return null;
// Update rifle aim
var angle = self.updateAim(targetX, targetY);
var bullet = new Bullet();
// Determine if target is on left or right side of the screen
var isTargetOnLeftSide = targetX < 2048 / 2;
var activeWeapon = self.weapons[self.currentWeapon];
var rifleLength = activeWeapon.width;
// Calculate bullet spawn position at end of rifle, with direction awareness
var bulletAngle = angle;
if (isTargetOnLeftSide) {
// When facing left, we need to adjust calculations
bulletAngle = angle + Math.PI; // Adjust for left facing
}
// Calculate proper bullet starting position and direction
bullet.x = self.x + Math.cos(bulletAngle) * rifleLength;
bullet.y = self.y + Math.sin(bulletAngle) * rifleLength;
// Set bullet direction - always use the original angle for bullet direction
bullet.speedX = Math.cos(angle) * bullet.speed;
bullet.speedY = Math.sin(angle) * bullet.speed;
bullet.damage = self.bulletDamage;
bullet.speed = self.bulletSpeed; // Set bullet speed from sniper
// Customize bullet appearance based on weapon type
if (self.currentWeapon === 'sniper') {
bullet.graphics.tint = 0x33CCFF; // Blue tint for sniper bullets
bullet.graphics.scale.set(0.8, 1.5); // Thinner, longer bullets
} else if (self.currentWeapon === 'machine') {
bullet.graphics.tint = 0xFFCC33; // Orange tint for machine gun bullets
bullet.graphics.scale.set(1.2, 0.8); // Wider, shorter bullets
}
// Add weapon recoil effect based on weapon type
var recoilDistance = 10; // Default recoil for rifle
var recoilDuration = 100; // Default recoil recovery time
var originX = activeWeapon.x;
// Set different recoil parameters based on weapon type
if (self.currentWeapon === 'sniper') {
recoilDistance = 20; // Stronger recoil for sniper
recoilDuration = 150;
} else if (self.currentWeapon === 'machine') {
recoilDistance = 12; // Moderate recoil for machine gun
recoilDuration = 80;
}
// Calculate recoil direction (opposite to shot direction)
// For recoil, we need to consider which direction the weapon is facing
var recoilDirection = isTargetOnLeftSide ? 1 : -1; // Reverse for left-facing
var recoilX = recoilDirection * Math.cos(bulletAngle) * recoilDistance;
var recoilY = -Math.sin(bulletAngle) * recoilDistance;
// Apply recoil to the active weapon
tween(activeWeapon, {
x: originX + recoilX,
y: recoilY
}, {
duration: 50,
// Quick recoil
easing: tween.easeOut,
onFinish: function onFinish() {
// Recover from recoil
tween(activeWeapon, {
x: originX,
y: 0
}, {
duration: recoilDuration,
easing: tween.easeInOut
});
}
});
LK.getSound('shoot').play();
return bullet;
};
return self;
});
var Tree = Container.expand(function () {
var self = Container.call(this);
// Random tree appearance with variation
var type = Math.floor(Math.random() * 3);
var size = Math.random() * 0.7 + 1.2; // Size between 1.2 and 1.9
var rotation = Math.random() * 0.2 - 0.1; // Slight rotation
// Create the tree trunk using bullet shape with brown tint
var treeTrunk = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8B4513,
// Saddle brown color
scaleX: size * 0.3,
scaleY: size * 0.8
});
// Create the tree crown using bullet shape with green tint
var treeCrown = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x228B22,
// Forest green color
scaleX: size * 1.2,
scaleY: size * 1.0
});
// Position crown on top of trunk
treeCrown.y = -treeTrunk.height * 0.5;
// Apply random rotation
self.rotation = rotation;
// Add some details to make trees look different from each other
if (type === 0) {
// First type - taller tree with darker green
treeCrown.scale.y *= 1.4;
treeCrown.tint = 0x006400; // Dark green
} else if (type === 1) {
// Second type - wider tree with lighter green
treeCrown.scale.x *= 1.3;
treeCrown.tint = 0x32CD32; // Lime green
} else {
// Third type - autumn tree with different color
treeCrown.tint = 0xFF8C00; // Dark orange
}
return self;
});
var WaveCountdown = Container.expand(function () {
var self = Container.call(this);
self.countdownTime = 60; // 60 seconds default
self.active = false;
// Create countdown text
self.countdownText = new Text2(self.countdownTime, {
size: 150,
fill: 0xFFFFFF
});
self.countdownText.anchor.set(0.5, 0.5);
self.addChild(self.countdownText);
// Create skip button
self.skipButton = new Text2("SKIP", {
size: 80,
fill: 0xFFFF00
});
self.skipButton.anchor.set(0.5, 0.5);
self.skipButton.y = 100;
self.addChild(self.skipButton);
// Skip button background for better visibility
var skipButtonBg = LK.getAsset('bullet', {
width: 200,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
skipButtonBg.alpha = 0.8;
skipButtonBg.y = 100;
self.addChild(skipButtonBg);
// Custom swap implementation since swapChildren is not available
var parent = self.skipButton.parent;
var skipButtonIndex = parent.children.indexOf(skipButtonBg);
var buttonIndex = parent.children.indexOf(self.skipButton);
// Manual reordering of children to create swap effect
if (skipButtonIndex !== -1 && buttonIndex !== -1) {
// Remove both from parent
parent.removeChild(skipButtonBg);
parent.removeChild(self.skipButton);
// Add them back in reverse order
parent.addChild(self.skipButton);
parent.addChild(skipButtonBg);
}
// Timer for countdown
self.timer = null;
// Start countdown
self.startCountdown = function (onComplete) {
self.active = true;
self.visible = true;
self.countdownTime = 60;
self.countdownText.setText(self.countdownTime);
self.onComplete = onComplete;
// Update countdown every second
self.timer = LK.setInterval(function () {
self.countdownTime--;
self.countdownText.setText(self.countdownTime);
if (self.countdownTime <= 0) {
self.stopCountdown();
if (self.onComplete) self.onComplete();
}
}, 1000);
};
// Stop countdown
self.stopCountdown = function () {
if (self.timer) {
LK.clearInterval(self.timer);
self.timer = null;
}
self.active = false;
self.visible = false;
};
// Skip button event handler
self.skipButton.down = function (x, y, obj) {
if (self.active) {
self.stopCountdown();
if (self.onComplete) self.onComplete();
}
};
return self;
});
var WeaponShop = Container.expand(function () {
var self = Container.call(this);
self.isOpen = false;
self.weapons = [{
name: "Basic Rifle",
price: 0,
damage: 1,
speed: 15,
owned: true
}, {
name: "Sniper Rifle",
price: 50,
damage: 3,
speed: 30,
owned: false
}, {
name: "Machine Gun",
price: 100,
damage: 2,
speed: 20,
owned: false
}];
// Shop button
self.shopButton = new Text2("WEAPONS", {
size: 80,
fill: 0xFFFF00
});
self.shopButton.anchor.set(0.5, 0);
// Add background to make button more visible
var buttonBg = LK.getAsset('bullet', {
width: 300,
height: 100,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
buttonBg.alpha = 0.8;
buttonBg.y = self.shopButton.height / 2;
self.addChild(buttonBg);
self.addChild(self.shopButton);
// Shop panel (hidden by default)
self.panel = new Container();
self.panel.visible = false;
self.addChild(self.panel);
// Create weapon options
self.weaponItems = [];
for (var i = 0; i < self.weapons.length; i++) {
var weapon = self.weapons[i];
var item = new Container();
var bg = LK.getAsset('bullet', {
width: 400,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
bg.alpha = 0.8;
item.addChild(bg);
var title = new Text2(weapon.name, {
size: 40,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.y = -50;
item.addChild(title);
var info = new Text2("Damage: " + weapon.damage + " | Speed: " + weapon.speed, {
size: 30,
fill: 0xFFFFFF
});
info.anchor.set(0.5, 0);
info.y = 0;
item.addChild(info);
var priceText = new Text2(weapon.owned ? "OWNED" : "$" + weapon.price, {
size: 35,
fill: weapon.owned ? 0x00FF00 : 0xFFFF00
});
priceText.anchor.set(0.5, 0);
priceText.y = 40;
item.addChild(priceText);
item.y = i * 200;
item.weaponIndex = i;
self.weaponItems.push(item);
self.panel.addChild(item);
}
// Position panel
self.panel.y = 100;
// Handle shop button press
self.shopButton.down = function (x, y, obj) {
self.toggleShop();
};
// Toggle shop visibility
self.toggleShop = function () {
self.isOpen = !self.isOpen;
self.panel.visible = self.isOpen;
};
// Handle weapon selection
self.selectWeapon = function (index) {
var weapon = self.weapons[index];
if (weapon.owned) {
// Equip weapon
sniper.bulletDamage = weapon.damage;
sniper.bulletSpeed = weapon.speed;
sniper.switchWeapon(index); // Switch to selected weapon appearance
// Visual feedback for equipped weapon
for (var i = 0; i < self.weaponItems.length; i++) {
var priceText = self.weaponItems[i].children[3];
if (i === index) {
priceText.setText("EQUIPPED", {
fill: 0x00FFFF
});
} else if (self.weapons[i].owned) {
priceText.setText("OWNED", {
fill: 0x00FF00
});
}
}
LK.getSound('upgrade').play();
return true;
} else if (currency >= weapon.price) {
// Purchase weapon
currency -= weapon.price;
weapon.owned = true;
// Update UI
var priceText = self.weaponItems[index].children[3];
priceText.setText("EQUIPPED", {
fill: 0x00FFFF
});
// Reset other weapon texts to "OWNED"
for (var i = 0; i < self.weaponItems.length; i++) {
if (i !== index && self.weapons[i].owned) {
self.weaponItems[i].children[3].setText("OWNED", {
fill: 0x00FF00
});
}
}
// Equip weapon
sniper.bulletDamage = weapon.damage;
sniper.bulletSpeed = weapon.speed;
sniper.switchWeapon(index); // Switch to selected weapon appearance
LK.getSound('upgrade').play();
updateUI();
return true;
} else {
// Not enough currency
LK.effects.flashScreen(0xFF0000, 300);
return false;
}
};
// Check if an item was clicked
self.checkItemClick = function (x, y) {
if (!self.isOpen) return false;
var pos = self.toLocal({
x: x,
y: y
});
for (var i = 0; i < self.weaponItems.length; i++) {
var item = self.weaponItems[i];
if (pos.y >= item.y - 75 && pos.y <= item.y + 75) {
return self.selectWeapon(item.weaponIndex);
}
}
return false;
};
// Add down event handlers to each weapon item
for (var i = 0; i < self.weaponItems.length; i++) {
var item = self.weaponItems[i];
item.interactive = true;
item.index = i; // Store the index
// Using custom event handler for each item
(function (index) {
item.down = function (x, y, obj) {
self.selectWeapon(index);
};
})(i);
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xC2B280 // Sandy/dry land color
});
/****
* Game Code
****/
// Create background
var background = game.attachAsset('background', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0,
tint: 0xC2B280 // Apply dry land tint to the background
});
// Game variables
var bunkerHealth = 100;
var maxBunkerHealth = 100;
var bunkerY = 2732 - 100; // Position near bottom of screen
var currency = 0;
var difficulty = 1;
var wave = 1;
var enemySpawnRate = 3000; // ms between enemy spawns
var lastEnemySpawn = 0;
var gameActive = true;
var waveInProgress = false;
var enemyIncreasePerWave = 0.5; // 50% more enemies per wave
var enemiesPerWave = 10; // Starting with 10 enemies
var enemiesSpawned = 0; // Track enemies spawned in current wave
var enemiesRequired = 10; // Initial enemies required for first wave
// Upgrade costs and values
var upgrades = {
fireRate: {
level: 1,
cost: 10,
value: 1000,
// ms between shots
increment: -100 // decrease time between shots
},
bulletDamage: {
level: 1,
cost: 15,
value: 1,
increment: 1 // increase damage
}
};
// Arrays for tracking game objects
var bullets = [];
var enemies = [];
// Create bunker
var bunker = new Bunker();
bunker.x = 2048 / 2;
bunker.y = bunkerY;
game.addChild(bunker);
// Create sniper
var sniper = new Sniper();
sniper.x = 2048 / 2;
sniper.y = bunkerY - 50;
game.addChild(sniper);
// Create weapon shop
var weaponShop = new WeaponShop();
weaponShop.x = 150; // Position on the left side of the screen
weaponShop.y = 1800; // Position higher on the screen for better visibility
game.addChild(weaponShop); // Add to game instead of GUI for better positioning
// Create wave countdown timer
var waveCountdown = new WaveCountdown();
waveCountdown.x = 2048 / 2; // Center horizontally
waveCountdown.y = 2732 / 2; // Center vertically
waveCountdown.visible = false; // Hide initially
game.addChild(waveCountdown);
// UI Elements
// Score display
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt);
// Wave display
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
LK.gui.topLeft.addChild(waveTxt);
waveTxt.x = 150; // Move away from the top left corner
// Health display
var healthTxt = new Text2('Bunker: 100%', {
size: 50,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 0);
healthTxt.y = 130;
LK.gui.top.addChild(healthTxt);
// Currency display
var currencyTxt = new Text2('$: 0', {
size: 50,
fill: 0x00FF00
});
currencyTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(currencyTxt);
currencyTxt.x = 150; // Move away from top left corner
currencyTxt.y = 60; // Position below wave display
// Upgrade buttons removed as requested
// Update UI elements
function updateUI() {
scoreTxt.setText('Score: ' + LK.getScore());
currencyTxt.setText('$: ' + currency);
waveTxt.setText('Wave: ' + wave);
updateUpgradeButtons();
}
function updateBunkerHealth() {
var healthPercentage = Math.max(0, Math.min(100, Math.round(bunkerHealth / maxBunkerHealth * 100)));
healthTxt.setText('Bunker: ' + healthPercentage + '%');
bunker.showDamage(bunkerHealth / maxBunkerHealth);
// Only make damage indicator visible and shake when actually taking damage
// Don't show it during initialization
// Only proceed with damage indication animations if bunker is actually taking damage
if (bunkerHealth < maxBunkerHealth) {
// Make damage indicator visible and shake when damage is taken
bunker.damageIndicator.alpha = 1;
// Shake effect
tween(bunker.damageIndicator, {
x: bunker.damageIndicator.originalX + (Math.random() * 10 - 5),
y: bunker.damageIndicator.originalY + (Math.random() * 10 - 5)
}, {
duration: 50,
repeat: 5,
yoyo: true,
onFinish: function onFinish() {
// Hide damage indicator after shake completes (1 second)
LK.setTimeout(function () {
if (gameActive) {
// Fade out damage indicator
tween(bunker.damageIndicator, {
alpha: 0
}, {
duration: 300
});
}
}, 1000);
}
});
}
// Create a visual indicator effect when health is low
if (bunkerHealth / maxBunkerHealth < 0.5) {
// Add continuous damage indicator update for low health
LK.setTimeout(function () {
if (gameActive) bunker.showDamage(bunkerHealth / maxBunkerHealth);
}, 100);
}
}
function updateUpgradeButtons() {
// Upgrade buttons removed as requested
}
// Game mechanics functions
function spawnEnemy() {
var now = Date.now();
if (!waveInProgress || now - lastEnemySpawn < enemySpawnRate) return;
// Check if we've already spawned enough enemies for this wave
if (enemiesSpawned >= enemiesRequired) return;
lastEnemySpawn = now;
// Calculate number of enemies to spawn based on score
var currentScore = LK.getScore();
var enemiesToSpawnAtOnce = 1; // Default spawn one enemy at a time
// Increase enemies spawned at once based on score thresholds
if (currentScore >= 500) {
enemiesToSpawnAtOnce = 5; // Spawn 5 enemies at once at high scores
} else if (currentScore >= 300) {
enemiesToSpawnAtOnce = 4; // Spawn 4 enemies at once
} else if (currentScore >= 200) {
enemiesToSpawnAtOnce = 3; // Spawn 3 enemies at once
} else if (currentScore >= 100) {
enemiesToSpawnAtOnce = 2; // Spawn 2 enemies at once
}
// Make sure we don't spawn more enemies than required for this wave
enemiesToSpawnAtOnce = Math.min(enemiesToSpawnAtOnce, enemiesRequired - enemiesSpawned);
// Spawn multiple enemies at once
for (var i = 0; i < enemiesToSpawnAtOnce; i++) {
// Determine enemy type based on score and wave progression
var enemyType = 'regular';
var random = Math.random();
// More advanced enemies appear based on score thresholds
if (currentScore >= 300 && random < 0.3) {
enemyType = 'tank';
} else if (currentScore >= 150 && random < 0.25) {
enemyType = 'tank';
} else if (currentScore >= 100 && random < 0.35) {
enemyType = 'fast';
} else if (currentScore >= 50 && random < 0.25) {
enemyType = 'fast';
}
var enemy = new Enemy(enemyType);
// Distribute enemies across the width of the screen
if (enemiesToSpawnAtOnce > 1) {
// Distribute evenly but with some randomness
var segment = 2048 / enemiesToSpawnAtOnce;
enemy.x = i * segment + Math.random() * (segment - 100) + 50;
} else {
enemy.x = Math.random() * (2048 - 100) + 50; // Random x position
}
enemy.y = -50; // Start above the screen
enemies.push(enemy);
game.addChild(enemy);
// Increment enemies spawned counter
enemiesSpawned++;
}
}
function checkCollisions() {
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (!bullet.active) {
game.removeChild(bullet);
bullets.splice(i, 1);
continue;
}
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (!enemy.active) {
game.removeChild(enemy);
enemies.splice(j, 1);
continue;
}
if (bullet.active && enemy.active && bullet.intersects(enemy)) {
enemy.takeDamage(bullet.damage);
bullet.hit();
break;
}
}
}
}
function upgradeFireRate() {
if (currency >= upgrades.fireRate.cost) {
currency -= upgrades.fireRate.cost;
upgrades.fireRate.level++;
upgrades.fireRate.value += upgrades.fireRate.increment;
// Ensure fire rate doesn't go below minimum
upgrades.fireRate.value = Math.max(200, upgrades.fireRate.value);
sniper.fireRate = upgrades.fireRate.value;
// Increase cost for next upgrade
upgrades.fireRate.cost = Math.floor(upgrades.fireRate.cost * 1.5);
LK.getSound('upgrade').play();
updateUI();
}
}
function upgradeBulletDamage() {
if (currency >= upgrades.bulletDamage.cost) {
currency -= upgrades.bulletDamage.cost;
upgrades.bulletDamage.level++;
upgrades.bulletDamage.value += upgrades.bulletDamage.increment;
sniper.bulletDamage = upgrades.bulletDamage.value;
// Increase cost for next upgrade
upgrades.bulletDamage.cost = Math.floor(upgrades.bulletDamage.cost * 1.5);
LK.getSound('upgrade').play();
updateUI();
}
}
function increaseDifficulty() {
// Check if all enemies for this wave are spawned and eliminated
if (waveInProgress && enemiesSpawned >= enemiesRequired && enemies.length === 0) {
// All enemies in current wave defeated, prepare for next wave
wave++;
// Calculate new enemies required for next wave (increase by 50%)
enemiesRequired = Math.ceil(enemiesPerWave * Math.pow(1 + enemyIncreasePerWave, wave - 1));
// Reset enemies spawned counter
enemiesSpawned = 0;
// Decrease spawn rate with each wave (faster spawns) based on score and wave
var currentScore = LK.getScore();
// More aggressive spawn rate reduction based on score
var scoreBasedReduction = Math.min(2000, Math.floor(currentScore / 8) * 25);
// Use an exponential reduction for higher scores to make spawns much faster
if (currentScore > 300) {
scoreBasedReduction += Math.min(1000, Math.pow(currentScore - 300, 1.2));
}
// Set a lower minimum spawn rate for higher scores
var minSpawnRate = currentScore > 400 ? 100 : currentScore > 200 ? 200 : 300;
enemySpawnRate = Math.max(minSpawnRate, 3000 - wave * 200 - scoreBasedReduction);
// Pause wave progression and show countdown
waveInProgress = false;
// Start countdown for next wave
waveCountdown.startCountdown(function () {
// When countdown completes, start the new wave
startNewWave();
});
}
}
function startNewWave() {
// Clear all existing enemies
for (var i = enemies.length - 1; i >= 0; i--) {
game.removeChild(enemies[i]);
}
enemies = [];
// Reset enemies spawned counter
enemiesSpawned = 0;
// Update UI to show new wave and enemy count
waveTxt.setText('Wave: ' + wave + ' (' + enemiesRequired + ' enemies)');
// Start spawning enemies again
waveInProgress = true;
// Flash screen to indicate new wave
LK.effects.flashScreen(0x00FF00, 500);
// Adjust difficulty based on score
var currentScore = LK.getScore();
if (currentScore > 300) {
difficulty = 5;
} else if (currentScore > 200) {
difficulty = 4;
} else if (currentScore > 100) {
difficulty = 3;
} else if (currentScore > 50) {
difficulty = 2;
} else {
difficulty = 1;
}
}
function gameOver() {
gameActive = false;
// Save high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Save currency for next game
storage.currency = currency;
// Show game over screen
LK.showGameOver();
}
// Event handlers
game.move = function (x, y, obj) {
if (gameActive) {
// Update rifle aim to follow cursor
var angle = sniper.updateAim(x, y);
// Let the updateAim method handle the character orientation
// We don't rotate the sniper character itself anymore
// This prevents the character from being upside down when aiming
}
};
game.down = function (x, y, obj) {
if (!gameActive) return;
// Check if weapon shop item was clicked
if (weaponShop.checkItemClick(x, y)) {
return;
}
// Fire at touch location
var bullet = sniper.shoot(x, y);
if (bullet) {
bullets.push(bullet);
game.addChild(bullet);
}
};
// Update function called every frame
game.update = function () {
if (!gameActive) return;
// Only spawn enemies if a wave is in progress
if (waveInProgress) {
// Spawn enemies
spawnEnemy();
// Update enemies
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].active) {
enemies[i].update();
}
}
// Check for collisions
checkCollisions();
}
// Update bullets regardless of wave status
for (var i = 0; i < bullets.length; i++) {
if (bullets[i].active) {
bullets[i].update();
}
}
// Update difficulty (handles wave transitions)
increaseDifficulty();
// Continuously update damage indicator when health is low
if (bunkerHealth / maxBunkerHealth < 0.4) {
// Move damage indicator more frequently as health gets lower
if (LK.ticks % Math.max(5, Math.floor(bunkerHealth / maxBunkerHealth * 20)) === 0) {
bunker.showDamage(bunkerHealth / maxBunkerHealth);
}
}
// Update UI
if (LK.ticks % 30 === 0) {
updateUI();
}
};
// Make sure the weapon shop starts with the appropriate weapon equipped
weaponShop.selectWeapon(0); // Start with basic rifle selected
// Initialize UI
updateUI();
// Ensure damage indicator is invisible at start
bunker.damageIndicator.alpha = 0;
updateBunkerHealth();
// Calculate initial enemies required for first wave
enemiesRequired = enemiesPerWave;
// Start the first wave with countdown
waveInProgress = false;
waveCountdown.startCountdown(function () {
startNewWave();
});
// Place random bushes and trees around the game area
function placeBushes() {
// Number of decorative elements to place
var bushCount = 25;
var treeCount = 15;
// Positions to avoid (bunker and sniper area)
var avoidX = 2048 / 2;
var avoidY = bunkerY;
var avoidRadius = 200;
// Also avoid the top-left corner where menu icon is located
var topLeftX = 50;
var topLeftY = 50;
var topLeftRadius = 100;
// Add bushes
for (var i = 0; i < bushCount; i++) {
var bush = new Bush();
// Keep generating positions until we find a suitable one
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 10) {
// Generate random position
bush.x = Math.random() * 2048;
bush.y = Math.random() * 2732;
// Check distance from bunker area
var distToBunker = Math.sqrt(Math.pow(bush.x - avoidX, 2) + Math.pow(bush.y - avoidY, 2));
// Check distance from top-left corner
var distToTopLeft = Math.sqrt(Math.pow(bush.x - topLeftX, 2) + Math.pow(bush.y - topLeftY, 2));
// Position is valid if it's away from both areas to avoid
if (distToBunker > avoidRadius && distToTopLeft > topLeftRadius) {
validPosition = true;
}
attempts++;
}
// Add bush behind other game elements (insert at the beginning of children array)
game.addChildAt(bush, 0);
}
// Add trees
for (var i = 0; i < treeCount; i++) {
var tree = new Tree();
// Keep generating positions until we find a suitable one
var validPosition = false;
var attempts = 0;
while (!validPosition && attempts < 10) {
// Generate random position
tree.x = Math.random() * 2048;
tree.y = Math.random() * 2732;
// Check distance from bunker area
var distToBunker = Math.sqrt(Math.pow(tree.x - avoidX, 2) + Math.pow(tree.y - avoidY, 2));
// Check distance from top-left corner
var distToTopLeft = Math.sqrt(Math.pow(tree.x - topLeftX, 2) + Math.pow(tree.y - topLeftY, 2));
// Position is valid if it's away from both areas to avoid
if (distToBunker > avoidRadius && distToTopLeft > topLeftRadius) {
validPosition = true;
}
attempts++;
}
// Add tree behind other game elements (insert at the beginning of children array)
game.addChildAt(tree, 0);
}
}
// Add bushes to the game
placeBushes();
// Start background music
LK.playMusic('gameBgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
}); ===================================================================
--- original.js
+++ change.js
@@ -424,8 +424,51 @@
return bullet;
};
return self;
});
+var Tree = Container.expand(function () {
+ var self = Container.call(this);
+ // Random tree appearance with variation
+ var type = Math.floor(Math.random() * 3);
+ var size = Math.random() * 0.7 + 1.2; // Size between 1.2 and 1.9
+ var rotation = Math.random() * 0.2 - 0.1; // Slight rotation
+ // Create the tree trunk using bullet shape with brown tint
+ var treeTrunk = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x8B4513,
+ // Saddle brown color
+ scaleX: size * 0.3,
+ scaleY: size * 0.8
+ });
+ // Create the tree crown using bullet shape with green tint
+ var treeCrown = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x228B22,
+ // Forest green color
+ scaleX: size * 1.2,
+ scaleY: size * 1.0
+ });
+ // Position crown on top of trunk
+ treeCrown.y = -treeTrunk.height * 0.5;
+ // Apply random rotation
+ self.rotation = rotation;
+ // Add some details to make trees look different from each other
+ if (type === 0) {
+ // First type - taller tree with darker green
+ treeCrown.scale.y *= 1.4;
+ treeCrown.tint = 0x006400; // Dark green
+ } else if (type === 1) {
+ // Second type - wider tree with lighter green
+ treeCrown.scale.x *= 1.3;
+ treeCrown.tint = 0x32CD32; // Lime green
+ } else {
+ // Third type - autumn tree with different color
+ treeCrown.tint = 0xFF8C00; // Dark orange
+ }
+ return self;
+});
var WaveCountdown = Container.expand(function () {
var self = Container.call(this);
self.countdownTime = 60; // 60 seconds default
self.active = false;
@@ -1084,20 +1127,22 @@
waveInProgress = false;
waveCountdown.startCountdown(function () {
startNewWave();
});
-// Place random bushes around the game area
+// Place random bushes and trees around the game area
function placeBushes() {
- // Number of bushes to place
+ // Number of decorative elements to place
var bushCount = 25;
+ var treeCount = 15;
// Positions to avoid (bunker and sniper area)
var avoidX = 2048 / 2;
var avoidY = bunkerY;
var avoidRadius = 200;
// Also avoid the top-left corner where menu icon is located
var topLeftX = 50;
var topLeftY = 50;
var topLeftRadius = 100;
+ // Add bushes
for (var i = 0; i < bushCount; i++) {
var bush = new Bush();
// Keep generating positions until we find a suitable one
var validPosition = false;
@@ -1118,8 +1163,31 @@
}
// Add bush behind other game elements (insert at the beginning of children array)
game.addChildAt(bush, 0);
}
+ // Add trees
+ for (var i = 0; i < treeCount; i++) {
+ var tree = new Tree();
+ // Keep generating positions until we find a suitable one
+ var validPosition = false;
+ var attempts = 0;
+ while (!validPosition && attempts < 10) {
+ // Generate random position
+ tree.x = Math.random() * 2048;
+ tree.y = Math.random() * 2732;
+ // Check distance from bunker area
+ var distToBunker = Math.sqrt(Math.pow(tree.x - avoidX, 2) + Math.pow(tree.y - avoidY, 2));
+ // Check distance from top-left corner
+ var distToTopLeft = Math.sqrt(Math.pow(tree.x - topLeftX, 2) + Math.pow(tree.y - topLeftY, 2));
+ // Position is valid if it's away from both areas to avoid
+ if (distToBunker > avoidRadius && distToTopLeft > topLeftRadius) {
+ validPosition = true;
+ }
+ attempts++;
+ }
+ // Add tree behind other game elements (insert at the beginning of children array)
+ game.addChildAt(tree, 0);
+ }
}
// Add bushes to the game
placeBushes();
// Start background music
kaya. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
sopalı düşman adam . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
koşan ninja. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
tek gözlü dev. In-Game asset. 2d. High contrast. No shadows
barbed wire wall. In-Game asset. 2d. High contrast. No shadows
gözcü kulesi. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
yazıyı sil
Çöl haydut sniper. In-Game asset. 2d. High contrast. No shadows
önden zırhlı araç . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
zırhlı aracaın arkası. In-Game asset. 2d. High contrast. No shadows
sağa giden askeri yeşil renkte zırhlı araç. In-Game asset. 2d. High contrast. No shadows