User prompt
each time all waves are complete, add 1 hit point to each enemy
User prompt
add logic to respawn waves once all waves are complete
User prompt
create a configurable level structure. each level will have 5 waves. each level waves will start with + hit point than the level before
User prompt
add a level structure to the game. every level will have 5 waves.
Code edit (1 edits merged)
Please save this source code
User prompt
Improve game performance
User prompt
Particles of exploded blovk ahould have block tint
User prompt
Make particles of exploded block bigger
User prompt
Please fix the bug: 'ReferenceError: Boss is not defined' in or related to this line: 'if (enemies[j].hitpoints <= 0 && !(enemies[j] instanceof Boss)) {' Line Number: 384
User prompt
Remove boss
User prompt
remove level logic but keep waves
User prompt
remove level structure
User prompt
remove boss lifbar
User prompt
remove boss bullets
User prompt
delete goblin class and asset
User prompt
add border to score
User prompt
destroy enemy boss when hitpoints are zero
User prompt
mirror goblin image when moving to the left
User prompt
mirror enemy image when moving to the left
User prompt
when enemyboss life is zero it should be destroyed
User prompt
fairy shoot should start on the top of the fairy not the center
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'hitpoints')' in or related to this line: 'score += enemies[l].hitpoints * 10;' Line Number: 652
User prompt
boss shoudl shoot boss bullets
User prompt
boss should not be destroyed unless shot by faily
User prompt
boss shoudl shoot bullest more often
/****
* Classes
****/
// Boss class
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.hitpoints = 20; // Boss hitpoints
self.update = function () {
// Logic to increase and decrease block sizes
if (LK.ticks % 120 < 60) {
self.scale.x += 0.001;
self.scale.y += 0.001;
} else {
self.scale.x -= 0.001;
self.scale.y -= 0.001;
}
// Create and update hitpoints display
if (!self.hitpointsDisplay) {
self.hitpointsDisplay = LK.getAsset('powerup', {
width: self.width,
height: 20,
color: 0x90ee90,
anchorX: 0.5,
anchorY: 0.5
});
self.hitpointsDisplay.y = -self.height / 2 - 20; // Position above the boss
self.addChild(self.hitpointsDisplay);
} else {
self.hitpointsDisplay.width = self.hitpoints / 20 * self.width;
if (self.hitpoints > 10) {
self.hitpointsDisplay.color = 0x66cc66; // Less shiny green
} else if (self.hitpoints > 5) {
self.hitpointsDisplay.color = 0xffff00; // Yellow
} else {
self.hitpointsDisplay.color = 0xff0000; // Red
}
}
// Ensure the boss stays within the top 30% of the screen
if (self.y < 0.3 * 2732) {
self.y += self.speed;
} else {
self.y = 0.3 * 2732;
}
// Add lateral movement
self.x += self.speed;
if (self.x < 0 || self.x > 2048) {
self.speed = -self.speed; // Reverse direction when hitting screen edges
}
// Boss shooting logic
if (LK.ticks % 30 == 0) {
// Boss shoots every 60 ticks
var newBullet = new Bullet();
newBullet.x = self.x;
newBullet.y = self.y;
// Calculate direction towards the fairy
var directionX = fairy.x - self.x;
var directionY = fairy.y - self.y;
var distance = Math.sqrt(directionX * directionX + directionY * directionY);
// Normalize direction
directionX /= distance;
directionY /= distance;
// Set bullet speed towards the fairy
newBullet.speedX = directionX * 5;
newBullet.speedY = directionY * 5;
// Override bullet update function to move towards the fairy
newBullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
bullets.push(newBullet);
game.addChild(newBullet);
}
};
});
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -5; // Default bullet speed, can be overridden
self.update = function () {
self.y += self.speed;
};
});
// Diamond class
var Diamond = Container.expand(function () {
var self = Container.call(this);
var diamondGraphics = self.attachAsset('diamond', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.update = function () {
self.y += self.speed;
self.rotation += 0.05; // Add rotation animation
if (LK.ticks % 120 < 60) {
self.scale.x += 0.002;
self.scale.y += 0.002;
} else {
self.scale.x -= 0.002;
self.scale.y -= 0.002;
}
if (self.y > 2732) {
self.destroy();
}
};
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('block', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xffffff // Default tint, will be overridden by wave configuration
});
self.speed = 3;
self.hitpoints = 3; // Add hitpoints to enemies
self.update = function () {
self.y += self.speed;
// Logic to increase and decrease block sizes
if (LK.ticks % 120 < 60) {
self.scale.x += 0.002;
self.scale.y += 0.002;
} else {
self.scale.x -= 0.002;
self.scale.y -= 0.002;
}
// Create and update hitpoints display
if (!self.hitpointsDisplay) {
self.hitpointsDisplay = new Text2(self.hitpoints.toString(), {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5
});
self.hitpointsDisplay.anchor.set(0.5, 0.5);
self.hitpointsDisplay.y = 0;
self.addChild(self.hitpointsDisplay);
} else {
self.hitpointsDisplay.setText(self.hitpoints.toString());
}
};
});
//<Assets used in the game will automatically appear here>
// Fairy class
var Fairy = Container.expand(function () {
var self = Container.call(this);
var fairyGraphics = self.attachAsset('fairy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.particles = [];
self.update = function () {
// Particle emitter logic
if (LK.ticks % 5 === 0) {
var particle = LK.getAsset('fairyemitter', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1,
scaleX: 12,
scaleY: 12
});
particle.x = self.x;
particle.y = self.y + self.height / 2;
particle.speedX = (Math.random() - 0.5) * 2;
particle.speedY = Math.random() * 2 + 1; // Push particles downwards
particle.update = function () {
this.x += this.speedX;
this.y += this.speedY;
this.alpha -= 0.01;
if (this.alpha <= 0) {
this.destroy();
}
};
self.particles.push(particle);
game.addChild(particle);
}
// Update existing particles
for (var i = self.particles.length - 1; i >= 0; i--) {
self.particles[i].update();
if (self.particles[i].alpha <= 0) {
self.particles.splice(i, 1);
}
}
// Fairy movement logic
};
});
// Goblin class
var Goblin = Container.expand(function () {
var self = Container.call(this);
var goblinGraphics = self.attachAsset('goblin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.hitpoints = 5; // Goblin hitpoints
self.update = function () {
// Create and update hitpoints display
if (!self.hitpointsDisplay) {
self.hitpointsDisplay = LK.getAsset('powerup', {
width: self.width,
height: 20,
color: 0x90ee90,
anchorX: 0.5,
anchorY: 0.5
});
self.hitpointsDisplay.y = -self.height / 2 - 20; // Position above the goblin
self.addChild(self.hitpointsDisplay);
} else {
self.hitpointsDisplay.width = self.hitpoints / 5 * self.width;
if (self.hitpoints > 3) {
self.hitpointsDisplay.color = 0x66cc66; // Less shiny green
} else if (self.hitpoints > 1) {
self.hitpointsDisplay.color = 0xffff00; // Yellow
} else {
self.hitpointsDisplay.color = 0xff0000; // Red
}
}
// Calculate direction towards the player
var directionX = fairy.x - self.x;
var directionY = fairy.y - self.y;
var distance = Math.sqrt(directionX * directionX + directionY * directionY);
// Normalize direction
directionX /= distance;
directionY /= distance;
// Apply jumpy movement
self.x += directionX * self.speed * (Math.random() * 2);
self.y += directionY * self.speed * (Math.random() * 2);
// Create and update hitpoints display
if (!self.hitpointsDisplay) {
self.hitpointsDisplay = new Text2(self.hitpoints.toString(), {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5
});
self.hitpointsDisplay.anchor.set(0.5, 0.5);
self.hitpointsDisplay.y = 0;
self.addChild(self.hitpointsDisplay);
} else {
self.hitpointsDisplay.width = self.hitpoints / 5 * self.width;
}
};
// Goblin shooting logic
self.shoot = function () {
var newBullet = new Bullet();
newBullet.x = self.x;
newBullet.y = self.y;
newBullet.speed = 5; // Goblin bullet speed
bullets.push(newBullet);
game.addChild(newBullet);
};
});
// Powerup class
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.update = function () {
self.y += self.speed;
if (self.y > 2732) {
self.destroy();
}
};
});
// Star class
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.update = function () {
self.y += self.speed;
if (self.y > 2732) {
self.y = -5;
self.x = Math.random() * 2048;
}
};
});
// UpgradeMenu class
var UpgradeMenu = Container.expand(function () {
var self = Container.call(this);
var menuGraphics = self.attachAsset('menu', {
anchorX: 0.5,
anchorY: 0.5
});
self.visible = false; // Initially hidden
self.update = function () {
// Update menu items
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x800080 //Init game with purple background
});
/****
* Game Code
****/
// Function to start a new level or replay the previous level
function startNewLevel() {
waveCount = 0; // Reset wave count
score = 0; // Reset score
scoreTxt.setText(score); // Update score text
coinCount = 0; // Reset coin count
coinCounterTxt.setText('Coins: ' + coinCount); // Update coin counter text
// Clear existing enemies and bullets
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
for (var j = bullets.length - 1; j >= 0; j--) {
bullets[j].destroy();
bullets.splice(j, 1);
}
// Reinitialize game elements
initGame();
LK.resumeGame(); // Resume the game
upgradeMenu.visible = false; // Hide the upgrade menu
}
// Initialize variables
var fairy;
var bullets = [];
var enemies = [];
var scoreTxt;
var score = 0;
var dragNode = null;
var diamondCount = 0; // Initialize diamond counter
var diamondCounterTxt; // Declare diamondCounterTxt variable
var isFairyHeld = false; // Track if the fairy is being held
var waveCount = 0; // Track the wave count
var waveConfig = [{
enemies: 4,
hitpoints: [1],
tints: [0xffe066]
}, {
enemies: 8,
hitpoints: [2, 1],
tints: [0xcc66ff, 0xffe066]
}, {
enemies: 12,
hitpoints: [3, 2, 1],
tints: [0xff6666, 0xcc66ff, 0xffe066]
}
// Add more wave configurations as needed
];
// Initialize game elements
function initGame() {
// Create and position the fairy
fairy = game.addChild(new Fairy());
fairy.particles = [];
fairy.x = 2048 / 2;
fairy.y = 2732 - 200;
// Create score text
scoreTxt = new Text2('0', {
size: 100,
fill: "#ffffff"
});
scoreTxt.anchor.set(0.5, 0); // Anchor to the top center
scoreTxt.x = 2048 / 2; // Position at the top center of the screen
scoreTxt.y = 20; // Position with a margin from the top
for (var i = 0; i < 50; i++) {
var star = game.addChild(new Star());
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
}
scoreTxt.anchor.set(0.5, 0);
// Create coin counter text
game.addChild(scoreTxt);
// Create coin counter text
var overlay = LK.getAsset('menu', {
width: 2048,
height: 150,
color: 0x000000,
alpha: 0.5,
anchorX: 0.5,
anchorY: 0
});
overlay.x = 2048 / 2;
overlay.y = 0;
game.addChild(overlay);
var diamondCounterContainer = new Container();
var diamondIcon = LK.getAsset('diamond', {
anchorX: 1,
anchorY: 0,
alpha: 0.8,
scaleX: 0.8,
scaleY: 0.8
});
diamondIcon.x = 2048 - 100;
diamondIcon.y = 20;
diamondCounterContainer.addChild(diamondIcon);
diamondCounterTxt = new Text2('0', {
size: 60,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5
});
diamondCounterTxt.anchor.set(0.5, 0.5);
diamondCounterTxt.x = diamondIcon.x + diamondIcon.width / 2 - 180;
diamondCounterTxt.y = diamondIcon.y + diamondIcon.height / 2 - 20;
diamondCounterContainer.addChild(diamondCounterTxt);
game.addChild(diamondCounterContainer);
// Set up game event listeners
game.down = function (x, y, obj) {
dragNode = fairy;
isFairyHeld = true; // Set isFairyHeld to true when the fairy is held
};
game.up = function (x, y, obj) {
dragNode = null;
isFairyHeld = false; // Set isFairyHeld to false when the fairy is released
};
game.move = handleMove;
// Update game every tick
game.update = updateGame;
}
// Handle move events
function handleMove(x, y, obj) {
if (dragNode) {
// Check if the fairy is moving to the right
if (x > dragNode.x) {
// Mirror the fairy image
dragNode.scale.x = -1;
} else {
// Reset the fairy image
dragNode.scale.x = 1;
}
// Create a ghost image of the fairy when it moves every other frame
if (LK.ticks % 4 === 0) {
var ghostFairy = LK.getAsset('fairy', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
ghostFairy.x = dragNode.x;
ghostFairy.y = dragNode.y;
if (dragNode.parent === game) {
game.addChildAt(ghostFairy, game.getChildIndex(dragNode));
} else {
game.addChild(ghostFairy);
}
// Remove the ghost image after 0.5 seconds
LK.setTimeout(function () {
ghostFairy.destroy();
}, 250);
}
dragNode.x += (x - dragNode.x) * 0.1;
if (y > 2732 * 0.6) {
dragNode.y += (y - dragNode.y) * 0.1;
} else {
dragNode.y += (2732 * 0.6 - dragNode.y) * 0.1;
}
}
}
// Update game logic
function updateGame() {
// Update starfield
for (var i = game.children.length - 1; i >= 0; i--) {
if (game.children[i] instanceof Star) {
game.children[i].update();
}
if (game.children[i] instanceof Diamond && game.children[i].intersects(fairy)) {
game.children[i].destroy();
diamondCount++;
diamondCounterTxt.setText(diamondCount);
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] instanceof Bullet) {
bullets[i].update();
}
bullets[i].update();
if (bullets[i].y < -50) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
for (var j = enemies.length - 1; j >= 0; j--) {
if (enemies[j] instanceof Boss) {
enemies[j].update();
}
enemies[j].update();
if (enemies[j].y > 2732 + 50) {
enemies[j].destroy();
enemies.splice(j, 1);
}
if (fairy.intersects(enemies[j])) {
var fairyX = fairy.x;
var fairyY = fairy.y;
// Create particle effect for fairy
for (var p = 0; p < 20; p++) {
var particle = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
particle.x = fairyX;
particle.y = fairyY;
particle.speedX = (Math.random() - 0.5) * 10;
particle.speedY = (Math.random() - 0.5) * 10;
particle.update = function () {
this.x += this.speedX;
this.y += this.speedY;
this.alpha -= 0.02;
if (this.alpha <= 0) {
this.destroy();
}
};
game.addChild(particle);
}
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
for (var k = bullets.length - 1; k >= 0; k--) {
if (bullets[k].intersects(enemies[j])) {
bullets[k].destroy();
bullets.splice(k, 1);
enemies[j].hitpoints--;
if (enemies[j].hitpoints <= 0) {
var enemyX = enemies[j].x;
var enemyY = enemies[j].y;
// Create particle effect
for (var p = 0; p < 20; p++) {
var particle = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
particle.x = enemyX;
particle.y = enemyY;
particle.speedX = (Math.random() - 0.5) * 10;
particle.speedY = (Math.random() - 0.5) * 10;
particle.update = function () {
this.x += this.speedX;
this.y += this.speedY;
this.alpha -= 0.02;
if (this.alpha <= 0) {
this.destroy();
}
};
game.addChild(particle);
}
enemies[j].destroy();
enemies.splice(j, 1);
if (enemies[j]) {
score += enemies[j].hitpoints * 10;
}
scoreTxt.setText(score);
var dropChance = Math.random();
if (dropChance < 0.2) {
var newDiamond = new Diamond();
newDiamond.x = enemyX;
newDiamond.y = enemyY;
game.addChild(newDiamond);
} else if (dropChance < 0.2) {
var newPowerup = new Powerup();
newPowerup.x = enemyX;
newPowerup.y = enemyY;
game.addChild(newPowerup);
}
if (enemies[j] instanceof Boss) {
// Create bigger particle effect for boss
for (var p = 0; p < 50; p++) {
var particle = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
particle.x = enemyX;
particle.y = enemyY;
particle.speedX = (Math.random() - 0.5) * 20;
particle.speedY = (Math.random() - 0.5) * 20;
particle.update = function () {
this.x += this.speedX;
this.y += this.speedY;
this.alpha -= 0.02;
if (this.alpha <= 0) {
this.destroy();
}
};
game.addChild(particle);
}
LK.pauseGame();
upgradeMenu.visible = true;
}
}
break;
}
}
}
// Check for collisions
// Check for coin collection
for (var i = game.children.length - 1; i >= 0; i--) {
if (game.children[i] instanceof Diamond && game.children[i].intersects(fairy)) {
game.children[i].destroy();
diamondCount++;
diamondCounterTxt.setText('Diamonds: ' + diamondCount);
}
}
for (var k = bullets.length - 1; k >= 0; k--) {
for (var l = enemies.length - 1; l >= 0; l--) {
if (bullets[k].intersects(enemies[l])) {
bullets[k].destroy();
bullets.splice(k, 1);
enemies[l].hitpoints--;
if (enemies[l].hitpoints <= 0) {
var enemyX = enemies[l].x;
var enemyY = enemies[l].y;
enemies[l].destroy();
enemies.splice(l, 1);
score += enemies[l].hitpoints * 10;
scoreTxt.setText(score);
// Randomly drop coins or powerups
var dropChance = Math.random();
if (dropChance < 0.2) {
var newDiamond = new Diamond();
newDiamond.x = enemyX;
newDiamond.y = enemyY;
game.addChild(newDiamond);
} else if (dropChance < 0.2) {
var newPowerup = new Powerup();
newPowerup.x = enemyX;
newPowerup.y = enemyY;
game.addChild(newPowerup);
}
// Check if the destroyed enemy is the boss
if (enemies[l] instanceof Boss) {
LK.pauseGame(); // Pause the game
upgradeMenu.visible = true; // Show the upgrade menu
}
}
break;
}
}
}
// Spawn new bullets
if (LK.ticks % 20 == 0 && isFairyHeld) {
// Only spawn new bullets if the fairy is being held
var newBullet = new Bullet();
newBullet.x = fairy.x;
newBullet.y = fairy.y;
bullets.push(newBullet);
game.addChild(newBullet);
}
// Spawn new enemies in a line
if (LK.ticks % 600 == 0) {
waveCount++;
if (waveCount <= waveConfig.length) {
var currentWave = waveConfig[waveCount - 1];
var maxEnemiesPerLine = 4;
var enemySpacing = 2048 / (maxEnemiesPerLine + 1); // Adjust spacing to center enemies
var totalRows = Math.ceil(currentWave.enemies / maxEnemiesPerLine);
for (var i = 0; i < currentWave.enemies; i++) {
var newBlock = new Enemy();
var row = Math.floor(i / maxEnemiesPerLine);
newBlock.hitpoints = currentWave.hitpoints[row] || currentWave.hitpoints[currentWave.hitpoints.length - 1];
newBlock.x = i % maxEnemiesPerLine * enemySpacing + enemySpacing / 2 - newBlock.width / 2;
newBlock.y = row * 220 - 50; // Increase row spacing by 20 pixels
newBlock.children[0].tint = currentWave.tints[row] || currentWave.tints[currentWave.tints.length - 1];
enemies.push(newBlock);
game.addChild(newBlock);
}
// Center the rows of enemies
var totalWidth = (Math.min(currentWave.enemies, maxEnemiesPerLine) - 1) * enemySpacing;
var offsetX = (2048 - totalWidth) / 2;
for (var j = 0; j < enemies.length; j++) {
enemies[j].x += offsetX - enemies[j].width / 2;
}
} else if (waveCount == waveConfig.length + 1) {
// Spawn boss enemy
var boss = new Boss();
boss.hitpoints = 20; // Set boss hitpoints
boss.x = 2048 / 2;
boss.y = 0;
boss.speed = 5; // Set initial speed for lateral movement
enemies.push(boss);
game.addChild(boss);
}
// Spawn goblin between waves
if (waveCount % 2 == 0) {
var goblin = new Goblin();
goblin.x = Math.random() * 2048;
goblin.y = -50;
enemies.push(goblin);
game.addChild(goblin);
}
}
// Goblin shooting logic
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] instanceof Goblin && LK.ticks % 100 == 0) {
enemies[i].shoot();
}
}
}
// Initialize the game
initGame();
// Create and position the upgrade menu
var upgradeMenu = game.addChild(new UpgradeMenu());
upgradeMenu.x = 2048 / 2;
upgradeMenu.y = 2732 / 2;
8-bit. cartoon. white star.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon 8 bit fairy dust. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon, 8bit, fireball. Black border. Cicular.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon, 8 bit, shield. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
8bit, cartoon, axe. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
dark electric ball, 8bit, cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
8bit, cartoon, treasure chest frame. very big empty center. only a fine border of chest. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
shoot
Sound effect
boom
Sound effect
Hit
Sound effect
backgroundmusic
Sound effect
bossbullet
Sound effect
bossappear
Sound effect
hit
Sound effect
diamondcollect
Sound effect
hooray
Sound effect
nono
Sound effect
letsgo
Sound effect
death
Sound effect
yes
Sound effect