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