/****
* 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