/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.health = 200; self.maxHealth = 200; self.attackPattern = 0; self.jumpCount = 0; // Initialize jump count self.attackCooldown = 3000; // ms self.canAttack = true; self.attackTimer = null; self.movementSpeed = 1.5; // Reduced speed for slower movement self.direction = 1; // 1 = right, -1 = left self.phaseChangeThreshold = 50; // Health threshold for phase change self.isPhaseTwo = false; self.update = function () { // Boss movement if (!self.isPhaseTwo) { // Phase 1 movement: back and forth self.x += self.movementSpeed * self.direction; if (self.x > 1800 || self.x < 600) { self.direction *= -1; } } else { // Phase 2 movement: predictive follow player // Maintain a safe distance from the hero var safeDistance = 200; var predictionFactor = 0.1; // Factor to predict hero's future position var predictedHeroX = hero.x + hero.speed * predictionFactor * (pressedRight ? 1 : pressedLeft ? -1 : 0); if (self.x < predictedHeroX - safeDistance) { self.x += self.movementSpeed * 0.5; } else if (self.x > predictedHeroX + safeDistance) { self.x -= self.movementSpeed * 0.5; } } // Always perform long jumps and attack if (self.isGrounded || self.jumpCount < 4) { self.velocityY = -30; // Increased jump force for long jumps self.isGrounded = false; self.jumpCount++; // Increment jump count self.attack(); // Attack during jump } self.velocityY += 0.7; // Gravity self.y += self.velocityY; if (self.y >= groundLevel - bossGraphics.height / 2) { self.y = groundLevel - bossGraphics.height / 2; self.velocityY = 0; self.isGrounded = true; self.jumpCount = 0; // Reset jump count when grounded } // Attack if possible if (self.canAttack) { self.attack(); } // Check for phase change if (!self.isPhaseTwo && self.health <= self.phaseChangeThreshold) { self.enterPhaseTwo(); } }; self.attack = function () { self.canAttack = false; // Different attack patterns if (self.isPhaseTwo) { // Phase 2 - more aggressive attacks switch (Math.floor(Math.random() * 3)) { case 0: self.spreadAttack(); break; case 1: self.targetedAttack(); break; } } else { // Phase 1 - basic attacks if (Math.random() > 0.5) { self.singleAttack(); } else { self.targetedAttack(); } } // Reset attack cooldown self.attackTimer = LK.setTimeout(function () { self.canAttack = true; }, self.attackCooldown); }; self.singleAttack = function () { var projectile = new BossProjectile(); projectile.x = self.x; projectile.y = self.y; game.addChild(projectile); bossProjectiles.push(projectile); }; self.spreadAttack = function () { for (var i = -2; i <= 2; i++) { var projectile = new BossProjectile(); projectile.x = self.x; projectile.y = self.y; projectile.velocityX = -5 + i * 2; projectile.velocityY = 5; game.addChild(projectile); bossProjectiles.push(projectile); } }; self.targetedAttack = function () { var projectile = new BossProjectile(); projectile.x = self.x; projectile.y = self.y; // Calculate direction toward player var dx = hero.x - self.x; var dy = hero.y - self.y; var angle = Math.atan2(dy, dx); projectile.velocityX = Math.cos(angle) * 8; projectile.velocityY = Math.sin(angle) * 8; game.addChild(projectile); bossProjectiles.push(projectile); }; self.takeDamage = function (damage) { self.health -= damage; // Flash boss red LK.effects.flashObject(self, 0xff0000, 300); if (self.health <= 0) { self.health = 0; self.onDefeat(); } updateBossHealthBar(); LK.getSound('hit').play(); }; self.enterPhaseTwo = function () { self.isPhaseTwo = true; self.attackCooldown = 1000; // Faster attacks in phase 2 self.movementSpeed = 4; // Faster movement // Flash the boss to indicate phase change LK.effects.flashObject(self, 0xffff00, 1000); // Clear any existing attack timer and reset if (self.attackTimer) { LK.clearTimeout(self.attackTimer); } self.canAttack = true; }; self.onDefeat = function () { LK.getSound('bossDeath').play(); LK.showYouWin(); }; return self; }); var BossProjectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = -8; // Normal speed for enemy bullets self.velocityY = 0; self.damage = 5; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; // Remove if off screen if (self.x < -projectileGraphics.width || self.x > 2048 + projectileGraphics.width || self.y < -projectileGraphics.height || self.y > 2732 + projectileGraphics.height) { self.destroy(); var index = bossProjectiles.indexOf(self); if (index !== -1) { bossProjectiles.splice(index, 1); } } }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.health = 300; self.maxHealth = 300; self.speed = 7; self.jumpForce = -15; self.gravity = 0.7; self.velocityY = 0; self.isJumping = false; self.jumpCount = 0; // Initialize jump count self.isGrounded = false; self.canShoot = true; self.shootCooldown = 500; // ms self.invulnerable = false; self.invulnerabilityTime = 1000; // ms self.update = function () { // Apply gravity self.velocityY += self.gravity; self.y += self.velocityY; // Check if hero is on ground if (self.y >= groundLevel - heroGraphics.height / 2) { self.y = groundLevel - heroGraphics.height / 2; self.velocityY = 0; self.isGrounded = true; self.isJumping = false; self.jumpCount = 0; // Reset jump count when grounded } else { self.isGrounded = false; } // Keep hero within game boundaries if (self.x < heroGraphics.width / 2) { self.x = heroGraphics.width / 2; } else if (self.x > 2048 - heroGraphics.width / 2) { self.x = 2048 - heroGraphics.width / 2; } }; self.jump = function () { if (self.isGrounded || self.jumpCount < 4) { // Allow triple jump self.velocityY = self.jumpForce; self.isJumping = true; self.isGrounded = false; self.jumpCount++; // Increment jump count } }; self.shoot = function () { if (!self.canShoot) { return; } var projectile = new HeroProjectile(); projectile.x = self.x + (pressedLeft ? -50 : 50); // Adjust position based on direction projectile.y = self.y; projectile.velocityX = pressedLeft ? -15 : 15; // Adjust velocity based on direction game.addChild(projectile); projectiles.push(projectile); LK.getSound('shoot').play(); self.canShoot = false; LK.setTimeout(function () { self.canShoot = true; }, self.shootCooldown); }; self.takeDamage = function (damage) { if (self.invulnerable) { return; } self.health -= damage; if (self.health <= 0) { self.health = 0; LK.showGameOver(); } LK.getSound('playerHit').play(); updateHealthBar(); // Flash hero and make invulnerable temporarily self.invulnerable = true; LK.effects.flashObject(self, 0xffffff, 1000); LK.setTimeout(function () { self.invulnerable = false; }, self.invulnerabilityTime); }; return self; }); var HeroProjectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('heroProjectile', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 10; // Increased bullet speed self.damage = 10; self.update = function () { self.x += self.velocityX; // Remove if off screen if (self.x > 2048 + projectileGraphics.width) { self.destroy(); var index = projectiles.indexOf(self); if (index !== -1) { projectiles.splice(index, 1); } } }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Store lastY for transition detection if (self.lastY === undefined) { self.lastY = self.y; } // Update lastY self.lastY = self.y; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // Game variables var hero; var boss; var platforms = []; var projectiles = []; var bossProjectiles = []; var groundLevel = 2400; var heroHealthBar; var heroHealthBarBg; var bossHealthBar; var bossHealthBarBg; var moveLeftBtn; var moveRightBtn; var jumpBtn; var shootBtn; var pressedLeft = false; var pressedRight = false; // Set up game environment function setupGame() { // Add background image var background = LK.getAsset('backgroundImage', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); game.addChild(background); // Create hero hero = new Hero(); hero.x = 400; hero.y = groundLevel - hero.height / 2; game.addChild(hero); // Create boss boss = new Boss(); boss.x = 1600; boss.y = groundLevel - boss.height / 2; game.addChild(boss); // Create platforms createPlatforms(); // Create UI createUI(); // Start background music LK.playMusic('battleMusic'); } function createPlatforms() { // Ground platform var ground = new Platform(); ground.x = 1024; ground.y = groundLevel + 20; ground.scaleX = 5.12; // Cover full width (2048 / 400) game.addChild(ground); platforms.push(ground); // Add some floating platforms var platformPositions = [{ x: 600, y: 2200 }, { x: 1200, y: 2100 }, { x: 1800, y: 2200 }, { x: 1000, y: 2000 }, { x: 1500, y: 1900 }]; for (var i = 0; i < platformPositions.length; i++) { var platform = new Platform(); platform.x = platformPositions[i].x; platform.y = platformPositions[i].y; game.addChild(platform); platforms.push(platform); } } function createUI() { // Create hero health bar background heroHealthBarBg = LK.getAsset('healthBarBackground', { anchorX: 0, anchorY: 0.5, x: 20, y: 50 }); LK.gui.topLeft.addChild(heroHealthBarBg); // Create hero health bar heroHealthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5, x: 20, y: 50 }); LK.gui.topLeft.addChild(heroHealthBar); // Create hero secondary health bar heroSecondaryHealthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5, x: 20, y: 90 }); LK.gui.topLeft.addChild(heroSecondaryHealthBar); // Create boss health bar background bossHealthBarBg = LK.getAsset('healthBarBackground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 50 }); LK.gui.top.addChild(bossHealthBarBg); // Create boss health bar bossHealthBar = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 50 }); LK.gui.top.addChild(bossHealthBar); // Create boss secondary health bar bossSecondaryHealthBar = LK.getAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 90 }); LK.gui.top.addChild(bossSecondaryHealthBar); // Create control buttons createControlButtons(); } function createControlButtons() { // Left movement button moveLeftBtn = LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, x: 150, y: -150 }); moveLeftBtn.width = 150; moveLeftBtn.height = 150; moveLeftBtn.tint = 0x3498db; LK.gui.bottomLeft.addChild(moveLeftBtn); // Right movement button moveRightBtn = LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, x: 320, y: -150 }); moveRightBtn.width = 150; moveRightBtn.height = 150; moveRightBtn.tint = 0x3498db; LK.gui.bottomLeft.addChild(moveRightBtn); // Jump button jumpBtn = LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, x: -150, y: -150 }); jumpBtn.width = 150; jumpBtn.height = 150; jumpBtn.tint = 0x2ecc71; LK.gui.bottomRight.addChild(jumpBtn); // Shoot button shootBtn = LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, x: -320, y: -150 }); shootBtn.width = 150; shootBtn.height = 150; shootBtn.tint = 0xe74c3c; LK.gui.bottomRight.addChild(shootBtn); // Add event handlers moveLeftBtn.interactive = true; moveRightBtn.interactive = true; jumpBtn.interactive = true; shootBtn.interactive = true; // Setup button events moveLeftBtn.down = function () { pressedLeft = true; }; moveLeftBtn.up = function () { pressedLeft = false; }; moveRightBtn.down = function () { pressedRight = true; }; moveRightBtn.up = function () { pressedRight = false; }; jumpBtn.down = function () { hero.jump(); }; shootBtn.down = function () { hero.shoot(); }; } function updateHealthBar() { var healthPercentage = hero.health / hero.maxHealth; heroHealthBar.scaleX = healthPercentage; // Update secondary health bar var secondaryHealthPercentage = Math.max(0, (hero.health - hero.maxHealth / 2) / (hero.maxHealth / 2)); heroSecondaryHealthBar.scaleX = secondaryHealthPercentage; } function updateBossHealthBar() { var healthPercentage = boss.health / boss.maxHealth; bossHealthBar.scaleX = healthPercentage; // Update secondary health bar var secondaryHealthPercentage = Math.max(0, (boss.health - boss.maxHealth / 2) / (boss.maxHealth / 2)); bossSecondaryHealthBar.scaleX = secondaryHealthPercentage; } function checkCollisions() { // Check hero-boss collision if (hero.intersects(boss) && !hero.invulnerable) { hero.takeDamage(20); // Knock hero back hero.velocityY = -10; if (hero.x < boss.x) { hero.x -= 100; } else { hero.x += 100; } } // Check platform collisions for hero for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; // Only check if hero is falling if (hero.velocityY > 0) { var heroPrevY = hero.y - hero.velocityY; // Check if hero was above platform in previous frame if (heroPrevY + hero.height / 2 <= platform.y - platform.height / 2) { // Check if hero is now colliding with platform if (hero.intersects(platform)) { hero.y = platform.y - platform.height / 2 - hero.height / 2; hero.velocityY = 0; hero.isGrounded = true; hero.isJumping = false; } } } } // Check hero projectile collisions with boss for (var j = projectiles.length - 1; j >= 0; j--) { var projectile = projectiles[j]; if (projectile.intersects(boss)) { boss.takeDamage(projectile.damage); // Remove projectile projectile.destroy(); projectiles.splice(j, 1); } } // Check boss projectile collisions with hero for (var k = bossProjectiles.length - 1; k >= 0; k--) { var bossProjectile = bossProjectiles[k]; if (bossProjectile.intersects(hero) && !hero.invulnerable) { hero.takeDamage(bossProjectile.damage); // Remove projectile bossProjectile.destroy(); bossProjectiles.splice(k, 1); } } } function handleGameInput() { // Handle movement based on button states if (pressedLeft) { hero.x -= hero.speed; } if (pressedRight) { hero.x += hero.speed; } } // Set up game setupGame(); boss.onDefeat = function () { LK.getSound('bossDeath').play(); LK.showYouWin(); }; // Game update loop game.update = function () { // Update hero hero.update(); // Update boss boss.update(); // Update platforms for (var i = 0; i < platforms.length; i++) { platforms[i].update(); } // Update projectiles for (var i = 0; i < projectiles.length; i++) { projectiles[i].update(); } for (var j = 0; j < bossProjectiles.length; j++) { bossProjectiles[j].update(); } // Handle input handleGameInput(); // Check collisions checkCollisions(); }; // Touch events for the game area game.down = function (x, y, obj) { // Check if touch was on control buttons var touchPoint = { x: x, y: y }; var moveLeftPos = moveLeftBtn.parent.toGlobal(moveLeftBtn.position); var moveRightPos = moveRightBtn.parent.toGlobal(moveRightBtn.position); var jumpPos = jumpBtn.parent.toGlobal(jumpBtn.position); var shootPos = shootBtn.parent.toGlobal(shootBtn.position); // Simple distance check for buttons if (distance(touchPoint, moveLeftPos) < 75) { pressedLeft = true; } else if (distance(touchPoint, moveRightPos) < 75) { pressedRight = true; } else if (distance(touchPoint, jumpPos) < 75) { hero.jump(); } else if (distance(touchPoint, shootPos) < 75) { hero.shoot(); } }; game.up = function (x, y, obj) { // Stop movement when touch is released pressedLeft = false; pressedRight = false; }; // Helper function to calculate distance between points function distance(p1, p2) { return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 200;
self.maxHealth = 200;
self.attackPattern = 0;
self.jumpCount = 0; // Initialize jump count
self.attackCooldown = 3000; // ms
self.canAttack = true;
self.attackTimer = null;
self.movementSpeed = 1.5; // Reduced speed for slower movement
self.direction = 1; // 1 = right, -1 = left
self.phaseChangeThreshold = 50; // Health threshold for phase change
self.isPhaseTwo = false;
self.update = function () {
// Boss movement
if (!self.isPhaseTwo) {
// Phase 1 movement: back and forth
self.x += self.movementSpeed * self.direction;
if (self.x > 1800 || self.x < 600) {
self.direction *= -1;
}
} else {
// Phase 2 movement: predictive follow player
// Maintain a safe distance from the hero
var safeDistance = 200;
var predictionFactor = 0.1; // Factor to predict hero's future position
var predictedHeroX = hero.x + hero.speed * predictionFactor * (pressedRight ? 1 : pressedLeft ? -1 : 0);
if (self.x < predictedHeroX - safeDistance) {
self.x += self.movementSpeed * 0.5;
} else if (self.x > predictedHeroX + safeDistance) {
self.x -= self.movementSpeed * 0.5;
}
}
// Always perform long jumps and attack
if (self.isGrounded || self.jumpCount < 4) {
self.velocityY = -30; // Increased jump force for long jumps
self.isGrounded = false;
self.jumpCount++; // Increment jump count
self.attack(); // Attack during jump
}
self.velocityY += 0.7; // Gravity
self.y += self.velocityY;
if (self.y >= groundLevel - bossGraphics.height / 2) {
self.y = groundLevel - bossGraphics.height / 2;
self.velocityY = 0;
self.isGrounded = true;
self.jumpCount = 0; // Reset jump count when grounded
}
// Attack if possible
if (self.canAttack) {
self.attack();
}
// Check for phase change
if (!self.isPhaseTwo && self.health <= self.phaseChangeThreshold) {
self.enterPhaseTwo();
}
};
self.attack = function () {
self.canAttack = false;
// Different attack patterns
if (self.isPhaseTwo) {
// Phase 2 - more aggressive attacks
switch (Math.floor(Math.random() * 3)) {
case 0:
self.spreadAttack();
break;
case 1:
self.targetedAttack();
break;
}
} else {
// Phase 1 - basic attacks
if (Math.random() > 0.5) {
self.singleAttack();
} else {
self.targetedAttack();
}
}
// Reset attack cooldown
self.attackTimer = LK.setTimeout(function () {
self.canAttack = true;
}, self.attackCooldown);
};
self.singleAttack = function () {
var projectile = new BossProjectile();
projectile.x = self.x;
projectile.y = self.y;
game.addChild(projectile);
bossProjectiles.push(projectile);
};
self.spreadAttack = function () {
for (var i = -2; i <= 2; i++) {
var projectile = new BossProjectile();
projectile.x = self.x;
projectile.y = self.y;
projectile.velocityX = -5 + i * 2;
projectile.velocityY = 5;
game.addChild(projectile);
bossProjectiles.push(projectile);
}
};
self.targetedAttack = function () {
var projectile = new BossProjectile();
projectile.x = self.x;
projectile.y = self.y;
// Calculate direction toward player
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var angle = Math.atan2(dy, dx);
projectile.velocityX = Math.cos(angle) * 8;
projectile.velocityY = Math.sin(angle) * 8;
game.addChild(projectile);
bossProjectiles.push(projectile);
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash boss red
LK.effects.flashObject(self, 0xff0000, 300);
if (self.health <= 0) {
self.health = 0;
self.onDefeat();
}
updateBossHealthBar();
LK.getSound('hit').play();
};
self.enterPhaseTwo = function () {
self.isPhaseTwo = true;
self.attackCooldown = 1000; // Faster attacks in phase 2
self.movementSpeed = 4; // Faster movement
// Flash the boss to indicate phase change
LK.effects.flashObject(self, 0xffff00, 1000);
// Clear any existing attack timer and reset
if (self.attackTimer) {
LK.clearTimeout(self.attackTimer);
}
self.canAttack = true;
};
self.onDefeat = function () {
LK.getSound('bossDeath').play();
LK.showYouWin();
};
return self;
});
var BossProjectile = Container.expand(function () {
var self = Container.call(this);
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = -8; // Normal speed for enemy bullets
self.velocityY = 0;
self.damage = 5;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Remove if off screen
if (self.x < -projectileGraphics.width || self.x > 2048 + projectileGraphics.width || self.y < -projectileGraphics.height || self.y > 2732 + projectileGraphics.height) {
self.destroy();
var index = bossProjectiles.indexOf(self);
if (index !== -1) {
bossProjectiles.splice(index, 1);
}
}
};
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 300;
self.maxHealth = 300;
self.speed = 7;
self.jumpForce = -15;
self.gravity = 0.7;
self.velocityY = 0;
self.isJumping = false;
self.jumpCount = 0; // Initialize jump count
self.isGrounded = false;
self.canShoot = true;
self.shootCooldown = 500; // ms
self.invulnerable = false;
self.invulnerabilityTime = 1000; // ms
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
self.y += self.velocityY;
// Check if hero is on ground
if (self.y >= groundLevel - heroGraphics.height / 2) {
self.y = groundLevel - heroGraphics.height / 2;
self.velocityY = 0;
self.isGrounded = true;
self.isJumping = false;
self.jumpCount = 0; // Reset jump count when grounded
} else {
self.isGrounded = false;
}
// Keep hero within game boundaries
if (self.x < heroGraphics.width / 2) {
self.x = heroGraphics.width / 2;
} else if (self.x > 2048 - heroGraphics.width / 2) {
self.x = 2048 - heroGraphics.width / 2;
}
};
self.jump = function () {
if (self.isGrounded || self.jumpCount < 4) {
// Allow triple jump
self.velocityY = self.jumpForce;
self.isJumping = true;
self.isGrounded = false;
self.jumpCount++; // Increment jump count
}
};
self.shoot = function () {
if (!self.canShoot) {
return;
}
var projectile = new HeroProjectile();
projectile.x = self.x + (pressedLeft ? -50 : 50); // Adjust position based on direction
projectile.y = self.y;
projectile.velocityX = pressedLeft ? -15 : 15; // Adjust velocity based on direction
game.addChild(projectile);
projectiles.push(projectile);
LK.getSound('shoot').play();
self.canShoot = false;
LK.setTimeout(function () {
self.canShoot = true;
}, self.shootCooldown);
};
self.takeDamage = function (damage) {
if (self.invulnerable) {
return;
}
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
LK.getSound('playerHit').play();
updateHealthBar();
// Flash hero and make invulnerable temporarily
self.invulnerable = true;
LK.effects.flashObject(self, 0xffffff, 1000);
LK.setTimeout(function () {
self.invulnerable = false;
}, self.invulnerabilityTime);
};
return self;
});
var HeroProjectile = Container.expand(function () {
var self = Container.call(this);
var projectileGraphics = self.attachAsset('heroProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 10; // Increased bullet speed
self.damage = 10;
self.update = function () {
self.x += self.velocityX;
// Remove if off screen
if (self.x > 2048 + projectileGraphics.width) {
self.destroy();
var index = projectiles.indexOf(self);
if (index !== -1) {
projectiles.splice(index, 1);
}
}
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Store lastY for transition detection
if (self.lastY === undefined) {
self.lastY = self.y;
}
// Update lastY
self.lastY = self.y;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// Game variables
var hero;
var boss;
var platforms = [];
var projectiles = [];
var bossProjectiles = [];
var groundLevel = 2400;
var heroHealthBar;
var heroHealthBarBg;
var bossHealthBar;
var bossHealthBarBg;
var moveLeftBtn;
var moveRightBtn;
var jumpBtn;
var shootBtn;
var pressedLeft = false;
var pressedRight = false;
// Set up game environment
function setupGame() {
// Add background image
var background = LK.getAsset('backgroundImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
game.addChild(background);
// Create hero
hero = new Hero();
hero.x = 400;
hero.y = groundLevel - hero.height / 2;
game.addChild(hero);
// Create boss
boss = new Boss();
boss.x = 1600;
boss.y = groundLevel - boss.height / 2;
game.addChild(boss);
// Create platforms
createPlatforms();
// Create UI
createUI();
// Start background music
LK.playMusic('battleMusic');
}
function createPlatforms() {
// Ground platform
var ground = new Platform();
ground.x = 1024;
ground.y = groundLevel + 20;
ground.scaleX = 5.12; // Cover full width (2048 / 400)
game.addChild(ground);
platforms.push(ground);
// Add some floating platforms
var platformPositions = [{
x: 600,
y: 2200
}, {
x: 1200,
y: 2100
}, {
x: 1800,
y: 2200
}, {
x: 1000,
y: 2000
}, {
x: 1500,
y: 1900
}];
for (var i = 0; i < platformPositions.length; i++) {
var platform = new Platform();
platform.x = platformPositions[i].x;
platform.y = platformPositions[i].y;
game.addChild(platform);
platforms.push(platform);
}
}
function createUI() {
// Create hero health bar background
heroHealthBarBg = LK.getAsset('healthBarBackground', {
anchorX: 0,
anchorY: 0.5,
x: 20,
y: 50
});
LK.gui.topLeft.addChild(heroHealthBarBg);
// Create hero health bar
heroHealthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 20,
y: 50
});
LK.gui.topLeft.addChild(heroHealthBar);
// Create hero secondary health bar
heroSecondaryHealthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 20,
y: 90
});
LK.gui.topLeft.addChild(heroSecondaryHealthBar);
// Create boss health bar background
bossHealthBarBg = LK.getAsset('healthBarBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 50
});
LK.gui.top.addChild(bossHealthBarBg);
// Create boss health bar
bossHealthBar = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 50
});
LK.gui.top.addChild(bossHealthBar);
// Create boss secondary health bar
bossSecondaryHealthBar = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 90
});
LK.gui.top.addChild(bossSecondaryHealthBar);
// Create control buttons
createControlButtons();
}
function createControlButtons() {
// Left movement button
moveLeftBtn = LK.getAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 150,
y: -150
});
moveLeftBtn.width = 150;
moveLeftBtn.height = 150;
moveLeftBtn.tint = 0x3498db;
LK.gui.bottomLeft.addChild(moveLeftBtn);
// Right movement button
moveRightBtn = LK.getAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 320,
y: -150
});
moveRightBtn.width = 150;
moveRightBtn.height = 150;
moveRightBtn.tint = 0x3498db;
LK.gui.bottomLeft.addChild(moveRightBtn);
// Jump button
jumpBtn = LK.getAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: -150,
y: -150
});
jumpBtn.width = 150;
jumpBtn.height = 150;
jumpBtn.tint = 0x2ecc71;
LK.gui.bottomRight.addChild(jumpBtn);
// Shoot button
shootBtn = LK.getAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: -320,
y: -150
});
shootBtn.width = 150;
shootBtn.height = 150;
shootBtn.tint = 0xe74c3c;
LK.gui.bottomRight.addChild(shootBtn);
// Add event handlers
moveLeftBtn.interactive = true;
moveRightBtn.interactive = true;
jumpBtn.interactive = true;
shootBtn.interactive = true;
// Setup button events
moveLeftBtn.down = function () {
pressedLeft = true;
};
moveLeftBtn.up = function () {
pressedLeft = false;
};
moveRightBtn.down = function () {
pressedRight = true;
};
moveRightBtn.up = function () {
pressedRight = false;
};
jumpBtn.down = function () {
hero.jump();
};
shootBtn.down = function () {
hero.shoot();
};
}
function updateHealthBar() {
var healthPercentage = hero.health / hero.maxHealth;
heroHealthBar.scaleX = healthPercentage;
// Update secondary health bar
var secondaryHealthPercentage = Math.max(0, (hero.health - hero.maxHealth / 2) / (hero.maxHealth / 2));
heroSecondaryHealthBar.scaleX = secondaryHealthPercentage;
}
function updateBossHealthBar() {
var healthPercentage = boss.health / boss.maxHealth;
bossHealthBar.scaleX = healthPercentage;
// Update secondary health bar
var secondaryHealthPercentage = Math.max(0, (boss.health - boss.maxHealth / 2) / (boss.maxHealth / 2));
bossSecondaryHealthBar.scaleX = secondaryHealthPercentage;
}
function checkCollisions() {
// Check hero-boss collision
if (hero.intersects(boss) && !hero.invulnerable) {
hero.takeDamage(20);
// Knock hero back
hero.velocityY = -10;
if (hero.x < boss.x) {
hero.x -= 100;
} else {
hero.x += 100;
}
}
// Check platform collisions for hero
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
// Only check if hero is falling
if (hero.velocityY > 0) {
var heroPrevY = hero.y - hero.velocityY;
// Check if hero was above platform in previous frame
if (heroPrevY + hero.height / 2 <= platform.y - platform.height / 2) {
// Check if hero is now colliding with platform
if (hero.intersects(platform)) {
hero.y = platform.y - platform.height / 2 - hero.height / 2;
hero.velocityY = 0;
hero.isGrounded = true;
hero.isJumping = false;
}
}
}
}
// Check hero projectile collisions with boss
for (var j = projectiles.length - 1; j >= 0; j--) {
var projectile = projectiles[j];
if (projectile.intersects(boss)) {
boss.takeDamage(projectile.damage);
// Remove projectile
projectile.destroy();
projectiles.splice(j, 1);
}
}
// Check boss projectile collisions with hero
for (var k = bossProjectiles.length - 1; k >= 0; k--) {
var bossProjectile = bossProjectiles[k];
if (bossProjectile.intersects(hero) && !hero.invulnerable) {
hero.takeDamage(bossProjectile.damage);
// Remove projectile
bossProjectile.destroy();
bossProjectiles.splice(k, 1);
}
}
}
function handleGameInput() {
// Handle movement based on button states
if (pressedLeft) {
hero.x -= hero.speed;
}
if (pressedRight) {
hero.x += hero.speed;
}
}
// Set up game
setupGame();
boss.onDefeat = function () {
LK.getSound('bossDeath').play();
LK.showYouWin();
};
// Game update loop
game.update = function () {
// Update hero
hero.update();
// Update boss
boss.update();
// Update platforms
for (var i = 0; i < platforms.length; i++) {
platforms[i].update();
}
// Update projectiles
for (var i = 0; i < projectiles.length; i++) {
projectiles[i].update();
}
for (var j = 0; j < bossProjectiles.length; j++) {
bossProjectiles[j].update();
}
// Handle input
handleGameInput();
// Check collisions
checkCollisions();
};
// Touch events for the game area
game.down = function (x, y, obj) {
// Check if touch was on control buttons
var touchPoint = {
x: x,
y: y
};
var moveLeftPos = moveLeftBtn.parent.toGlobal(moveLeftBtn.position);
var moveRightPos = moveRightBtn.parent.toGlobal(moveRightBtn.position);
var jumpPos = jumpBtn.parent.toGlobal(jumpBtn.position);
var shootPos = shootBtn.parent.toGlobal(shootBtn.position);
// Simple distance check for buttons
if (distance(touchPoint, moveLeftPos) < 75) {
pressedLeft = true;
} else if (distance(touchPoint, moveRightPos) < 75) {
pressedRight = true;
} else if (distance(touchPoint, jumpPos) < 75) {
hero.jump();
} else if (distance(touchPoint, shootPos) < 75) {
hero.shoot();
}
};
game.up = function (x, y, obj) {
// Stop movement when touch is released
pressedLeft = false;
pressedRight = false;
};
// Helper function to calculate distance between points
function distance(p1, p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
chibi mario bross stand fight Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
chibi fat bowser left pose. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
rock pattern. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
chibi fire ball. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
8 bit image dark castle corridor cartoon style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows