/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.speed = 20; self.directionX = 0; self.directionY = 0; self.trailParticles = []; self.startAnimation = function () { // Add bullet trail effect with scale animation tween(bulletGraphics, { scaleX: 1.8, scaleY: 1.8 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(bulletGraphics, { scaleX: 1.5, scaleY: 1.5 }, { duration: 100, easing: tween.easeIn }); } }); // Add rotation animation for bullet spin tween(bulletGraphics, { rotation: Math.PI * 4 }, { duration: 1000, easing: tween.linear }); }; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Create trail particles every few frames if (LK.ticks % 3 === 0) { var trailParticle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, x: self.x, y: self.y }); trailParticle.alpha = 0.6; trailParticle.tint = 0xFFAA00; self.parent.addChild(trailParticle); self.trailParticles.push(trailParticle); // Fade out and remove trail particle tween(trailParticle, { alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { if (trailParticle.parent) { trailParticle.parent.removeChild(trailParticle); } } }); } }; return self; }); var Crosshair = Container.expand(function () { var self = Container.call(this); // Outer circle var outerRing = self.attachAsset('crosshair_outer', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6 }); // Inner dot var centerDot = self.attachAsset('crosshair_inner', { anchorX: 0.5, anchorY: 0.5 }); // Horizontal line var horizontalLine = self.attachAsset('crosshair_line_h', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); // Vertical line var verticalLine = self.attachAsset('crosshair_line_v', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.updatePosition = function (x, y) { self.x = x; self.y = y; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.0, scaleY: 2.0 }); self.speed = 2.5; self.directionX = 0; self.directionY = 0; self.health = 1; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Running animation - create bobbing effect if (!self.animationStarted) { self.animationStarted = true; self.startAnimation(); } }; self.startAnimation = function () { // Create more realistic running animation with multiple tween effects var animationDuration = 200; var scaleVariation = 0.15; var rotationVariation = 0.08; var yMovement = 8; // Main body bobbing animation (vertical movement) tween(enemyGraphics, { y: -yMovement, scaleX: 2.0 + scaleVariation, scaleY: 2.0 - scaleVariation / 2 }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(enemyGraphics, { y: yMovement, scaleX: 2.0 - scaleVariation, scaleY: 2.0 + scaleVariation / 2 }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(enemyGraphics, { y: 0, scaleX: 2.0, scaleY: 2.0 }, { duration: animationDuration / 2, easing: tween.easeInOut, onFinish: function onFinish() { if (self.parent) { self.startAnimation(); // Loop the animation } } }); } }); } }); // Add body sway/lean animation for realistic running tween(self, { rotation: rotationVariation }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { rotation: -rotationVariation }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { rotation: 0 }, { duration: animationDuration / 2, easing: tween.easeInOut }); } }); } }); // Add slight horizontal wobble for arm movement simulation tween(enemyGraphics, { x: 3 }, { duration: animationDuration / 2, easing: tween.easeInOut, onFinish: function onFinish() { tween(enemyGraphics, { x: -3 }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(enemyGraphics, { x: 0 }, { duration: animationDuration / 2, easing: tween.easeInOut }); } }); } }); }; self.hitAnimation = function () { // Stop all current animations tween.stop(enemyGraphics); tween.stop(self); // Hit animation: enemy staggers backward and flashes red var hitForceX = -self.directionX * 15; var hitForceY = -self.directionY * 15; // Create blood particles for (var i = 0; i < 5; i++) { var bloodParticle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, x: self.x + (Math.random() - 0.5) * 30, y: self.y + (Math.random() - 0.5) * 30 }); bloodParticle.tint = 0xFF0000; // Red blood color bloodParticle.alpha = 0.8; self.parent.addChild(bloodParticle); // Animate blood splatter var bloodVelX = (Math.random() - 0.5) * 50; var bloodVelY = (Math.random() - 0.5) * 50; tween(bloodParticle, { x: bloodParticle.x + bloodVelX, y: bloodParticle.y + bloodVelY, alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { if (bloodParticle.parent) { bloodParticle.parent.removeChild(bloodParticle); } } }); } // Enemy hit reaction: stagger back and flash tween(self, { x: self.x + hitForceX, y: self.y + hitForceY }, { duration: 150, easing: tween.easeOut }); // Flash red when hit tween(enemyGraphics, { tint: 0xFF0000 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { tint: 0xFFFFFF }, { duration: 100, easing: tween.easeIn }); } }); // Scale animation for impact effect tween(enemyGraphics, { scaleX: 2.3, scaleY: 1.7 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { scaleX: 2.0, scaleY: 2.0 }, { duration: 80, easing: tween.easeIn }); } }); }; return self; }); var Gunman = Container.expand(function () { var self = Container.call(this); var gunmanGraphics = self.attachAsset('gunman', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); var gun = self.attachAsset('gun', { anchorX: 0, anchorY: 0.5, x: 30, y: 0, scaleX: 2.0, scaleY: 2.0 }); gun.tint = 0x333333; self.aimAngle = 0; self.setAimDirection = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; self.aimAngle = Math.atan2(dy, dx); self.rotation = self.aimAngle; }; self.createGunSmoke = function () { var smokeParticle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, x: gun.x + 40, y: gun.y }); smokeParticle.alpha = 0.7; smokeParticle.tint = 0x888888; self.addChild(smokeParticle); // Animate smoke dispersal tween(smokeParticle, { alpha: 0, scaleX: 1.5, scaleY: 1.5, x: smokeParticle.x + Math.cos(self.aimAngle) * 20, y: smokeParticle.y + Math.sin(self.aimAngle) * 20 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { if (smokeParticle.parent) { smokeParticle.parent.removeChild(smokeParticle); } } }); }; return self; }); var Plane = Container.expand(function () { var self = Container.call(this); var planeGraphics = self.attachAsset('plane', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 1.5 }); planeGraphics.tint = 0x6666CC; // Blue-gray for plane self.speed = 4.0; // Faster than other enemies self.directionX = 0; self.directionY = 0; self.health = 2; // Medium health self.maxHealth = 2; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Plane flight animation if (!self.animationStarted) { self.animationStarted = true; self.startAnimation(); } }; self.startAnimation = function () { // Plane has smooth flying animation with banking turns var animationDuration = 150; var rotationVariation = 0.15; var yMovement = 5; // Banking/tilting animation for flight tween(self, { rotation: rotationVariation }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { rotation: -rotationVariation }, { duration: animationDuration * 2, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { rotation: 0 }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { if (self.parent) { self.startAnimation(); // Loop the animation } } }); } }); } }); // Vertical bobbing for flight effect tween(planeGraphics, { y: -yMovement }, { duration: animationDuration * 1.5, easing: tween.easeInOut, onFinish: function onFinish() { tween(planeGraphics, { y: yMovement }, { duration: animationDuration * 3, easing: tween.easeInOut, onFinish: function onFinish() { tween(planeGraphics, { y: 0 }, { duration: animationDuration * 1.5, easing: tween.easeInOut }); } }); } }); }; self.hitAnimation = function () { // Stop all current animations tween.stop(planeGraphics); tween.stop(self); // Plane hit animation - dramatic spinning var hitForceX = -self.directionX * 12; var hitForceY = -self.directionY * 12; // Create smoke particles for plane for (var i = 0; i < 4; i++) { var smokeParticle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, x: self.x + (Math.random() - 0.5) * 35, y: self.y + (Math.random() - 0.5) * 35 }); smokeParticle.tint = 0x333333; // Dark smoke smokeParticle.alpha = 0.8; self.parent.addChild(smokeParticle); // Animate smoke dispersal var smokeVelX = (Math.random() - 0.5) * 40; var smokeVelY = (Math.random() - 0.5) * 40; tween(smokeParticle, { x: smokeParticle.x + smokeVelX, y: smokeParticle.y + smokeVelY, alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { if (smokeParticle.parent) { smokeParticle.parent.removeChild(smokeParticle); } } }); } // Plane spin when hit tween(self, { x: self.x + hitForceX, y: self.y + hitForceY, rotation: self.rotation + Math.PI }, { duration: 300, easing: tween.easeOut }); // Flash red when hit tween(planeGraphics, { tint: 0xFF4444 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(planeGraphics, { tint: 0x6666CC // Back to blue-gray }, { duration: 100, easing: tween.easeIn }); } }); }; return self; }); var Tank = Container.expand(function () { var self = Container.call(this); var tankGraphics = self.attachAsset('tank', { anchorX: 0.5, anchorY: 0.5, scaleX: 3.0, scaleY: 2.5 }); tankGraphics.tint = 0x444444; // Dark gray for tank self.speed = 1.5; // Slower than regular enemies self.directionX = 0; self.directionY = 0; self.health = 5; // Much more health than regular enemies self.maxHealth = 5; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Tank movement animation - less bobbing, more stable if (!self.animationStarted) { self.animationStarted = true; self.startAnimation(); } }; self.startAnimation = function () { // Tank has more stable movement animation var animationDuration = 400; var scaleVariation = 0.05; var yMovement = 3; // Subtle tank movement animation tween(tankGraphics, { y: -yMovement, scaleX: 3.0 + scaleVariation, scaleY: 2.5 - scaleVariation / 2 }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(tankGraphics, { y: yMovement, scaleX: 3.0 - scaleVariation, scaleY: 2.5 + scaleVariation / 2 }, { duration: animationDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(tankGraphics, { y: 0, scaleX: 3.0, scaleY: 2.5 }, { duration: animationDuration / 2, easing: tween.easeInOut, onFinish: function onFinish() { if (self.parent) { self.startAnimation(); // Loop the animation } } }); } }); } }); }; self.hitAnimation = function () { // Stop all current animations tween.stop(tankGraphics); tween.stop(self); // Tank hit animation - less dramatic than regular enemy var hitForceX = -self.directionX * 8; var hitForceY = -self.directionY * 8; // Create sparks instead of blood for tank for (var i = 0; i < 3; i++) { var sparkParticle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, x: self.x + (Math.random() - 0.5) * 40, y: self.y + (Math.random() - 0.5) * 40 }); sparkParticle.tint = 0xFFFF00; // Yellow sparks sparkParticle.alpha = 0.9; self.parent.addChild(sparkParticle); // Animate sparks var sparkVelX = (Math.random() - 0.5) * 30; var sparkVelY = (Math.random() - 0.5) * 30; tween(sparkParticle, { x: sparkParticle.x + sparkVelX, y: sparkParticle.y + sparkVelY, alpha: 0, scaleX: 0.05, scaleY: 0.05 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { if (sparkParticle.parent) { sparkParticle.parent.removeChild(sparkParticle); } } }); } // Tank stagger - less movement than regular enemy tween(self, { x: self.x + hitForceX, y: self.y + hitForceY }, { duration: 200, easing: tween.easeOut }); // Flash orange when hit (different from regular enemies) tween(tankGraphics, { tint: 0xFF8800 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(tankGraphics, { tint: 0x444444 // Back to dark gray }, { duration: 150, easing: tween.easeIn }); } }); // Minimal scale animation for tank tween(tankGraphics, { scaleX: 3.2, scaleY: 2.3 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(tankGraphics, { scaleX: 3.0, scaleY: 2.5 }, { duration: 100, easing: tween.easeIn }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2F4F2F }); /**** * Game Code ****/ var centerX = 2048 / 2; var centerY = 2732 / 2; // Create shelter var shelter = game.addChild(LK.getAsset('shelter', { anchorX: 0.5, anchorY: 0.5, x: centerX, y: centerY })); // Create gunman var gunman = game.addChild(new Gunman()); gunman.x = centerX; gunman.y = centerY; // Game arrays var bullets = []; var enemies = []; // Game state var shelterHealth = 5; var enemySpawnTimer = 0; var enemySpawnRate = 80; // frames between spawns var waveNumber = 1; var lastShotTime = 0; var shootCooldown = 8; // frames between shots var bulletCount = 20; // Starting bullets var maxBullets = 100; // Maximum bullets // UI elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var healthTxt = new Text2('Health: ' + shelterHealth, { size: 50, fill: 0xFF4444 }); healthTxt.anchor.set(0, 0); healthTxt.x = 100; healthTxt.y = 100; LK.gui.topLeft.addChild(healthTxt); var waveTxt = new Text2('Wave: 1', { size: 50, fill: 0x44FF44 }); waveTxt.anchor.set(1, 0); LK.gui.topRight.addChild(waveTxt); var bulletTxt = new Text2('Bullets: ' + bulletCount, { size: 50, fill: 0xFFAA00 }); bulletTxt.anchor.set(0, 0); bulletTxt.x = 100; bulletTxt.y = 180; LK.gui.topLeft.addChild(bulletTxt); // Input handling var aimX = centerX + 100; var aimY = centerY; var isShooting = false; // Create crosshair cursor var crosshair = game.addChild(new Crosshair()); crosshair.x = aimX; crosshair.y = aimY; function spawnEnemy() { var enemy; var enemyType = Math.random(); // 60% chance for regular enemy, 25% chance for tank, 15% chance for plane if (enemyType < 0.6) { enemy = new Enemy(); } else if (enemyType < 0.85) { enemy = new Tank(); } else { enemy = new Plane(); } // Spawn from random position on perimeter var angle = Math.random() * Math.PI * 2; var spawnDistance = 1200; enemy.x = centerX + Math.cos(angle) * spawnDistance; enemy.y = centerY + Math.sin(angle) * spawnDistance; // Set direction toward shelter var dx = centerX - enemy.x; var dy = centerY - enemy.y; var distance = Math.sqrt(dx * dx + dy * dy); enemy.directionX = dx / distance; enemy.directionY = dy / distance; // Adjust speed based on wave (tanks and planes have their own base speeds) if (enemy instanceof Enemy) { enemy.speed = 2.5 + waveNumber * 0.3; } else if (enemy instanceof Tank) { enemy.speed = 1.5 + waveNumber * 0.2; // Tanks get slower speed increase } else if (enemy instanceof Plane) { enemy.speed = 4.0 + waveNumber * 0.4; // Planes get faster speed increase } enemies.push(enemy); game.addChild(enemy); } function shootBullet() { if (LK.ticks - lastShotTime < shootCooldown) return; if (bulletCount <= 0) return; // No bullets left bulletCount--; bulletTxt.setText('Bullets: ' + bulletCount); var bullet = new Bullet(); bullet.x = gunman.x; bullet.y = gunman.y; bullet.directionX = Math.cos(gunman.aimAngle); bullet.directionY = Math.sin(gunman.aimAngle); bullet.startAnimation(); bullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); gunman.createGunSmoke(); lastShotTime = LK.ticks; } // Game input handlers game.move = function (x, y, obj) { aimX = x; aimY = y; gunman.setAimDirection(aimX, aimY); crosshair.updatePosition(aimX, aimY); }; game.down = function (x, y, obj) { aimX = x; aimY = y; gunman.setAimDirection(aimX, aimY); crosshair.updatePosition(aimX, aimY); isShooting = true; shootBullet(); }; game.up = function (x, y, obj) { isShooting = false; }; // Main game loop game.update = function () { // Enemy spawning enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnRate) { spawnEnemy(); enemySpawnTimer = 0; // Increase difficulty over time if (enemySpawnRate > 30) { enemySpawnRate -= 1; } // Increase wave number if (LK.ticks % 600 === 0) { waveNumber++; waveTxt.setText('Wave: ' + waveNumber); } } // Continuous shooting while touching if (isShooting && LK.ticks % 6 === 0) { shootBullet(); } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Check if bullet is off screen if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check bullet-enemy collisions var bulletHit = false; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { // Enemy hit - reduce health enemy.health--; LK.getSound('enemyHit').play(); // Trigger hit animation enemy.hitAnimation(); // Check if enemy is destroyed if (enemy.health <= 0) { // Different scoring for different enemy types if (enemy instanceof Tank) { LK.setScore(LK.getScore() + 50); // Tanks worth more points bulletCount = Math.min(bulletCount + 5, maxBullets); // More bullets from tanks } else if (enemy instanceof Plane) { LK.setScore(LK.getScore() + 30); // Planes worth medium points bulletCount = Math.min(bulletCount + 4, maxBullets); // Medium bullets from planes } else { LK.setScore(LK.getScore() + 10); // Regular enemies bulletCount = Math.min(bulletCount + 3, maxBullets); // Standard bullets } scoreTxt.setText('Score: ' + LK.getScore()); bulletTxt.setText('Bullets: ' + bulletCount); // Delay enemy destruction to show hit animation LK.setTimeout(function () { if (enemy.parent) { enemy.destroy(); var enemyIndex = enemies.indexOf(enemy); if (enemyIndex > -1) { enemies.splice(enemyIndex, 1); } } }, 200); } bullet.destroy(); bullets.splice(i, 1); bulletHit = true; break; } } } // Update enemies for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; // Check if enemy reached shelter var distanceToShelter = Math.sqrt(Math.pow(enemy.x - centerX, 2) + Math.pow(enemy.y - centerY, 2)); if (distanceToShelter < 100) { shelterHealth--; healthTxt.setText('Health: ' + shelterHealth); LK.getSound('shelterHit').play(); LK.effects.flashObject(shelter, 0xFF0000, 300); enemy.destroy(); enemies.splice(k, 1); if (shelterHealth <= 0) { LK.showGameOver(); return; } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.speed = 20;
self.directionX = 0;
self.directionY = 0;
self.trailParticles = [];
self.startAnimation = function () {
// Add bullet trail effect with scale animation
tween(bulletGraphics, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(bulletGraphics, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Add rotation animation for bullet spin
tween(bulletGraphics, {
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.linear
});
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Create trail particles every few frames
if (LK.ticks % 3 === 0) {
var trailParticle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
x: self.x,
y: self.y
});
trailParticle.alpha = 0.6;
trailParticle.tint = 0xFFAA00;
self.parent.addChild(trailParticle);
self.trailParticles.push(trailParticle);
// Fade out and remove trail particle
tween(trailParticle, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (trailParticle.parent) {
trailParticle.parent.removeChild(trailParticle);
}
}
});
}
};
return self;
});
var Crosshair = Container.expand(function () {
var self = Container.call(this);
// Outer circle
var outerRing = self.attachAsset('crosshair_outer', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6
});
// Inner dot
var centerDot = self.attachAsset('crosshair_inner', {
anchorX: 0.5,
anchorY: 0.5
});
// Horizontal line
var horizontalLine = self.attachAsset('crosshair_line_h', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Vertical line
var verticalLine = self.attachAsset('crosshair_line_v', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.updatePosition = function (x, y) {
self.x = x;
self.y = y;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
self.speed = 2.5;
self.directionX = 0;
self.directionY = 0;
self.health = 1;
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Running animation - create bobbing effect
if (!self.animationStarted) {
self.animationStarted = true;
self.startAnimation();
}
};
self.startAnimation = function () {
// Create more realistic running animation with multiple tween effects
var animationDuration = 200;
var scaleVariation = 0.15;
var rotationVariation = 0.08;
var yMovement = 8;
// Main body bobbing animation (vertical movement)
tween(enemyGraphics, {
y: -yMovement,
scaleX: 2.0 + scaleVariation,
scaleY: 2.0 - scaleVariation / 2
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
y: yMovement,
scaleX: 2.0 - scaleVariation,
scaleY: 2.0 + scaleVariation / 2
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
y: 0,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: animationDuration / 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
self.startAnimation(); // Loop the animation
}
}
});
}
});
}
});
// Add body sway/lean animation for realistic running
tween(self, {
rotation: rotationVariation
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: -rotationVariation
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0
}, {
duration: animationDuration / 2,
easing: tween.easeInOut
});
}
});
}
});
// Add slight horizontal wobble for arm movement simulation
tween(enemyGraphics, {
x: 3
}, {
duration: animationDuration / 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
x: -3
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
x: 0
}, {
duration: animationDuration / 2,
easing: tween.easeInOut
});
}
});
}
});
};
self.hitAnimation = function () {
// Stop all current animations
tween.stop(enemyGraphics);
tween.stop(self);
// Hit animation: enemy staggers backward and flashes red
var hitForceX = -self.directionX * 15;
var hitForceY = -self.directionY * 15;
// Create blood particles
for (var i = 0; i < 5; i++) {
var bloodParticle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
x: self.x + (Math.random() - 0.5) * 30,
y: self.y + (Math.random() - 0.5) * 30
});
bloodParticle.tint = 0xFF0000; // Red blood color
bloodParticle.alpha = 0.8;
self.parent.addChild(bloodParticle);
// Animate blood splatter
var bloodVelX = (Math.random() - 0.5) * 50;
var bloodVelY = (Math.random() - 0.5) * 50;
tween(bloodParticle, {
x: bloodParticle.x + bloodVelX,
y: bloodParticle.y + bloodVelY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
if (bloodParticle.parent) {
bloodParticle.parent.removeChild(bloodParticle);
}
}
});
}
// Enemy hit reaction: stagger back and flash
tween(self, {
x: self.x + hitForceX,
y: self.y + hitForceY
}, {
duration: 150,
easing: tween.easeOut
});
// Flash red when hit
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 100,
easing: tween.easeIn
});
}
});
// Scale animation for impact effect
tween(enemyGraphics, {
scaleX: 2.3,
scaleY: 1.7
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 80,
easing: tween.easeIn
});
}
});
};
return self;
});
var Gunman = Container.expand(function () {
var self = Container.call(this);
var gunmanGraphics = self.attachAsset('gunman', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
var gun = self.attachAsset('gun', {
anchorX: 0,
anchorY: 0.5,
x: 30,
y: 0,
scaleX: 2.0,
scaleY: 2.0
});
gun.tint = 0x333333;
self.aimAngle = 0;
self.setAimDirection = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
self.aimAngle = Math.atan2(dy, dx);
self.rotation = self.aimAngle;
};
self.createGunSmoke = function () {
var smokeParticle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: gun.x + 40,
y: gun.y
});
smokeParticle.alpha = 0.7;
smokeParticle.tint = 0x888888;
self.addChild(smokeParticle);
// Animate smoke dispersal
tween(smokeParticle, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5,
x: smokeParticle.x + Math.cos(self.aimAngle) * 20,
y: smokeParticle.y + Math.sin(self.aimAngle) * 20
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
if (smokeParticle.parent) {
smokeParticle.parent.removeChild(smokeParticle);
}
}
});
};
return self;
});
var Plane = Container.expand(function () {
var self = Container.call(this);
var planeGraphics = self.attachAsset('plane', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 1.5
});
planeGraphics.tint = 0x6666CC; // Blue-gray for plane
self.speed = 4.0; // Faster than other enemies
self.directionX = 0;
self.directionY = 0;
self.health = 2; // Medium health
self.maxHealth = 2;
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Plane flight animation
if (!self.animationStarted) {
self.animationStarted = true;
self.startAnimation();
}
};
self.startAnimation = function () {
// Plane has smooth flying animation with banking turns
var animationDuration = 150;
var rotationVariation = 0.15;
var yMovement = 5;
// Banking/tilting animation for flight
tween(self, {
rotation: rotationVariation
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: -rotationVariation
}, {
duration: animationDuration * 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
self.startAnimation(); // Loop the animation
}
}
});
}
});
}
});
// Vertical bobbing for flight effect
tween(planeGraphics, {
y: -yMovement
}, {
duration: animationDuration * 1.5,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(planeGraphics, {
y: yMovement
}, {
duration: animationDuration * 3,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(planeGraphics, {
y: 0
}, {
duration: animationDuration * 1.5,
easing: tween.easeInOut
});
}
});
}
});
};
self.hitAnimation = function () {
// Stop all current animations
tween.stop(planeGraphics);
tween.stop(self);
// Plane hit animation - dramatic spinning
var hitForceX = -self.directionX * 12;
var hitForceY = -self.directionY * 12;
// Create smoke particles for plane
for (var i = 0; i < 4; i++) {
var smokeParticle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
x: self.x + (Math.random() - 0.5) * 35,
y: self.y + (Math.random() - 0.5) * 35
});
smokeParticle.tint = 0x333333; // Dark smoke
smokeParticle.alpha = 0.8;
self.parent.addChild(smokeParticle);
// Animate smoke dispersal
var smokeVelX = (Math.random() - 0.5) * 40;
var smokeVelY = (Math.random() - 0.5) * 40;
tween(smokeParticle, {
x: smokeParticle.x + smokeVelX,
y: smokeParticle.y + smokeVelY,
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
if (smokeParticle.parent) {
smokeParticle.parent.removeChild(smokeParticle);
}
}
});
}
// Plane spin when hit
tween(self, {
x: self.x + hitForceX,
y: self.y + hitForceY,
rotation: self.rotation + Math.PI
}, {
duration: 300,
easing: tween.easeOut
});
// Flash red when hit
tween(planeGraphics, {
tint: 0xFF4444
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(planeGraphics, {
tint: 0x6666CC // Back to blue-gray
}, {
duration: 100,
easing: tween.easeIn
});
}
});
};
return self;
});
var Tank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('tank', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.0,
scaleY: 2.5
});
tankGraphics.tint = 0x444444; // Dark gray for tank
self.speed = 1.5; // Slower than regular enemies
self.directionX = 0;
self.directionY = 0;
self.health = 5; // Much more health than regular enemies
self.maxHealth = 5;
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Tank movement animation - less bobbing, more stable
if (!self.animationStarted) {
self.animationStarted = true;
self.startAnimation();
}
};
self.startAnimation = function () {
// Tank has more stable movement animation
var animationDuration = 400;
var scaleVariation = 0.05;
var yMovement = 3;
// Subtle tank movement animation
tween(tankGraphics, {
y: -yMovement,
scaleX: 3.0 + scaleVariation,
scaleY: 2.5 - scaleVariation / 2
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(tankGraphics, {
y: yMovement,
scaleX: 3.0 - scaleVariation,
scaleY: 2.5 + scaleVariation / 2
}, {
duration: animationDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(tankGraphics, {
y: 0,
scaleX: 3.0,
scaleY: 2.5
}, {
duration: animationDuration / 2,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
self.startAnimation(); // Loop the animation
}
}
});
}
});
}
});
};
self.hitAnimation = function () {
// Stop all current animations
tween.stop(tankGraphics);
tween.stop(self);
// Tank hit animation - less dramatic than regular enemy
var hitForceX = -self.directionX * 8;
var hitForceY = -self.directionY * 8;
// Create sparks instead of blood for tank
for (var i = 0; i < 3; i++) {
var sparkParticle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
x: self.x + (Math.random() - 0.5) * 40,
y: self.y + (Math.random() - 0.5) * 40
});
sparkParticle.tint = 0xFFFF00; // Yellow sparks
sparkParticle.alpha = 0.9;
self.parent.addChild(sparkParticle);
// Animate sparks
var sparkVelX = (Math.random() - 0.5) * 30;
var sparkVelY = (Math.random() - 0.5) * 30;
tween(sparkParticle, {
x: sparkParticle.x + sparkVelX,
y: sparkParticle.y + sparkVelY,
alpha: 0,
scaleX: 0.05,
scaleY: 0.05
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
if (sparkParticle.parent) {
sparkParticle.parent.removeChild(sparkParticle);
}
}
});
}
// Tank stagger - less movement than regular enemy
tween(self, {
x: self.x + hitForceX,
y: self.y + hitForceY
}, {
duration: 200,
easing: tween.easeOut
});
// Flash orange when hit (different from regular enemies)
tween(tankGraphics, {
tint: 0xFF8800
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(tankGraphics, {
tint: 0x444444 // Back to dark gray
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Minimal scale animation for tank
tween(tankGraphics, {
scaleX: 3.2,
scaleY: 2.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(tankGraphics, {
scaleX: 3.0,
scaleY: 2.5
}, {
duration: 100,
easing: tween.easeIn
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F4F2F
});
/****
* Game Code
****/
var centerX = 2048 / 2;
var centerY = 2732 / 2;
// Create shelter
var shelter = game.addChild(LK.getAsset('shelter', {
anchorX: 0.5,
anchorY: 0.5,
x: centerX,
y: centerY
}));
// Create gunman
var gunman = game.addChild(new Gunman());
gunman.x = centerX;
gunman.y = centerY;
// Game arrays
var bullets = [];
var enemies = [];
// Game state
var shelterHealth = 5;
var enemySpawnTimer = 0;
var enemySpawnRate = 80; // frames between spawns
var waveNumber = 1;
var lastShotTime = 0;
var shootCooldown = 8; // frames between shots
var bulletCount = 20; // Starting bullets
var maxBullets = 100; // Maximum bullets
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var healthTxt = new Text2('Health: ' + shelterHealth, {
size: 50,
fill: 0xFF4444
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 100;
healthTxt.y = 100;
LK.gui.topLeft.addChild(healthTxt);
var waveTxt = new Text2('Wave: 1', {
size: 50,
fill: 0x44FF44
});
waveTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(waveTxt);
var bulletTxt = new Text2('Bullets: ' + bulletCount, {
size: 50,
fill: 0xFFAA00
});
bulletTxt.anchor.set(0, 0);
bulletTxt.x = 100;
bulletTxt.y = 180;
LK.gui.topLeft.addChild(bulletTxt);
// Input handling
var aimX = centerX + 100;
var aimY = centerY;
var isShooting = false;
// Create crosshair cursor
var crosshair = game.addChild(new Crosshair());
crosshair.x = aimX;
crosshair.y = aimY;
function spawnEnemy() {
var enemy;
var enemyType = Math.random();
// 60% chance for regular enemy, 25% chance for tank, 15% chance for plane
if (enemyType < 0.6) {
enemy = new Enemy();
} else if (enemyType < 0.85) {
enemy = new Tank();
} else {
enemy = new Plane();
}
// Spawn from random position on perimeter
var angle = Math.random() * Math.PI * 2;
var spawnDistance = 1200;
enemy.x = centerX + Math.cos(angle) * spawnDistance;
enemy.y = centerY + Math.sin(angle) * spawnDistance;
// Set direction toward shelter
var dx = centerX - enemy.x;
var dy = centerY - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
enemy.directionX = dx / distance;
enemy.directionY = dy / distance;
// Adjust speed based on wave (tanks and planes have their own base speeds)
if (enemy instanceof Enemy) {
enemy.speed = 2.5 + waveNumber * 0.3;
} else if (enemy instanceof Tank) {
enemy.speed = 1.5 + waveNumber * 0.2; // Tanks get slower speed increase
} else if (enemy instanceof Plane) {
enemy.speed = 4.0 + waveNumber * 0.4; // Planes get faster speed increase
}
enemies.push(enemy);
game.addChild(enemy);
}
function shootBullet() {
if (LK.ticks - lastShotTime < shootCooldown) return;
if (bulletCount <= 0) return; // No bullets left
bulletCount--;
bulletTxt.setText('Bullets: ' + bulletCount);
var bullet = new Bullet();
bullet.x = gunman.x;
bullet.y = gunman.y;
bullet.directionX = Math.cos(gunman.aimAngle);
bullet.directionY = Math.sin(gunman.aimAngle);
bullet.startAnimation();
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
gunman.createGunSmoke();
lastShotTime = LK.ticks;
}
// Game input handlers
game.move = function (x, y, obj) {
aimX = x;
aimY = y;
gunman.setAimDirection(aimX, aimY);
crosshair.updatePosition(aimX, aimY);
};
game.down = function (x, y, obj) {
aimX = x;
aimY = y;
gunman.setAimDirection(aimX, aimY);
crosshair.updatePosition(aimX, aimY);
isShooting = true;
shootBullet();
};
game.up = function (x, y, obj) {
isShooting = false;
};
// Main game loop
game.update = function () {
// Enemy spawning
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnRate) {
spawnEnemy();
enemySpawnTimer = 0;
// Increase difficulty over time
if (enemySpawnRate > 30) {
enemySpawnRate -= 1;
}
// Increase wave number
if (LK.ticks % 600 === 0) {
waveNumber++;
waveTxt.setText('Wave: ' + waveNumber);
}
}
// Continuous shooting while touching
if (isShooting && LK.ticks % 6 === 0) {
shootBullet();
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check if bullet is off screen
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
var bulletHit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Enemy hit - reduce health
enemy.health--;
LK.getSound('enemyHit').play();
// Trigger hit animation
enemy.hitAnimation();
// Check if enemy is destroyed
if (enemy.health <= 0) {
// Different scoring for different enemy types
if (enemy instanceof Tank) {
LK.setScore(LK.getScore() + 50); // Tanks worth more points
bulletCount = Math.min(bulletCount + 5, maxBullets); // More bullets from tanks
} else if (enemy instanceof Plane) {
LK.setScore(LK.getScore() + 30); // Planes worth medium points
bulletCount = Math.min(bulletCount + 4, maxBullets); // Medium bullets from planes
} else {
LK.setScore(LK.getScore() + 10); // Regular enemies
bulletCount = Math.min(bulletCount + 3, maxBullets); // Standard bullets
}
scoreTxt.setText('Score: ' + LK.getScore());
bulletTxt.setText('Bullets: ' + bulletCount);
// Delay enemy destruction to show hit animation
LK.setTimeout(function () {
if (enemy.parent) {
enemy.destroy();
var enemyIndex = enemies.indexOf(enemy);
if (enemyIndex > -1) {
enemies.splice(enemyIndex, 1);
}
}
}, 200);
}
bullet.destroy();
bullets.splice(i, 1);
bulletHit = true;
break;
}
}
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
// Check if enemy reached shelter
var distanceToShelter = Math.sqrt(Math.pow(enemy.x - centerX, 2) + Math.pow(enemy.y - centerY, 2));
if (distanceToShelter < 100) {
shelterHealth--;
healthTxt.setText('Health: ' + shelterHealth);
LK.getSound('shelterHit').play();
LK.effects.flashObject(shelter, 0xFF0000, 300);
enemy.destroy();
enemies.splice(k, 1);
if (shelterHealth <= 0) {
LK.showGameOver();
return;
}
}
}
};
silahla hedef alır şekilde olsun
silahla koşan terörist. In-Game asset. 2d. High contrast. No shadows
bullet. In-Game asset. 2d. High contrast. No shadows
ağır makinalı tüfek. In-Game asset. 2d. High contrast. No shadows
askeri 4 tarafı açık bir sığınak. In-Game asset. 2d. High contrast. No shadows
tank. In-Game asset. 2d. High contrast. No shadows
warplane. In-Game asset. 2d. High contrast. No shadows