User prompt
Agac 2 ve desdroyhomeyi sil
User prompt
Delorasyonlari haritanin her yerine ekle karakterin yuruduyu yerde ortaya cikmasin
User prompt
Bu modeledim agaci haritanin rasgele yerlerine ekle
User prompt
Agac 2 yi modelle
User prompt
Haritadaki dekorasyonlari tum harita boyunca olsun yakin olmasin evler random yerlerde ağaclar random yerlerde olsun cimpar tum harita boyunca olsun
User prompt
Dekorasyonlar yakin yakin olmasin uzak uzak rasgele olsun tum haritayi kapsasin
User prompt
Haritayi sonsuz yap dusmanlarda karakterin yakinda dosun
User prompt
Haritaya ağaclar cimler yikilmis evler kamp atesi rasgele yerlere yerlesdir
User prompt
Bos ve dusmanlar hitboxun disindan vurmasinlar
User prompt
Karakterin hitboxunu yeniden yap
User prompt
Bosun saldirilarindan biride havadan yere kirmizi iz birakib mermi atsin
User prompt
Boosun en cok kullandi saldirisi mermi atmak olsun
User prompt
Boos saldirilarindan biride yerde kirmizi iz birakim oraya ziplasin
User prompt
Kasadan 10sansla level artilan esya ciksin
User prompt
Sandiklarin icinden 50sansla xb ciksin
User prompt
Kutulari modelle
User prompt
Haritada kutular olusun bu kutulari kirinci icinde can ciksin
User prompt
Fasterenemey olunce patlasin
User prompt
Simsek buyucusunun mermilerini modele
User prompt
UI secdiklerimizi buyut ve alt alta koy
User prompt
Her level atlayinca 3ozelik ciksin ve biz 1ini secelim
User prompt
Bosun mermilerini modelle
User prompt
Elektirik buyucusunun atti mermileri modelle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ozelik secerken oyun dursun ve secdiyimiz ozelikler alt alta dursunlar
User prompt
Her level atladimizda rasgele 3ozeliyimizden birini secib artira bilelim
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BasicEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('basicEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 25;
self.maxHealth = 25;
self.damage = 15;
self.speed = 3;
self.scoreValue = 10;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
// Drop XP orb
var xpOrb = new XPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
self.destroy();
LK.setScore(LK.getScore() + self.scoreValue);
scoreTxt.setText(LK.getScore());
LK.getSound('enemyDestroy').play();
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
};
self.update = function () {
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var BoosAmmo = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0x8B4513; // Brown viking ammo color
bulletGraphics.scaleX = 6; // Much bigger boosammo
bulletGraphics.scaleY = 6; // Much bigger boosammo
self.speed = 4;
self.damage = 50; // Higher damage for boosammo
self.targetX = 0;
self.targetY = 0;
self.directionX = 0;
self.directionY = 0;
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
var dx = x - self.x;
var dy = y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
}
// Rotate bullet to face direction
bulletGraphics.rotation = Math.atan2(dy, dx) + Math.PI / 2;
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Remove bullet if it goes off screen
if (self.x < -50 || self.x > 8242 || self.y < -50 || self.y > 10978) {
self.destroy();
for (var i = boosAmmos.length - 1; i >= 0; i--) {
if (boosAmmos[i] === self) {
boosAmmos.splice(i, 1);
break;
}
}
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('wikingboss', {
anchorX: 0.5,
anchorY: 0.5
});
bossGraphics.tint = 0x8B4513; // Brown viking color
bossGraphics.scaleX = 4.0; // Much larger viking boss model
bossGraphics.scaleY = 4.0; // Much larger viking boss model
// Add viking boss aura effect
var auraGraphics = self.attachAsset('wikingboss', {
anchorX: 0.5,
anchorY: 0.5
});
auraGraphics.tint = 0xDAA520; // Golden viking aura
auraGraphics.alpha = 0.4;
auraGraphics.scaleX = 4.5; // Larger aura to match viking boss size
auraGraphics.scaleY = 4.5; // Larger aura to match viking boss size
// Add pulsing viking aura animation
tween(auraGraphics, {
scaleX: 5.0,
scaleY: 5.0,
alpha: 0.2
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(auraGraphics, {
scaleX: 4.5,
scaleY: 4.5,
alpha: 0.4
}, {
duration: 1500,
easing: tween.easeInOut
});
}
});
self.health = 400 + (currentWave - 3) * 85; // Much higher health for viking boss
self.maxHealth = self.health;
self.damage = 70; // Higher damage for intimidating viking boss
self.speed = 1.1; // Slightly slower due to massive viking size
self.scoreValue = 250; // Higher reward for defeating viking boss
self.lastLightningTime = 0;
self.lightningCooldown = 120; // 2 seconds at 60fps
self.lastChargeTime = 0;
self.chargeCooldown = 300; // 5 seconds at 60fps
self.isCharging = false;
self.chargeSpeed = 8;
self.chargeTargetX = 0;
self.chargeTargetY = 0;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
// Drop multiple XP orbs
for (var orbCount = 0; orbCount < 5; orbCount++) {
var xpOrb = new XPOrb();
xpOrb.x = self.x + (Math.random() - 0.5) * 100;
xpOrb.y = self.y + (Math.random() - 0.5) * 100;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
}
self.destroy();
LK.setScore(LK.getScore() + self.scoreValue);
scoreTxt.setText(LK.getScore());
LK.getSound('enemyDestroy').play();
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
};
self.shootBigBullets = function () {
// Create multiple boosammos
for (var bulletCount = 0; bulletCount < 5; bulletCount++) {
var boosAmmo = new BoosAmmo();
boosAmmo.x = self.x;
boosAmmo.y = self.y;
// Spread boosammos around hero
var angleOffset = (bulletCount - 2) * Math.PI / 8;
var targetX = hero.x + Math.cos(angleOffset) * 150;
var targetY = hero.y + Math.sin(angleOffset) * 150;
boosAmmo.setTarget(targetX, targetY);
boosAmmos.push(boosAmmo);
game.addChild(boosAmmo);
}
LK.effects.flashObject(self, 0xFF4500, 400);
};
self.startCharge = function () {
self.isCharging = true;
self.chargeTargetX = hero.x;
self.chargeTargetY = hero.y;
LK.effects.flashObject(self, 0xFF4500, 500);
// Viking boss grows larger during charge
tween(bossGraphics, {
scaleX: 4.5,
scaleY: 4.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Charge for 1 second then return to normal
LK.setTimeout(function () {
self.isCharging = false;
tween(bossGraphics, {
scaleX: 4.0,
scaleY: 4.0
}, {
duration: 200,
easing: tween.easeIn
});
}, 1000);
}
});
};
self.update = function () {
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var currentTime = LK.ticks;
// Normal attack (close range) - direct damage without projectiles
if (distance < 200 && currentTime - self.lastLightningTime > self.lightningCooldown) {
// Close range normal attack - direct damage to hero
hero.takeDamage(self.damage);
LK.effects.flashObject(self, 0xFF4500, 400);
LK.effects.flashObject(hero, 0xFF0000, 300);
self.lastLightningTime = currentTime;
}
// Big bullet attack from much greater distance
if (distance >= 600 && distance < 1200 && currentTime - self.lastLightningTime > self.lightningCooldown) {
self.shootBigBullets();
self.lastLightningTime = currentTime;
}
// Charge attack from much greater distance
if (distance > 400 && distance < 1000 && currentTime - self.lastChargeTime > self.chargeCooldown && !self.isCharging) {
self.startCharge();
self.lastChargeTime = currentTime;
}
// Movement behavior
if (self.isCharging) {
// Charge towards target position
var chargeDx = self.chargeTargetX - self.x;
var chargeDy = self.chargeTargetY - self.y;
var chargeDistance = Math.sqrt(chargeDx * chargeDx + chargeDy * chargeDy);
if (chargeDistance > 0) {
self.x += chargeDx / chargeDistance * self.chargeSpeed;
self.y += chargeDy / chargeDistance * self.chargeSpeed;
}
} else {
// Normal movement - maintain much greater distance from hero
if (distance > 800) {
// Move closer
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
} else if (distance < 600) {
// Move away
if (distance > 0) {
self.x -= dx / distance * self.speed;
self.y -= dy / distance * self.speed;
}
}
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 25;
self.targetX = 0;
self.targetY = 0;
self.directionX = 0;
self.directionY = 0;
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
var dx = x - self.x;
var dy = y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
}
// Rotate bullet to face direction
bulletGraphics.rotation = Math.atan2(dy, dx) + Math.PI / 2;
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Remove bullet if it goes off screen
if (self.x < -50 || self.x > 8242 || self.y < -50 || self.y > 10978) {
self.destroy();
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
}
};
return self;
});
var FastEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 15;
self.maxHealth = 15;
self.damage = 10;
self.speed = 4.5;
self.scoreValue = 15;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
// Drop XP orb
var xpOrb = new XPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
self.destroy();
LK.setScore(LK.getScore() + self.scoreValue);
scoreTxt.setText(LK.getScore());
LK.getSound('enemyDestroy').play();
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
};
self.update = function () {
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
var weaponGraphics = self.attachAsset('weapon', {
anchorX: 0.5,
anchorY: 0.9
});
weaponGraphics.x = 25;
weaponGraphics.y = -10;
self.maxHealth = 100;
self.health = self.maxHealth;
self.attackDamage = 25;
self.isInvulnerable = false;
self.takeDamage = function (damage) {
if (self.isInvulnerable) return;
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
return;
}
// Flash red when taking damage
LK.effects.flashObject(self, 0xFF0000, 300);
LK.getSound('playerHit').play();
// Brief invulnerability
self.isInvulnerable = true;
LK.setTimeout(function () {
self.isInvulnerable = false;
}, 500);
};
self.attack = function (enemy) {
enemy.takeDamage(self.attackDamage);
LK.getSound('enemyHit').play();
// Weapon swing animation
tween(weaponGraphics, {
rotation: weaponGraphics.rotation + Math.PI / 3
}, {
duration: 100
});
};
self.updateWeapon = function (targetX, targetY) {
// Calculate angle to target
var dx = targetX - self.x;
var dy = targetY - self.y;
var angle = Math.atan2(dy, dx);
weaponGraphics.rotation = angle + Math.PI / 2;
};
self.shoot = function (targetX, targetY) {
var bullet = new Bullet();
bullet.x = self.x + Math.cos(weaponGraphics.rotation - Math.PI / 2) * 40;
bullet.y = self.y + Math.sin(weaponGraphics.rotation - Math.PI / 2) * 40;
bullet.setTarget(targetX, targetY);
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('weaponShoot').play();
// Weapon recoil animation
tween(weaponGraphics, {
y: weaponGraphics.y + 5
}, {
duration: 50,
onComplete: function onComplete() {
tween(weaponGraphics, {
y: weaponGraphics.y - 5
}, {
duration: 50
});
}
});
};
self.isWalking = false;
self.moveSpeed = 4;
self.analogMove = function (deltaX, deltaY) {
// Analog movement with bounds checking
var newX = self.x + deltaX * self.moveSpeed;
var newY = self.y + deltaY * self.moveSpeed;
// Keep within bounds
self.x = Math.max(40, Math.min(8152, newX));
self.y = Math.max(40, Math.min(10888, newY));
};
self.walkTo = function (targetX, targetY) {
// Don't start new walk if already walking
if (self.isWalking) {
tween.stop(self, {
x: true,
y: true
});
}
self.isWalking = true;
// Keep within bounds
targetX = Math.max(40, Math.min(8152, targetX));
targetY = Math.max(40, Math.min(10888, targetY));
// Calculate distance for duration
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var duration = distance * 2; // Adjust speed by changing multiplier
// Walking animation with slight bounce
tween(heroGraphics, {
scaleY: 0.9
}, {
duration: duration / 4,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(heroGraphics, {
scaleY: 1.1
}, {
duration: duration / 4,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(heroGraphics, {
scaleY: 1.0
}, {
duration: duration / 2,
easing: tween.easeOut
});
}
});
}
});
// Move to target position
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isWalking = false;
}
});
};
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var lightningGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
lightningGraphics.tint = 0x00FFFF; // Electric cyan lightning
lightningGraphics.scaleX = 1.5;
lightningGraphics.scaleY = 4;
self.speed = 7;
self.damage = 30;
self.targetX = 0;
self.targetY = 0;
self.directionX = 0;
self.directionY = 0;
self.lifetime = 0;
self.maxLifetime = 180; // 3 seconds at 60fps
// Create electric aura effect
var auraGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
auraGraphics.tint = 0x4444FF; // Blue electric aura
auraGraphics.alpha = 0.4;
auraGraphics.scaleX = 3;
auraGraphics.scaleY = 6;
// Electric pulsing aura animation
tween(auraGraphics, {
scaleX: 4,
scaleY: 8,
alpha: 0.1
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(auraGraphics, {
scaleX: 2.5,
scaleY: 5,
alpha: 0.5
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
// Enhanced lightning crackling effect with rapid flashing
tween(lightningGraphics, {
alpha: 0.2,
scaleX: 2.0,
scaleY: 5
}, {
duration: 80,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(lightningGraphics, {
alpha: 1.0,
scaleX: 1.2,
scaleY: 3.5
}, {
duration: 60,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue crackling cycle
tween(lightningGraphics, {
alpha: 0.6,
scaleX: 1.8,
scaleY: 4.5
}, {
duration: 70,
easing: tween.easeInOut
});
}
});
}
});
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
var dx = x - self.x;
var dy = y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
}
// Rotate lightning to face direction
lightningGraphics.rotation = Math.atan2(dy, dx) + Math.PI / 2;
auraGraphics.rotation = lightningGraphics.rotation;
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
self.lifetime++;
// Enhanced electric crackling with color shifts
if (Math.random() < 0.4) {
lightningGraphics.alpha = Math.random() * 0.7 + 0.3;
// Random electric color variations
var colorVariations = [0x00FFFF, 0x66CCFF, 0x0099FF, 0x33AAFF];
lightningGraphics.tint = colorVariations[Math.floor(Math.random() * colorVariations.length)];
}
// Electric spark effect - randomly adjust scale
if (Math.random() < 0.2) {
lightningGraphics.scaleX = 1.2 + Math.random() * 0.8;
lightningGraphics.scaleY = 3.5 + Math.random() * 1.5;
}
// Remove lightning after lifetime expires or goes off screen
if (self.lifetime > self.maxLifetime || self.x < -50 || self.x > 8242 || self.y < -50 || self.y > 10978) {
self.destroy();
for (var i = lightningBolts.length - 1; i >= 0; i--) {
if (lightningBolts[i] === self) {
lightningBolts.splice(i, 1);
break;
}
}
}
};
return self;
});
var StrongEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('strongEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.damage = 25;
self.speed = 2.8;
self.scoreValue = 25;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
// Drop XP orb
var xpOrb = new XPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
self.destroy();
LK.setScore(LK.getScore() + self.scoreValue);
scoreTxt.setText(LK.getScore());
LK.getSound('enemyDestroy').play();
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
};
self.update = function () {
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var Wizard = Container.expand(function () {
var self = Container.call(this);
var wizardGraphics = self.attachAsset('Wizard', {
anchorX: 0.5,
anchorY: 0.5
});
// Add magical aura effect using the wizard asset
var auraGraphics = self.attachAsset('Wizard', {
anchorX: 0.5,
anchorY: 0.5
});
auraGraphics.tint = 0x9370DB; // Purple aura
auraGraphics.alpha = 0.3;
auraGraphics.scaleX = 1.3;
auraGraphics.scaleY = 1.3;
// Add pulsing magical aura animation
tween(auraGraphics, {
scaleX: 1.8,
scaleY: 1.8,
alpha: 0.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(auraGraphics, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.3
}, {
duration: 1000,
easing: tween.easeInOut
});
}
});
self.health = 60;
self.maxHealth = 60;
self.damage = 20;
self.speed = 2.5;
self.scoreValue = 30;
self.lastLightningTime = 0;
self.lightningCooldown = 180; // 3 seconds at 60fps
self.lightningRange = 400;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
// Drop XP orb
var xpOrb = new XPOrb();
xpOrb.x = self.x;
xpOrb.y = self.y;
xpOrbs.push(xpOrb);
game.addChild(xpOrb);
self.destroy();
LK.setScore(LK.getScore() + self.scoreValue);
scoreTxt.setText(LK.getScore());
LK.getSound('enemyDestroy').play();
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
}
};
self.shootLightning = function () {
// Create lightning bolt
var lightning = new Lightning();
lightning.x = self.x;
lightning.y = self.y;
lightning.setTarget(hero.x, hero.y);
lightningBolts.push(lightning);
game.addChild(lightning);
// Enhanced lightning casting effects
LK.effects.flashObject(self, 0xFFFF00, 300);
LK.effects.flashObject(auraGraphics, 0xFFFFFF, 400);
// Dramatic casting animation - wizard grows larger then returns
tween(wizardGraphics, {
scaleX: 1.5,
scaleY: 1.5,
rotation: wizardGraphics.rotation + Math.PI / 6
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(wizardGraphics, {
scaleX: 1.2,
scaleY: 1.2,
rotation: wizardGraphics.rotation - Math.PI / 6
}, {
duration: 250,
easing: tween.easeIn
});
}
});
// Aura intensifies during casting
tween(auraGraphics, {
scaleX: 2.2,
scaleY: 2.2,
alpha: 0.6
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(auraGraphics, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.3
}, {
duration: 300,
easing: tween.easeIn
});
}
});
};
self.update = function () {
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Keep distance and shoot lightning
if (distance < self.lightningRange && distance > 150) {
// Stop moving and prepare to shoot
var currentTime = LK.ticks;
if (currentTime - self.lastLightningTime > self.lightningCooldown) {
self.shootLightning();
self.lastLightningTime = currentTime;
}
} else if (distance > self.lightningRange) {
// Move closer to hero
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
} else if (distance < 150) {
// Move away from hero
if (distance > 0) {
self.x -= dx / distance * self.speed;
self.y -= dy / distance * self.speed;
}
}
};
return self;
});
var XPOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('xpOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.xpValue = 5;
self.moveSpeed = 2;
self.attractRange = 150;
// Add pulsing animation to make XP orbs more attractive
tween(orbGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(orbGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Restart the pulsing animation
tween(orbGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
});
self.update = function () {
// XP orb magnetic attraction to other nearby orbs
for (var o = 0; o < xpOrbs.length; o++) {
var otherOrb = xpOrbs[o];
if (otherOrb !== self) {
var orbDx = otherOrb.x - self.x;
var orbDy = otherOrb.y - self.y;
var orbDistance = Math.sqrt(orbDx * orbDx + orbDy * orbDy);
// Attract to nearby orbs within 80 pixels
if (orbDistance < 80 && orbDistance > 0) {
var attractForce = 0.5;
self.x += orbDx / orbDistance * attractForce;
self.y += orbDy / orbDistance * attractForce;
}
}
}
// Move toward hero if within attract range
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.attractRange) {
if (distance > 0) {
self.x += dx / distance * self.moveSpeed;
self.y += dy / distance * self.moveSpeed;
}
}
// Check if collected by hero
if (distance < 30) {
// Give XP to player
currentXP += self.xpValue;
LK.setScore(LK.getScore() + self.xpValue);
scoreTxt.setText(LK.getScore());
LK.getSound('xpCollect').play();
// Remove from xpOrbs array
for (var i = xpOrbs.length - 1; i >= 0; i--) {
if (xpOrbs[i] === self) {
xpOrbs.splice(i, 1);
break;
}
}
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
var hero;
var enemies = [];
var bullets = [];
var xpOrbs = [];
var lightningBolts = [];
var boosAmmos = [];
var spawnTimer = 0;
var difficultyLevel = 1;
var scoreTxt;
var healthBar;
var healthBarBg;
var attackIndicator;
var lastShootTime = 0;
var joystickBase;
var joystickKnob;
var isJoystickActive = false;
var joystickStartX = 0;
var joystickStartY = 0;
var joystickRadius = 80;
var movementX = 0;
var movementY = 0;
var healthText;
var levelBar;
var levelBarBg;
var levelText;
var playerLevel = 1;
var currentXP = 0;
var xpToNextLevel = 30;
var currentWave = 1;
var waveStartTime = 0;
var waveDuration = 60000; // 1 minute in milliseconds
var waveEnemyCount = 0;
var baseEnemiesPerWave = 20;
var waveText;
var waveTimer;
var bossSpawned = false;
// Ability upgrade system
var playerAbilities = {
damage: 1,
// Damage multiplier
speed: 1,
// Movement speed multiplier
health: 1 // Max health multiplier
};
var abilityUpgradeMenu = null;
var isUpgradeMenuActive = false;
// Create score display
scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create health bar background
healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
healthBarBg.x = 150;
healthBarBg.y = 50;
LK.gui.topLeft.addChild(healthBarBg);
// Create health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0
});
healthBar.x = 150;
healthBar.y = 50;
LK.gui.topLeft.addChild(healthBar);
// Create health text
healthText = new Text2('100/100', {
size: 40,
fill: 0xFFFFFF
});
healthText.anchor.set(0, 0.5);
healthText.x = 370;
healthText.y = 60;
LK.gui.topLeft.addChild(healthText);
// Create level bar background at bottom
levelBarBg = LK.getAsset('levelBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
levelBarBg.x = 2048 / 2;
levelBarBg.y = 2732 - 60;
game.addChild(levelBarBg);
// Create level bar fill
levelBar = LK.getAsset('levelBar', {
anchorX: 0,
anchorY: 0.5
});
levelBar.x = levelBarBg.x - levelBarBg.width / 2;
levelBar.y = levelBarBg.y;
game.addChild(levelBar);
// Create level text
levelText = new Text2('Level 1', {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
levelText.x = levelBarBg.x;
levelText.y = levelBarBg.y - 50;
game.addChild(levelText);
// Create wave display
waveText = new Text2('Wave 1', {
size: 60,
fill: 0xFFD700
});
waveText.anchor.set(1, 0);
waveText.x = 2048 - 20;
waveText.y = 20;
LK.gui.topRight.addChild(waveText);
// Create wave timer display
waveTimer = new Text2('2:00', {
size: 50,
fill: 0xFFFFFF
});
waveTimer.anchor.set(0.5, 0);
waveTimer.x = 0;
waveTimer.y = 80;
LK.gui.top.addChild(waveTimer);
// Create boss health bar background
var bossHealthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0
});
bossHealthBarBg.x = 0;
bossHealthBarBg.y = 140;
bossHealthBarBg.visible = false;
bossHealthBarBg.scaleX = 2;
LK.gui.top.addChild(bossHealthBarBg);
// Create boss health bar
var bossHealthBar = LK.getAsset('healthBar', {
anchorX: 0.5,
anchorY: 0
});
bossHealthBar.x = 0;
bossHealthBar.y = 140;
bossHealthBar.visible = false;
bossHealthBar.scaleX = 2;
bossHealthBar.tint = 0xFF4444; // Red color for boss health
LK.gui.top.addChild(bossHealthBar);
// Create boss health text
var bossHealthText = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
bossHealthText.anchor.set(0.5, 0);
bossHealthText.x = 0;
bossHealthText.y = 180;
bossHealthText.visible = false;
LK.gui.top.addChild(bossHealthText);
// Create hero
hero = game.addChild(new Hero());
hero.x = 4096;
hero.y = 5464;
// Camera following variables
var cameraX = 0;
var cameraY = 0;
var cameraFollowSpeed = 0.1;
var cameraSmoothing = true;
// Create attack range indicator (initially hidden)
attackIndicator = LK.getAsset('attackRange', {
anchorX: 0.5,
anchorY: 0.5
});
attackIndicator.alpha = 0.3;
attackIndicator.visible = false;
game.addChild(attackIndicator);
// Create analog joystick base
joystickBase = LK.getAsset('attackRange', {
anchorX: 0.5,
anchorY: 0.5
});
joystickBase.alpha = 0.2;
joystickBase.visible = false;
joystickBase.scaleX = 1.5;
joystickBase.scaleY = 1.5;
game.addChild(joystickBase);
// Create analog joystick knob
joystickKnob = LK.getAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
joystickKnob.alpha = 0.7;
joystickKnob.visible = false;
joystickKnob.scaleX = 0.6;
joystickKnob.scaleY = 0.6;
game.addChild(joystickKnob);
// Create map boundary walls
var topWall = LK.getAsset('wallHorizontal', {
anchorX: 0.5,
anchorY: 0.5
});
topWall.x = 4096;
topWall.y = 20;
game.addChild(topWall);
var bottomWall = LK.getAsset('wallHorizontal', {
anchorX: 0.5,
anchorY: 0.5
});
bottomWall.x = 4096;
bottomWall.y = 10928 - 20;
game.addChild(bottomWall);
var leftWall = LK.getAsset('wallVertical', {
anchorX: 0.5,
anchorY: 0.5
});
leftWall.x = 20;
leftWall.y = 5464;
game.addChild(leftWall);
var rightWall = LK.getAsset('wallVertical', {
anchorX: 0.5,
anchorY: 0.5
});
rightWall.x = 8192 - 20;
rightWall.y = 5464;
game.addChild(rightWall);
function createAbilityUpgradeMenu() {
// Create menu background
abilityUpgradeMenu = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
abilityUpgradeMenu.scaleX = 8;
abilityUpgradeMenu.scaleY = 6;
abilityUpgradeMenu.x = hero.x;
abilityUpgradeMenu.y = hero.y;
abilityUpgradeMenu.tint = 0x333333;
abilityUpgradeMenu.alpha = 0.9;
game.addChild(abilityUpgradeMenu);
// Create menu title
var menuTitle = new Text2('Choose Upgrade:', {
size: 80,
fill: 0xFFFFFF
});
menuTitle.anchor.set(0.5, 0.5);
menuTitle.x = abilityUpgradeMenu.x;
menuTitle.y = abilityUpgradeMenu.y - 150;
abilityUpgradeMenu.titleText = menuTitle;
game.addChild(menuTitle);
// Generate 3 random ability options
var availableAbilities = ['damage', 'speed', 'health'];
var selectedAbilities = [];
// Randomly select 3 abilities (can have duplicates for balance)
for (var i = 0; i < 3; i++) {
var randomIndex = Math.floor(Math.random() * availableAbilities.length);
selectedAbilities.push(availableAbilities[randomIndex]);
}
abilityUpgradeMenu.upgradeButtons = [];
// Create upgrade option buttons
for (var i = 0; i < 3; i++) {
var ability = selectedAbilities[i];
var button = LK.getAsset('levelBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
button.scaleX = 1.5;
button.scaleY = 1;
button.x = abilityUpgradeMenu.x;
button.y = abilityUpgradeMenu.y + (i - 1) * 120;
button.tint = 0x4CAF50;
button.alpha = 0.8;
button.abilityType = ability;
// Add button interaction
button.down = function (x, y, obj) {
if (isUpgradeMenuActive) {
selectAbilityUpgrade(obj.abilityType);
}
};
var buttonText = new Text2(getAbilityDisplayName(ability), {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = button.x;
buttonText.y = button.y - 20;
var levelText = new Text2('Level ' + (playerAbilities[ability] + 1), {
size: 35,
fill: 0xFFD700
});
levelText.anchor.set(0.5, 0.5);
levelText.x = button.x;
levelText.y = button.y + 25;
button.buttonText = buttonText;
button.levelText = levelText;
abilityUpgradeMenu.upgradeButtons.push(button);
game.addChild(button);
game.addChild(buttonText);
game.addChild(levelText);
}
isUpgradeMenuActive = true;
}
function getAbilityDisplayName(ability) {
switch (ability) {
case 'damage':
return 'Attack Power';
case 'speed':
return 'Movement Speed';
case 'health':
return 'Max Health';
default:
return ability;
}
}
function selectAbilityUpgrade(abilityType) {
if (!isUpgradeMenuActive) return;
// Upgrade the selected ability
playerAbilities[abilityType]++;
// Apply the upgrade effects
switch (abilityType) {
case 'damage':
hero.attackDamage = 25 * playerAbilities.damage;
break;
case 'speed':
hero.moveSpeed = 4 * playerAbilities.speed;
break;
case 'health':
var healthIncrease = 20;
hero.maxHealth += healthIncrease;
hero.health += healthIncrease; // Also heal for the increase
break;
}
// Show upgrade effect
LK.effects.flashScreen(0x00FF00, 500);
// Close upgrade menu
closeAbilityUpgradeMenu();
}
function closeAbilityUpgradeMenu() {
if (!abilityUpgradeMenu) return;
// Remove all menu elements
abilityUpgradeMenu.titleText.destroy();
for (var i = 0; i < abilityUpgradeMenu.upgradeButtons.length; i++) {
var button = abilityUpgradeMenu.upgradeButtons[i];
button.buttonText.destroy();
button.levelText.destroy();
button.destroy();
}
abilityUpgradeMenu.destroy();
abilityUpgradeMenu = null;
isUpgradeMenuActive = false;
}
function spawnEnemy() {
var enemyType = Math.random();
var enemy;
if (enemyType < 0.5) {
enemy = new BasicEnemy();
} else if (enemyType < 0.75) {
enemy = new FastEnemy();
} else if (enemyType < 0.95) {
enemy = new StrongEnemy();
} else {
enemy = new Wizard();
}
// Spawn at random edge position
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 8192;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 8192 + 50;
enemy.y = Math.random() * 10928;
break;
case 2:
// Bottom
enemy.x = Math.random() * 8192;
enemy.y = 10928 + 50;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 10928;
break;
}
enemies.push(enemy);
game.addChild(enemy);
}
function updateHealthBar() {
var healthPercent = hero.health / hero.maxHealth;
healthBar.scaleX = healthPercent;
if (healthPercent > 0.5) {
healthBar.tint = 0x4CAF50; // Green
} else if (healthPercent > 0.25) {
healthBar.tint = 0xFFC107; // Yellow
} else {
healthBar.tint = 0xF44336; // Red
}
// Update health text
healthText.setText(Math.ceil(hero.health) + '/' + hero.maxHealth);
}
function updateLevelBar() {
var xpPercent = currentXP / xpToNextLevel;
levelBar.scaleX = xpPercent;
// Check for level up
if (currentXP >= xpToNextLevel) {
playerLevel++;
currentXP = 0;
xpToNextLevel = playerLevel * 30; // Increase XP requirement
levelText.setText('Level ' + playerLevel);
// Level up effects
LK.effects.flashScreen(0xFFD700, 500);
// Show ability upgrade menu
createAbilityUpgradeMenu();
}
}
function updateBossHealthBar() {
// Find if there's a boss enemy alive
var currentBoss = null;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i] instanceof Boss) {
currentBoss = enemies[i];
break;
}
}
// Show/hide boss health bar based on boss presence
if (currentBoss) {
bossHealthBarBg.visible = true;
bossHealthBar.visible = true;
bossHealthText.visible = true;
// Update boss health bar
var bossHealthPercent = currentBoss.health / currentBoss.maxHealth;
bossHealthBar.scaleX = bossHealthPercent * 2; // Scale to match background
// Update boss health text
bossHealthText.setText('Boss: ' + Math.ceil(currentBoss.health) + '/' + currentBoss.maxHealth);
} else {
bossHealthBarBg.visible = false;
bossHealthBar.visible = false;
bossHealthText.visible = false;
}
}
function startNewWave() {
currentWave++;
waveStartTime = Date.now();
waveEnemyCount = 0;
bossSpawned = false;
waveText.setText('Wave ' + currentWave);
// Wave start effects
LK.effects.flashScreen(0x00FF00, 800);
// Increase difficulty each wave
difficultyLevel = currentWave;
}
function updateWaveTimer() {
var currentTime = Date.now();
var timeElapsed = currentTime - waveStartTime;
var timeRemaining = Math.max(0, waveDuration - timeElapsed);
var minutes = Math.floor(timeRemaining / 60000);
var seconds = Math.floor(timeRemaining % 60000 / 1000);
var timeText = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
waveTimer.setText(timeText);
// Check if wave time is up
if (timeRemaining <= 0) {
startNewWave();
}
}
function updateCamera() {
// Calculate target camera position (center hero on screen)
var targetCameraX = -(hero.x - 2048 / 2);
var targetCameraY = -(hero.y - 2732 / 2);
// Apply camera bounds to prevent showing outside game world
var minCameraX = -8192; // Allow some movement beyond left edge
var maxCameraX = 8192; // Allow some movement beyond right edge
var minCameraY = -10928; // Allow some movement beyond top edge
var maxCameraY = 10928; // Allow some movement beyond bottom edge
targetCameraX = Math.max(minCameraX, Math.min(maxCameraX, targetCameraX));
targetCameraY = Math.max(minCameraY, Math.min(maxCameraY, targetCameraY));
if (cameraSmoothing) {
// Smooth camera following using interpolation
cameraX += (targetCameraX - cameraX) * cameraFollowSpeed;
cameraY += (targetCameraY - cameraY) * cameraFollowSpeed;
} else {
// Direct camera following
cameraX = targetCameraX;
cameraY = targetCameraY;
}
// Apply camera position to game container
game.x = cameraX;
game.y = cameraY;
// Update level bar position to follow hero
levelBarBg.x = hero.x;
levelBarBg.y = hero.y + 300; // Position below hero
levelBar.x = levelBarBg.x - levelBarBg.width / 2;
levelBar.y = levelBarBg.y;
levelText.x = levelBarBg.x;
levelText.y = levelBarBg.y - 50;
}
function handleMove(x, y, obj) {
// Handle analog joystick movement
if (isJoystickActive) {
var deltaX = x - joystickStartX;
var deltaY = y - joystickStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Limit joystick range
if (distance > joystickRadius) {
deltaX = deltaX / distance * joystickRadius;
deltaY = deltaY / distance * joystickRadius;
}
// Update joystick knob position
joystickKnob.x = joystickStartX + deltaX;
joystickKnob.y = joystickStartY + deltaY;
// Calculate movement values (-1 to 1)
movementX = deltaX / joystickRadius;
movementY = deltaY / joystickRadius;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Make hero walk to touch position
hero.walkTo(x, y);
};
game.up = function (x, y, obj) {
// Deactivate analog joystick
if (isJoystickActive) {
isJoystickActive = false;
joystickBase.visible = false;
joystickKnob.visible = false;
movementX = 0;
movementY = 0;
}
attackIndicator.visible = false;
};
game.update = function () {
// Don't update game logic when upgrade menu is active
if (isUpgradeMenuActive) {
// Update camera to follow hero even during upgrade menu
updateCamera();
return;
}
// Initialize wave system on first update
if (waveStartTime === 0) {
waveStartTime = Date.now();
}
// Update wave timer
updateWaveTimer();
// Process analog movement
if (isJoystickActive && (Math.abs(movementX) > 0.1 || Math.abs(movementY) > 0.1)) {
hero.analogMove(movementX, movementY);
}
spawnTimer++;
// Wave-based enemy spawning
var maxEnemiesThisWave = baseEnemiesPerWave + (currentWave - 1) * 5;
var spawnRate = Math.max(60 - currentWave * 3, 15);
// Only spawn if we haven't reached the wave enemy limit
if (spawnTimer >= spawnRate && waveEnemyCount < maxEnemiesThisWave) {
spawnEnemy();
waveEnemyCount++;
spawnTimer = 0;
}
// Boss spawning for wave 1 and above
if (currentWave >= 1 && !bossSpawned && waveEnemyCount >= maxEnemiesThisWave / 2) {
var boss = new Boss();
// Spawn boss at random edge position
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
boss.x = Math.random() * 8192;
boss.y = -100;
break;
case 1:
// Right
boss.x = 8192 + 100;
boss.y = Math.random() * 10928;
break;
case 2:
// Bottom
boss.x = Math.random() * 8192;
boss.y = 10928 + 100;
break;
case 3:
// Left
boss.x = -100;
boss.y = Math.random() * 10928;
break;
}
enemies.push(boss);
game.addChild(boss);
bossSpawned = true;
// Boss spawn effects
LK.effects.flashScreen(0xFF0000, 1000);
}
// Update weapon to point towards nearest enemy
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var j = 0; j < enemies.length; j++) {
var tempEnemy = enemies[j];
var tempDx = hero.x - tempEnemy.x;
var tempDy = hero.y - tempEnemy.y;
var tempDistance = Math.sqrt(tempDx * tempDx + tempDy * tempDy);
if (tempDistance < nearestDistance) {
nearestEnemy = tempEnemy;
nearestDistance = tempDistance;
}
}
if (nearestEnemy) {
hero.updateWeapon(nearestEnemy.x, nearestEnemy.y);
// Auto-shoot while moving - shoot at nearest enemy every 40 ticks
var currentTime = LK.ticks;
if (currentTime - lastShootTime > 80 && nearestDistance < 800) {
hero.shoot(nearestEnemy.x, nearestEnemy.y);
lastShootTime = currentTime;
}
}
// Check bullet collisions with enemies
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
var bulletHit = false;
for (var e = enemies.length - 1; e >= 0; e--) {
var enemy = enemies[e];
if (bullet.intersects(enemy)) {
// Bullet hits enemy
enemy.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(b, 1);
bulletHit = true;
break;
}
}
}
// Check lightning bolt collisions with hero
for (var l = lightningBolts.length - 1; l >= 0; l--) {
var lightning = lightningBolts[l];
if (lightning.intersects(hero)) {
// Lightning hits hero
hero.takeDamage(lightning.damage);
LK.effects.flashObject(hero, 0xFFFF00, 300);
lightning.destroy();
lightningBolts.splice(l, 1);
}
}
// Clear all boss bullets (transfer to void)
for (var bb = boosAmmos.length - 1; bb >= 0; bb--) {
var boosAmmo = boosAmmos[bb];
// Transfer boss bullets to void (remove them)
boosAmmo.destroy();
boosAmmos.splice(bb, 1);
}
// Check collisions and close combat between hero and enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var dx = hero.x - enemy.x;
var dy = hero.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Auto-attack when very close (melee range)
if (distance < 60 && !enemy.justAttacked) {
hero.attack(enemy);
enemy.justAttacked = true;
// Reset attack flag after short delay
LK.setTimeout(function () {
if (enemy && !enemy.destroyed) {
enemy.justAttacked = false;
}
}, 300);
} else if (hero.intersects(enemy) && !enemy.justHitHero) {
// Take damage from collision but don't destroy enemy
hero.takeDamage(enemy.damage);
enemy.justHitHero = true;
// Reset hit flag after short delay to prevent rapid damage
LK.setTimeout(function () {
if (enemy && !enemy.destroyed) {
enemy.justHitHero = false;
}
}, 1000); // 1 second cooldown between hits
}
// Remove enemies that are too far off screen
if (enemy.x < -200 || enemy.x > 8392 || enemy.y < -200 || enemy.y > 11128) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Update health bar
updateHealthBar();
// Update level bar
updateLevelBar();
// Update boss health bar
updateBossHealthBar();
// Update camera to follow hero
updateCamera();
scoreTxt.setText(LK.getScore());
}; ===================================================================
--- original.js
+++ change.js
@@ -489,31 +489,74 @@
var lightningGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
- lightningGraphics.tint = 0xFFFF00; // Yellow lightning
- lightningGraphics.scaleX = 2;
- lightningGraphics.scaleY = 3;
- self.speed = 6;
- self.damage = 25;
+ lightningGraphics.tint = 0x00FFFF; // Electric cyan lightning
+ lightningGraphics.scaleX = 1.5;
+ lightningGraphics.scaleY = 4;
+ self.speed = 7;
+ self.damage = 30;
self.targetX = 0;
self.targetY = 0;
self.directionX = 0;
self.directionY = 0;
self.lifetime = 0;
- self.maxLifetime = 120; // 2 seconds at 60fps
- // Lightning crackling effect
+ self.maxLifetime = 180; // 3 seconds at 60fps
+ // Create electric aura effect
+ var auraGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ auraGraphics.tint = 0x4444FF; // Blue electric aura
+ auraGraphics.alpha = 0.4;
+ auraGraphics.scaleX = 3;
+ auraGraphics.scaleY = 6;
+ // Electric pulsing aura animation
+ tween(auraGraphics, {
+ scaleX: 4,
+ scaleY: 8,
+ alpha: 0.1
+ }, {
+ duration: 200,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(auraGraphics, {
+ scaleX: 2.5,
+ scaleY: 5,
+ alpha: 0.5
+ }, {
+ duration: 150,
+ easing: tween.easeInOut
+ });
+ }
+ });
+ // Enhanced lightning crackling effect with rapid flashing
tween(lightningGraphics, {
- alpha: 0.3
+ alpha: 0.2,
+ scaleX: 2.0,
+ scaleY: 5
}, {
- duration: 100,
+ duration: 80,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(lightningGraphics, {
- alpha: 1.0
+ alpha: 1.0,
+ scaleX: 1.2,
+ scaleY: 3.5
}, {
- duration: 100,
- easing: tween.easeInOut
+ duration: 60,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ // Continue crackling cycle
+ tween(lightningGraphics, {
+ alpha: 0.6,
+ scaleX: 1.8,
+ scaleY: 4.5
+ }, {
+ duration: 70,
+ easing: tween.easeInOut
+ });
+ }
});
}
});
self.setTarget = function (x, y) {
@@ -527,17 +570,26 @@
self.directionY = dy / distance;
}
// Rotate lightning to face direction
lightningGraphics.rotation = Math.atan2(dy, dx) + Math.PI / 2;
+ auraGraphics.rotation = lightningGraphics.rotation;
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
self.lifetime++;
- // Random flickering effect
- if (Math.random() < 0.3) {
- lightningGraphics.alpha = Math.random() * 0.5 + 0.5;
+ // Enhanced electric crackling with color shifts
+ if (Math.random() < 0.4) {
+ lightningGraphics.alpha = Math.random() * 0.7 + 0.3;
+ // Random electric color variations
+ var colorVariations = [0x00FFFF, 0x66CCFF, 0x0099FF, 0x33AAFF];
+ lightningGraphics.tint = colorVariations[Math.floor(Math.random() * colorVariations.length)];
}
+ // Electric spark effect - randomly adjust scale
+ if (Math.random() < 0.2) {
+ lightningGraphics.scaleX = 1.2 + Math.random() * 0.8;
+ lightningGraphics.scaleY = 3.5 + Math.random() * 1.5;
+ }
// Remove lightning after lifetime expires or goes off screen
if (self.lifetime > self.maxLifetime || self.x < -50 || self.x > 8242 || self.y < -50 || self.y > 10978) {
self.destroy();
for (var i = lightningBolts.length - 1; i >= 0; i--) {
Ucan bomba. In-Game asset. 2d. High contrast. No shadows
Qanli iskelet. In-Game asset. 2d. High contrast. No shadows
Beyaz zirhli sovalye. In-Game asset. 2d. High contrast. No shadows
Iskeleten Elektirik buycusu. In-Game asset. 2d. High contrast. No shadows
Wiking boss. In-Game asset. 2d. High contrast. No shadows
Mavi tatli kucuk slime gozleri parildasin. In-Game asset. 2d. High contrast. No shadows
Yesil top halinde tukuruk. In-Game asset. 2d. High contrast. No shadows
Simsek topu. In-Game asset. 2d. High contrast. No shadows
Sandik. In-Game asset. 2d. High contrast. No shadows
Ağac. In-Game asset. 2d. High contrast. No shadows
Cim yesilik. In-Game asset. 2d. High contrast. No shadows
Kamp atesi. In-Game asset. 2d. High contrast. No shadows
Madeni para. In-Game asset. 2d. High contrast. No shadows
Bullet. In-Game asset. 2d. High contrast. No shadows
Lasergun. In-Game asset. 2d. High contrast. No shadows