User prompt
add red flash effect when enemy explode ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix enemy explode ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
enemy explode ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat efek musuh meledak merah saat tertembak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
perbaiki musik latar belakang
User prompt
fix music background
User prompt
add level change notice ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
remove flash effect
User prompt
make background a static background
User prompt
add background
User prompt
hapus jumlah boss dalam game ganti dengan naik level. tambah naik level musuh tambah sulit dikalahkan
User prompt
boss death after 55 time shoots
User prompt
kurangi kecepatan gerak player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
tambah asset life powerup untuk menambah life
User prompt
make easy control player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
reduce boss bullet
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'destroy')' in or related to this line: 'currentBoss.destroy();' Line Number: 372
User prompt
buat gerakan player agak melambat ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat sistem pertempuran melawan bos setiap kelipatan score 200
User prompt
buat kontrol player lebih mudah dengan sentuhan ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat peluru player menyebar sekali tiga
User prompt
tingkatkan kecepatan peluru player
User prompt
buat kendali player mudah saat menggulir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat kontrol player lebih halus dan tidak asal cepat ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
bossGraphics.tint = 0x800080; // Purple tint for boss
self.maxHealth = 20;
self.health = self.maxHealth;
self.speed = 1;
self.direction = 1;
self.shootTimer = 0;
self.shootInterval = 30; // Shoot every 0.5 seconds
self.specialAttackTimer = 0;
self.specialAttackInterval = 180; // Special attack every 3 seconds
self.points = 100;
self.phase = 1;
self.movementTimer = 0;
self.lastShoot = 0;
self.shotCount = 0; // Track number of shots fired
self.update = function () {
self.movementTimer++;
// Movement pattern
if (self.movementTimer < 120) {
// Move horizontally
self.x += self.direction * self.speed;
if (self.x <= 150 || self.x >= 1900) {
self.direction *= -1;
}
} else if (self.movementTimer < 180) {
// Move down slightly
self.y += 0.5;
} else {
// Reset movement cycle
self.movementTimer = 0;
}
// Regular shooting
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shootAtPlayer();
}
// Special attack
self.specialAttackTimer++;
if (self.specialAttackTimer >= self.specialAttackInterval) {
self.specialAttackTimer = 0;
self.specialAttack();
}
};
self.shootAtPlayer = function () {
// Create single bullet aimed at player
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 100;
// Calculate direction towards player
var deltaX = player.x - bullet.x;
var deltaY = player.y - bullet.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
bullet.directionX = deltaX / distance * bullet.speed;
bullet.directionY = deltaY / distance * bullet.speed;
enemyBullets.push(bullet);
game.addChild(bullet);
// Increment shot count and check for death after 55 shots
self.shotCount++;
if (self.shotCount >= 55) {
// Boss dies after 55 shots
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('bossDefeat').play();
self.destroy();
currentBoss = null;
isBossFight = false;
}
};
self.specialAttack = function () {
// Circular pattern of bullets
for (var i = 0; i < 4; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 50;
var angle = i / 4 * Math.PI * 2;
bullet.directionX = Math.cos(angle) * bullet.speed;
bullet.directionY = Math.sin(angle) * bullet.speed;
enemyBullets.push(bullet);
game.addChild(bullet);
// Increment shot count for each bullet
self.shotCount++;
}
// Check for death after 55 total shots
if (self.shotCount >= 55) {
// Boss dies after 55 shots
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('bossDefeat').play();
self.destroy();
currentBoss = null;
isBossFight = false;
}
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
// Boss defeated - give big score bonus
LK.setScore(LK.getScore() + 500);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('enemyHit').play();
self.destroy();
currentBoss = null;
return true; // Boss destroyed
}
return false; // Boss still alive
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.direction = 1;
self.moveDownDistance = 60;
self.shootChance = 0.001;
self.points = 10;
self.health = 1;
self.maxHealth = 1;
self.lastShoot = 0;
self.update = function () {
self.y += self.speed;
};
self.moveDown = function () {
self.y += self.moveDownDistance;
self.direction *= -1;
};
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
// Mark enemy as dying to prevent further damage
self.isDying = true;
// Flash screen red when enemy explodes
LK.effects.flashScreen(0xFF0000, 150);
// Enemy explodes - dramatic visual effect
tween(self, {
tint: 0xFF0000,
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mark for removal after animation
self.readyForDestroy = true;
}
});
return true; // Enemy destroyed
} else {
// Add red flash effect for damage
tween(self, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
return false; // Enemy still alive
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.directionX = 0;
self.directionY = self.speed;
self.update = function () {
self.x += self.directionX;
self.y += self.directionY;
};
return self;
});
var LifePowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('lifePowerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.type = 'life';
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.lastShoot = 0;
self.shootDelay = 15;
self.lives = 3;
self.invulnerable = false;
self.invulnerableTime = 0;
self.shoot = function () {
if (LK.ticks - self.lastShoot > self.shootDelay) {
// Create three bullets in a spread pattern
for (var i = 0; i < 3; i++) {
var bullet = new PlayerBullet();
bullet.x = self.x + (i - 1) * 30; // Spread bullets horizontally: -30, 0, +30
bullet.y = self.y - 40;
playerBullets.push(bullet);
game.addChild(bullet);
}
self.lastShoot = LK.ticks;
LK.getSound('shoot').play();
}
};
self.takeDamage = function () {
if (!self.invulnerable) {
self.lives--;
self.invulnerable = true;
self.invulnerableTime = LK.ticks + 120; // 2 seconds of invulnerability
LK.getSound('playerHit').play();
livesText.setText('Lives: ' + self.lives);
if (self.lives <= 0) {
LK.showGameOver();
}
}
};
self.update = function () {
if (self.invulnerable && LK.ticks > self.invulnerableTime) {
self.invulnerable = false;
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -18;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.type = 'rapidfire'; // Default type
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Create static background
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
var player = new Player();
player.x = 1024;
player.y = 2500;
game.addChild(player);
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerups = [];
var lifePowerups = [];
var enemySpawnTimer = 0;
var enemySpawnInterval = 120; // Spawn enemy every 2 seconds (120 ticks at 60fps)
var maxEnemies = 12; // Maximum enemies on screen at once
var dragNode = null;
var rapidFireEndTime = 0;
var currentShootingEnemyIndex = 0;
var enemyShootTimer = 0;
var enemyShootInterval = 90; // Shoot every 1.5 seconds (90 ticks at 60fps)
var playerAutoShootTimer = 0;
var playerAutoShootInterval = 60; // Auto shoot every 1 second (60 ticks at 60fps)
var currentLevel = 1;
var enemiesKilledThisLevel = 0;
var enemiesNeededForNextLevel = 10;
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 50;
scoreText.y = 50;
LK.gui.topLeft.addChild(scoreText);
var livesText = new Text2('Lives: 3', {
size: 80,
fill: 0xFFFFFF
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
var levelText = new Text2('Level: 1', {
size: 60,
fill: 0x00FF00
});
levelText.anchor.set(0.5, 0);
levelText.x = 1024;
levelText.y = 100;
LK.gui.top.addChild(levelText);
var levelChangeNotice = new Text2('', {
size: 100,
fill: 0xFFD700
});
levelChangeNotice.anchor.set(0.5, 0.5);
levelChangeNotice.x = 1024;
levelChangeNotice.y = 1366;
levelChangeNotice.alpha = 0;
LK.gui.center.addChild(levelChangeNotice);
function spawnEnemy() {
if (enemies.length < maxEnemies) {
var enemy = new Enemy();
enemy.x = Math.random() * (2048 - 120) + 60; // Random X position
enemy.y = -60; // Start above screen
// Increase difficulty based on level
enemy.speed = 2 + Math.random() * 3 + (currentLevel - 1) * 0.5; // Speed increases with level
enemy.shootChance = 0.001 + (currentLevel - 1) * 0.0005; // Shooting frequency increases
enemy.health = 1 + Math.floor((currentLevel - 1) / 3); // Health increases every 3 levels
enemy.maxHealth = enemy.health;
enemy.points = 10 + (currentLevel - 1) * 2; // More points per level
enemies.push(enemy);
game.addChild(enemy);
}
}
// Play background music when game starts
LK.playMusic('1battlefieldepic');
function handleTouch(x, y, obj) {
// Allow free movement in all directions within screen bounds
var targetX = Math.max(40, Math.min(2008, x));
var targetY = Math.max(40, Math.min(2692, y));
// Stop any existing movement tween
tween.stop(player, {
x: true,
y: true
});
// Slower and more controlled movement to target position
tween(player, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut
});
}
game.move = handleTouch;
game.down = function (x, y, obj) {
// Move player to touch position immediately
handleTouch(x, y, obj);
player.shoot();
};
game.up = function (x, y, obj) {
// Continue moving to last touch position on release
handleTouch(x, y, obj);
};
game.update = function () {
// Static background - no scrolling logic needed
// Check if rapid fire is active
var isRapidFire = LK.ticks < rapidFireEndTime;
if (isRapidFire) {
player.shootDelay = 5;
} else {
player.shootDelay = 15;
}
// Auto shoot every 1 second
playerAutoShootTimer++;
if (playerAutoShootTimer >= playerAutoShootInterval) {
playerAutoShootTimer = 0;
player.shoot();
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -10 && bullet.y < -10) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
if (bullet.intersects(enemies[j]) && !enemies[j].isDying) {
var enemyDestroyed = enemies[j].takeDamage();
if (enemyDestroyed) {
LK.setScore(LK.getScore() + enemies[j].points);
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('enemyHit').play();
enemiesKilledThisLevel++;
// Check for level up
if (enemiesKilledThisLevel >= enemiesNeededForNextLevel) {
currentLevel++;
enemiesKilledThisLevel = 0;
enemiesNeededForNextLevel += 5; // Need 5 more enemies each level
levelText.setText('Level: ' + currentLevel);
// Show level change notice with animation
levelChangeNotice.setText('LEVEL ' + currentLevel);
levelChangeNotice.alpha = 0;
tween(levelChangeNotice, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(levelChangeNotice, {
alpha: 0
}, {
duration: 1000,
easing: tween.easeIn
});
}
});
}
// Chance to drop power-up
if (Math.random() < 0.1) {
var powerup = new PowerUp();
powerup.x = enemies[j].x;
powerup.y = enemies[j].y;
powerups.push(powerup);
game.addChild(powerup);
}
// Chance to drop life power-up (lower chance)
if (Math.random() < 0.05) {
var lifePowerup = new LifePowerUp();
lifePowerup.x = enemies[j].x;
lifePowerup.y = enemies[j].y;
lifePowerups.push(lifePowerup);
game.addChild(lifePowerup);
}
// Don't destroy immediately - wait for animation
}
hitEnemy = true;
break;
}
}
if (hitEnemy) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2742 && bullet.y > 2742) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
player.takeDamage();
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Handle alternating enemy shooting
enemyShootTimer++;
if (enemyShootTimer >= enemyShootInterval && enemies.length > 0) {
// Reset timer
enemyShootTimer = 0;
// Find next valid enemy to shoot
var attempts = 0;
var maxAttempts = enemies.length;
while (attempts < maxAttempts) {
// Make sure index is within bounds
if (currentShootingEnemyIndex >= enemies.length) {
currentShootingEnemyIndex = 0;
}
var shootingEnemy = enemies[currentShootingEnemyIndex];
if (shootingEnemy && shootingEnemy.y < 2000) {
// Only shoot if enemy is not too low
// Create bullet from this enemy
var bullet = new EnemyBullet();
bullet.x = shootingEnemy.x;
bullet.y = shootingEnemy.y + 30;
// Calculate direction towards player
var deltaX = player.x - shootingEnemy.x;
var deltaY = player.y - shootingEnemy.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Normalize direction and apply speed
bullet.directionX = deltaX / distance * bullet.speed;
bullet.directionY = deltaY / distance * bullet.speed;
enemyBullets.push(bullet);
game.addChild(bullet);
break;
}
// Move to next enemy
currentShootingEnemyIndex = (currentShootingEnemyIndex + 1) % enemies.length;
attempts++;
}
// Move to next enemy for next turn
currentShootingEnemyIndex = (currentShootingEnemyIndex + 1) % enemies.length;
}
// Spawn new enemies continuously with level-based spawn rate
enemySpawnTimer++;
var adjustedSpawnInterval = Math.max(60, enemySpawnInterval - (currentLevel - 1) * 5); // Faster spawning at higher levels
if (enemySpawnTimer >= adjustedSpawnInterval) {
enemySpawnTimer = 0;
spawnEnemy();
}
// Update enemies and remove off-screen ones
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that finished exploding
if (enemy.readyForDestroy) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Remove enemies that go off bottom of screen
if (enemy.lastY <= 2800 && enemy.y > 2800) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check if enemies reached player (only if not dying)
if (enemy.y > 2300 && enemy.intersects(player) && !enemy.isDying) {
player.takeDamage();
}
enemy.lastY = enemy.y;
}
// Update power-ups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.lastY === undefined) powerup.lastY = powerup.y;
// Remove power-ups that go off screen
if (powerup.lastY <= 2742 && powerup.y > 2742) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with player
if (powerup.intersects(player)) {
if (powerup.type === 'rapidfire') {
rapidFireEndTime = LK.ticks + 300; // 5 seconds of rapid fire
}
LK.getSound('powerupCollect').play();
powerup.destroy();
powerups.splice(i, 1);
continue;
}
powerup.lastY = powerup.y;
}
// Update life power-ups
for (var i = lifePowerups.length - 1; i >= 0; i--) {
var lifePowerup = lifePowerups[i];
if (lifePowerup.lastY === undefined) lifePowerup.lastY = lifePowerup.y;
// Remove life power-ups that go off screen
if (lifePowerup.lastY <= 2742 && lifePowerup.y > 2742) {
lifePowerup.destroy();
lifePowerups.splice(i, 1);
continue;
}
// Check collision with player
if (lifePowerup.intersects(player)) {
if (lifePowerup.type === 'life') {
player.lives++;
livesText.setText('Lives: ' + player.lives);
}
LK.getSound('powerupCollect').play();
lifePowerup.destroy();
lifePowerups.splice(i, 1);
continue;
}
lifePowerup.lastY = lifePowerup.y;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -147,8 +147,10 @@
self.health--;
if (self.health <= 0) {
// Mark enemy as dying to prevent further damage
self.isDying = true;
+ // Flash screen red when enemy explodes
+ LK.effects.flashScreen(0xFF0000, 150);
// Enemy explodes - dramatic visual effect
tween(self, {
tint: 0xFF0000,
scaleX: 2.5,