User prompt
slightly lower
User prompt
not that whitte text, delete that, move the bloe buttom
User prompt
move it higer
User prompt
move the blue " select difficulty:" a bit higger and rename it Back to menu
User prompt
just eliminate the grey menu buttom
User prompt
add the menu buttom in the team selection
User prompt
move start team selection bellow back to menu buttom
User prompt
move all back to menu buttoms and the start team selection buttom lower from their current position
User prompt
make play normal select fighters select fighters difficulty buttoms and menu buttoms 2 times bigger
User prompt
in team battles move the "Team:" texts up to the fighters representations
User prompt
make that "Arena Warriors" text dissapear when chosing any game mode
User prompt
is fixed now! good job, but now the last figther dont die even when his life reach 0
User prompt
now only defeating one count as defeating 3
User prompt
fix all that just to be sure
User prompt
im gonna test it, if you detect two characters losing but only one defeated fix the issue, ok?
User prompt
it keeps appening
User prompt
fix it
User prompt
make if first team character is defeated second character and third character cant die untill they are defeated on combat
User prompt
make defeating ONE figther only count as defeating ONE
User prompt
error: defeating one figther defeats two of them, fix it
User prompt
for some reason only two figthers of the team are defeated and the fight ends, fix it
User prompt
all the not defeated fighthers show in normal colour and the selected one is a little bigger and the defeated ones are grey ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
in the 3 vs 3 mode all 3 fighters of a team must be defeated to end the combat
User prompt
move it bellow to the back to menu bottom
User prompt
i meant move it from the start team selection menu to the player team and enemy team selection menu
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var EnergyBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('energyBarBg', {
anchorX: 0,
anchorY: 0
});
// Create 3 individual energy bars
self.energyBars = [];
for (var i = 0; i < 3; i++) {
var energyBar = self.attachAsset('energyBar', {
anchorX: 0,
anchorY: 0
});
energyBar.x = i * 335; // Space bars evenly (1000/3 ≈ 333)
energyBar.width = 310; // Slightly smaller to have gaps
self.energyBars.push(energyBar);
}
self.update = function () {
// Show energy bars based on current energy level (0-3)
var energyLevel = Math.floor(self.fighter.energy / (self.fighter.maxEnergy / 3));
for (var i = 0; i < 3; i++) {
self.energyBars[i].visible = i < energyLevel;
}
};
return self;
});
var Fighter = Container.expand(function (fighterType, isPlayer) {
var self = Container.call(this);
// Fighter properties
self.fighterType = fighterType || 1;
self.isPlayer = isPlayer || false;
self.maxHealth = 100;
self.health = 100;
self.maxEnergy = 3; // Changed to 3 energy units
self.energy = 3; // Start with full energy
self.speed = 3;
self.isBlocking = false;
self.attackCooldown = 0;
self.specialCooldown = 0;
self.maxSpecialCharge = 100;
self.specialCharge = 0;
self.isCrouching = false;
self.isJumping = false;
self.jumpHeight = 0;
self.maxJumpHeight = 100;
self.jumpSpeed = 14;
self.originalY = 0;
self.gravity = 0.25;
self.velocityY = 0;
self.groundY = 1600; // Ground level for all fighters
// Create fighter graphics
var fighterGraphics = self.attachAsset('fighter' + self.fighterType, {
anchorX: 0.5,
anchorY: 1.0
});
// Create blocking shield (initially hidden)
var blockingShield = self.attachAsset('blockAsset', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0.0
});
blockingShield.visible = false;
// Animation properties
self.currentAnimation = 'normal';
self.animationTimer = 0;
self.animationDuration = 0;
self.isWalking = false;
self.isCrouchingAnimated = false;
self.lastX = self.x;
// Fighter stats based on type
switch (self.fighterType) {
case 1:
// Red Fighter - Balanced
self.attackDamage = 8;
self.specialDamage = 10;
self.specialCost = 1; // 1 energy bar per special attack
break;
case 2:
// Blue Fighter - Fast
self.attackDamage = 6;
self.specialDamage = 8;
self.specialCost = 1; // 1 energy bar per special attack
self.speed = 4;
break;
case 3:
// Green Fighter - Strong
self.attackDamage = 10;
self.specialDamage = 12;
self.specialCost = 1; // 1 energy bar per special attack
self.speed = 2;
break;
case 4:
// Yellow Fighter - Energy Efficient
self.attackDamage = 7;
self.specialDamage = 9;
self.specialCost = 1; // 1 energy bar per special attack
break;
case 5:
// Purple Fighter - High Health
self.attackDamage = 7;
self.specialDamage = 9;
self.specialCost = 1; // 1 energy bar per special attack
self.maxHealth = 120;
self.health = 120;
break;
}
// Apply difficulty modifiers for enemy fighters
if (!self.isPlayer && gameDifficulty) {
if (gameDifficulty === 'easy') {
self.attackDamage = Math.floor(self.attackDamage * 0.7);
self.specialDamage = Math.floor(self.specialDamage * 0.7);
self.speed = Math.floor(self.speed * 0.8);
self.maxHealth = Math.floor(self.maxHealth * 0.8);
self.health = self.maxHealth;
} else if (gameDifficulty === 'hard') {
self.attackDamage = Math.floor(self.attackDamage * 1.3);
self.specialDamage = Math.floor(self.specialDamage * 1.3);
self.speed = Math.floor(self.speed * 1.2);
self.maxHealth = Math.floor(self.maxHealth * 1.2);
self.health = self.maxHealth;
}
}
// Track if this fighter has taken damage yet
self.hasBeenDamaged = false;
self.takeDamage = function (damage, isSuperProjectile, attacker) {
// Prevent multiple damage calls when fighter is already defeated
if (self.health <= 0 || self.isBeingDefeated) {
return; // No damage taken, fighter is already defeated or being defeated
}
// In team battle mode, prevent damage to fighters that haven't been damaged yet unless they are the current active fighter
if (gameMode === 'teamBattle') {
var isCurrentPlayerFighter = self.isPlayer && self === player;
var isCurrentEnemyFighter = !self.isPlayer && self === enemy;
var isCurrentActiveFighter = isCurrentPlayerFighter || isCurrentEnemyFighter;
// If this fighter hasn't been damaged yet and isn't the current active fighter, make them invulnerable
if (!self.hasBeenDamaged && !isCurrentActiveFighter) {
return; // No damage taken, fighter is invulnerable
}
}
if (self.isPlayer && playerIsBlocking) {
// Check if within perfect block window (0.5 seconds = 30 ticks at 60fps)
var timeSinceBlockStart = LK.ticks - playerBlockStartTime;
if (timeSinceBlockStart <= 30) {
// 30 ticks = 0.5 seconds at 60fps
damage = Math.floor(damage * 0.5); // 50% damage reduction (reduced from 100%)
// Show brief white flash effect during immunity period (like blue flash when blocked)
LK.effects.flashObject(fighterGraphics, 0xffffff, 200);
} else {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.85); // Only 15% damage reduction for super projectiles after perfect block window (85% damage goes through)
} else {
damage = Math.floor(damage * 0.7); // 30% damage reduction for regular attacks after perfect block window
}
}
} else if (self.isBlocking) {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.85); // Only 15% damage reduction when blocking super projectile (85% damage goes through)
} else {
damage = Math.floor(damage * 0.7); // 30% damage reduction for normal blocking (reduced from 50%)
}
}
// Mark fighter as having been damaged (once they take any damage)
if (damage > 0) {
self.hasBeenDamaged = true;
}
self.health = Math.max(0, self.health - damage);
// Charge special attack bar by 2% when taking damage (only if damage > 0)
if (damage > 0) {
self.chargeSpecial(2); // 2% of maxSpecialCharge (100)
}
// Flash red when taking damage
LK.effects.flashObject(fighterGraphics, 0xFF0000, 300);
};
self.useEnergy = function (amount) {
if (self.energy >= amount) {
self.energy -= amount;
return true;
}
return false;
};
self.attack = function (attackType) {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
self.lastAttackType = attackType || 'punch';
return true;
}
return false;
};
self.specialAttack = function (specialType) {
if (self.specialCooldown <= 0 && self.useEnergy(self.specialCost)) {
self.specialCooldown = 90;
self.lastSpecialType = specialType || 'range';
return true;
}
return false;
};
self.chargeSpecial = function (amount) {
self.specialCharge = Math.min(self.maxSpecialCharge, self.specialCharge + amount);
};
self.canUseSpecialAttack = function () {
return self.specialCharge >= self.maxSpecialCharge;
};
self.useSpecialAttack = function () {
if (self.canUseSpecialAttack()) {
self.specialCharge = 0;
return true;
}
return false;
};
self.crouch = function () {
if (!self.isJumping) {
self.isCrouching = true;
if (self.currentAnimation === 'normal') {
self.setAnimation('crouching');
self.isCrouchingAnimated = true;
}
}
};
self.stopCrouch = function () {
self.isCrouching = false;
if (self.isCrouchingAnimated && self.currentAnimation === 'crouching') {
self.setAnimation('normal');
self.isCrouchingAnimated = false;
}
};
self.jump = function () {
if (!self.isCrouching && !self.isJumping && self.y >= self.groundY) {
self.isJumping = true;
self.velocityY = -self.jumpSpeed; // Negative velocity for upward movement
}
};
self.setAnimation = function (animationType, duration) {
if (animationType === self.currentAnimation) return;
self.currentAnimation = animationType;
self.animationTimer = duration || 0;
// Store current direction before removing graphics
var currentDirection = fighterGraphics.scaleX;
// Remove current graphics
self.removeChild(fighterGraphics);
// Add new graphics based on animation
var assetName = 'fighter' + self.fighterType;
if (animationType === 'punching') {
assetName = 'punchingAnimation' + self.fighterType;
} else if (animationType === 'kicking') {
assetName = 'kickAnimation' + self.fighterType;
} else if (animationType === 'walking') {
assetName = 'walkingAnimation' + self.fighterType;
} else if (animationType === 'crouching') {
assetName = 'crouchingAnimation' + self.fighterType;
} else if (animationType === 'rangeShooting') {
assetName = 'rangeShoot' + self.fighterType;
} else if (animationType === 'potentShooting') {
assetName = 'potentShoot' + self.fighterType;
}
fighterGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 1.0
});
// Maintain direction after asset change
fighterGraphics.scaleX = currentDirection;
};
self.update = function () {
// Direction checking - determine if asset should face left or right
if (player && enemy) {
var shouldFaceRight = false;
if (self === player) {
shouldFaceRight = enemy.x > player.x; // Player faces enemy
} else if (self === enemy) {
shouldFaceRight = player.x > enemy.x; // Enemy faces player
}
// Update asset direction only when needed to prevent flashing
var currentFacingRight = fighterGraphics.scaleX > 0;
if (currentFacingRight !== shouldFaceRight) {
if (shouldFaceRight) {
fighterGraphics.scaleX = Math.abs(fighterGraphics.scaleX); // Face right
} else {
fighterGraphics.scaleX = -Math.abs(fighterGraphics.scaleX); // Face left
}
}
}
// Walking animation detection
var currentlyWalking = Math.abs(self.x - self.lastX) > 0.5;
if (currentlyWalking && !self.isWalking && self.currentAnimation === 'normal') {
self.setAnimation('walking');
self.isWalking = true;
} else if (!currentlyWalking && self.isWalking && self.currentAnimation === 'walking') {
self.setAnimation('normal');
self.isWalking = false;
}
// Crouching animation detection
if (self.isCrouching && !self.isCrouchingAnimated && self.currentAnimation === 'normal') {
self.setAnimation('crouching');
self.isCrouchingAnimated = true;
} else if (!self.isCrouching && self.isCrouchingAnimated && self.currentAnimation === 'crouching') {
self.setAnimation('normal');
self.isCrouchingAnimated = false;
}
self.lastX = self.x;
// Animation management
if (self.animationTimer > 0) {
self.animationTimer--;
if (self.animationTimer <= 0) {
self.setAnimation('normal');
self.isWalking = false;
}
}
// Cooldown management
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.specialCooldown > 0) self.specialCooldown--;
// Energy regeneration - regenerate 1 energy bar every 10 seconds (600 ticks), only one bar at a time
// Initialize lastEnergyRegenTime if not set
if (self.lastEnergyRegenTime === undefined) {
self.lastEnergyRegenTime = 0;
}
// Check if 10 seconds (600 ticks) have passed since last regeneration
if (self.energy < self.maxEnergy && LK.ticks - self.lastEnergyRegenTime >= 600) {
// Only regenerate if we're exactly at a whole number threshold (0, 1, or 2)
var currentEnergyLevel = Math.floor(self.energy);
// Only regenerate if current energy is exactly at the integer threshold
// This ensures sequential regeneration: 0->1, then 1->2, then 2->3
if (self.energy === currentEnergyLevel && currentEnergyLevel < self.maxEnergy) {
self.energy = currentEnergyLevel + 1;
self.lastEnergyRegenTime = LK.ticks; // Update last regeneration time
}
}
// Handle jumping and gravity physics
if (self.isJumping) {
// Apply gravity to vertical velocity
self.velocityY += self.gravity;
// Update position based on velocity
self.y += self.velocityY;
// Check if landed on ground
if (self.y >= self.groundY) {
self.y = self.groundY;
self.isJumping = false;
self.velocityY = 0;
}
} else {
// Ensure fighter stays on ground when not jumping
if (self.y > self.groundY) {
self.y = self.groundY;
}
}
// Handle blocking visual effect
if (self.isBlocking) {
// Show blocking shield
if (!blockingShield.visible) {
blockingShield.visible = true;
blockingShield.alpha = 0.7;
}
// Position shield to always point toward opponent
if (player && enemy) {
var opponent = self === player ? enemy : player;
// Shield always points toward opponent regardless of fighter facing direction
if (opponent.x > self.x) {
blockingShield.x = 100; // Shield on right side (facing right toward opponent)
blockingShield.scaleX = Math.abs(blockingShield.scaleX); // Face right
} else {
blockingShield.x = -100; // Shield on left side (facing left toward opponent)
blockingShield.scaleX = -Math.abs(blockingShield.scaleX); // Face left
}
}
} else {
// Hide blocking shield
if (blockingShield.visible) {
blockingShield.visible = false;
blockingShield.alpha = 0.0;
}
}
// Handle crouching visual effect
if (self.isCrouching && !self.isJumping) {
// Scale down vertically when crouching - slightly bigger hitbox than before
if (fighterGraphics.scaleY > 0.25) {
fighterGraphics.scaleY -= 0.05;
}
} else {
// Return to normal scale
if (fighterGraphics.scaleY < 1.0) {
fighterGraphics.scaleY += 0.05;
}
}
};
return self;
});
var HealthBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
var healthPercent = self.fighter.health / self.fighter.maxHealth;
healthBar.width = 1000 * healthPercent;
};
return self;
});
var Projectile = Container.expand(function (x, y, direction, damage, owner) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.direction = direction; // 1 for right, -1 for left
self.damage = damage;
self.owner = owner;
self.speed = 8;
var projectileAsset = 'projectile' + owner.fighterType;
var projectileGraphics = self.attachAsset(projectileAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Set projectile direction to match shoot direction
if (direction < 0) {
projectileGraphics.scaleX = -Math.abs(projectileGraphics.scaleX); // Face left
} else {
projectileGraphics.scaleX = Math.abs(projectileGraphics.scaleX); // Face right
}
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
var SpecialBar = Container.expand(function (fighter, x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.fighter = fighter;
var bgBar = self.attachAsset('specialBarBg', {
anchorX: 0,
anchorY: 0
});
var specialBar = self.attachAsset('specialBar', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
var specialPercent = self.fighter.specialCharge / self.fighter.maxSpecialCharge;
specialBar.width = 1000 * specialPercent;
};
return self;
});
var SuperProjectile = Container.expand(function (x, y, direction, damage, owner) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.direction = direction; // 1 for right, -1 for left
self.damage = damage;
self.owner = owner;
self.speed = 6;
self.isSuperProjectile = true;
var superProjectileAsset = 'superProjectile' + owner.fighterType;
var superProjectileGraphics = self.attachAsset(superProjectileAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Set super projectile direction to match shoot direction
if (direction < 0) {
superProjectileGraphics.scaleX = -Math.abs(superProjectileGraphics.scaleX); // Face left
} else {
superProjectileGraphics.scaleX = Math.abs(superProjectileGraphics.scaleX); // Face right
}
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Add background
var gameBackground = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 1.33,
scaleY: 0.75
});
game.addChild(gameBackground);
// Sounds
// Combat elements
// UI elements
// Character assets
// Game states
// Animation assets for different actions
var gameState = 'titleScreen'; // 'titleScreen', 'characterSelect', 'playerSelect', 'teamSelect', 'combat', 'gameOver'
var selectedCharacter = 1;
var enemyCharacter = 2;
var gameMode = 'normal'; // 'normal', 'playerVsPlayer', 'teamBattle'
var gameDifficulty = 'normal'; // 'easy', 'normal', 'hard'
var playerTeam = [];
var enemyTeam = [];
var currentPlayerSelection = 1;
var currentEnemySelection = 1;
var teamSize = 2;
var selectedTeamIndex = 0;
var titleButtons = [];
// Character selection
var characterSelectors = [];
var selectionBorder = null;
// Combat variables
var player = null;
var enemy = null;
var playerHealthBar = null;
var playerEnergyBar = null;
var playerSpecialBar = null;
var enemyHealthBar = null;
var enemyEnergyBar = null;
var enemySpecialBar = null;
var projectiles = [];
var superProjectiles = [];
var punchButton = null;
var kickButton = null;
var rangeButton = null;
var blockButton = null;
var specialButton = null;
var playerBlockStartTime = 0;
var playerIsBlocking = false;
var punchButtonText = null;
var kickButtonText = null;
var rangeButtonText = null;
var blockButtonText = null;
var specialButtonText = null;
var leftMoveButton = null;
var rightMoveButton = null;
var leftMoveButtonText = null;
var rightMoveButtonText = null;
var crouchButton = null;
var jumpButton = null;
var crouchButtonText = null;
var jumpButtonText = null;
var isMovingLeft = false;
var isMovingRight = false;
var enemyIsMovingLeft = false;
var enemyIsMovingRight = false;
var enemyMovementTimer = 0;
var currentPlayerTeamIndex = 0;
var currentEnemyTeamIndex = 0;
var teamPlayerDisplays = [];
var teamEnemyDisplays = [];
var lastPlayerDefeatCheck = -1;
var lastEnemyDefeatCheck = -1;
// UI elements
var titleText = new Text2('Arena Warriors', {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
titleText.y = 30;
var instructionText = new Text2('Select Your Fighter', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
// Combat controls text
var controlsText = new Text2('Left: Move | Right: Move | Center Left: Punch | Center Right: Kick | Top: Block | Bottom: Special', {
size: 30,
fill: 0xFFFFFF
});
controlsText.anchor.set(0.5, 1);
function initTitleScreen() {
titleText.setText('Arena Warriors');
titleText.y = 200;
// Create title screen buttons
var normalButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalButton.x = 1024;
normalButton.y = 800;
normalButton.buttonType = 'normal';
game.addChild(normalButton);
titleButtons.push(normalButton);
var normalButtonText = new Text2('PLAY NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalButtonText.anchor.set(0.5, 0.5);
normalButtonText.x = normalButton.x;
normalButtonText.y = normalButton.y;
game.addChild(normalButtonText);
var selectButton = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
selectButton.x = 1024;
selectButton.y = 1000;
selectButton.buttonType = 'select';
game.addChild(selectButton);
titleButtons.push(selectButton);
var selectButtonText = new Text2('SELECT FIGHTERS', {
size: 30,
fill: 0xFFFFFF
});
selectButtonText.anchor.set(0.5, 0.5);
selectButtonText.x = selectButton.x;
selectButtonText.y = selectButton.y;
game.addChild(selectButtonText);
var teamButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
teamButton.x = 1024;
teamButton.y = 1200;
teamButton.buttonType = 'team';
game.addChild(teamButton);
titleButtons.push(teamButton);
var teamButtonText = new Text2('TEAM BATTLE', {
size: 30,
fill: 0xFFFFFF
});
teamButtonText.anchor.set(0.5, 0.5);
teamButtonText.x = teamButton.x;
teamButtonText.y = teamButton.y;
game.addChild(teamButtonText);
var instructionsText = new Text2('Choose your game mode', {
size: 40,
fill: 0xFFFFFF
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 500;
game.addChild(instructionsText);
}
function clearTitleScreen() {
for (var i = 0; i < titleButtons.length; i++) {
game.removeChild(titleButtons[i]);
}
titleButtons = [];
// Remove all text elements by checking children
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child instanceof Text2) {
game.removeChild(child);
}
}
}
function initPlayerSelection() {
instructionText.setText('Player 1: Select Fighter');
instructionText.y = 150;
game.addChild(instructionText);
// Create character selection grid
for (var i = 1; i <= 5; i++) {
var fighter = LK.getAsset('fighter' + i, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var col = (i - 1) % 5;
var row = Math.floor((i - 1) / 5);
fighter.x = 300 + col * 280;
fighter.y = 400 + row * 300;
fighter.fighterIndex = i;
characterSelectors.push(fighter);
game.addChild(fighter);
}
// Create selection border
selectionBorder = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionBorder.alpha = 0.3;
updateSelectionBorder();
game.addChild(selectionBorder);
// Add difficulty selection for player vs player mode
// Add difficulty selection text
var difficultyText = new Text2('Select Difficulty:', {
size: 35,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.x = 1024;
difficultyText.y = 700;
game.addChild(difficultyText);
// Easy difficulty button
var easyButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
easyButton.x = 600;
easyButton.y = 800;
easyButton.buttonType = 'easy';
if (gameDifficulty === 'easy') {
easyButton.tint = 0xff9500; // Lighter orange when selected
}
game.addChild(easyButton);
titleButtons.push(easyButton);
var easyButtonText = new Text2('EASY', {
size: 30,
fill: 0xFFFFFF
});
easyButtonText.anchor.set(0.5, 0.5);
easyButtonText.x = easyButton.x;
easyButtonText.y = easyButton.y;
game.addChild(easyButtonText);
// Normal difficulty button
var normalDiffButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalDiffButton.x = 1024;
normalDiffButton.y = 800;
normalDiffButton.buttonType = 'normalDiff';
game.addChild(normalDiffButton);
titleButtons.push(normalDiffButton);
var normalDiffButtonText = new Text2('NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalDiffButtonText.anchor.set(0.5, 0.5);
normalDiffButtonText.x = normalDiffButton.x;
normalDiffButtonText.y = normalDiffButton.y;
game.addChild(normalDiffButtonText);
// Hard difficulty button
var hardButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
hardButton.x = 1448;
hardButton.y = 800;
hardButton.buttonType = 'hard';
game.addChild(hardButton);
titleButtons.push(hardButton);
var hardButtonText = new Text2('HARD', {
size: 30,
fill: 0xFFFFFF
});
hardButtonText.anchor.set(0.5, 0.5);
hardButtonText.x = hardButton.x;
hardButtonText.y = hardButton.y;
game.addChild(hardButtonText);
// Add back to menu button
var backButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = 1000;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
}
function initTeamSelection() {
instructionText.setText('Select Team Size: ' + teamSize + ' vs ' + teamSize);
instructionText.y = 100;
game.addChild(instructionText);
// Team size buttons
var size2Button = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
size2Button.x = 400;
size2Button.y = 200;
size2Button.buttonType = 'size2';
if (teamSize === 2) {
size2Button.tint = 0x44ff44; // Green when selected
}
game.addChild(size2Button);
titleButtons.push(size2Button);
var size2Text = new Text2('2 vs 2', {
size: 30,
fill: 0xFFFFFF
});
size2Text.anchor.set(0.5, 0.5);
size2Text.x = size2Button.x;
size2Text.y = size2Button.y;
game.addChild(size2Text);
var size3Button = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
size3Button.x = 800;
size3Button.y = 200;
size3Button.buttonType = 'size3';
if (teamSize === 3) {
size3Button.tint = 0x44ff44; // Green when selected
}
game.addChild(size3Button);
titleButtons.push(size3Button);
var size3Text = new Text2('3 vs 3', {
size: 30,
fill: 0xFFFFFF
});
size3Text.anchor.set(0.5, 0.5);
size3Text.x = size3Button.x;
size3Text.y = size3Button.y;
game.addChild(size3Text);
// Add back to menu button
var backButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = 750;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
var startButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
startButton.x = 1024;
startButton.y = 950;
startButton.buttonType = 'startTeam';
game.addChild(startButton);
titleButtons.push(startButton);
var startText = new Text2('START TEAM SELECTION', {
size: 30,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = startButton.x;
startText.y = startButton.y;
game.addChild(startText);
// Show current teams
updateTeamDisplay();
}
function initTeamFighterSelection() {
// Clear previous state
selectedTeamIndex = 0;
var currentTeam = selectedTeamIndex < teamSize ? 'player' : 'enemy';
var fighterNumber = selectedTeamIndex % teamSize + 1;
var teamName = currentTeam === 'player' ? 'Player' : 'Enemy';
instructionText.setText(teamName + ' Team - Select Fighter ' + fighterNumber);
instructionText.y = 150;
game.addChild(instructionText);
// Create character selection grid
for (var i = 1; i <= 5; i++) {
var fighter = LK.getAsset('fighter' + i, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var col = (i - 1) % 5;
var row = Math.floor((i - 1) / 5);
fighter.x = 300 + col * 280;
fighter.y = 600 + row * 300;
fighter.fighterIndex = i;
characterSelectors.push(fighter);
game.addChild(fighter);
}
// Create selection border
selectionBorder = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionBorder.alpha = 0.3;
selectionBorder.x = characterSelectors[0].x;
selectionBorder.y = characterSelectors[0].y;
game.addChild(selectionBorder);
// Show current team selections below the character grid
updateTeamBattleDisplay();
// Add back to menu button
var backButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = 1250;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
// Add difficulty selection for team battle mode below back button
// Easy difficulty button
var easyButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
easyButton.x = 600;
easyButton.y = 1500;
easyButton.buttonType = 'easy';
if (gameDifficulty === 'easy') {
easyButton.tint = 0xff9500; // Lighter orange when selected
}
game.addChild(easyButton);
titleButtons.push(easyButton);
var easyButtonText = new Text2('EASY', {
size: 30,
fill: 0xFFFFFF
});
easyButtonText.anchor.set(0.5, 0.5);
easyButtonText.x = easyButton.x;
easyButtonText.y = easyButton.y;
game.addChild(easyButtonText);
// Normal difficulty button
var normalDiffButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalDiffButton.x = 1024;
normalDiffButton.y = 1500;
normalDiffButton.buttonType = 'normalDiff';
if (gameDifficulty === 'normal') {
normalDiffButton.tint = 0xcc6600; // Darker orange when selected
}
game.addChild(normalDiffButton);
titleButtons.push(normalDiffButton);
var normalDiffButtonText = new Text2('NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalDiffButtonText.anchor.set(0.5, 0.5);
normalDiffButtonText.x = normalDiffButton.x;
normalDiffButtonText.y = normalDiffButton.y;
game.addChild(normalDiffButtonText);
// Hard difficulty button
var hardButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
hardButton.x = 1448;
hardButton.y = 1500;
hardButton.buttonType = 'hard';
if (gameDifficulty === 'hard') {
hardButton.tint = 0xff0000; // Red when selected
}
game.addChild(hardButton);
titleButtons.push(hardButton);
var hardButtonText = new Text2('HARD', {
size: 30,
fill: 0xFFFFFF
});
hardButtonText.anchor.set(0.5, 0.5);
hardButtonText.x = hardButton.x;
hardButtonText.y = hardButton.y;
game.addChild(hardButtonText);
}
function updateTeamBattleDisplay() {
// Remove existing team battle display
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.isTeamBattleDisplay) {
game.removeChild(child);
}
}
// Player team display
var playerTeamText = new Text2('Player Team:', {
size: 35,
fill: 0x44ff44
});
playerTeamText.anchor.set(0.5, 0);
playerTeamText.x = 500;
playerTeamText.y = 1000;
playerTeamText.isTeamBattleDisplay = true;
game.addChild(playerTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = playerTeam[i] || 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.35,
scaleY: 0.35
});
teamFighter.x = 250 + i * 120;
teamFighter.y = 1100;
teamFighter.isTeamBattleDisplay = true;
// Add selection indicator for current selection
if (selectedTeamIndex === i) {
var selectionIndicator = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionIndicator.alpha = 0.6;
selectionIndicator.tint = 0x00ff00;
selectionIndicator.x = teamFighter.x;
selectionIndicator.y = teamFighter.y;
selectionIndicator.scaleX = 0.4;
selectionIndicator.scaleY = 0.4;
selectionIndicator.isTeamBattleDisplay = true;
game.addChild(selectionIndicator);
}
game.addChild(teamFighter);
}
// Enemy team display
var enemyTeamText = new Text2('Enemy Team:', {
size: 35,
fill: 0xff4444
});
enemyTeamText.anchor.set(0.5, 0);
enemyTeamText.x = 1500;
enemyTeamText.y = 1000;
enemyTeamText.isTeamBattleDisplay = true;
game.addChild(enemyTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = enemyTeam[i] || (i + 1) % 5 + 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.35,
scaleY: 0.35
});
teamFighter.x = 1250 + i * 120;
teamFighter.y = 1100;
teamFighter.isTeamBattleDisplay = true;
// Add selection indicator for current selection
if (selectedTeamIndex === teamSize + i) {
var selectionIndicator = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionIndicator.alpha = 0.6;
selectionIndicator.tint = 0xff0000;
selectionIndicator.x = teamFighter.x;
selectionIndicator.y = teamFighter.y;
selectionIndicator.scaleX = 0.4;
selectionIndicator.scaleY = 0.4;
selectionIndicator.isTeamBattleDisplay = true;
game.addChild(selectionIndicator);
}
game.addChild(teamFighter);
}
}
function updateTeamDisplay() {
// Remove existing team display
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.isTeamDisplay) {
game.removeChild(child);
}
}
// Player team display
var playerTeamText = new Text2('Player Team:', {
size: 40,
fill: 0x44ff44
});
playerTeamText.anchor.set(0.5, 0);
playerTeamText.x = 500;
playerTeamText.y = 400;
playerTeamText.isTeamDisplay = true;
game.addChild(playerTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = playerTeam[i] || i + 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
teamFighter.x = 300 + i * 150;
teamFighter.y = 500;
teamFighter.isTeamDisplay = true;
game.addChild(teamFighter);
}
// Enemy team display
var enemyTeamText = new Text2('Enemy Team:', {
size: 40,
fill: 0xff4444
});
enemyTeamText.anchor.set(0.5, 0);
enemyTeamText.x = 1500;
enemyTeamText.y = 400;
enemyTeamText.isTeamDisplay = true;
game.addChild(enemyTeamText);
for (var i = 0; i < teamSize; i++) {
var fighterType = enemyTeam[i] || (i + 2) % 5 + 1;
var teamFighter = LK.getAsset('fighter' + fighterType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4
});
teamFighter.x = 1300 + i * 150;
teamFighter.y = 500;
teamFighter.isTeamDisplay = true;
game.addChild(teamFighter);
}
}
function initCharacterSelection() {
instructionText.y = 150;
game.addChild(instructionText);
// Create character selection grid
for (var i = 1; i <= 5; i++) {
var fighter = LK.getAsset('fighter' + i, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var col = (i - 1) % 5;
var row = Math.floor((i - 1) / 5);
fighter.x = 300 + col * 280;
fighter.y = 400 + row * 300;
fighter.fighterIndex = i;
characterSelectors.push(fighter);
game.addChild(fighter);
}
// Create selection border
selectionBorder = LK.getAsset('selectionBorder', {
anchorX: 0.5,
anchorY: 0.5
});
selectionBorder.alpha = 0.3;
updateSelectionBorder();
game.addChild(selectionBorder);
// Add difficulty selection if in normal mode
if (gameMode === 'normal') {
// Add difficulty selection text
var difficultyText = new Text2('Select Difficulty:', {
size: 35,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.x = 1024;
difficultyText.y = 700;
game.addChild(difficultyText);
// Easy difficulty button
var easyButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
easyButton.x = 600;
easyButton.y = 800;
easyButton.buttonType = 'easy';
if (gameDifficulty === 'easy') {
easyButton.tint = 0xff9500; // Lighter orange when selected
}
game.addChild(easyButton);
titleButtons.push(easyButton);
var easyButtonText = new Text2('EASY', {
size: 30,
fill: 0xFFFFFF
});
easyButtonText.anchor.set(0.5, 0.5);
easyButtonText.x = easyButton.x;
easyButtonText.y = easyButton.y;
game.addChild(easyButtonText);
// Normal difficulty button
var normalDiffButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
normalDiffButton.x = 1024;
normalDiffButton.y = 800;
normalDiffButton.buttonType = 'normalDiff';
game.addChild(normalDiffButton);
titleButtons.push(normalDiffButton);
var normalDiffButtonText = new Text2('NORMAL', {
size: 30,
fill: 0xFFFFFF
});
normalDiffButtonText.anchor.set(0.5, 0.5);
normalDiffButtonText.x = normalDiffButton.x;
normalDiffButtonText.y = normalDiffButton.y;
game.addChild(normalDiffButtonText);
// Hard difficulty button
var hardButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
hardButton.x = 1448;
hardButton.y = 800;
hardButton.buttonType = 'hard';
game.addChild(hardButton);
titleButtons.push(hardButton);
var hardButtonText = new Text2('HARD', {
size: 30,
fill: 0xFFFFFF
});
hardButtonText.anchor.set(0.5, 0.5);
hardButtonText.x = hardButton.x;
hardButtonText.y = hardButton.y;
game.addChild(hardButtonText);
}
// Add back to menu button
var backButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
backButton.y = gameMode === 'normal' ? 1000 : 900;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
}
function updateSelectionBorder() {
if (selectionBorder && characterSelectors[selectedCharacter - 1]) {
selectionBorder.x = characterSelectors[selectedCharacter - 1].x;
selectionBorder.y = characterSelectors[selectedCharacter - 1].y;
}
}
function startCombat() {
gameState = 'combat';
// Clear character selection
game.removeChild(instructionText);
for (var i = 0; i < characterSelectors.length; i++) {
game.removeChild(characterSelectors[i]);
}
game.removeChild(selectionBorder);
// Clear title screen and team displays when starting combat
titleText.visible = false;
clearTitleScreen();
// Remove team battle displays
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child.isTeamDisplay || child.isTeamBattleDisplay) {
game.removeChild(child);
}
}
// Reset defeat tracking
lastPlayerDefeatCheck = -1;
lastEnemyDefeatCheck = -1;
// Create fighters
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 300;
player.y = 1600;
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 2432;
enemy.y = 1600;
// Create health and energy bars
playerHealthBar = game.addChild(new HealthBar(player, 150, 100));
playerEnergyBar = game.addChild(new EnergyBar(player, 150, 140));
playerSpecialBar = game.addChild(new SpecialBar(player, 150, 180));
enemyHealthBar = game.addChild(new HealthBar(enemy, 2182, 100));
enemyEnergyBar = game.addChild(new EnergyBar(enemy, 2182, 140));
enemySpecialBar = game.addChild(new SpecialBar(enemy, 2182, 180));
// Create combat control buttons
punchButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5
});
punchButton.x = 250;
punchButton.y = 1800;
game.addChild(punchButton);
kickButton = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5
});
kickButton.x = 450;
kickButton.y = 1800;
game.addChild(kickButton);
rangeButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5
});
rangeButton.x = 850;
rangeButton.y = 1800;
game.addChild(rangeButton);
blockButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5
});
blockButton.x = 650;
blockButton.y = 1800;
game.addChild(blockButton);
specialButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5
});
specialButton.x = 1050;
specialButton.y = 1800;
game.addChild(specialButton);
// Create movement buttons on the right side
leftMoveButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.75,
scaleY: 0.75
});
leftMoveButton.x = 1200;
leftMoveButton.y = 1800;
game.addChild(leftMoveButton);
rightMoveButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.75,
scaleY: 0.75
});
rightMoveButton.x = 1400;
rightMoveButton.y = 1800;
game.addChild(rightMoveButton);
// Create crouch and jump buttons
crouchButton = LK.getAsset('crouchButton', {
anchorX: 0.5,
anchorY: 0.5
});
crouchButton.x = 1300;
crouchButton.y = 1900;
game.addChild(crouchButton);
jumpButton = LK.getAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5
});
jumpButton.x = 1300;
jumpButton.y = 1700;
game.addChild(jumpButton);
// Add button labels
punchButtonText = new Text2('PUNCH', {
size: 30,
fill: 0xFFFFFF
});
punchButtonText.anchor.set(0.5, 0.5);
punchButtonText.x = punchButton.x;
punchButtonText.y = punchButton.y;
game.addChild(punchButtonText);
kickButtonText = new Text2('KICK', {
size: 30,
fill: 0xFFFFFF
});
kickButtonText.anchor.set(0.5, 0.5);
kickButtonText.x = kickButton.x;
kickButtonText.y = kickButton.y;
game.addChild(kickButtonText);
rangeButtonText = new Text2('RANGE', {
size: 30,
fill: 0xFFFFFF
});
rangeButtonText.anchor.set(0.5, 0.5);
rangeButtonText.x = rangeButton.x;
rangeButtonText.y = rangeButton.y;
game.addChild(rangeButtonText);
blockButtonText = new Text2('BLOCK', {
size: 30,
fill: 0xFFFFFF
});
blockButtonText.anchor.set(0.5, 0.5);
blockButtonText.x = blockButton.x;
blockButtonText.y = blockButton.y;
game.addChild(blockButtonText);
specialButtonText = new Text2('SPECIAL', {
size: 30,
fill: 0xFFFFFF
});
specialButtonText.anchor.set(0.5, 0.5);
specialButtonText.x = specialButton.x;
specialButtonText.y = specialButton.y;
game.addChild(specialButtonText);
leftMoveButtonText = new Text2('←', {
size: 60,
fill: 0xFFFFFF
});
leftMoveButtonText.anchor.set(0.5, 0.5);
leftMoveButtonText.x = leftMoveButton.x;
leftMoveButtonText.y = leftMoveButton.y;
game.addChild(leftMoveButtonText);
rightMoveButtonText = new Text2('→', {
size: 60,
fill: 0xFFFFFF
});
rightMoveButtonText.anchor.set(0.5, 0.5);
rightMoveButtonText.x = rightMoveButton.x;
rightMoveButtonText.y = rightMoveButton.y;
game.addChild(rightMoveButtonText);
crouchButtonText = new Text2('↓', {
size: 60,
fill: 0xFFFFFF
});
crouchButtonText.anchor.set(0.5, 0.5);
crouchButtonText.x = crouchButton.x;
crouchButtonText.y = crouchButton.y;
game.addChild(crouchButtonText);
jumpButtonText = new Text2('↑', {
size: 60,
fill: 0xFFFFFF
});
jumpButtonText.anchor.set(0.5, 0.5);
jumpButtonText.x = jumpButton.x;
jumpButtonText.y = jumpButton.y;
game.addChild(jumpButtonText);
// Add back to menu button
var backButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5
});
backButton.x = 1666; // Position between player (ends at 1150) and enemy (starts at 2182) health bars: (1150 + 2182) / 2 = 1666
backButton.y = 100; // Same Y position as health bars
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
var backButtonText = new Text2('MENU', {
size: 30,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = backButton.x;
backButtonText.y = backButton.y;
game.addChild(backButtonText);
// Add controls text
controlsText.setText('Tap buttons to fight! Use arrow buttons to move.');
controlsText.y = 1950;
game.addChild(controlsText);
// Add player and enemy name labels
var playerLabel = new Text2('Player', {
size: 40,
fill: 0xFFFFFF
});
playerLabel.anchor.set(0, 0);
playerLabel.x = 150;
playerLabel.y = 60;
game.addChild(playerLabel);
var enemyLabel = new Text2('Enemy', {
size: 40,
fill: 0xFFFFFF
});
enemyLabel.anchor.set(1, 0);
enemyLabel.x = 2582;
enemyLabel.y = 60;
game.addChild(enemyLabel);
// Add team displays if in team battle mode
if (gameMode === 'teamBattle') {
// Player team display below special bar
for (var i = 0; i < playerTeam.length; i++) {
var baseScale = 0.3;
var isCurrentFighter = i === currentPlayerTeamIndex;
var teamFighter = LK.getAsset('fighter' + playerTeam[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: isCurrentFighter ? baseScale * 1.2 : baseScale,
scaleY: isCurrentFighter ? baseScale * 1.2 : baseScale
});
teamFighter.x = 200 + i * 80;
teamFighter.y = 280;
teamFighter.teamIndex = i;
teamFighter.isTeamDisplay = true;
teamFighter.tint = 0xffffff; // Normal color for all fighters initially
teamPlayerDisplays.push(teamFighter);
game.addChild(teamFighter);
}
// Enemy team display below special bar
for (var i = 0; i < enemyTeam.length; i++) {
var baseScale = 0.3;
var isCurrentFighter = i === currentEnemyTeamIndex;
var teamFighter = LK.getAsset('fighter' + enemyTeam[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: isCurrentFighter ? baseScale * 1.2 : baseScale,
scaleY: isCurrentFighter ? baseScale * 1.2 : baseScale
});
teamFighter.x = 1800 + i * 80;
teamFighter.y = 280;
teamFighter.teamIndex = i;
teamFighter.isTeamDisplay = true;
teamFighter.tint = 0xffffff; // Normal color for all fighters initially
teamEnemyDisplays.push(teamFighter);
game.addChild(teamFighter);
}
}
}
function handleCombatInput(x, y) {
if (!player || gameState !== 'combat') return;
var gameWidth = 2048;
var gameHeight = 2732;
// Check button presses first
if (punchButton && Math.abs(x - punchButton.x) < 100 && Math.abs(y - punchButton.y) < 40) {
// Punch button pressed
if (player.attack('punch')) {
player.setAnimation('punching', 20); // 20 ticks punch animation
var hit = checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75), 'punch');
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
}
return;
}
if (kickButton && Math.abs(x - kickButton.x) < 100 && Math.abs(y - kickButton.y) < 40) {
// Kick button pressed - can't kick while crouching
if (!player.isCrouching && player.attack('kick')) {
player.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
var hit = checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75), 'kick');
if (hit) player.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
}
return;
}
if (rangeButton && Math.abs(x - rangeButton.x) < 100 && Math.abs(y - rangeButton.y) < 40) {
// Range attack button pressed
if (enemy && player.specialAttack('range')) {
player.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust projectile origin based on player stance
var projectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
projectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(player.x + projectileXOffset, projectileY, shootDirection, player.specialDamage, player);
projectiles.push(projectile);
game.addChild(projectile);
player.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
}
return;
}
if (specialButton && Math.abs(x - specialButton.x) < 100 && Math.abs(y - specialButton.y) < 40) {
// Special button pressed
if (enemy && player.useSpecialAttack()) {
player.lastSpecialType = 'potent';
// Start charging animation before firing
tween(player, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
player.setAnimation('potentShooting', 30); // 30 ticks potent shooting animation
// Return to normal size and color after charging
tween(player, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
superProjectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired in a horizontal row
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = player.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY; // Same Y position for all projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(player.specialDamage * 2 / 7), player);
// Increase speed for potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (player.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
LK.getSound('special').play();
}
});
}
return;
}
if (blockButton && Math.abs(x - blockButton.x) < 100 && Math.abs(y - blockButton.y) < 40) {
// Block button pressed
if (!playerIsBlocking) {
playerBlockStartTime = LK.ticks;
playerIsBlocking = true;
}
player.isBlocking = true;
LK.getSound('block').play();
return;
}
if (leftMoveButton && Math.abs(x - leftMoveButton.x) < 75 && Math.abs(y - leftMoveButton.y) < 75) {
// Left movement button pressed
if (!playerIsBlocking && player.x > 200) {
player.stopCrouch(); // Stop crouching when moving left
player.x -= player.speed * 10;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
}
return;
}
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 75 && Math.abs(y - rightMoveButton.y) < 75) {
// Right movement button pressed
if (!playerIsBlocking && player.x < 2532) {
player.stopCrouch(); // Stop crouching when moving right
player.x += player.speed * 10;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
}
return;
}
if (crouchButton && Math.abs(x - crouchButton.x) < 75 && Math.abs(y - crouchButton.y) < 40) {
// Crouch button pressed
player.crouch();
return;
}
if (jumpButton && Math.abs(x - jumpButton.x) < 75 && Math.abs(y - jumpButton.y) < 40) {
// Jump button pressed
player.jump();
if (player.currentAnimation === 'normal') {
player.setAnimation('walking', 30);
}
return;
}
// Movement is now handled by dedicated buttons above
}
function checkMeleeHit(attacker, target, damage, attackType) {
var distance = Math.abs(attacker.x - target.x);
if (distance < 560) {
// Punch attacks can't hit crouching targets
if (attackType === 'punch' && target.isCrouching && !target.isJumping) {
return false; // Punch misses crouching target
}
if (target.isBlocking) {
// Attack was blocked - reduced damage and pushback
target.takeDamage(Math.floor(damage * 0.7)); // 30% damage reduction for normal blocking (increased from 70% reduction)
LK.getSound('block').play();
// Apply pushback to the attacker
var pushDirection = attacker.x < target.x ? -1 : 1;
var pushDistance = 60;
var newX = attacker.x + pushDirection * pushDistance;
// Make sure attacker stays within bounds
newX = Math.max(200, Math.min(1848, newX));
// Animate the pushback using tween
tween(attacker, {
x: newX
}, {
duration: 200,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 300);
return false; // Hit was blocked
} else {
// Normal hit
target.takeDamage(damage);
return true; // Hit was successful
}
}
return false; // No hit
}
function updateAI() {
if (!enemy || !player) return;
var distance = Math.abs(enemy.x - player.x);
// Handle enemy movement holding
if (enemyMovementTimer > 0) {
enemyMovementTimer--;
if (enemyIsMovingLeft && enemy.x > 200) {
enemy.x -= enemy.speed * 2;
// Set walking animation when moving
if (enemy.currentAnimation === 'normal') {
enemy.setAnimation('walking');
}
}
if (enemyIsMovingRight && enemy.x < 2532) {
enemy.x += enemy.speed * 2;
// Set walking animation when moving
if (enemy.currentAnimation === 'normal') {
enemy.setAnimation('walking');
}
}
} else {
enemyIsMovingLeft = false;
enemyIsMovingRight = false;
// Reset walking animation when movement stops
if (enemy.currentAnimation === 'walking') {
enemy.setAnimation('normal');
}
}
// Enhanced AI behavior - mix of range attacks, melee attacks, movement, jumping and crouching
var aiUpdateFrequency = 30;
if (gameDifficulty === 'easy') {
aiUpdateFrequency = 45; // Slower AI reactions
} else if (gameDifficulty === 'hard') {
aiUpdateFrequency = 8; // Much faster AI reactions for hard mode - increased from 15
}
// Check for player actions to react to (normal and hard modes only)
var reactToPlayerAction = false;
if (gameDifficulty === 'normal' || gameDifficulty === 'hard') {
// Hard mode AI tries to block all attacks
if (gameDifficulty === 'hard') {
// Try to block all incoming attacks with perfect timing
if (player.currentAnimation === 'punching' || player.currentAnimation === 'kicking' || player.currentAnimation === 'rangeShooting' || player.currentAnimation === 'potentShooting') {
if (distance < 1000) {
// Even wider detection range for hard mode - increased from 800
enemy.isBlocking = true;
reactToPlayerAction = true;
}
}
// Try to maintain distance for range attacks - more aggressive
if (distance < 500 && Math.random() < 0.95) {
if (enemy.x > player.x) {
enemyIsMovingRight = true;
enemyMovementTimer = 35; // Hold movement even longer - increased from 25
} else {
enemyIsMovingLeft = true;
enemyMovementTimer = 35; // Hold movement even longer - increased from 25
}
reactToPlayerAction = true;
}
// Jump and crouch to avoid projectiles - much more frequently
if (player.currentAnimation === 'rangeShooting' || player.currentAnimation === 'potentShooting') {
if (Math.random() < 0.85) {
if (Math.random() < 0.5) {
enemy.jump(); // Jump to avoid projectiles
} else {
enemy.crouch(); // Crouch to avoid projectiles
}
reactToPlayerAction = true;
}
}
// Attack player based on their position - more aggressively
if (player.isCrouching && distance < 560 && Math.random() < 0.98) {
if (enemy.attack('kick')) {
enemy.setAnimation('kicking', 25);
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15);
LK.getSound('kick').play();
reactToPlayerAction = true;
}
}
// Attack jumping player with range/potent attacks - more frequently
if (player.isJumping && distance > 200 && distance < 800) {
if (enemy.energy >= 1 && enemy.specialAttack() && Math.random() < 0.9) {
enemy.setAnimation('rangeShooting', 15);
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
var projectileY = enemy.y - 300; // Aim higher for jumping player
var projectile = new Projectile(enemy.x + projectileXOffset, projectileY, shootDirection, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7);
LK.getSound('special').play();
reactToPlayerAction = true;
}
}
// Counter-attack immediately after blocking
if (enemy.isBlocking && distance < 560 && Math.random() < 0.7) {
// Stop blocking and counter-attack
enemy.isBlocking = false;
if (enemy.attack('punch')) {
enemy.setAnimation('punching', 20);
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15);
LK.getSound('punch').play();
reactToPlayerAction = true;
}
}
// Use special attacks more aggressively when player is vulnerable
if (player.currentAnimation === 'punching' || player.currentAnimation === 'kicking') {
if (distance > 400 && distance < 700 && enemy.canUseSpecialAttack() && Math.random() < 0.6) {
if (enemy.useSpecialAttack()) {
enemy.setAnimation('potentShooting', 30);
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
var superProjectileY = enemy.y - 280;
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = enemy.x + projectileXOffset + (index - 3) * 60;
var projectileYOffset = superProjectileY;
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(enemy.specialDamage * 2 / 7), enemy);
superProjectile.speed = 10; // Even faster super projectiles in hard mode
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 80); // Faster deployment - reduced from 100ms
})(i);
}
LK.getSound('special').play();
reactToPlayerAction = true;
}
}
}
} else {
// Normal mode behavior (existing)
// Check if player is punching - try to crouch
if (player.currentAnimation === 'punching' && distance < 560) {
if (Math.random() < 0.7) {
enemy.crouch();
reactToPlayerAction = true;
}
}
// Check if player is kicking - try to jump
else if (player.currentAnimation === 'kicking' && distance < 560) {
if (Math.random() < 0.7) {
enemy.jump();
reactToPlayerAction = true;
}
}
// Check if player is shooting range attacks - try to block
else if (player.currentAnimation === 'rangeShooting') {
if (Math.random() < 0.8) {
enemy.isBlocking = true;
reactToPlayerAction = true;
}
}
// Check if player is crouching - try to kick
else if (player.isCrouching && distance < 560) {
if (Math.random() < 0.6) {
if (enemy.attack('kick')) {
enemy.setAnimation('kicking', 25);
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15);
LK.getSound('kick').play();
reactToPlayerAction = true;
}
}
}
}
}
if (LK.ticks % aiUpdateFrequency === 0 && !reactToPlayerAction) {
var actionRange = 12;
if (gameDifficulty === 'easy') {
actionRange = 8; // Less varied AI behavior
} else if (gameDifficulty === 'hard') {
actionRange = 25; // Much more varied and aggressive AI behavior for hard mode - increased from 20
}
var action = Math.floor(Math.random() * actionRange);
// Check if enemy is in melee range (close enough to punch/kick)
if (distance < 560) {
// In melee range - try to attack or block
if (gameDifficulty === 'hard') {
// Hard mode: much more aggressive melee combat
if (action <= 8 && enemy.attack()) {
// More frequent punch attacks in hard mode
enemy.setAnimation('punching', 20); // 20 ticks punch animation
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
} else if (action <= 15 && !enemy.isCrouching && enemy.attack()) {
// Much more frequent kick attacks in hard mode
enemy.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
} else if (action <= 18) {
// Block when not attacking
enemy.isBlocking = true;
} else if (action <= 20) {
// Back away occasionally when too close
if (enemy.x > player.x) {
enemyIsMovingRight = true;
enemyMovementTimer = 15; // Shorter movement in hard mode for more aggression
} else {
enemyIsMovingLeft = true;
enemyMovementTimer = 15; // Shorter movement in hard mode for more aggression
}
} else if (action <= 22) {
// Jump more frequently in melee range in hard mode
enemy.jump();
} else {
// Crouch more frequently in melee range in hard mode
enemy.crouch();
}
} else {
// Normal and easy mode: existing behavior
if (action <= 3 && enemy.attack()) {
// Punch attack
enemy.setAnimation('punching', 20); // 20 ticks punch animation
var hit = checkMeleeHit(enemy, player, Math.floor(enemy.attackDamage * 0.75), 'punch');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('punch').play();
} else if (action <= 6 && !enemy.isCrouching && enemy.attack()) {
// Kick attack (slightly more damage) - can't kick while crouching
enemy.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
var hit = checkMeleeHit(enemy, player, Math.floor((enemy.attackDamage + 1) * 0.75), 'kick');
if (hit) enemy.chargeSpecial(15); // Charge special on successful hit
LK.getSound('kick').play();
} else if (action <= 8) {
// Block when not attacking
enemy.isBlocking = true;
} else if (action <= 9) {
// Back away occasionally when too close
if (enemy.x > player.x) {
enemyIsMovingRight = true;
enemyMovementTimer = 20; // Hold movement for 20 ticks
} else {
enemyIsMovingLeft = true;
enemyMovementTimer = 20; // Hold movement for 20 ticks
}
} else if (action <= 10) {
// Jump occasionally in melee range
enemy.jump();
} else {
// Crouch occasionally in melee range
enemy.crouch();
}
}
} else if (distance < 400) {
// Medium range - move closer for melee or use range attack
if (action <= 4) {
// Move closer to get into melee range
if (enemy.x > player.x) {
enemyIsMovingLeft = true;
enemyMovementTimer = 15; // Hold movement for 15 ticks
} else {
enemyIsMovingRight = true;
enemyMovementTimer = 15; // Hold movement for 15 ticks
}
} else if (action <= 6 && enemy.canUseSpecialAttack() && enemy.useSpecialAttack()) {
// Use super special attack with charging animation
tween(enemy, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
enemy.setAnimation('potentShooting', 30); // 30 ticks potent shooting animation
// Return to normal size and color after charging
tween(enemy, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired in a horizontal row
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = enemy.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY; // Same Y position for all projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(enemy.specialDamage * 2 / 7), enemy);
// Increase speed for AI potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (enemy.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
LK.getSound('special').play();
}
});
} else if (action <= 6 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack (reduced frequency)
enemy.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust projectile origin based on enemy stance
var projectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
projectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(enemy.x + projectileXOffset, projectileY, shootDirection, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
} else if (action <= 8) {
// Block occasionally
enemy.isBlocking = true;
} else if (action <= 9) {
// Jump occasionally at medium range
enemy.jump();
} else {
// Crouch occasionally at medium range
enemy.crouch();
}
} else {
// Long range - use range attacks or move closer
if (action <= 2 && enemy.canUseSpecialAttack() && enemy.useSpecialAttack()) {
// Use super special attack when available (reduced frequency) with charging animation
tween(enemy, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
enemy.setAnimation('potentShooting', 30); // 30 ticks potent shooting animation
// Return to normal size and color after charging
tween(enemy, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on enemy stance
var superProjectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired in a horizontal row
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = enemy.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY; // Same Y position for all projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(enemy.specialDamage * 2 / 7), enemy);
// Increase speed for AI long range potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (enemy.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
LK.getSound('special').play();
}
});
} else if (action <= 3 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack when available (reduced frequency)
enemy.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on player position
var shootDirection = player.x > enemy.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on enemy stance
var projectileY = enemy.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (enemy.isJumping) {
projectileY = enemy.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(enemy.x + projectileXOffset, projectileY, shootDirection, enemy.specialDamage, enemy);
projectiles.push(projectile);
game.addChild(projectile);
enemy.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
} else if (action <= 8) {
// Move closer to player for melee combat
if (enemy.x > player.x) {
enemyIsMovingLeft = true;
enemyMovementTimer = 25; // Hold movement for 25 ticks
} else {
enemyIsMovingRight = true;
enemyMovementTimer = 25; // Hold movement for 25 ticks
}
} else if (action <= 9) {
// Occasionally block at range
enemy.isBlocking = true;
} else if (action <= 10) {
// Jump occasionally at long range
enemy.jump();
} else {
// Crouch occasionally at long range
enemy.crouch();
}
}
}
// Reset blocking and crouching periodically
var resetFrequency = 45;
if (gameDifficulty === 'hard') {
resetFrequency = 25; // Much faster reset in hard mode for more responsive AI
}
if (LK.ticks % resetFrequency === 0) {
enemy.isBlocking = false;
enemy.stopCrouch(); // Release crouch periodically
}
}
function updateCombatTeamDisplays() {
if (gameMode !== 'teamBattle') return;
var baseScale = 0.3;
var activeScale = baseScale * 1.2;
// Update player team displays
for (var i = 0; i < teamPlayerDisplays.length; i++) {
var fighter = teamPlayerDisplays[i];
if (i < currentPlayerTeamIndex) {
// Defeated fighter - grey tint
tween(fighter, {
tint: 0x666666,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
} else if (i === currentPlayerTeamIndex) {
// Active fighter - normal color and bigger
tween(fighter, {
tint: 0xffffff,
scaleX: activeScale,
scaleY: activeScale
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Not yet active fighter - normal color and size
tween(fighter, {
tint: 0xffffff,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
}
}
// Update enemy team displays
for (var i = 0; i < teamEnemyDisplays.length; i++) {
var fighter = teamEnemyDisplays[i];
if (i < currentEnemyTeamIndex) {
// Defeated fighter - grey tint
tween(fighter, {
tint: 0x666666,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
} else if (i === currentEnemyTeamIndex) {
// Active fighter - normal color and bigger
tween(fighter, {
tint: 0xffffff,
scaleX: activeScale,
scaleY: activeScale
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Not yet active fighter - normal color and size
tween(fighter, {
tint: 0xffffff,
scaleX: baseScale,
scaleY: baseScale
}, {
duration: 300,
easing: tween.easeOut
});
}
}
}
function switchToNextTeamFighter(isPlayer) {
if (gameMode !== 'teamBattle') return false;
if (isPlayer) {
// Check if player is already being defeated to prevent double switching
if (player.isBeingDefeated || lastPlayerDefeatCheck === currentPlayerTeamIndex) return false;
player.isBeingDefeated = true;
lastPlayerDefeatCheck = currentPlayerTeamIndex;
// Flash defeated fighter red before switching
tween(player, {
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mark current fighter as defeated (grey)
if (teamPlayerDisplays[currentPlayerTeamIndex]) {
tween(teamPlayerDisplays[currentPlayerTeamIndex], {
tint: 0x333333
}, {
duration: 500,
easing: tween.easeOut
});
}
currentPlayerTeamIndex++;
if (currentPlayerTeamIndex < playerTeam.length) {
// Switch to next player team fighter
selectedCharacter = playerTeam[currentPlayerTeamIndex];
// Remove current player
player.destroy();
game.removeChild(player);
// Create new player
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 300;
player.y = 1600;
// Flash new fighter with immunity
tween(player, {
tint: 0xffffff,
alpha: 0.5
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(player, {
alpha: 1.0,
tint: 0x44ff44
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(player, {
tint: 0xffffff
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}
});
// Update health bars to reference new fighter
playerHealthBar.fighter = player;
playerEnergyBar.fighter = player;
playerSpecialBar.fighter = player;
// Update team displays to show new states
updateCombatTeamDisplays();
}
}
});
return true;
} else {
// Check if enemy is already being defeated to prevent double switching
if (enemy.isBeingDefeated || lastEnemyDefeatCheck === currentEnemyTeamIndex) return false;
enemy.isBeingDefeated = true;
lastEnemyDefeatCheck = currentEnemyTeamIndex;
// Flash defeated fighter red before switching
tween(enemy, {
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mark current fighter as defeated (grey)
if (teamEnemyDisplays[currentEnemyTeamIndex]) {
tween(teamEnemyDisplays[currentEnemyTeamIndex], {
tint: 0x333333
}, {
duration: 500,
easing: tween.easeOut
});
}
currentEnemyTeamIndex++;
if (currentEnemyTeamIndex < enemyTeam.length) {
// Switch to next enemy team fighter
enemyCharacter = enemyTeam[currentEnemyTeamIndex];
// Remove current enemy
enemy.destroy();
game.removeChild(enemy);
// Create new enemy
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 2432;
enemy.y = 1600;
// Flash new fighter with immunity
tween(enemy, {
tint: 0xffffff,
alpha: 0.5
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemy, {
alpha: 1.0,
tint: 0x44ff44
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xffffff
}, {
duration: 400,
easing: tween.easeOut
});
}
});
}
});
// Update health bars to reference new fighter
enemyHealthBar.fighter = enemy;
enemyEnergyBar.fighter = enemy;
enemySpecialBar.fighter = enemy;
// Update team displays to show new states
updateCombatTeamDisplays();
}
}
});
return true;
}
return false;
}
function checkGameOver() {
if (player && player.health <= 0) {
// Try to switch to next team fighter
if (gameMode === 'teamBattle') {
// Only check game over if we can't switch to another fighter
var switched = switchToNextTeamFighter(true);
if (!switched) {
// Check if all team fighters are actually defeated
var allPlayerDefeated = true;
for (var i = 0; i < playerTeam.length; i++) {
if (i > currentPlayerTeamIndex) {
allPlayerDefeated = false;
break;
}
}
if (allPlayerDefeated) {
// All team fighters defeated - game over
LK.showGameOver();
}
}
} else {
LK.showGameOver();
}
} else if (enemy && enemy.health <= 0) {
// Try to switch to next team fighter
if (gameMode === 'teamBattle') {
// Only check win condition if we can't switch to another fighter
var switched = switchToNextTeamFighter(false);
if (!switched) {
// Check if all enemy team fighters are actually defeated
var allEnemyDefeated = true;
for (var i = 0; i < enemyTeam.length; i++) {
if (i > currentEnemyTeamIndex) {
allEnemyDefeated = false;
break;
}
}
if (allEnemyDefeated) {
// All team fighters defeated - player wins
LK.showYouWin();
}
}
} else {
LK.showYouWin();
}
}
}
// Character selection input
game.down = function (x, y, obj) {
// Check back to menu button for all states
for (var i = 0; i < game.children.length; i++) {
var child = game.children[i];
if (child.buttonType === 'backToMenu' && Math.abs(x - child.x) < 100 && Math.abs(y - child.y) < 40) {
// Clear current game state and return to title screen
gameState = 'titleScreen';
// Remove all game objects
for (var k = game.children.length - 1; k >= 0; k--) {
game.removeChild(game.children[k]);
}
game.addChild(gameBackground);
// Reset variables
player = null;
enemy = null;
projectiles = [];
superProjectiles = [];
teamPlayerDisplays = [];
teamEnemyDisplays = [];
currentPlayerTeamIndex = 0;
currentEnemyTeamIndex = 0;
selectedTeamIndex = 0;
characterSelectors = [];
titleButtons = [];
selectionBorder = null;
currentPlayerSelection = 1;
titleText.visible = true;
initTitleScreen();
return;
}
}
if (gameState === 'titleScreen') {
// Check title screen buttons
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 40) {
if (button.buttonType === 'normal') {
gameMode = 'normal';
titleText.visible = false;
clearTitleScreen();
gameState = 'characterSelect';
initCharacterSelection();
} else if (button.buttonType === 'select') {
gameMode = 'playerVsPlayer';
titleText.visible = false;
clearTitleScreen();
gameState = 'playerSelect';
initPlayerSelection();
} else if (button.buttonType === 'team') {
gameMode = 'teamBattle';
titleText.visible = false;
clearTitleScreen();
gameState = 'teamSelect';
initTeamSelection();
}
break;
}
}
} else if (gameState === 'teamSelect') {
// Check team selection buttons
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 40) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'size2') {
teamSize = 2;
playerTeam = [];
enemyTeam = [];
instructionText.setText('Select Team Size: ' + teamSize + ' vs ' + teamSize);
updateTeamDisplay();
// Update button colors to show selection
for (var k = 0; k < titleButtons.length; k++) {
var sizeButton = titleButtons[k];
if (sizeButton.buttonType === 'size2') {
sizeButton.tint = 0x44ff44; // Green when selected
} else if (sizeButton.buttonType === 'size3') {
sizeButton.tint = 0xffffff; // White when not selected
}
}
} else if (button.buttonType === 'size3') {
teamSize = 3;
playerTeam = [];
enemyTeam = [];
instructionText.setText('Select Team Size: ' + teamSize + ' vs ' + teamSize);
updateTeamDisplay();
// Update button colors to show selection
for (var k = 0; k < titleButtons.length; k++) {
var sizeButton = titleButtons[k];
if (sizeButton.buttonType === 'size3') {
sizeButton.tint = 0x44ff44; // Green when selected
} else if (sizeButton.buttonType === 'size2') {
sizeButton.tint = 0xffffff; // White when not selected
}
}
} else if (button.buttonType === 'startTeam') {
// Remove team display elements
for (var k = game.children.length - 1; k >= 0; k--) {
var child = game.children[k];
if (child.isTeamDisplay) {
game.removeChild(child);
}
}
// Initialize teams if empty
for (var j = 0; j < teamSize; j++) {
if (!playerTeam[j]) playerTeam[j] = j + 1;
if (!enemyTeam[j]) enemyTeam[j] = (j + 2) % 5 + 1;
}
// Reset team indices
currentPlayerTeamIndex = 0;
currentEnemyTeamIndex = 0;
clearTitleScreen();
gameState = 'teamFighterSelect';
initTeamFighterSelection();
}
break;
}
}
} else if (gameState === 'characterSelect') {
// Check difficulty buttons first
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 40) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
}
}
}
// Check which character was selected
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
// Use x,y coordinates directly since they're already in game coordinates
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
selectedCharacter = fighter.fighterIndex;
enemyCharacter = selectedCharacter % 5 + 1; // Simple enemy selection
storage.lastPlayerFighter = selectedCharacter;
storage.lastEnemyFighter = enemyCharacter;
updateSelectionBorder();
// Clear character selection
game.removeChild(instructionText);
for (var j = 0; j < characterSelectors.length; j++) {
game.removeChild(characterSelectors[j]);
}
game.removeChild(selectionBorder);
characterSelectors = [];
gameState = 'combat';
startCombat();
break;
}
}
} else if (gameState === 'playerSelect') {
// Check difficulty buttons first
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 40) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
}
}
}
// Check which character was selected for player vs player
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
if (currentPlayerSelection === 1) {
selectedCharacter = fighter.fighterIndex;
storage.lastPlayerFighter = selectedCharacter;
currentPlayerSelection = 2;
instructionText.setText('Player 2: Select Fighter');
} else {
enemyCharacter = fighter.fighterIndex;
storage.lastEnemyFighter = enemyCharacter;
// Clear character selection
game.removeChild(instructionText);
for (var j = 0; j < characterSelectors.length; j++) {
game.removeChild(characterSelectors[j]);
}
game.removeChild(selectionBorder);
characterSelectors = [];
gameState = 'combat';
startCombat();
}
updateSelectionBorder();
break;
}
}
} else if (gameState === 'teamFighterSelect') {
// Check difficulty buttons first
for (var i = 0; i < titleButtons.length; i++) {
var button = titleButtons[i];
if (Math.abs(x - button.x) < 100 && Math.abs(y - button.y) < 40) {
if (button.buttonType === 'easy') {
gameDifficulty = 'easy';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'easy') {
diffButton.tint = 0xff9500; // Lighter orange for easy
} else if (diffButton.buttonType === 'normalDiff' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'normalDiff') {
gameDifficulty = 'normal';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xcc6600; // Darker orange for normal
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'hard') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
} else if (button.buttonType === 'hard') {
gameDifficulty = 'hard';
// Update button colors
for (var k = 0; k < titleButtons.length; k++) {
var diffButton = titleButtons[k];
if (diffButton.buttonType === 'hard') {
diffButton.tint = 0xff0000; // Red for hard
} else if (diffButton.buttonType === 'easy' || diffButton.buttonType === 'normalDiff') {
diffButton.tint = 0xffffff; // White for others
}
}
return;
}
}
}
// Check which character was selected for team battle
for (var i = 0; i < characterSelectors.length; i++) {
var fighter = characterSelectors[i];
if (Math.abs(x - fighter.x) < 100 && Math.abs(y - fighter.y) < 150) {
// Determine which team and position we're selecting for
if (selectedTeamIndex < teamSize) {
// Selecting for player team
playerTeam[selectedTeamIndex] = fighter.fighterIndex;
} else {
// Selecting for enemy team
enemyTeam[selectedTeamIndex - teamSize] = fighter.fighterIndex;
}
selectedTeamIndex++;
// Check if we've selected all fighters for both teams
if (selectedTeamIndex >= teamSize * 2) {
// All fighters selected, start combat
// Clear character selection
game.removeChild(instructionText);
for (var j = 0; j < characterSelectors.length; j++) {
game.removeChild(characterSelectors[j]);
}
game.removeChild(selectionBorder);
characterSelectors = [];
gameState = 'combat';
selectedCharacter = playerTeam[0];
enemyCharacter = enemyTeam[0];
startCombat();
} else {
// Update display for next selection
var currentTeam = selectedTeamIndex < teamSize ? 'player' : 'enemy';
var fighterNumber = selectedTeamIndex % teamSize + 1;
var teamName = currentTeam === 'player' ? 'Player' : 'Enemy';
instructionText.setText(teamName + ' Team - Select Fighter ' + fighterNumber);
updateTeamBattleDisplay();
}
break;
}
}
} else if (gameState === 'combat') {
handleCombatInput(x, y);
}
};
game.move = function (x, y, obj) {
if (gameState === 'combat' && player && !playerIsBlocking) {
// Check if moving over left button
if (leftMoveButton && Math.abs(x - leftMoveButton.x) < 75 && Math.abs(y - leftMoveButton.y) < 75) {
isMovingLeft = true;
player.stopCrouch(); // Stop crouching when moving left
} else {
isMovingLeft = false;
}
// Check if moving over right button
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 75 && Math.abs(y - rightMoveButton.y) < 75) {
isMovingRight = true;
player.stopCrouch(); // Stop crouching when moving right
} else {
isMovingRight = false;
}
// Check if holding crouch button
if (crouchButton && Math.abs(x - crouchButton.x) < 75 && Math.abs(y - crouchButton.y) < 40) {
player.crouch();
}
}
};
game.up = function (x, y, obj) {
if (player && gameState === 'combat') {
player.isBlocking = false;
playerIsBlocking = false;
isMovingLeft = false;
isMovingRight = false;
player.stopCrouch();
// Reset walking animation to normal when movement stops
if (player.currentAnimation === 'walking') {
player.setAnimation('normal');
}
}
};
game.update = function () {
if (gameState === 'combat') {
// Update fighters
if (player) player.update();
if (enemy) enemy.update();
// Update UI bars
if (playerHealthBar) playerHealthBar.update();
if (playerEnergyBar) playerEnergyBar.update();
if (playerSpecialBar) playerSpecialBar.update();
if (enemyHealthBar) enemyHealthBar.update();
if (enemyEnergyBar) enemyEnergyBar.update();
if (enemySpecialBar) enemySpecialBar.update();
// Update button availability visual feedback
if (rangeButtonText && player) {
if (player.energy >= player.specialCost) {
rangeButtonText.tint = 0xFFFFFF; // White when available
} else {
rangeButtonText.tint = 0x666666; // Gray when not available
}
}
if (specialButtonText && player) {
if (player.canUseSpecialAttack()) {
specialButtonText.tint = 0xFFFFFF; // White when available
} else {
specialButtonText.tint = 0x666666; // Gray when not available
}
}
// Update super projectiles
for (var i = superProjectiles.length - 1; i >= 0; i--) {
var superProj = superProjectiles[i];
superProj.update();
// Check for super projectile clashes
for (var j = superProjectiles.length - 1; j >= 0; j--) {
if (i !== j) {
var otherSuperProj = superProjectiles[j];
if (Math.abs(superProj.x - otherSuperProj.x) < 80 && Math.abs(superProj.y - otherSuperProj.y) < 80) {
// Super projectiles clash - destroy both
LK.effects.flashScreen(0xffffff, 200);
superProj.destroy();
otherSuperProj.destroy();
superProjectiles.splice(Math.max(i, j), 1);
superProjectiles.splice(Math.min(i, j), 1);
i = Math.min(i, j) - 1; // Adjust index
break;
}
}
}
if (i >= 0 && i < superProjectiles.length) {
var superProj = superProjectiles[i];
// Check super projectile hits
var target = superProj.owner === player ? enemy : player;
if (target && Math.abs(superProj.x - target.x) < 200 && Math.abs(superProj.y - target.y) < 300) {
// Check if super projectile should miss crouching target
// Standing super projectiles (fired from y-280) should miss crouching targets
var superProjectileFromStanding = Math.abs(superProj.y - (superProj.owner.y - 280)) < 20;
if (target.isCrouching && !target.isJumping && superProjectileFromStanding) {
// Super projectile passes over crouching target - no hit
// Remove off-screen super projectiles
if (superProj.x < -50 || superProj.x > 2782) {
superProj.destroy();
superProjectiles.splice(i, 1);
}
continue; // Skip hit detection for crouching dodge
}
if (target.isBlocking) {
// Super projectile was blocked - apply 50% damage and pushback
target.takeDamage(superProj.damage, true, superProj.owner);
LK.getSound('block').play();
// No pushback for shooter when projectile impacts on block
// Push back the receiver (target) - much stronger pushback
var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 450;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 800,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 400);
} else {
// Normal hit
target.takeDamage(superProj.damage, true, superProj.owner);
// Push back the target when receiving super projectile hit - much stronger pushback
var targetPushDirection = target.x < superProj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 500;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 900,
easing: tween.easeOut
});
// Also push back the shooter (attacker) when hitting unblocked target
var shooterPushDirection = superProj.owner.x < target.x ? -1 : 1;
var shooterNewX = superProj.owner.x + shooterPushDirection * 180;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(superProj.owner, {
x: shooterNewX
}, {
duration: 600,
easing: tween.easeOut
});
}
superProj.destroy();
superProjectiles.splice(i, 1);
continue;
}
// Remove off-screen super projectiles
if (superProj.x < -50 || superProj.x > 2782) {
superProj.destroy();
superProjectiles.splice(i, 1);
}
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var proj = projectiles[i];
proj.update();
// Check for projectile clashes (range attacks destroying each other)
for (var j = projectiles.length - 1; j >= 0; j--) {
if (i !== j) {
var otherProj = projectiles[j];
if (Math.abs(proj.x - otherProj.x) < 50 && Math.abs(proj.y - otherProj.y) < 50) {
// Regular projectiles clash - destroy both
LK.effects.flashScreen(0xffffff, 150);
proj.destroy();
otherProj.destroy();
projectiles.splice(Math.max(i, j), 1);
projectiles.splice(Math.min(i, j), 1);
i = Math.min(i, j) - 1; // Adjust index
break;
}
}
}
if (i >= 0 && i < projectiles.length) {
var proj = projectiles[i];
// Check if regular projectile hits super projectile
for (var j = superProjectiles.length - 1; j >= 0; j--) {
var superProj = superProjectiles[j];
if (Math.abs(proj.x - superProj.x) < 60 && Math.abs(proj.y - superProj.y) < 60) {
// Regular projectile destroyed by super projectile
proj.destroy();
projectiles.splice(i, 1);
break;
}
}
}
if (i >= 0 && i < projectiles.length) {
var proj = projectiles[i];
// Check projectile hits
var target = proj.owner === player ? enemy : player;
if (target && Math.abs(proj.x - target.x) < 200 && Math.abs(proj.y - target.y) < 300) {
// Check if projectile should miss crouching target
// Standing projectiles (fired from y-280) should miss crouching targets
var projectileFromStanding = Math.abs(proj.y - (proj.owner.y - 280)) < 20;
if (target.isCrouching && !target.isJumping && projectileFromStanding) {
// Projectile passes over crouching target - no hit
// Remove off-screen projectiles
if (proj.x < -50 || proj.x > 2782) {
proj.destroy();
projectiles.splice(i, 1);
}
continue; // Skip hit detection for crouching dodge
}
if (target.isBlocking) {
// Projectile was blocked - apply reduced damage and pushback
target.takeDamage(Math.floor(proj.damage * 0.7)); // 30% damage reduction for normal blocking (increased from 70% reduction)
LK.getSound('block').play();
// No pushback for shooter when projectile impacts on block
// Push back the receiver (target)
var targetPushDirection = target.x < proj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 120;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 400,
easing: tween.easeOut
});
// Flash the target to show block effect
LK.effects.flashObject(target, 0x4444ff, 300);
} else {
// Normal hit
target.takeDamage(proj.damage);
// Push back the target when hit by regular projectile
var targetPushDirection = target.x < proj.owner.x ? -1 : 1;
var targetNewX = target.x + targetPushDirection * 120;
targetNewX = Math.max(200, Math.min(1848, targetNewX));
tween(target, {
x: targetNewX
}, {
duration: 400,
easing: tween.easeOut
});
}
proj.owner.chargeSpecial(7); // Charge special at 50% rate for successful range hit
proj.destroy();
projectiles.splice(i, 1);
continue;
}
// Remove off-screen projectiles
if (proj.x < -50 || proj.x > 2782) {
proj.destroy();
projectiles.splice(i, 1);
}
}
}
// Handle continuous movement
if (player && !playerIsBlocking) {
if (isMovingLeft && player.x > 200) {
player.stopCrouch(); // Stop crouching when moving left
player.x -= player.speed * 3;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
} else if (isMovingRight && player.x < 2532) {
player.stopCrouch(); // Stop crouching when moving right
player.x += player.speed * 3;
if (player.currentAnimation === 'normal') {
player.setAnimation('walking');
}
} else {
// Neither left nor right movement is active, reset walking animation
if (player.currentAnimation === 'walking') {
player.setAnimation('normal');
}
}
}
// Update AI
updateAI();
// Check game over with debounce protection (only check every 10 ticks to prevent rapid multiple calls)
if (LK.ticks % 10 === 0) {
checkGameOver();
}
}
};
// Keyboard event handler
LK.on('keydown', function (event) {
if (gameState !== 'combat' || !player) return;
var key = event.key.toLowerCase();
if (key === 'z') {
// Z key - Punch
if (player.attack()) {
player.setAnimation('punching', 20); // 20 ticks punch animation
checkMeleeHit(player, enemy, Math.floor(player.attackDamage * 0.75), 'punch');
LK.getSound('punch').play();
}
} else if (key === 'x') {
// X key - Kick - can't kick while crouching
if (!player.isCrouching && player.attack()) {
player.setAnimation('kicking', 25); // 25 ticks kick animation (slightly longer)
checkMeleeHit(player, enemy, Math.floor((player.attackDamage + 1) * 0.75), 'kick');
LK.getSound('kick').play();
}
} else if (key === 'c') {
// C key - Range attack (special)
if (enemy && player.specialAttack()) {
player.setAnimation('rangeShooting', 15); // 15 ticks range shooting animation
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust projectile origin based on player stance
var projectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
projectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
var projectile = new Projectile(player.x + projectileXOffset, projectileY, shootDirection, player.specialDamage, player);
projectiles.push(projectile);
game.addChild(projectile);
player.chargeSpecial(7); // Charge special at 50% rate (15 * 0.5 = 7.5, rounded to 7)
LK.getSound('special').play();
}
} else if (key === 'v') {
// V key - Super special attack
if (enemy && player.useSpecialAttack()) {
// Start charging animation before firing
tween(player, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xffaa00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Set potent shooting animation
player.setAnimation('potentShooting', 30); // 30 ticks potent shooting animation
// Return to normal size and color after charging
tween(player, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
// Determine shoot direction based on enemy position
var shootDirection = enemy.x > player.x ? 1 : -1;
var projectileXOffset = shootDirection > 0 ? 50 : -50;
// Adjust super projectile origin based on player stance
var superProjectileY = player.y - 280; // Default standing position - adjusted for 2x bigger fighters
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 100; // Lower origin when crouching - adjusted for 2x bigger fighters
} else if (player.isJumping) {
superProjectileY = player.y - 300; // Higher origin when jumping - adjusted for 2x bigger fighters
}
// Create 7 super projectiles fired in a horizontal row
for (var i = 0; i < 7; i++) {
(function (index) {
LK.setTimeout(function () {
var projectileX = player.x + projectileXOffset + (index - 3) * 60; // Horizontal spread in a row
var projectileYOffset = superProjectileY; // Same Y position for all projectiles
var superProjectile = new SuperProjectile(projectileX, projectileYOffset, shootDirection, Math.floor(player.specialDamage * 2 / 7), player);
// Increase speed for keyboard potent projectiles
superProjectile.speed = 8; // Increased speed to match regular projectiles
// Add laser effects for fighter 3
if (player.fighterType === 3) {
// Initial bright laser effect
tween(superProjectile, {
tint: 0xff0000
}, {
duration: 50
});
// Pulsing laser effect
tween(superProjectile, {
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeInOut
});
tween(superProjectile, {
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeInOut
});
}
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// No pushback when firing potent projectiles
LK.getSound('special').play();
}
});
}
}
});
// Initialize title screen
initTitleScreen();
; ===================================================================
--- original.js
+++ change.js
@@ -923,9 +923,9 @@
scaleX: 2.0,
scaleY: 2.0
});
backButton.x = 1024;
- backButton.y = 1200;
+ backButton.y = 1250;
backButton.buttonType = 'backToMenu';
game.addChild(backButton);
titleButtons.push(backButton);
var backButtonText = new Text2('BACK TO MENU', {
transparent bubble. In-Game asset. 2d. High contrast. No shadows
shield
arm with a fist
band-aid
a little bit smaller image
hornless
whitte
whole gloves
fire
transparent kicking feet simbol. In-Game asset. 2d. High contrast. No shadows
red
2D
crouching with blue background
teeth close to bite
scratch attack
teeth
toothless open mouth
shark teeth. In-Game asset. 2d. High contrast. No shadows
simbolo transparente de bala. In-Game asset. 2d. High contrast. No shadows
transparent fist simbol. In-Game asset. 2d. High contrast. No shadows
transparent fire simbol. In-Game asset. 2d. High contrast. No shadows
right arrow. In-Game asset. 2d. High contrast. No shadows
add sand
building roof