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
// 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 () {
if (self.attackCooldown <= 0) {
self.attackCooldown = 30;
return true;
}
return false;
};
self.specialAttack = function () {
if (self.specialCooldown <= 0 && self.useEnergy(self.specialCost)) {
self.specialCooldown = 90;
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.update = function () {
// 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;
// Create main ring projectile
var mainRing = self.attachAsset('superProjectileRing', {
anchorX: 0.5,
anchorY: 0.5
});
// Create inner ring
var innerRing = self.attachAsset('superProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
// Create outer ring
var outerRing = self.attachAsset('superProjectileRing', {
anchorX: 0.5,
anchorY: 0.5
});
// Position rings at center
mainRing.x = 0;
mainRing.y = 0;
innerRing.x = 0;
innerRing.y = 0;
outerRing.x = 0;
outerRing.y = 0;
// Set initial ring scales to create ring appearance
mainRing.scaleX = 1.0;
mainRing.scaleY = 1.0;
innerRing.scaleX = 0.3;
innerRing.scaleY = 0.3;
outerRing.scaleX = 1.5;
outerRing.scaleY = 1.5;
outerRing.alpha = 0.6;
// Animate rings to grow continuously
tween(mainRing, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0.4
}, {
duration: 800,
easing: tween.easeOut
});
tween(innerRing, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.8
}, {
duration: 600,
easing: tween.easeOut
});
tween(outerRing, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 0.2
}, {
duration: 1000,
easing: tween.easeOut
});
self.update = function () {
self.x += self.speed * self.direction;
// Make rings continuously grow in size
mainRing.scaleX += 0.04;
mainRing.scaleY += 0.04;
innerRing.scaleX += 0.02;
innerRing.scaleY += 0.02;
outerRing.scaleX += 0.06;
outerRing.scaleY += 0.06;
// Rotate rings for visual effect
mainRing.rotation += 0.08 * self.direction;
innerRing.rotation -= 0.1 * self.direction;
outerRing.rotation += 0.05 * self.direction;
// Fade rings as they grow larger
mainRing.alpha = Math.max(0.2, mainRing.alpha - 0.006);
innerRing.alpha = Math.max(0.3, innerRing.alpha - 0.004);
outerRing.alpha = Math.max(0.1, outerRing.alpha - 0.008);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C1810
});
/****
* Game Code
****/
// 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()) {
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()) {
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()) {
// 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()) {
// 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;
}
if (isMovingRight && player.x < 1848) {
player.x += player.speed * 3;
}
}
// 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
@@ -282,81 +282,80 @@
self.damage = damage;
self.owner = owner;
self.speed = 6;
self.isSuperProjectile = true;
- // Create main sonic wave core
- var sonicCore = self.attachAsset('superProjectile', {
+ // Create main ring projectile
+ var mainRing = self.attachAsset('superProjectileRing', {
anchorX: 0.5,
anchorY: 0.5
});
- // Create expanding sonic rings
- var ring1 = self.attachAsset('sonicRing1', {
+ // Create inner ring
+ var innerRing = self.attachAsset('superProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
- var ring2 = self.attachAsset('sonicRing2', {
+ // Create outer ring
+ var outerRing = self.attachAsset('superProjectileRing', {
anchorX: 0.5,
anchorY: 0.5
});
// Position rings at center
- ring1.x = 0;
- ring1.y = 0;
- ring2.x = 0;
- ring2.y = 0;
- // Start all elements small and animate to create sonic wave effect
- sonicCore.scaleX = 0.1;
- sonicCore.scaleY = 0.1;
- ring1.scaleX = 0.1;
- ring1.scaleY = 0.1;
- ring2.scaleX = 0.1;
- ring2.scaleY = 0.1;
- // Animate core sonic wave
- tween(sonicCore, {
+ mainRing.x = 0;
+ mainRing.y = 0;
+ innerRing.x = 0;
+ innerRing.y = 0;
+ outerRing.x = 0;
+ outerRing.y = 0;
+ // Set initial ring scales to create ring appearance
+ mainRing.scaleX = 1.0;
+ mainRing.scaleY = 1.0;
+ innerRing.scaleX = 0.3;
+ innerRing.scaleY = 0.3;
+ outerRing.scaleX = 1.5;
+ outerRing.scaleY = 1.5;
+ outerRing.alpha = 0.6;
+ // Animate rings to grow continuously
+ tween(mainRing, {
+ scaleX: 2.0,
+ scaleY: 2.0,
+ alpha: 0.4
+ }, {
+ duration: 800,
+ easing: tween.easeOut
+ });
+ tween(innerRing, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.8
}, {
- duration: 300,
+ duration: 600,
easing: tween.easeOut
});
- // Animate first ring with expanding effect
- tween(ring1, {
- scaleX: 2.0,
- scaleY: 2.0,
- alpha: 0.3
- }, {
- duration: 400,
- easing: tween.easeOut
- });
- // Animate second ring with different timing
- tween(ring2, {
+ tween(outerRing, {
scaleX: 3.0,
scaleY: 3.0,
- alpha: 0.1
+ alpha: 0.2
}, {
- duration: 500,
+ duration: 1000,
easing: tween.easeOut
});
- // Add pulsing effect to sonic core
- self.pulseTimer = 0;
self.update = function () {
self.x += self.speed * self.direction;
- // Create pulsing sonic wave effect
- self.pulseTimer += 0.3;
- var pulseScale = 1.0 + Math.sin(self.pulseTimer) * 0.2;
- sonicCore.scaleX = pulseScale;
- sonicCore.scaleY = pulseScale;
// Make rings continuously grow in size
- ring1.scaleX += 0.05;
- ring1.scaleY += 0.05;
- ring2.scaleX += 0.08;
- ring2.scaleY += 0.08;
- // Also rotate rings for additional visual effect
- ring1.rotation += 0.1 * self.direction;
- ring2.rotation -= 0.08 * self.direction;
+ mainRing.scaleX += 0.04;
+ mainRing.scaleY += 0.04;
+ innerRing.scaleX += 0.02;
+ innerRing.scaleY += 0.02;
+ outerRing.scaleX += 0.06;
+ outerRing.scaleY += 0.06;
+ // Rotate rings for visual effect
+ mainRing.rotation += 0.08 * self.direction;
+ innerRing.rotation -= 0.1 * self.direction;
+ outerRing.rotation += 0.05 * self.direction;
// Fade rings as they grow larger
- ring1.alpha = Math.max(0.1, ring1.alpha - 0.008);
- ring2.alpha = Math.max(0.05, ring2.alpha - 0.012);
+ mainRing.alpha = Math.max(0.2, mainRing.alpha - 0.006);
+ innerRing.alpha = Math.max(0.3, innerRing.alpha - 0.004);
+ outerRing.alpha = Math.max(0.1, outerRing.alpha - 0.008);
};
return self;
});
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