User prompt
remove walking animations
User prompt
make walking assets appear when walking βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the walking animation to appear when the character is moving βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
add animation for punching and give all figthers his own βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make every fighter have their own
User prompt
add one asset for walking
User prompt
re-add figher 3
User prompt
change assets back to before animations
User prompt
change crouch animation back to normal βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
change crouch buttom asset to orange
User prompt
make block buttom blue
User prompt
add assets for walking animation, kick animation, punch animation, range attack animation, crouch animation, jump animation, and potent attack animation βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
i meant change it to the simple orange proyectile
User prompt
turn potent proyectile to his original form
User prompt
limite the growing effect the its original zise and remove the sonic effect βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
i meant change the proyectile appearence to rings βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it look like rings that grow in zise βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
change the potent proyectiles to loock like a sonic attack βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
try again
User prompt
it only reduces 25% of the potent attack damage
User prompt
after the 0,5 nanosecons it only reduces 50% of the damage βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the 100% damage reduction of the block to only last for 0,5 nanoseconds βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
change the rectangle proyectile to a ")" shape
User prompt
make them grow faster and reduce range βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
makw them loock small at the start and slowly grow to full zise βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.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 * 135; // Space bars evenly (400/3 β 133)
energyBar.width = 125; // Slightly smaller to have gaps
self.energyBars.push(energyBar);
}
self.update = function () {
// Show energy bars based on current energy level (0-3)
var energyLevel = Math.floor(self.fighter.energy / (self.fighter.maxEnergy / 3));
for (var i = 0; i < 3; i++) {
self.energyBars[i].visible = i < energyLevel;
}
};
return self;
});
var Fighter = Container.expand(function (fighterType, isPlayer) {
var self = Container.call(this);
// Fighter properties
self.fighterType = fighterType || 1;
self.isPlayer = isPlayer || false;
self.maxHealth = 100;
self.health = 100;
self.maxEnergy = 3; // Changed to 3 energy units
self.energy = 3; // Start with full energy
self.speed = 3;
self.isBlocking = false;
self.attackCooldown = 0;
self.specialCooldown = 0;
self.maxSpecialCharge = 100;
self.specialCharge = 0;
self.isCrouching = false;
self.isJumping = false;
self.jumpHeight = 0;
self.maxJumpHeight = 100;
self.jumpSpeed = 14;
self.originalY = 0;
self.gravity = 0.25;
self.velocityY = 0;
self.groundY = 2200; // Ground level for all fighters
// Animation properties
self.currentAction = 'idle';
self.animationFrame = 1;
self.animationTimer = 0;
self.animationSpeed = 10; // Frames between animation updates
// Create fighter graphics
var fighterGraphics = self.attachAsset('fighter' + self.fighterType, {
anchorX: 0.5,
anchorY: 1.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;
}
self.takeDamage = function (damage, isSuperProjectile, attacker) {
if (self.isPlayer && playerIsBlocking) {
// Check if within perfect block window (0.5 nanoseconds - essentially instantaneous)
var timeSinceBlockStart = LK.ticks - playerBlockStartTime;
if (timeSinceBlockStart <= 0.00003) {
// 0.00003 ticks β 0.5 nanoseconds at 60fps
damage = 0; // 100% damage reduction
} else {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.75); // Only 25% damage reduction for super projectiles after perfect block window (75% damage goes through)
} else {
damage = Math.floor(damage * 0.5); // 50% damage reduction for regular attacks after perfect block window
}
}
} else if (self.isBlocking) {
if (isSuperProjectile) {
damage = Math.floor(damage * 0.75); // Only 25% damage reduction when blocking super projectile (75% damage goes through)
} else {
damage = Math.floor(damage * 0.3);
}
}
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;
}
};
self.stopCrouch = function () {
self.isCrouching = 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.updateAnimation = function () {
self.animationTimer++;
if (self.animationTimer >= self.animationSpeed) {
self.animationTimer = 0;
// Determine current action based on fighter state
var newAction = 'idle';
if (self.isJumping) {
newAction = 'jump';
} else if (self.isCrouching) {
newAction = 'crouch';
} else if (self.attackCooldown > 25) {
if (self.lastAttackType === 'punch') {
newAction = 'punch';
} else if (self.lastAttackType === 'kick') {
newAction = 'kick';
}
} else if (self.specialCooldown > 80) {
if (self.lastSpecialType === 'range') {
newAction = 'range';
} else if (self.lastSpecialType === 'potent') {
newAction = 'potent';
}
}
// Update animation frame
if (newAction !== self.currentAction) {
self.currentAction = newAction;
self.animationFrame = 1;
} else {
// Cycle through animation frames for multi-frame actions
if (newAction === 'walk' || newAction === 'kick' || newAction === 'punch' || newAction === 'range' || newAction === 'jump' || newAction === 'potent') {
self.animationFrame = self.animationFrame === 1 ? 2 : 1;
}
}
// Update fighter graphics based on current action and frame
self.updateGraphics();
}
};
self.updateGraphics = function () {
// Remove current graphics
self.removeChild(fighterGraphics);
// Determine which asset to use based on action and frame
var assetName = 'fighter' + self.fighterType;
if (self.currentAction === 'walk') {
assetName = 'walkingFrame' + self.animationFrame;
} else if (self.currentAction === 'kick') {
assetName = 'kickFrame' + self.animationFrame;
} else if (self.currentAction === 'punch') {
assetName = 'punchFrame' + self.animationFrame;
} else if (self.currentAction === 'range') {
assetName = 'rangeFrame' + self.animationFrame;
} else if (self.currentAction === 'crouch') {
assetName = 'crouchFrame1';
} else if (self.currentAction === 'jump') {
assetName = 'jumpFrame' + self.animationFrame;
} else if (self.currentAction === 'potent') {
assetName = 'potentFrame' + self.animationFrame;
}
// Create new graphics with animation asset
fighterGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 1.0
});
};
self.update = function () {
// Update animations
self.updateAnimation();
// Cooldown management
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.specialCooldown > 0) self.specialCooldown--;
// Energy regeneration - regenerate 1 energy every 10 seconds (600 ticks), one bar at a time
if (self.energy < self.maxEnergy && LK.ticks % 600 === 0) {
self.energy = Math.min(self.maxEnergy, self.energy + 1);
}
// 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 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 = 400 * 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 projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
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 = 400 * 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 superProjectileGraphics = self.attachAsset('superProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x += self.speed * self.direction;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// Animation assets for different actions
// Game states
// Character assets
// UI elements
// Combat elements
// Sounds
var gameState = 'characterSelect'; // 'characterSelect', 'combat', 'gameOver'
var selectedCharacter = 1;
var enemyCharacter = 2;
// 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;
// UI elements
var titleText = new Text2('Arena Warriors', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
titleText.y = 50;
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 initCharacterSelection() {
instructionText.y = 200;
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.7,
scaleY: 0.7
});
var col = (i - 1) % 3;
var row = Math.floor((i - 1) / 3);
fighter.x = 400 + col * 300;
fighter.y = 600 + row * 350;
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);
}
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);
// Create fighters
player = game.addChild(new Fighter(selectedCharacter, true));
player.x = 400;
player.y = 2200;
enemy = game.addChild(new Fighter(enemyCharacter, false));
enemy.x = 1648;
enemy.y = 2200;
// Create health and energy bars
playerHealthBar = game.addChild(new HealthBar(player, 150, 150));
playerEnergyBar = game.addChild(new EnergyBar(player, 150, 200));
playerSpecialBar = game.addChild(new SpecialBar(player, 150, 250));
enemyHealthBar = game.addChild(new HealthBar(enemy, 1498, 150));
enemyEnergyBar = game.addChild(new EnergyBar(enemy, 1498, 200));
enemySpecialBar = game.addChild(new SpecialBar(enemy, 1498, 250));
// Create combat control buttons
punchButton = LK.getAsset('punchButton', {
anchorX: 0.5,
anchorY: 0.5
});
punchButton.x = 350;
punchButton.y = 2500;
game.addChild(punchButton);
kickButton = LK.getAsset('kickButton', {
anchorX: 0.5,
anchorY: 0.5
});
kickButton.x = 700;
kickButton.y = 2500;
game.addChild(kickButton);
rangeButton = LK.getAsset('rangeButton', {
anchorX: 0.5,
anchorY: 0.5
});
rangeButton.x = 1400;
rangeButton.y = 2500;
game.addChild(rangeButton);
blockButton = LK.getAsset('blockButton', {
anchorX: 0.5,
anchorY: 0.5
});
blockButton.x = 1050;
blockButton.y = 2400;
game.addChild(blockButton);
specialButton = LK.getAsset('specialButton', {
anchorX: 0.5,
anchorY: 0.5
});
specialButton.x = 1050;
specialButton.y = 2600;
game.addChild(specialButton);
// Create movement buttons on the right side
leftMoveButton = LK.getAsset('leftMoveButton', {
anchorX: 0.5,
anchorY: 0.5
});
leftMoveButton.x = 1650;
leftMoveButton.y = 2450;
game.addChild(leftMoveButton);
rightMoveButton = LK.getAsset('rightMoveButton', {
anchorX: 0.5,
anchorY: 0.5
});
rightMoveButton.x = 1850;
rightMoveButton.y = 2450;
game.addChild(rightMoveButton);
// Create crouch and jump buttons
crouchButton = LK.getAsset('crouchButton', {
anchorX: 0.5,
anchorY: 0.5
});
crouchButton.x = 1750;
crouchButton.y = 2500;
game.addChild(crouchButton);
jumpButton = LK.getAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5
});
jumpButton.x = 1750;
jumpButton.y = 2400;
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 controls text
controlsText.setText('Tap buttons to fight! Use arrow buttons to move.');
controlsText.y = 2600;
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 = 100;
game.addChild(playerLabel);
var enemyLabel = new Text2('Enemy', {
size: 40,
fill: 0xFFFFFF
});
enemyLabel.anchor.set(1, 0);
enemyLabel.x = 1898;
enemyLabel.y = 100;
game.addChild(enemyLabel);
}
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')) {
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')) {
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')) {
// 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 - 140; // Default standing position - slightly higher
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
projectileY = player.y - 150; // Higher origin when jumping
}
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() {
// 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 - 140; // Default standing position - slightly higher
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
superProjectileY = player.y - 150; // Higher origin when jumping
}
// 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);
// Reduce range by modifying speed
superProjectile.speed = 1.0; // Reduced from 1.5 to 1.0 for further range reduction
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the shooter when firing special attack
var shooterPushDirection = -shootDirection; // Player pushes back opposite to shoot direction
var shooterNewX = player.x + shooterPushDirection * 120;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(player, {
x: shooterNewX
}, {
duration: 400,
easing: tween.easeOut
});
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.x -= player.speed * 10;
}
return;
}
if (rightMoveButton && Math.abs(x - rightMoveButton.x) < 75 && Math.abs(y - rightMoveButton.y) < 75) {
// Right movement button pressed
if (!playerIsBlocking && player.x < 1848) {
player.x += player.speed * 10;
}
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();
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 < 280) {
// 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.3));
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;
}
if (enemyIsMovingRight && enemy.x < 1848) {
enemy.x += enemy.speed * 2;
}
} else {
enemyIsMovingLeft = false;
enemyIsMovingRight = false;
}
// Enhanced AI behavior - mix of range attacks, melee attacks, movement, jumping and crouching
if (LK.ticks % 30 === 0) {
var action = Math.floor(Math.random() * 12); // Increased range to include jump/crouch actions
// Check if enemy is in melee range (close enough to punch/kick)
if (distance < 280) {
// In melee range - try to attack or block
if (action <= 3 && enemy.attack()) {
// Punch attack
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
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() {
// 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 - 140; // Default standing position - slightly higher
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 150; // Higher origin when jumping
}
// 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);
// Reduce range by modifying speed
superProjectile.speed = 1.0; // Reduced from 1.5 to 1.0 for further range reduction
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the enemy when firing special attack
var shooterPushDirection = -shootDirection; // Enemy pushes back opposite to shoot direction
var shooterNewX = enemy.x + shooterPushDirection * 120;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(enemy, {
x: shooterNewX
}, {
duration: 400,
easing: tween.easeOut
});
LK.getSound('special').play();
}
});
} else if (action <= 6 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack (reduced frequency)
// 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 - 140; // Default standing position - slightly higher
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
projectileY = enemy.y - 150; // Higher origin when jumping
}
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() {
// 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 - 140; // Default standing position - slightly higher
if (enemy.isCrouching && !enemy.isJumping) {
superProjectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
superProjectileY = enemy.y - 150; // Higher origin when jumping
}
// 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);
// Reduce range by modifying speed
superProjectile.speed = 1.0; // Reduced from 1.5 to 1.0 for further range reduction
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the enemy when firing special attack
var shooterPushDirection = -shootDirection; // Enemy pushes back opposite to shoot direction
var shooterNewX = enemy.x + shooterPushDirection * 120;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(enemy, {
x: shooterNewX
}, {
duration: 400,
easing: tween.easeOut
});
LK.getSound('special').play();
}
});
} else if (action <= 3 && enemy.energy >= 1 && enemy.specialAttack()) {
// Use range attack when available (reduced frequency)
// 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 - 140; // Default standing position - slightly higher
if (enemy.isCrouching && !enemy.isJumping) {
projectileY = enemy.y - 50; // Lower origin when crouching
} else if (enemy.isJumping) {
projectileY = enemy.y - 150; // Higher origin when jumping
}
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
if (LK.ticks % 45 === 0) {
enemy.isBlocking = false;
enemy.stopCrouch(); // Release crouch periodically
}
}
function checkGameOver() {
if (player && player.health <= 0) {
LK.showGameOver();
} else if (enemy && enemy.health <= 0) {
LK.showYouWin();
}
}
// Character selection input
game.down = function (x, y, obj) {
if (gameState === 'characterSelect') {
// 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
updateSelectionBorder();
// Start combat after selection
LK.setTimeout(function () {
startCombat();
}, 500);
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;
} 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;
} 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();
}
};
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) < 100 && Math.abs(superProj.y - target.y) < 150) {
if (target.isBlocking) {
// Super projectile was blocked - apply 50% damage and pushback
target.takeDamage(superProj.damage, true, superProj.owner);
LK.getSound('block').play();
// Push back the shooter (attacker) - increased distance
var shooterPushDirection = superProj.owner.x < target.x ? -1 : 1;
var shooterNewX = superProj.owner.x + shooterPushDirection * 300;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(superProj.owner, {
x: shooterNewX
}, {
duration: 700,
easing: tween.easeOut
});
// 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 > 2098) {
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) < 100 && Math.abs(proj.y - target.y) < 150) {
// Check if projectile should miss crouching target
// Standing projectiles (fired from y-140) should miss crouching targets
var projectileFromStanding = Math.abs(proj.y - (proj.owner.y - 140)) < 20;
if (target.isCrouching && !target.isJumping && projectileFromStanding) {
// Projectile passes over crouching target - no hit
// Remove off-screen projectiles
if (proj.x < -50 || proj.x > 2098) {
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.3));
LK.getSound('block').play();
// Push back the shooter (attacker)
var shooterPushDirection = proj.owner.x < target.x ? -1 : 1;
var shooterNewX = proj.owner.x + shooterPushDirection * 150;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(proj.owner, {
x: shooterNewX
}, {
duration: 400,
easing: tween.easeOut
});
// 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 > 2098) {
proj.destroy();
projectiles.splice(i, 1);
}
}
}
// Handle continuous movement
if (player && !playerIsBlocking) {
if (isMovingLeft && player.x > 200) {
player.x -= player.speed * 3;
player.currentAction = 'walk';
}
if (isMovingRight && player.x < 1848) {
player.x += player.speed * 3;
player.currentAction = 'walk';
}
}
// Update AI
updateAI();
// Check game over
checkGameOver();
}
};
// Keyboard event handler
LK.on('keydown', function (event) {
if (gameState !== 'combat' || !player) return;
var key = event.key.toLowerCase();
if (key === 'z') {
// Z key - Punch
if (player.attack()) {
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()) {
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()) {
// 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 - 140; // Default standing position - slightly higher
if (player.isCrouching && !player.isJumping) {
projectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
projectileY = player.y - 150; // Higher origin when jumping
}
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() {
// 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 - 140; // Default standing position - slightly higher
if (player.isCrouching && !player.isJumping) {
superProjectileY = player.y - 50; // Lower origin when crouching
} else if (player.isJumping) {
superProjectileY = player.y - 150; // Higher origin when jumping
}
// 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);
// Reduce range by modifying speed
superProjectile.speed = 1.0; // Reduced from 1.5 to 1.0 for further range reduction
superProjectiles.push(superProjectile);
game.addChild(superProjectile);
}, index * 100); // 100ms delay between each projectile
})(i);
}
// Push back the shooter when firing special attack
var shooterPushDirection = -shootDirection; // Player pushes back opposite to shoot direction
var shooterNewX = player.x + shooterPushDirection * 120;
shooterNewX = Math.max(200, Math.min(1848, shooterNewX));
tween(player, {
x: shooterNewX
}, {
duration: 400,
easing: tween.easeOut
});
LK.getSound('special').play();
}
});
}
}
});
// Initialize character selection screen
initCharacterSelection();
; ===================================================================
--- original.js
+++ change.js
@@ -58,8 +58,13 @@
self.originalY = 0;
self.gravity = 0.25;
self.velocityY = 0;
self.groundY = 2200; // Ground level for all fighters
+ // Animation properties
+ self.currentAction = 'idle';
+ self.animationFrame = 1;
+ self.animationTimer = 0;
+ self.animationSpeed = 10; // Frames between animation updates
// Create fighter graphics
var fighterGraphics = self.attachAsset('fighter' + self.fighterType, {
anchorX: 0.5,
anchorY: 1.0
@@ -136,18 +141,20 @@
return true;
}
return false;
};
- self.attack = function () {
+ self.attack = function (attackType) {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
+ self.lastAttackType = attackType || 'punch';
return true;
}
return false;
};
- self.specialAttack = function () {
+ self.specialAttack = function (specialType) {
if (self.specialCooldown <= 0 && self.useEnergy(self.specialCost)) {
self.specialCooldown = 90;
+ self.lastSpecialType = specialType || 'range';
return true;
}
return false;
};
@@ -177,9 +184,74 @@
self.isJumping = true;
self.velocityY = -self.jumpSpeed; // Negative velocity for upward movement
}
};
+ self.updateAnimation = function () {
+ self.animationTimer++;
+ if (self.animationTimer >= self.animationSpeed) {
+ self.animationTimer = 0;
+ // Determine current action based on fighter state
+ var newAction = 'idle';
+ if (self.isJumping) {
+ newAction = 'jump';
+ } else if (self.isCrouching) {
+ newAction = 'crouch';
+ } else if (self.attackCooldown > 25) {
+ if (self.lastAttackType === 'punch') {
+ newAction = 'punch';
+ } else if (self.lastAttackType === 'kick') {
+ newAction = 'kick';
+ }
+ } else if (self.specialCooldown > 80) {
+ if (self.lastSpecialType === 'range') {
+ newAction = 'range';
+ } else if (self.lastSpecialType === 'potent') {
+ newAction = 'potent';
+ }
+ }
+ // Update animation frame
+ if (newAction !== self.currentAction) {
+ self.currentAction = newAction;
+ self.animationFrame = 1;
+ } else {
+ // Cycle through animation frames for multi-frame actions
+ if (newAction === 'walk' || newAction === 'kick' || newAction === 'punch' || newAction === 'range' || newAction === 'jump' || newAction === 'potent') {
+ self.animationFrame = self.animationFrame === 1 ? 2 : 1;
+ }
+ }
+ // Update fighter graphics based on current action and frame
+ self.updateGraphics();
+ }
+ };
+ self.updateGraphics = function () {
+ // Remove current graphics
+ self.removeChild(fighterGraphics);
+ // Determine which asset to use based on action and frame
+ var assetName = 'fighter' + self.fighterType;
+ if (self.currentAction === 'walk') {
+ assetName = 'walkingFrame' + self.animationFrame;
+ } else if (self.currentAction === 'kick') {
+ assetName = 'kickFrame' + self.animationFrame;
+ } else if (self.currentAction === 'punch') {
+ assetName = 'punchFrame' + self.animationFrame;
+ } else if (self.currentAction === 'range') {
+ assetName = 'rangeFrame' + self.animationFrame;
+ } else if (self.currentAction === 'crouch') {
+ assetName = 'crouchFrame1';
+ } else if (self.currentAction === 'jump') {
+ assetName = 'jumpFrame' + self.animationFrame;
+ } else if (self.currentAction === 'potent') {
+ assetName = 'potentFrame' + self.animationFrame;
+ }
+ // Create new graphics with animation asset
+ fighterGraphics = self.attachAsset(assetName, {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ };
self.update = function () {
+ // Update animations
+ self.updateAnimation();
// Cooldown management
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.specialCooldown > 0) self.specialCooldown--;
// Energy regeneration - regenerate 1 energy every 10 seconds (600 ticks), one bar at a time
@@ -302,8 +374,9 @@
/****
* Game Code
****/
+// Animation assets for different actions
// Game states
// Character assets
// UI elements
// Combat elements
@@ -592,27 +665,27 @@
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()) {
+ if (player.attack('punch')) {
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()) {
+ if (!player.isCrouching && player.attack('kick')) {
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()) {
+ if (enemy && player.specialAttack('range')) {
// 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
@@ -632,8 +705,9 @@
}
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,
@@ -1285,11 +1359,13 @@
// Handle continuous movement
if (player && !playerIsBlocking) {
if (isMovingLeft && player.x > 200) {
player.x -= player.speed * 3;
+ player.currentAction = 'walk';
}
if (isMovingRight && player.x < 1848) {
player.x += player.speed * 3;
+ player.currentAction = 'walk';
}
}
// Update AI
updateAI();
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