User prompt
Please fix the bug: 'ReferenceError: PlayerBullet is not defined' in or related to this line: 'var bullet = new PlayerBullet();' Line Number: 367
User prompt
Please fix the bug: 'Enemy is not defined' in or related to this line: 'var enemy = new Enemy();' Line Number: 224
User prompt
Please fix the bug: 'Player is not defined' in or related to this line: 'player = new Player();' Line Number: 135
User prompt
uzaktan ateş eden yeni bir dron çeşidi oluştur farklı bir karakter olsun güçlendirmesini de oluştur aldığımızda olduğu yerde kurulup düşmanlara ateş etsin
User prompt
bossu kaldır boss olmasın
User prompt
uzaktan ateş eden yeni bir dron çeşidi oluştur farklı bir karakter olsun
User prompt
boss her 5 dalgada bir gelsin
User prompt
bossun canını azalt hızını arttır
User prompt
bossun hareket hızını arttır
User prompt
daha çok çağırsın
User prompt
bossun çağırdığı düşmanların sayısını arttır
User prompt
boss işleri zorlaştırmak için yanına birkaç tane düşman çağırsın
User prompt
bossu biraz daha hızlandır
User prompt
3 wave de bir devasa bir boss gelsin bossun olduğu dalgada boss harici diğer düşmanlar gelmesin, boss başka bir düşman çeşidi olsun, yavaş olsun ama yakalarsa tüm canları götürsün
User prompt
boss arkaplanın üzerinde dursun görünür olsun
User prompt
bossun canı yüksek olsun
User prompt
boss 3 dalgada bir gelsin
User prompt
5 wave de bir devasa bir boss gelsin bossun olduğu dalgada diğer düşmanlar gelmesin boss başka bir düşman çeşidi olsun
User prompt
5 wave de bir devasa bir boss gelsin bossun olduğu dalgada diğer düşmanlar gelmesin
User prompt
dron sadece 1 tane stacklenebilsin
User prompt
drone mermi ateşlemesin kendisi saldırsın
User prompt
can göstergesini sol aşağıya koy
User prompt
can göstergesini aşağıya al ve ortala
User prompt
düşmanların da boyutlarını büyüt
User prompt
biraz daha büyüt
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Drone class var Drone = Container.expand(function (player) { var self = Container.call(this); var droneSprite = self.attachAsset('drone', { anchorX: 0.5, anchorY: 0.5 }); self.radius = droneSprite.width / 2; self.player = player; self.shootInterval = 30; self.lastShotTick = 0; self.target = null; self.speed = 10 + Math.random() * 3; self._pickNewTarget = function () { // Pick a random enemy as target, or move to a random point if no enemies if (enemies.length > 0) { var idx = Math.floor(Math.random() * enemies.length); self.target = enemies[idx]; } else { // Move to a random point on the screen self.target = { x: 200 + Math.random() * (2048 - 400), y: 200 + Math.random() * (2732 - 400) }; } }; self._pickNewTarget(); self.x = player.x + (Math.random() - 0.5) * 400; self.y = player.y + (Math.random() - 0.5) * 400; self.update = function () { // If target is gone or destroyed, pick a new one if (!self.target || self.target.destroyed === true) { self._pickNewTarget(); } // Move toward target if (self.target) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } else { // Arrived at target, pick a new one self._pickNewTarget(); } } }; return self; }); // Drone bullet class var DroneBullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('drone_bullet', { anchorX: 0.5, anchorY: 0.5 }); self.radius = bulletSprite.width / 2; self.speed = 14; self.damage = 1; self.dirX = 0; self.dirY = -1; self.update = function () { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; }; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); self.type = 'normal'; // 'normal', 'fast', 'tank' self.speed = 6; self.health = 2; self.radius = 50; self.reward = 1; self.target = null; self.init = function (type) { self.type = type; if (type === 'normal') { self.attachAsset('enemy_normal', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3 + Math.random() * 1; // normal enemy slower self.health = 2; self.radius = 50; self.reward = 1; } else if (type === 'fast') { self.attachAsset('enemy_fast', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5.5 + Math.random() * 1; // fast enemy slower self.health = 1; self.radius = 40; self.reward = 2; } else if (type === 'tank') { self.attachAsset('enemy_tank', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 1.5 + Math.random() * 0.7; // tank enemy slower self.health = 6; self.radius = 80; self.reward = 4; } }; self.takeDamage = function (amount) { self.health -= amount; LK.getSound('enemy_hit').play(); LK.effects.flashObject(self, 0xffffff, 200); if (self.health <= 0) { self.destroyed = true; } }; self.update = function () { if (!self.target) return; var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var playerSprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.0, scaleY: 2.0 }); self.radius = playerSprite.width * 2.0 / 2; self.speed = 9; self.maxHealth = 8; self.health = self.maxHealth; self.shield = 0; self.dualShot = false; self.enhanced = false; self.hasDrone = false; // Remove single drone reference, use drones array // self.drone = null; self.lastShotTick = 0; self.shootInterval = 18; // frames self.invulnTicks = 0; // For powerup timers self.dualShotTicks = 0; self.enhancedTicks = 0; self.shieldTicks = 0; // For touch drag self.isDragging = false; // Damage method self.takeDamage = function (amount) { if (self.invulnTicks > 0) return; if (self.shield > 0) { self.shield = 0; self.shieldTicks = 0; LK.effects.flashObject(self, 0x00e6e6, 400); return; } // On taking damage, clear all powerups except health and shield self.dualShot = false; self.dualShotTicks = 0; self.enhanced = false; self.enhancedTicks = 0; // Destroy all drones and clear stack if (self.hasDrone && drones.length > 0) { for (var i = 0; i < drones.length; i++) { if (drones[i]) drones[i].destroy(); } drones = []; } self.hasDrone = false; self.health -= amount; self.invulnTicks = 30; LK.effects.flashObject(self, 0xff0000, 400); LK.getSound('player_hit').play(); if (self.health <= 0) { LK.showGameOver(); } }; // Powerup methods self.applyPowerup = function (type) { if (type === 'shield') { self.shield = 1; self.shieldTicks = 600; } else if (type === 'health') { self.health = Math.min(self.maxHealth, self.health + 3); } else if (type === 'dual') { self.dualShot = true; self.dualShotTicks = 0; // not used anymore } else if (type === 'enhanced') { self.enhanced = true; self.enhancedTicks = 0; // not used anymore } else if (type === 'drone') { // Allow up to 3 drones if (drones.length < 3) { self.hasDrone = true; var newDrone = new Drone(self); // Alternate each new drone to spawn on the opposite side of the previous one // First drone: angle 0, second: PI, third: 0 again (or PI*2/3, 5PI/3, PI/3 for triangle, but here: strict opposite) if (drones.length === 0) { newDrone.angle = 0; } else if (drones.length === 1) { newDrone.angle = Math.PI; } else if (drones.length === 2) { // Place third drone at 0 again (or could use 2*PI/3 for triangle, but requirement is "opposite" so cycle) newDrone.angle = 0; } game.addChild(newDrone); drones.push(newDrone); } } }; // Update powerup timers self.updatePowerups = function () { if (self.shield > 0) { self.shieldTicks--; if (self.shieldTicks <= 0) self.shield = 0; } // dualShot, enhanced, and drone are now cleared only on damage, not by timer }; // Update method self.update = function () { if (self.invulnTicks > 0) self.invulnTicks--; self.updatePowerups(); // Keep player inside bounds if (self.x < self.radius) self.x = self.radius; if (self.x > 2048 - self.radius) self.x = 2048 - self.radius; if (self.y < self.radius) self.y = self.radius; if (self.y > 2732 - self.radius) self.y = 2732 - self.radius; }; return self; }); // Player bullet class var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('player_bullet', { anchorX: 0.5, anchorY: 0.5 }); self.radius = bulletSprite.width / 2; self.speed = 16; self.damage = 1; self.dirX = 0; self.dirY = -1; self.fromDrone = false; self.update = function () { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; }; return self; }); // Powerup class var Powerup = Container.expand(function () { var self = Container.call(this); self.type = 'shield'; self.radius = 40; self.init = function (type) { self.type = type; if (type === 'shield') { self.attachAsset('powerup_shield', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'health') { self.attachAsset('powerup_health', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'dual') { self.attachAsset('powerup_dual', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'enhanced') { self.attachAsset('powerup_enhanced', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'drone') { self.attachAsset('powerup_drone', { anchorX: 0.5, anchorY: 0.5 }); } }; self.update = function () { // Float up and down self.y += Math.sin(LK.ticks / 20 + self._floatPhase) * 1.2; }; self._floatPhase = Math.random() * Math.PI * 2; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c24 }); /**** * Game Code ****/ // Add background shape to the game scene var backgroundShape = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, color: 0x23283a // dark blueish background, adjust as desired }); game.addChild(backgroundShape); // Music // Sounds // Drone // Powerups // Bullets // Enemy types // Player // Game state variables var player; var enemies = []; var bullets = []; var droneBullets = []; var powerups = []; var wave = 1; var waveTicks = 0; var spawnTick = 0; var nextPowerupTick = 0; var dragging = false; var dragOffsetX = 0; var dragOffsetY = 0; var score = 0; var healthBar; var shieldBar; var waveText; var scoreText; var lastTouchX = 0; var lastTouchY = 0; // Track up to 3 drones var drones = []; // GUI function createGUI() { // Health bar healthBar = new Text2('', { size: 80, fill: 0xFF3A3A }); healthBar.anchor.set(0, 0); LK.gui.top.addChild(healthBar); // Shield bar shieldBar = new Text2('', { size: 60, fill: 0x00E6E6 }); shieldBar.anchor.set(0, 0); LK.gui.top.addChild(shieldBar); // Score scoreText = new Text2('Score: 0', { size: 80, fill: "#fff" }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); // Wave waveText = new Text2('Wave 1', { size: 70, fill: 0xFFE066 }); waveText.anchor.set(0.5, 0); LK.gui.top.addChild(waveText); // Position GUI healthBar.x = 120; healthBar.y = 20; shieldBar.x = 120; shieldBar.y = 110; scoreText.x = -40; scoreText.y = 20; waveText.x = 1024; waveText.y = 20; } function updateGUI() { var hearts = ''; for (var i = 0; i < player.maxHealth; i++) { hearts += i < player.health ? '♥ ' : '♡ '; } healthBar.setText('HP: ' + hearts.trim()); shieldBar.setText(player.shield > 0 ? 'Shield: ON' : ''); scoreText.setText('Score: ' + score); waveText.setText('Wave ' + wave); } // Spawn player function spawnPlayer() { player = new Player(); player.x = 2048 / 2; player.y = 2732 * 0.7; game.addChild(player); } // Spawn enemies for current wave function spawnEnemies() { var num = 4 + wave * 2; for (var i = 0; i < num; i++) { var type; if (wave >= 5 && Math.random() < 0.2) { type = 'tank'; } else if (Math.random() < 0.3 + wave * 0.02) { type = 'fast'; } else { type = 'normal'; } var enemy = new Enemy(); enemy.init(type); // Spawn outside screen var edge = Math.floor(Math.random() * 4); var ex, ey; if (edge === 0) { // top ex = Math.random() * 2048; ey = -enemy.radius - 20; } else if (edge === 1) { // right ex = 2048 + enemy.radius + 20; ey = Math.random() * 2732; } else if (edge === 2) { // bottom ex = Math.random() * 2048; ey = 2732 + enemy.radius + 20; } else { // left ex = -enemy.radius - 20; ey = Math.random() * 2732; } enemy.x = ex; enemy.y = ey; enemy.target = player; enemies.push(enemy); game.addChild(enemy); } } // Spawn a powerup at random location function spawnPowerup() { var types = ['shield', 'health', 'dual', 'enhanced', 'drone']; var type = types[Math.floor(Math.random() * types.length)]; var powerup = new Powerup(); powerup.init(type); powerup.x = 200 + Math.random() * (2048 - 400); powerup.y = 400 + Math.random() * (2732 - 800); powerups.push(powerup); game.addChild(powerup); } // Fire player bullets function firePlayerBullets() { if (LK.ticks - player.lastShotTick < player.shootInterval) return; player.lastShotTick = LK.ticks; // Find nearest enemy var nearest = null; var minDist = 999999; for (var i = 0; i < enemies.length; i++) { var dx = enemies[i].x - player.x; var dy = enemies[i].y - player.y; var d = dx * dx + dy * dy; if (d < minDist) { minDist = d; nearest = enemies[i]; } } if (!nearest) return; // Don't shoot if no enemies // Calculate angle toward nearest enemy var dx = nearest.x - player.x; var dy = nearest.y - player.y; var angle = Math.atan2(dy, dx); var num = player.dualShot ? 2 : 1; for (var i = 0; i < num; i++) { var bullet = new PlayerBullet(); bullet.damage = player.enhanced ? 2 : 1; // For dual shot, both bullets go straight (no spread), but offset horizontally var offset = 0; if (num === 2) { // Perpendicular to shooting direction var perpX = -Math.sin(angle); var perpY = Math.cos(angle); offset = (i === 0 ? -1 : 1) * 32; // 32px left/right bullet.x = player.x + Math.cos(angle) * (player.radius + 30) + perpX * offset; bullet.y = player.y + Math.sin(angle) * (player.radius + 30) + perpY * offset; } else { bullet.x = player.x + Math.cos(angle) * (player.radius + 30); bullet.y = player.y + Math.sin(angle) * (player.radius + 30); } bullet.dirX = Math.cos(angle); bullet.dirY = Math.sin(angle); bullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot').play(); } // Fire drone bullets function fireDroneBullets() { if (!player.hasDrone || !player.drone) return; if (LK.ticks - player.drone.lastShotTick < player.drone.shootInterval) return; player.drone.lastShotTick = LK.ticks; // Find nearest enemy var nearest = null; var minDist = 99999; for (var i = 0; i < enemies.length; i++) { var dx = enemies[i].x - player.drone.x; var dy = enemies[i].y - player.drone.y; var d = dx * dx + dy * dy; if (d < minDist) { minDist = d; nearest = enemies[i]; } } if (!nearest) return; var dx = nearest.x - player.drone.x; var dy = nearest.y - player.drone.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist === 0) return; var bullet = new DroneBullet(); bullet.dirX = dx / dist; bullet.dirY = dy / dist; bullet.x = player.drone.x + bullet.dirX * (player.drone.radius + 20); bullet.y = player.drone.y + bullet.dirY * (player.drone.radius + 20); droneBullets.push(bullet); game.addChild(bullet); LK.getSound('drone_shoot').play(); } // Handle dragging function handleMove(x, y, obj) { if (!dragging) return; // Clamp to bounds var nx = x - dragOffsetX; var ny = y - dragOffsetY; var r = player.radius; if (nx < r) nx = r; if (nx > 2048 - r) nx = 2048 - r; if (ny < r) ny = r; if (ny > 2732 - r) ny = 2732 - r; player.x = nx; player.y = ny; lastTouchX = x; lastTouchY = y; } // Touch events game.down = function (x, y, obj) { // Don't allow drag from top left 100x100 if (x < 100 && y < 100) return; var dx = x - player.x; var dy = y - player.y; if (dx * dx + dy * dy < player.radius * player.radius * 2.5) { dragging = true; dragOffsetX = x - player.x; dragOffsetY = y - player.y; lastTouchX = x; lastTouchY = y; } }; game.move = function (x, y, obj) { handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragging = false; }; // Main update loop game.update = function () { // Player update player.update(); // Player auto-fire firePlayerBullets(); // Drone update and fire if (player.hasDrone && drones.length > 0) { for (var d = 0; d < drones.length; d++) { var drone = drones[d]; drone.update(); // Fire bullets for each drone at random enemy if (LK.ticks - drone.lastShotTick >= drone.shootInterval) { if (enemies.length > 0) { var idx = Math.floor(Math.random() * enemies.length); var target = enemies[idx]; var dx = target.x - drone.x; var dy = target.y - drone.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var bullet = new DroneBullet(); bullet.dirX = dx / dist; bullet.dirY = dy / dist; bullet.x = drone.x + bullet.dirX * (drone.radius + 20); bullet.y = drone.y + bullet.dirY * (drone.radius + 20); droneBullets.push(bullet); game.addChild(bullet); LK.getSound('drone_shoot').play(); } } drone.lastShotTick = LK.ticks; } // Drone contact damage to enemies for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; var dx = e.x - drone.x; var dy = e.y - drone.y; var dist = Math.sqrt(dx * dx + dy * dy); // Use a unique contact key per drone var contactKey = "_lastDroneContact" + d; if (dist < e.radius + drone.radius - 10) { if (!e[contactKey] || LK.ticks - e[contactKey] > 10) { e.takeDamage(1); e[contactKey] = LK.ticks; } } else { e[contactKey] = null; } } } } // Enemies update for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Check collision with player var dx = e.x - player.x; var dy = e.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < e.radius + player.radius - 10) { player.takeDamage(e.type === 'tank' ? 3 : 1); e.destroyed = true; } // Remove if offscreen if (e.x < -200 || e.x > 2248 || e.y < -200 || e.y > 2932) { e.destroyed = true; } // Remove if destroyed if (e.destroyed) { e.destroy(); enemies.splice(i, 1); score += e.reward; LK.setScore(score); } } // Bullets update for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); var hit = false; for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; var dx = e.x - b.x; var dy = e.y - b.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < e.radius + b.radius - 10) { e.takeDamage(b.damage); hit = true; break; } } // Remove if hit or offscreen if (hit || b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) { b.destroy(); bullets.splice(i, 1); } } // Drone bullets update for (var i = droneBullets.length - 1; i >= 0; i--) { var b = droneBullets[i]; b.update(); var hit = false; for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; var dx = e.x - b.x; var dy = e.y - b.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < e.radius + b.radius - 10) { e.takeDamage(1); hit = true; break; } } if (hit || b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) { b.destroy(); droneBullets.splice(i, 1); } } // Powerups update for (var i = powerups.length - 1; i >= 0; i--) { var p = powerups[i]; p.update(); var dx = p.x - player.x; var dy = p.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < p.radius + player.radius + 10) { player.applyPowerup(p.type); LK.getSound('powerup').play(); p.destroy(); powerups.splice(i, 1); } } // Wave logic waveTicks++; if (enemies.length === 0 && waveTicks > 60) { wave++; waveTicks = 0; spawnEnemies(); LK.effects.flashScreen(0x00ffcc, 400); } // Powerup spawn logic if (LK.ticks > nextPowerupTick) { spawnPowerup(); nextPowerupTick = LK.ticks + 600 + Math.floor(Math.random() * 600); } // Update GUI updateGUI(); }; // Game start function startGame() { createGUI(); spawnPlayer(); spawnEnemies(); nextPowerupTick = LK.ticks + 300; score = 0; LK.setScore(0); LK.playMusic('bgmusic', { fade: { start: 0, end: 1, duration: 1200 } }); } startGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Drone class
var Drone = Container.expand(function (player) {
var self = Container.call(this);
var droneSprite = self.attachAsset('drone', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = droneSprite.width / 2;
self.player = player;
self.shootInterval = 30;
self.lastShotTick = 0;
self.target = null;
self.speed = 10 + Math.random() * 3;
self._pickNewTarget = function () {
// Pick a random enemy as target, or move to a random point if no enemies
if (enemies.length > 0) {
var idx = Math.floor(Math.random() * enemies.length);
self.target = enemies[idx];
} else {
// Move to a random point on the screen
self.target = {
x: 200 + Math.random() * (2048 - 400),
y: 200 + Math.random() * (2732 - 400)
};
}
};
self._pickNewTarget();
self.x = player.x + (Math.random() - 0.5) * 400;
self.y = player.y + (Math.random() - 0.5) * 400;
self.update = function () {
// If target is gone or destroyed, pick a new one
if (!self.target || self.target.destroyed === true) {
self._pickNewTarget();
}
// Move toward target
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 10) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
} else {
// Arrived at target, pick a new one
self._pickNewTarget();
}
}
};
return self;
});
// Drone bullet class
var DroneBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('drone_bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletSprite.width / 2;
self.speed = 14;
self.damage = 1;
self.dirX = 0;
self.dirY = -1;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.type = 'normal'; // 'normal', 'fast', 'tank'
self.speed = 6;
self.health = 2;
self.radius = 50;
self.reward = 1;
self.target = null;
self.init = function (type) {
self.type = type;
if (type === 'normal') {
self.attachAsset('enemy_normal', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 1; // normal enemy slower
self.health = 2;
self.radius = 50;
self.reward = 1;
} else if (type === 'fast') {
self.attachAsset('enemy_fast', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5.5 + Math.random() * 1; // fast enemy slower
self.health = 1;
self.radius = 40;
self.reward = 2;
} else if (type === 'tank') {
self.attachAsset('enemy_tank', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5 + Math.random() * 0.7; // tank enemy slower
self.health = 6;
self.radius = 80;
self.reward = 4;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.getSound('enemy_hit').play();
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
self.destroyed = true;
}
};
self.update = function () {
if (!self.target) return;
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
self.radius = playerSprite.width * 2.0 / 2;
self.speed = 9;
self.maxHealth = 8;
self.health = self.maxHealth;
self.shield = 0;
self.dualShot = false;
self.enhanced = false;
self.hasDrone = false;
// Remove single drone reference, use drones array
// self.drone = null;
self.lastShotTick = 0;
self.shootInterval = 18; // frames
self.invulnTicks = 0;
// For powerup timers
self.dualShotTicks = 0;
self.enhancedTicks = 0;
self.shieldTicks = 0;
// For touch drag
self.isDragging = false;
// Damage method
self.takeDamage = function (amount) {
if (self.invulnTicks > 0) return;
if (self.shield > 0) {
self.shield = 0;
self.shieldTicks = 0;
LK.effects.flashObject(self, 0x00e6e6, 400);
return;
}
// On taking damage, clear all powerups except health and shield
self.dualShot = false;
self.dualShotTicks = 0;
self.enhanced = false;
self.enhancedTicks = 0;
// Destroy all drones and clear stack
if (self.hasDrone && drones.length > 0) {
for (var i = 0; i < drones.length; i++) {
if (drones[i]) drones[i].destroy();
}
drones = [];
}
self.hasDrone = false;
self.health -= amount;
self.invulnTicks = 30;
LK.effects.flashObject(self, 0xff0000, 400);
LK.getSound('player_hit').play();
if (self.health <= 0) {
LK.showGameOver();
}
};
// Powerup methods
self.applyPowerup = function (type) {
if (type === 'shield') {
self.shield = 1;
self.shieldTicks = 600;
} else if (type === 'health') {
self.health = Math.min(self.maxHealth, self.health + 3);
} else if (type === 'dual') {
self.dualShot = true;
self.dualShotTicks = 0; // not used anymore
} else if (type === 'enhanced') {
self.enhanced = true;
self.enhancedTicks = 0; // not used anymore
} else if (type === 'drone') {
// Allow up to 3 drones
if (drones.length < 3) {
self.hasDrone = true;
var newDrone = new Drone(self);
// Alternate each new drone to spawn on the opposite side of the previous one
// First drone: angle 0, second: PI, third: 0 again (or PI*2/3, 5PI/3, PI/3 for triangle, but here: strict opposite)
if (drones.length === 0) {
newDrone.angle = 0;
} else if (drones.length === 1) {
newDrone.angle = Math.PI;
} else if (drones.length === 2) {
// Place third drone at 0 again (or could use 2*PI/3 for triangle, but requirement is "opposite" so cycle)
newDrone.angle = 0;
}
game.addChild(newDrone);
drones.push(newDrone);
}
}
};
// Update powerup timers
self.updatePowerups = function () {
if (self.shield > 0) {
self.shieldTicks--;
if (self.shieldTicks <= 0) self.shield = 0;
}
// dualShot, enhanced, and drone are now cleared only on damage, not by timer
};
// Update method
self.update = function () {
if (self.invulnTicks > 0) self.invulnTicks--;
self.updatePowerups();
// Keep player inside bounds
if (self.x < self.radius) self.x = self.radius;
if (self.x > 2048 - self.radius) self.x = 2048 - self.radius;
if (self.y < self.radius) self.y = self.radius;
if (self.y > 2732 - self.radius) self.y = 2732 - self.radius;
};
return self;
});
// Player bullet class
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('player_bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletSprite.width / 2;
self.speed = 16;
self.damage = 1;
self.dirX = 0;
self.dirY = -1;
self.fromDrone = false;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
return self;
});
// Powerup class
var Powerup = Container.expand(function () {
var self = Container.call(this);
self.type = 'shield';
self.radius = 40;
self.init = function (type) {
self.type = type;
if (type === 'shield') {
self.attachAsset('powerup_shield', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'health') {
self.attachAsset('powerup_health', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'dual') {
self.attachAsset('powerup_dual', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'enhanced') {
self.attachAsset('powerup_enhanced', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'drone') {
self.attachAsset('powerup_drone', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.update = function () {
// Float up and down
self.y += Math.sin(LK.ticks / 20 + self._floatPhase) * 1.2;
};
self._floatPhase = Math.random() * Math.PI * 2;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c24
});
/****
* Game Code
****/
// Add background shape to the game scene
var backgroundShape = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
color: 0x23283a // dark blueish background, adjust as desired
});
game.addChild(backgroundShape);
// Music
// Sounds
// Drone
// Powerups
// Bullets
// Enemy types
// Player
// Game state variables
var player;
var enemies = [];
var bullets = [];
var droneBullets = [];
var powerups = [];
var wave = 1;
var waveTicks = 0;
var spawnTick = 0;
var nextPowerupTick = 0;
var dragging = false;
var dragOffsetX = 0;
var dragOffsetY = 0;
var score = 0;
var healthBar;
var shieldBar;
var waveText;
var scoreText;
var lastTouchX = 0;
var lastTouchY = 0;
// Track up to 3 drones
var drones = [];
// GUI
function createGUI() {
// Health bar
healthBar = new Text2('', {
size: 80,
fill: 0xFF3A3A
});
healthBar.anchor.set(0, 0);
LK.gui.top.addChild(healthBar);
// Shield bar
shieldBar = new Text2('', {
size: 60,
fill: 0x00E6E6
});
shieldBar.anchor.set(0, 0);
LK.gui.top.addChild(shieldBar);
// Score
scoreText = new Text2('Score: 0', {
size: 80,
fill: "#fff"
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Wave
waveText = new Text2('Wave 1', {
size: 70,
fill: 0xFFE066
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
// Position GUI
healthBar.x = 120;
healthBar.y = 20;
shieldBar.x = 120;
shieldBar.y = 110;
scoreText.x = -40;
scoreText.y = 20;
waveText.x = 1024;
waveText.y = 20;
}
function updateGUI() {
var hearts = '';
for (var i = 0; i < player.maxHealth; i++) {
hearts += i < player.health ? '♥ ' : '♡ ';
}
healthBar.setText('HP: ' + hearts.trim());
shieldBar.setText(player.shield > 0 ? 'Shield: ON' : '');
scoreText.setText('Score: ' + score);
waveText.setText('Wave ' + wave);
}
// Spawn player
function spawnPlayer() {
player = new Player();
player.x = 2048 / 2;
player.y = 2732 * 0.7;
game.addChild(player);
}
// Spawn enemies for current wave
function spawnEnemies() {
var num = 4 + wave * 2;
for (var i = 0; i < num; i++) {
var type;
if (wave >= 5 && Math.random() < 0.2) {
type = 'tank';
} else if (Math.random() < 0.3 + wave * 0.02) {
type = 'fast';
} else {
type = 'normal';
}
var enemy = new Enemy();
enemy.init(type);
// Spawn outside screen
var edge = Math.floor(Math.random() * 4);
var ex, ey;
if (edge === 0) {
// top
ex = Math.random() * 2048;
ey = -enemy.radius - 20;
} else if (edge === 1) {
// right
ex = 2048 + enemy.radius + 20;
ey = Math.random() * 2732;
} else if (edge === 2) {
// bottom
ex = Math.random() * 2048;
ey = 2732 + enemy.radius + 20;
} else {
// left
ex = -enemy.radius - 20;
ey = Math.random() * 2732;
}
enemy.x = ex;
enemy.y = ey;
enemy.target = player;
enemies.push(enemy);
game.addChild(enemy);
}
}
// Spawn a powerup at random location
function spawnPowerup() {
var types = ['shield', 'health', 'dual', 'enhanced', 'drone'];
var type = types[Math.floor(Math.random() * types.length)];
var powerup = new Powerup();
powerup.init(type);
powerup.x = 200 + Math.random() * (2048 - 400);
powerup.y = 400 + Math.random() * (2732 - 800);
powerups.push(powerup);
game.addChild(powerup);
}
// Fire player bullets
function firePlayerBullets() {
if (LK.ticks - player.lastShotTick < player.shootInterval) return;
player.lastShotTick = LK.ticks;
// Find nearest enemy
var nearest = null;
var minDist = 999999;
for (var i = 0; i < enemies.length; i++) {
var dx = enemies[i].x - player.x;
var dy = enemies[i].y - player.y;
var d = dx * dx + dy * dy;
if (d < minDist) {
minDist = d;
nearest = enemies[i];
}
}
if (!nearest) return; // Don't shoot if no enemies
// Calculate angle toward nearest enemy
var dx = nearest.x - player.x;
var dy = nearest.y - player.y;
var angle = Math.atan2(dy, dx);
var num = player.dualShot ? 2 : 1;
for (var i = 0; i < num; i++) {
var bullet = new PlayerBullet();
bullet.damage = player.enhanced ? 2 : 1;
// For dual shot, both bullets go straight (no spread), but offset horizontally
var offset = 0;
if (num === 2) {
// Perpendicular to shooting direction
var perpX = -Math.sin(angle);
var perpY = Math.cos(angle);
offset = (i === 0 ? -1 : 1) * 32; // 32px left/right
bullet.x = player.x + Math.cos(angle) * (player.radius + 30) + perpX * offset;
bullet.y = player.y + Math.sin(angle) * (player.radius + 30) + perpY * offset;
} else {
bullet.x = player.x + Math.cos(angle) * (player.radius + 30);
bullet.y = player.y + Math.sin(angle) * (player.radius + 30);
}
bullet.dirX = Math.cos(angle);
bullet.dirY = Math.sin(angle);
bullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shoot').play();
}
// Fire drone bullets
function fireDroneBullets() {
if (!player.hasDrone || !player.drone) return;
if (LK.ticks - player.drone.lastShotTick < player.drone.shootInterval) return;
player.drone.lastShotTick = LK.ticks;
// Find nearest enemy
var nearest = null;
var minDist = 99999;
for (var i = 0; i < enemies.length; i++) {
var dx = enemies[i].x - player.drone.x;
var dy = enemies[i].y - player.drone.y;
var d = dx * dx + dy * dy;
if (d < minDist) {
minDist = d;
nearest = enemies[i];
}
}
if (!nearest) return;
var dx = nearest.x - player.drone.x;
var dy = nearest.y - player.drone.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) return;
var bullet = new DroneBullet();
bullet.dirX = dx / dist;
bullet.dirY = dy / dist;
bullet.x = player.drone.x + bullet.dirX * (player.drone.radius + 20);
bullet.y = player.drone.y + bullet.dirY * (player.drone.radius + 20);
droneBullets.push(bullet);
game.addChild(bullet);
LK.getSound('drone_shoot').play();
}
// Handle dragging
function handleMove(x, y, obj) {
if (!dragging) return;
// Clamp to bounds
var nx = x - dragOffsetX;
var ny = y - dragOffsetY;
var r = player.radius;
if (nx < r) nx = r;
if (nx > 2048 - r) nx = 2048 - r;
if (ny < r) ny = r;
if (ny > 2732 - r) ny = 2732 - r;
player.x = nx;
player.y = ny;
lastTouchX = x;
lastTouchY = y;
}
// Touch events
game.down = function (x, y, obj) {
// Don't allow drag from top left 100x100
if (x < 100 && y < 100) return;
var dx = x - player.x;
var dy = y - player.y;
if (dx * dx + dy * dy < player.radius * player.radius * 2.5) {
dragging = true;
dragOffsetX = x - player.x;
dragOffsetY = y - player.y;
lastTouchX = x;
lastTouchY = y;
}
};
game.move = function (x, y, obj) {
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragging = false;
};
// Main update loop
game.update = function () {
// Player update
player.update();
// Player auto-fire
firePlayerBullets();
// Drone update and fire
if (player.hasDrone && drones.length > 0) {
for (var d = 0; d < drones.length; d++) {
var drone = drones[d];
drone.update();
// Fire bullets for each drone at random enemy
if (LK.ticks - drone.lastShotTick >= drone.shootInterval) {
if (enemies.length > 0) {
var idx = Math.floor(Math.random() * enemies.length);
var target = enemies[idx];
var dx = target.x - drone.x;
var dy = target.y - drone.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var bullet = new DroneBullet();
bullet.dirX = dx / dist;
bullet.dirY = dy / dist;
bullet.x = drone.x + bullet.dirX * (drone.radius + 20);
bullet.y = drone.y + bullet.dirY * (drone.radius + 20);
droneBullets.push(bullet);
game.addChild(bullet);
LK.getSound('drone_shoot').play();
}
}
drone.lastShotTick = LK.ticks;
}
// Drone contact damage to enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
var dx = e.x - drone.x;
var dy = e.y - drone.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Use a unique contact key per drone
var contactKey = "_lastDroneContact" + d;
if (dist < e.radius + drone.radius - 10) {
if (!e[contactKey] || LK.ticks - e[contactKey] > 10) {
e.takeDamage(1);
e[contactKey] = LK.ticks;
}
} else {
e[contactKey] = null;
}
}
}
}
// Enemies update
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Check collision with player
var dx = e.x - player.x;
var dy = e.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < e.radius + player.radius - 10) {
player.takeDamage(e.type === 'tank' ? 3 : 1);
e.destroyed = true;
}
// Remove if offscreen
if (e.x < -200 || e.x > 2248 || e.y < -200 || e.y > 2932) {
e.destroyed = true;
}
// Remove if destroyed
if (e.destroyed) {
e.destroy();
enemies.splice(i, 1);
score += e.reward;
LK.setScore(score);
}
}
// Bullets update
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
var hit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
var dx = e.x - b.x;
var dy = e.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < e.radius + b.radius - 10) {
e.takeDamage(b.damage);
hit = true;
break;
}
}
// Remove if hit or offscreen
if (hit || b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) {
b.destroy();
bullets.splice(i, 1);
}
}
// Drone bullets update
for (var i = droneBullets.length - 1; i >= 0; i--) {
var b = droneBullets[i];
b.update();
var hit = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
var dx = e.x - b.x;
var dy = e.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < e.radius + b.radius - 10) {
e.takeDamage(1);
hit = true;
break;
}
}
if (hit || b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) {
b.destroy();
droneBullets.splice(i, 1);
}
}
// Powerups update
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
var dx = p.x - player.x;
var dy = p.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < p.radius + player.radius + 10) {
player.applyPowerup(p.type);
LK.getSound('powerup').play();
p.destroy();
powerups.splice(i, 1);
}
}
// Wave logic
waveTicks++;
if (enemies.length === 0 && waveTicks > 60) {
wave++;
waveTicks = 0;
spawnEnemies();
LK.effects.flashScreen(0x00ffcc, 400);
}
// Powerup spawn logic
if (LK.ticks > nextPowerupTick) {
spawnPowerup();
nextPowerupTick = LK.ticks + 600 + Math.floor(Math.random() * 600);
}
// Update GUI
updateGUI();
};
// Game start
function startGame() {
createGUI();
spawnPlayer();
spawnEnemies();
nextPowerupTick = LK.ticks + 300;
score = 0;
LK.setScore(0);
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
}
startGame();
Draw a chibi-style top-down (bird's-eye view) park field. The scene should be cute and colorful, with soft, rounded shapes typical of chibi environments. Include details like small patches of flowers, tiny rocks, and gentle variations in the grass. The overall style should be whimsical and simple, with clean lines and a bright, cheerful color palette. In-Game asset. 2d. High contrast. No shadows