User prompt
move the team battle difficulty options to the start team selection menu
User prompt
make it be able to chose 2 vs 2 or 3 vs 3 without dissaparing the buttoms so i can chose wich one i want
User prompt
make the hard mode harder
User prompt
make the hard buttom turn red when selected, when the hard mode is selected the ai will try to block all your attacks, make distance bethwhen you and it to use range attacks and potet attacks, will kick you if crouching, will try to jump and crouch to aboid proyectiles, will also jump and crouch to hit you with the range attacks and potent attacks if you are crouching or jumping respectively, will try to land as much attacks as posible
User prompt
make the easy buttom selection a different orange when selected
User prompt
change it to a darker orange
User prompt
normal buttom also turns orange if selected
User prompt
if easy is selected the buttom turns orange and the enemy ai stays like the current one when starting combat, the normal mode ai will try crouch if you punch it and jump if you kick it, will try to block if you shoot range attacks and will kick you if youre crouching
User prompt
move difficulty selecion to the game modes, not the choose game mode menu
User prompt
in all the game modes add 3 dificulty options: easy normal and hard
User prompt
only one energy bar regens every 10 seconds ONLY ONE ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when all energy bars are empty onmly the first one fills, only then the second one starts filling and then the third one
User prompt
energy bars fill slowly
User prompt
second energy bar only start regenering after first energy bar regens and third energy bar only start regening when second bar regens
User prompt
make only one energy bar regens at the time
User prompt
potent attack proyectiles can be dodged with crouching
User prompt
make the shield assets swich directions like the standing assets
User prompt
make shield always point to the oponent
User prompt
make the shield swich direction acording to the opponent direction
User prompt
move the Menu buttom betwhen the player healt bar and enemy healt bar
User prompt
move the menu buttom to the midle of the two healtbars
User prompt
add a blocking asset
User prompt
make potent attack proyectiles dont lose speed
User prompt
make the healt, energy and special attack bars bigger
User prompt
make all movement buttoms the same colour and make left and rigth a little bit smaller
/****
* 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;
}
}
self.takeDamage = function (damage, isSuperProjectile, attacker) {
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%)
}
}
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 = [];
// 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
});
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
});
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
});
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
});
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
});
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
});
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
});
backButton.x = 1024;
backButton.y = 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 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
});
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
});
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);
var startButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5
});
startButton.x = 1024;
startButton.y = 300;
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);
// Add difficulty selection for team battle 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 = 450;
game.addChild(difficultyText);
// Easy difficulty button
var easyButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5
});
easyButton.x = 600;
easyButton.y = 550;
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
});
normalDiffButton.x = 1024;
normalDiffButton.y = 550;
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
});
hardButton.x = 1448;
hardButton.y = 550;
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);
// Add back to menu button
var backButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5
});
backButton.x = 1024;
backButton.y = 650;
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);
// 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
});
backButton.x = 1024;
backButton.y = 1300;
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 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
});
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
});
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
});
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
});
backButton.x = 1024;
backButton.y = gameMode === 'normal' ? 900 : 800;
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);
}
}
// 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 teamFighter = LK.getAsset('fighter' + playerTeam[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
teamFighter.x = 200 + i * 80;
teamFighter.y = 280;
teamFighter.teamIndex = i;
teamFighter.isTeamDisplay = true;
if (i !== currentPlayerTeamIndex) {
teamFighter.tint = 0x666666; // Grey for inactive fighters
}
teamPlayerDisplays.push(teamFighter);
game.addChild(teamFighter);
}
// Enemy team display below special bar
for (var i = 0; i < enemyTeam.length; i++) {
var teamFighter = LK.getAsset('fighter' + enemyTeam[i], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
teamFighter.x = 1800 + i * 80;
teamFighter.y = 280;
teamFighter.teamIndex = i;
teamFighter.isTeamDisplay = true;
if (i !== currentEnemyTeamIndex) {
teamFighter.tint = 0x666666; // Grey for inactive fighters
}
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 switchToNextTeamFighter(isPlayer) {
if (gameMode !== 'teamBattle') return false;
if (isPlayer) {
// 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;
// Highlight current active fighter
if (teamPlayerDisplays[currentPlayerTeamIndex]) {
tween(teamPlayerDisplays[currentPlayerTeamIndex], {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
}
}
});
return true;
} else {
// 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;
// Highlight current active fighter
if (teamEnemyDisplays[currentEnemyTeamIndex]) {
tween(teamEnemyDisplays[currentEnemyTeamIndex], {
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut
});
}
}
}
});
return true;
}
return false;
}
function checkGameOver() {
if (player && player.health <= 0) {
// Try to switch to next team fighter
if (gameMode === 'teamBattle') {
if (currentPlayerTeamIndex + 1 >= playerTeam.length) {
// No more player team fighters left - game over
LK.showGameOver();
} else {
switchToNextTeamFighter(true);
}
} else {
LK.showGameOver();
}
} else if (enemy && enemy.health <= 0) {
// Try to switch to next team fighter
if (gameMode === 'teamBattle') {
if (currentEnemyTeamIndex + 1 >= enemyTeam.length) {
// No more enemy team fighters left - player wins
LK.showYouWin();
} else {
switchToNextTeamFighter(false);
}
} 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';
clearTitleScreen();
gameState = 'characterSelect';
initCharacterSelection();
} else if (button.buttonType === 'select') {
gameMode = 'playerVsPlayer';
clearTitleScreen();
gameState = 'playerSelect';
initPlayerSelection();
} else if (button.buttonType === 'team') {
gameMode = 'teamBattle';
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 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
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
@@ -853,8 +853,11 @@
});
normalDiffButton.x = 1024;
normalDiffButton.y = 550;
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,
@@ -871,8 +874,11 @@
});
hardButton.x = 1448;
hardButton.y = 550;
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,
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