User prompt
turret ve dron güçlendirmesi çıkma şansını arttır
User prompt
turret ve dron güçlendirmesi çıkma şansını çok az arttır
User prompt
turret en fazla 3 wave sürecek kadar süreye sahip olsun
User prompt
dron en fazla 3 wave sürecek kadar süreye sahip olsun
User prompt
düşmanların sıklığını daha yavaş arttır
User prompt
gelen hızlı düşmanların hızını birazcık yavaşlat
User prompt
çok az daha büyüt
User prompt
normal ve hızlı düşmanların boyunu çok az büyüt
User prompt
turretin ateş etme sıklığını biraz arttır ama fazla olmasın
User prompt
turretin boyutunu biraz küçült
User prompt
turretin boyutunu büyüt
User prompt
karakter turret ile üst üste geldiğinde üstte karakter gözüksün
User prompt
tüm düşmanların ilk wavelerde gelme sıklığını biraz azalt
User prompt
turret ve turret güçlendirmesini iki farklı öğe olarak ayır
User prompt
yeni bir güçlendirme ekle aldığında ateş eden bir turret spawnlasın
User prompt
Please fix the bug: 'ReferenceError: PlayerBullet is not defined' in or related to this line: 'var bullet = new PlayerBullet();' Line Number: 346
User prompt
Please fix the bug: 'Enemy is not defined' in or related to this line: 'var enemy = new Enemy();' Line Number: 209
User prompt
Please fix the bug: 'Player is not defined' in or related to this line: 'player = new Player();' Line Number: 135
User prompt
Please fix the bug: 'ReferenceError: RemoteShooterDrone is not defined' in or related to this line: 'var newRemoteShooterDrone = new RemoteShooterDrone(p.x, p.y);' Line Number: 707
User prompt
Please fix the bug: 'ReferenceError: Powerup is not defined' in or related to this line: 'var powerup = new Powerup();' Line Number: 365
/****
* 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 = 90; // updated for new size
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 = 70; // updated for new size
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 = 130; // updated for new size
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') {
// Only allow 1 drone at a time
if (drones.length < 1) {
self.hasDrone = true;
var newDrone = new Drone(self);
newDrone.angle = 0;
game.addChild(newDrone);
drones.push(newDrone);
}
} else if (type === 'remote_turret') {
// Allow up to 2 turrets at a time
if (remoteTurrets.length < 2) {
var turret = new RemoteTurret(self);
game.addChild(turret);
remoteTurrets.push(turret);
}
}
};
// 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
});
} else if (type === 'remote_turret') {
self.attachAsset('powerup_remote_shooter_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;
});
// RemoteTurret class
var RemoteTurret = Container.expand(function (player) {
var self = Container.call(this);
var turretSprite = self.attachAsset('powerup_remote_shooter_drone', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = turretSprite.width / 2;
self.player = player;
self.shootInterval = 24;
self.lastShotTick = 0;
self.lifetime = 900; // 15 seconds at 60fps
self.ticks = 0;
// Place turret near player, but not on top
self.x = player.x + (Math.random() - 0.5) * 400;
self.y = player.y - 300 + (Math.random() - 0.5) * 100;
self.update = function () {
self.ticks++;
// Fire at nearest enemy
if (LK.ticks - self.lastShotTick >= self.shootInterval) {
var nearest = null;
var minDist = 999999;
for (var i = 0; i < enemies.length; i++) {
var dx = enemies[i].x - self.x;
var dy = enemies[i].y - self.y;
var d = dx * dx + dy * dy;
if (d < minDist) {
minDist = d;
nearest = enemies[i];
}
}
if (nearest) {
var dx = nearest.x - self.x;
var dy = nearest.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var bullet = new RemoteTurretBullet();
bullet.x = self.x + dx / dist * (self.radius + 20);
bullet.y = self.y + dy / dist * (self.radius + 20);
bullet.dirX = dx / dist;
bullet.dirY = dy / dist;
remoteTurretBullets.push(bullet);
game.addChild(bullet);
LK.getSound('drone_shoot').play();
}
self.lastShotTick = LK.ticks;
}
}
// Remove after lifetime
if (self.ticks > self.lifetime) {
self.destroy();
var idx = remoteTurrets.indexOf(self);
if (idx !== -1) remoteTurrets.splice(idx, 1);
}
};
return self;
});
// RemoteTurretBullet class
var RemoteTurretBullet = 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 = 18;
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;
});
/****
* 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 remoteTurrets = [];
var remoteTurretBullets = [];
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.5, 1);
LK.gui.bottom.addChild(healthBar);
// Shield bar
shieldBar = new Text2('', {
size: 60,
fill: 0x00E6E6
});
shieldBar.anchor.set(0.5, 1);
LK.gui.bottom.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
// Bottom left, stacked vertically (health at bottom, shield above)
healthBar.x = 180;
healthBar.y = -40;
shieldBar.x = 180;
shieldBar.y = -130;
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() {
// No boss waves, only normal enemy waves
// Normal enemy waves
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', 'remote_turret'];
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 contact attack only (no bullet firing)
if (player.hasDrone && drones.length > 0) {
for (var d = 0; d < drones.length; d++) {
var drone = drones[d];
drone.update();
// 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;
}
}
}
}
// Remote turrets update
for (var t = remoteTurrets.length - 1; t >= 0; t--) {
var turret = remoteTurrets[t];
turret.update();
}
// 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);
}
}
// Remote turret bullets update
for (var i = remoteTurretBullets.length - 1; i >= 0; i--) {
var b = remoteTurretBullets[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();
remoteTurretBullets.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 && wave % 3 !== 0) {
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(); ===================================================================
--- original.js
+++ change.js
@@ -5,50 +5,124 @@
/****
* Classes
****/
-// Minimal Enemy class definition to fix 'Enemy is not defined' error
+// 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);
- // Default type
- self.type = 'normal';
- // Attach asset based on type
+ 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;
- var assetId;
- if (type === 'tank') {
- assetId = 'enemy_tank';
+ 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 = 90; // updated for new size
+ self.reward = 1;
} else if (type === 'fast') {
- assetId = 'enemy_fast';
- } else {
- assetId = 'enemy_normal';
- }
- // Remove previous children if any
- while (self.children && self.children.length > 0) {
- self.removeChild(self.children[0]);
- }
- var sprite = self.attachAsset(assetId, {
- anchorX: 0.5,
- anchorY: 0.5
- });
- self.radius = sprite.width / 2;
- // Set health and reward based on type
- if (type === 'tank') {
+ 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 = 70; // updated for new size
+ 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.reward = 30;
- self.speed = 2;
- } else if (type === 'fast') {
- self.health = 2;
- self.reward = 10;
- self.speed = 7;
- } else {
- self.health = 3;
- self.reward = 15;
- self.speed = 4;
+ self.radius = 130; // updated for new size
+ self.reward = 4;
}
- self.destroyed = false;
};
- // Move toward target (player)
+ 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;
@@ -57,104 +131,259 @@
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
};
- // Take damage
- self.takeDamage = function (amount) {
- self.health -= amount;
- if (self.health <= 0) {
- self.destroyed = true;
- }
- };
- // Destroy method (placeholder)
- self.destroy = function () {
- // Remove from parent if needed
- if (self.parent) {
- self.parent.removeChild(self);
- }
- };
return self;
});
-// Minimal Player class definition to fix 'Player is not defined' error
+// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
- // Attach player asset
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
- anchorY: 0.5
+ anchorY: 0.5,
+ scaleX: 2.0,
+ scaleY: 2.0
});
- // Player properties
- self.radius = playerSprite.width / 2;
- self.maxHealth = 5;
+ self.radius = playerSprite.width * 2.0 / 2;
+ self.speed = 9;
+ self.maxHealth = 8;
self.health = self.maxHealth;
self.shield = 0;
- self.lastShotTick = 0;
- self.shootInterval = 30;
self.dualShot = false;
self.enhanced = false;
self.hasDrone = false;
- self.drone = null;
- // Update method (called every frame)
- self.update = function () {
- // Placeholder for player update logic
- };
- // Take damage method
+ // 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--;
- } else {
- self.health -= amount;
- if (self.health < 0) self.health = 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();
+ }
};
- // Apply powerup method
+ // Powerup methods
self.applyPowerup = function (type) {
- if (type === 'health') {
- self.health = Math.min(self.maxHealth, self.health + 2);
- } else if (type === 'shield') {
- self.shield = 3;
+ 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') {
- self.hasDrone = true;
- // Drone instantiation logic can be added here if needed
+ // Only allow 1 drone at a time
+ if (drones.length < 1) {
+ self.hasDrone = true;
+ var newDrone = new Drone(self);
+ newDrone.angle = 0;
+ game.addChild(newDrone);
+ drones.push(newDrone);
+ }
+ } else if (type === 'remote_turret') {
+ // Allow up to 2 turrets at a time
+ if (remoteTurrets.length < 2) {
+ var turret = new RemoteTurret(self);
+ game.addChild(turret);
+ remoteTurrets.push(turret);
+ }
}
};
+ // 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;
});
-// Minimal PlayerBullet class definition to fix 'PlayerBullet is not defined' error
+// Player bullet class
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
- // Attach bullet asset
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.speed = 32;
- // Update method (called every frame)
+ self.fromDrone = false;
self.update = function () {
- // Store last position for good practice (if needed)
- if (self.lastX === undefined) self.lastX = self.x;
- if (self.lastY === undefined) self.lastY = self.y;
- self.lastX = self.x;
- self.lastY = self.y;
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
- // Destroy method (placeholder)
- self.destroy = function () {
- if (self.parent) {
- self.parent.removeChild(self);
+ 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
+ });
+ } else if (type === 'remote_turret') {
+ self.attachAsset('powerup_remote_shooter_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;
});
+// RemoteTurret class
+var RemoteTurret = Container.expand(function (player) {
+ var self = Container.call(this);
+ var turretSprite = self.attachAsset('powerup_remote_shooter_drone', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = turretSprite.width / 2;
+ self.player = player;
+ self.shootInterval = 24;
+ self.lastShotTick = 0;
+ self.lifetime = 900; // 15 seconds at 60fps
+ self.ticks = 0;
+ // Place turret near player, but not on top
+ self.x = player.x + (Math.random() - 0.5) * 400;
+ self.y = player.y - 300 + (Math.random() - 0.5) * 100;
+ self.update = function () {
+ self.ticks++;
+ // Fire at nearest enemy
+ if (LK.ticks - self.lastShotTick >= self.shootInterval) {
+ var nearest = null;
+ var minDist = 999999;
+ for (var i = 0; i < enemies.length; i++) {
+ var dx = enemies[i].x - self.x;
+ var dy = enemies[i].y - self.y;
+ var d = dx * dx + dy * dy;
+ if (d < minDist) {
+ minDist = d;
+ nearest = enemies[i];
+ }
+ }
+ if (nearest) {
+ var dx = nearest.x - self.x;
+ var dy = nearest.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ var bullet = new RemoteTurretBullet();
+ bullet.x = self.x + dx / dist * (self.radius + 20);
+ bullet.y = self.y + dy / dist * (self.radius + 20);
+ bullet.dirX = dx / dist;
+ bullet.dirY = dy / dist;
+ remoteTurretBullets.push(bullet);
+ game.addChild(bullet);
+ LK.getSound('drone_shoot').play();
+ }
+ self.lastShotTick = LK.ticks;
+ }
+ }
+ // Remove after lifetime
+ if (self.ticks > self.lifetime) {
+ self.destroy();
+ var idx = remoteTurrets.indexOf(self);
+ if (idx !== -1) remoteTurrets.splice(idx, 1);
+ }
+ };
+ return self;
+});
+// RemoteTurretBullet class
+var RemoteTurretBullet = 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 = 18;
+ 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;
+});
/****
* Initialize Game
****/
@@ -187,8 +416,10 @@
var player;
var enemies = [];
var bullets = [];
var droneBullets = [];
+var remoteTurrets = [];
+var remoteTurretBullets = [];
var powerups = [];
var wave = 1;
var waveTicks = 0;
var spawnTick = 0;
@@ -204,11 +435,8 @@
var lastTouchX = 0;
var lastTouchY = 0;
// Track up to 3 drones
var drones = [];
-// Remote shooter drones and their bullets
-var remoteShooterDrones = [];
-var remoteShooterDroneBullets = [];
// GUI
function createGUI() {
// Health bar
healthBar = new Text2('', {
@@ -310,9 +538,9 @@
}
}
// Spawn a powerup at random location
function spawnPowerup() {
- var types = ['shield', 'health', 'dual', 'enhanced', 'drone', 'remote_shooter_drone'];
+ var types = ['shield', 'health', 'dual', 'enhanced', 'drone', 'remote_turret'];
var type = types[Math.floor(Math.random() * types.length)];
var powerup = new Powerup();
powerup.init(type);
powerup.x = 200 + Math.random() * (2048 - 400);
@@ -461,8 +689,13 @@
}
}
}
}
+ // Remote turrets update
+ for (var t = remoteTurrets.length - 1; t >= 0; t--) {
+ var turret = remoteTurrets[t];
+ turret.update();
+ }
// Enemies update
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
@@ -528,61 +761,41 @@
b.destroy();
droneBullets.splice(i, 1);
}
}
- // Remote shooter drone bullets update
- for (var i = remoteShooterDroneBullets.length - 1; i >= 0; i--) {
- var b = remoteShooterDroneBullets[i];
+ // Remote turret bullets update
+ for (var i = remoteTurretBullets.length - 1; i >= 0; i--) {
+ var b = remoteTurretBullets[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);
+ e.takeDamage(1);
hit = true;
break;
}
}
if (hit || b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) {
b.destroy();
- remoteShooterDroneBullets.splice(i, 1);
+ remoteTurretBullets.splice(i, 1);
}
}
- // Remote shooter drones update
- for (var i = remoteShooterDrones.length - 1; i >= 0; i--) {
- var d = remoteShooterDrones[i];
- if (d.destroyed) {
- d.destroy();
- remoteShooterDrones.splice(i, 1);
- continue;
- }
- d.update();
- }
// 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) {
- if (p.type === 'remote_shooter_drone') {
- // Deploy stationary drone at pickup location
- var newRemoteShooterDrone = new RemoteShooterDrone(p.x, p.y);
- remoteShooterDrones.push(newRemoteShooterDrone);
- game.addChild(newRemoteShooterDrone);
- LK.getSound('powerup').play();
- p.destroy();
- powerups.splice(i, 1);
- } else {
- player.applyPowerup(p.type);
- LK.getSound('powerup').play();
- p.destroy();
- powerups.splice(i, 1);
- }
+ player.applyPowerup(p.type);
+ LK.getSound('powerup').play();
+ p.destroy();
+ powerups.splice(i, 1);
}
}
// Wave logic
waveTicks++;
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