User prompt
Optimiza y soluciona errores para poder entrar a mi juego
User prompt
Optimiza soluciona errores
User prompt
Al boss le daré un nuevo ataque, y es que aparezca varias advertencias y aparezca un rayo lanzado por el jefe por 3 segundos, cuando el jefe esté a poca vida sucede esto, y también dale una textura a las balas qué dispara el player y una textura a los ataques del boss, y una textura a la pistola, y cuando el boss muera te de un arma que dispare 2 proyectiles, y que sus balas sean 6, y que tenga recarga ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Pero dale textura cuando se seleccione el muro o valla y también textura al botón cuando se selecciona una trampa, también una textura a los personajes al médico y al enginner
User prompt
Añadele textura a todos los botones al mando, la barra de vida del player y textura a cada botón y personaje, también una textura al boss
User prompt
Soluciona los errores optimiza y haz lo que te dije ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Chat al mando dale una textura y también dale una textura al jefe y también en el menú principal dale una textura a los botones, y textura a la barra de vida del player, y también dale una textura única a cada personaje, al médico y enginner
User prompt
Reduce el lag porque siempre en la noche 3 da muchísimo lag da tanto, y hazle una animación a los monstruos de correr y al player también, y que los proyectiles de balas que dispara el player qué sean más grandes que están muy pequeños, y que no aparezcan monstruos cuando esta el boss, solo cuando el boss tiene alguna habilidad de crear monstruos aparecen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que los monstruos corruptos cuando mueran se queden tirados en el suelo y desaparezcan en 2 segundos, y que no puedan seguir al player ni hacerle daño hasta que desaparezcan, y también añadele dos fondos, el primer fondo es en el día un fondo verde con pasto, y el otro es en la noche, un fondo verde oscuro y el pasto morado oscuro ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ahora en el boss, que la noche no se pase hasta matar al boss, y que tenga una barra de vida arriba, y añadele un ataque donde aparezca un símbolo de exclamacion (!) que indica que allí el boss atacara y que el boss ataque donde esta ese lugar, y que el boss aparezca en el medio, y que no se pueda mover solo hacer sus ataques ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que aparezca que al presionar un personaje o player tenga un respectivo color, por ejemplo el médico verde, el enginner azul y el warrior normal, cuando el warrior este apunto de morir qué tenga 30 de vida, active su modo berserk, que le otorga más velocidad que los enemigos se muevan lento, y más fuerza, con el medico que cuando este apunto de morir 30 de vida, su vida se restaure a 50 solo se puede usar una vez. Y que lance bombas que aturde al enemigo, y causan explosiones, y cuando tenga 30 de vida el enginner, el enginner qué le de más velocidad y que sus proyectiles sean más grandes. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Reduce la cantidad de monstruos que la inicio haigan 6 y ya después tus le aumentas la cantidad, y que en cada noche se aumente el tiempo de la noche, y que haiga una animación de correr y otra animación al matar un enemigo, y el botón de curar que no esté en el medio a un lado para que no moleste ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Para saber si seleccionaste ese personaje que cambie la apariencia, y para usar la habilidad del personaje médico que al pasar una noche aparezca un botón que diga curar y que cure 10 de vida, también que los personajes al disparar aparezca una pistola en la dirección donde se disparo en la mano del personaje ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ahora en el menú de personajes, que al presionar un personaje ese se seleccione para la partida, y que para matar un corrupto Swarm sea de un disparo, y para matar un corrupto scout sea de 2 tiros, y un corrupto tank sea de 3 tiros
User prompt
A partir de la noche 3 hay muchísimo lag reduce el lag, y también que haiga un menú principal donde aparezcan 2 botones, jugar y personajes, en el botón d e personajes que te lleve a otro menú donde estén 3 personajes, el primero que es el player principal, que haga un 30% más de daño, el segundo player o personaje, que se pueda curar un 10 de vida por cada noche, y el último personaje o player, que te permita que haiga un 20% menos de costo al comprar algún muro o algo así ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Ahora quita todos los botones y remplaza los por un mando
User prompt
Haz que los monstruos sean más grandes y los botones con su distancia también, y también que cuando se presione un botón y se mantenga presionado el player no pare de correr hasta que el botón deje de ser presionado
User prompt
Pero que los monstruos no puedan atravesar las vallas o muros a menos de que lo destruyan, y los botones hazlos GRANDES
User prompt
Arregla los errores y haz lo que te dije
User prompt
Si un monstruo golpea 3 veces una valla o muro se destruya, el monstruo cada dos segundos golpea, solo cuando esta cerca el player o ve un muro, y que cada noche aparezcan un poco más de enemigos
User prompt
Que al disparar 5 balas, ya no se pueda disparar y tiene que esperar 3 segundos para que se recargue el arma y pueda volver a disparar
User prompt
Pero que espere un segundo, y ya se pueda colocar objetos, que aparezca un contador en la pantalla, y disparar y esas cosas
User prompt
Al presionar un botón, se anule poner objetos, y cuando se deje de presionar se pueda colocar objetos
User prompt
Y que aigan más monedas
User prompt
Pero que los monstruos la pistola los mate de un disparo y que no aigan tantos monstruos
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
bombGraphics.tint = 0xFF0000; // Red bombs
self.speed = 6;
self.type = 'bomb';
self.direction = {
x: 0,
y: 0
};
self.explosionRadius = 120;
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Remove bomb if it goes off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === self) {
bombs.splice(i, 1);
break;
}
}
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('corruptedTank', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
bossGraphics.tint = 0x4a0080; // Darker purple for boss
self.health = 20;
self.maxHealth = 20;
self.speed = 0; // Boss doesn't move
self.damage = 30;
self.type = 'boss';
self.spawnTimer = 0;
self.attackTimer = 0;
self.attackWarning = null;
self.attackCooldown = 300; // 5 seconds between attacks
self.update = function () {
// Boss stays at center
self.x = 1024;
self.y = 1366;
// Attack system
self.attackTimer++;
if (self.attackTimer >= self.attackCooldown) {
self.attackTimer = 0;
// Create warning at player position
if (self.attackWarning) {
self.attackWarning.destroy();
}
self.attackWarning = game.addChild(new Text2('!', {
size: 200,
fill: 0xFF0000
}));
self.attackWarning.anchor.set(0.5, 0.5);
self.attackWarning.x = player.x;
self.attackWarning.y = player.y;
self.attackWarning.alpha = 1;
// Flash warning
tween(self.attackWarning, {
alpha: 0.3,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeInOut
});
// Attack after 2 seconds
LK.setTimeout(function () {
if (self.attackWarning) {
// Check if player is still in attack area
var dx = player.x - self.attackWarning.x;
var dy = player.y - self.attackWarning.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Player is in attack area, take damage
playerHealth -= self.damage;
healthText.setText('Health: ' + playerHealth);
LK.getSound('damage').play();
if (playerHealth <= 0) {
LK.showGameOver();
}
}
// Create explosion effect
LK.effects.flashObject(self.attackWarning, 0xFF6600, 500);
self.attackWarning.destroy();
self.attackWarning = null;
}
}, 2000);
}
// Spawn zombies every 10 seconds (600 frames at 60fps)
self.spawnTimer++;
if (self.spawnTimer >= 600) {
self.spawnTimer = 0;
// Spawn a zombie near the boss
var zombie = new CorruptedScout();
zombie.x = self.x + (Math.random() - 0.5) * 200;
zombie.y = self.y + (Math.random() - 0.5) * 200;
zombie.health = 15; // Weaker zombies
monsters.push(zombie);
game.addChild(zombie);
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
bulletGraphics.tint = 0xffff00; // Yellow bullets
self.speed = 8;
self.damage = 1;
self.type = 'bullet';
self.direction = {
x: 0,
y: 0
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Remove bullet if it goes off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
}
};
return self;
});
var CorruptedScout = Container.expand(function () {
var self = Container.call(this);
var scoutGraphics = self.attachAsset('corruptedScout', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.maxHealth = 2;
self.speed = 2;
self.damage = 10;
self.type = 'scout';
self.isDead = false;
self.deadTimer = 0;
self.update = function () {
if (self.isDead) {
self.deadTimer++;
if (self.deadTimer >= 120) {
// 2 seconds at 60fps
self.destroy();
for (var i = monsters.length - 1; i >= 0; i--) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
}
return;
}
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Calculate intended next position
var nextX = self.x + dx / distance * self.speed;
var nextY = self.y + dy / distance * self.speed;
var blocked = false;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (wall.health > 0) {
// Simulate monster at next position
var tempDist = Math.sqrt((nextX - wall.x) * (nextX - wall.x) + (nextY - wall.y) * (nextY - wall.y));
if (tempDist < 50) {
blocked = true;
break;
}
}
}
if (!blocked) {
self.x = nextX;
self.y = nextY;
}
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
self.isDead = true;
self.alpha = 0.5;
scoutGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
return self;
});
var CorruptedSwarm = Container.expand(function () {
var self = Container.call(this);
var swarmGraphics = self.attachAsset('corruptedSwarm', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.maxHealth = 1;
self.speed = 3;
self.damage = 5;
self.type = 'swarm';
self.isDead = false;
self.deadTimer = 0;
self.update = function () {
if (self.isDead) {
self.deadTimer++;
if (self.deadTimer >= 120) {
// 2 seconds at 60fps
self.destroy();
for (var i = monsters.length - 1; i >= 0; i--) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
}
return;
}
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Calculate intended next position
var nextX = self.x + dx / distance * self.speed;
var nextY = self.y + dy / distance * self.speed;
var blocked = false;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (wall.health > 0) {
var tempDist = Math.sqrt((nextX - wall.x) * (nextX - wall.x) + (nextY - wall.y) * (nextY - wall.y));
if (tempDist < 50) {
blocked = true;
break;
}
}
}
if (!blocked) {
self.x = nextX;
self.y = nextY;
}
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
self.isDead = true;
self.alpha = 0.5;
swarmGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
return self;
});
var CorruptedTank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('corruptedTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 1;
self.damage = 25;
self.type = 'tank';
self.isDead = false;
self.deadTimer = 0;
self.update = function () {
if (self.isDead) {
self.deadTimer++;
if (self.deadTimer >= 120) {
// 2 seconds at 60fps
self.destroy();
for (var i = monsters.length - 1; i >= 0; i--) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
}
return;
}
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Calculate intended next position
var nextX = self.x + dx / distance * self.speed;
var nextY = self.y + dy / distance * self.speed;
var blocked = false;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (wall.health > 0) {
var tempDist = Math.sqrt((nextX - wall.x) * (nextX - wall.x) + (nextY - wall.y) * (nextY - wall.y));
if (tempDist < 50) {
blocked = true;
break;
}
}
}
if (!blocked) {
self.x = nextX;
self.y = nextY;
}
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
self.isDead = true;
self.alpha = 0.5;
tankGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
return self;
});
var Resource = Container.expand(function () {
var self = Container.call(this);
var resourceGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.type = 'resource';
self.update = function () {
self.rotation += 0.05;
};
return self;
});
var Trap = Container.expand(function () {
var self = Container.call(this);
var trapGraphics = self.attachAsset('trap', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 30;
self.cooldown = 0;
self.type = 'trap';
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
}
};
self.activate = function () {
if (self.cooldown <= 0) {
self.cooldown = 60;
LK.effects.flashObject(self, 0xff6b35, 300);
return self.damage;
}
return 0;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.type = 'wall';
// Track monster hits
self.hitCount = 0;
self.lastMonsterHitTick = 0; // LK.ticks of last monster hit
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
wallGraphics.alpha = 0.3;
} else {
wallGraphics.alpha = 0.5 + self.health / self.maxHealth * 0.5;
}
};
self.registerMonsterHit = function () {
self.hitCount++;
self.lastMonsterHitTick = LK.ticks;
if (self.hitCount >= 3) {
self.health = 0;
wallGraphics.alpha = 0.3;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Add backgrounds
var dayBackground = game.addChild(LK.getAsset('dayBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
dayBackground.alpha = 1;
var nightBackground = game.addChild(LK.getAsset('nightBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
nightBackground.alpha = 0;
var gameState = 'mainMenu'; // Start with main menu
var currentNight = 0;
var dayTimer = 1800; // 30 seconds at 60fps
var nightTimer = 0;
var playerHealth = 100;
var playerResources = 50;
var selectedDefense = 'wall';
var walls = [];
var traps = [];
var resources = [];
var monsters = [];
var boss = null;
var bullets = [];
var bombs = [];
var playerPistol = true; // Player has pistol
var pistolBullets = 5; // Bullets left before reload
var pistolReloading = false; // Is pistol reloading
var pistolReloadTimer = 0; // Frames left for reload (180 = 3s)
var selectedCharacter = storage.selectedCharacter || 0; // 0=damage, 1=heal, 2=discount
var characterStats = {
damageMultiplier: selectedCharacter === 0 ? 1.3 : 1.0,
healPerNight: selectedCharacter === 1 ? 10 : 0,
discountMultiplier: selectedCharacter === 2 ? 0.8 : 1.0
};
// Special ability states
var berserkMode = false;
var berserkUsed = false;
var medicReviveUsed = false;
var engineerBoostActive = false;
var engineerBoostUsed = false;
var slowEnemiesActive = false;
var slowEnemiesTimer = 0;
// Heal button for medic character
var healButton = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: -250,
y: 0,
scaleX: 3,
scaleY: 3
});
healButton.tint = 0x00FF00;
healButton.alpha = 0;
var healButtonText = new Text2('HEAL', {
size: 60,
fill: 0xFFFFFF
});
healButtonText.anchor.set(0.5, 0.5);
healButtonText.x = -250;
healButtonText.y = 0;
healButtonText.alpha = 0;
LK.gui.center.addChild(healButton);
LK.gui.center.addChild(healButtonText);
var pistolReloadText = new Text2('', {
size: 80,
fill: 0xFF0000
});
pistolReloadText.anchor.set(0.5, 0.5);
pistolReloadText.x = 0;
pistolReloadText.y = 200;
pistolReloadText.alpha = 0;
LK.gui.center.addChild(pistolReloadText);
// Main Menu UI
var mainMenuContainer = new Container();
var mainMenuTitle = new Text2('SURVIVAL GAME', {
size: 120,
fill: 0xFFFFFF
});
mainMenuTitle.anchor.set(0.5, 0.5);
mainMenuTitle.x = 0;
mainMenuTitle.y = -300;
mainMenuContainer.addChild(mainMenuTitle);
var playButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -100,
scaleX: 4,
scaleY: 2
});
var playButtonText = new Text2('PLAY', {
size: 80,
fill: 0xFFFFFF
});
playButtonText.anchor.set(0.5, 0.5);
playButtonText.x = 0;
playButtonText.y = -100;
mainMenuContainer.addChild(playButton);
mainMenuContainer.addChild(playButtonText);
var charactersButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 50,
scaleX: 4,
scaleY: 2
});
var charactersButtonText = new Text2('CHARACTERS', {
size: 80,
fill: 0xFFFFFF
});
charactersButtonText.anchor.set(0.5, 0.5);
charactersButtonText.x = 0;
charactersButtonText.y = 50;
mainMenuContainer.addChild(charactersButton);
mainMenuContainer.addChild(charactersButtonText);
LK.gui.center.addChild(mainMenuContainer);
// Character Selection UI
var characterMenuContainer = new Container();
var characterMenuTitle = new Text2('SELECT CHARACTER', {
size: 100,
fill: 0xFFFFFF
});
characterMenuTitle.anchor.set(0.5, 0.5);
characterMenuTitle.x = 0;
characterMenuTitle.y = -400;
characterMenuContainer.addChild(characterMenuTitle);
// Character 1 - Damage
var char1Button = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -100,
scaleX: 2,
scaleY: 2
});
var char1Text = new Text2('WARRIOR\n+30% Damage', {
size: 50,
fill: 0xFFFFFF
});
char1Text.anchor.set(0.5, 0.5);
char1Text.x = -300;
char1Text.y = 50;
characterMenuContainer.addChild(char1Button);
characterMenuContainer.addChild(char1Text);
// Character 2 - Heal
var char2Button = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -100,
scaleX: 2,
scaleY: 2
});
char2Button.tint = 0x00FF00;
var char2Text = new Text2('MEDIC\n+10 Health\nper Night', {
size: 50,
fill: 0xFFFFFF
});
char2Text.anchor.set(0.5, 0.5);
char2Text.x = 0;
char2Text.y = 50;
characterMenuContainer.addChild(char2Button);
characterMenuContainer.addChild(char2Text);
// Character 3 - Discount
var char3Button = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: -100,
scaleX: 2,
scaleY: 2
});
char3Button.tint = 0x0000FF;
var char3Text = new Text2('ENGINEER\n-20% Build\nCost', {
size: 50,
fill: 0xFFFFFF
});
// Set initial character selection visual state
if (selectedCharacter === 0) {
char1Button.tint = 0x00FF00;
} else if (selectedCharacter === 1) {
char2Button.tint = 0x00FF00;
} else if (selectedCharacter === 2) {
char3Button.tint = 0x00FF00;
}
char3Text.anchor.set(0.5, 0.5);
char3Text.x = 300;
char3Text.y = 50;
characterMenuContainer.addChild(char3Button);
characterMenuContainer.addChild(char3Text);
var backButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 300,
scaleX: 3,
scaleY: 2
});
var backButtonText = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 0;
backButtonText.y = 300;
characterMenuContainer.addChild(backButton);
characterMenuContainer.addChild(backButtonText);
characterMenuContainer.alpha = 0;
LK.gui.center.addChild(characterMenuContainer);
var player = game.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Apply character colors
if (selectedCharacter === 1) {
player.tint = 0x00FF00; // Green for medic
} else if (selectedCharacter === 2) {
player.tint = 0x0000FF; // Blue for engineer
} else {
player.tint = 0xFFFFFF; // White for warrior
}
// Button visibility is now handled by the UI buttons
disablePlacement = false;
var gameStateText = new Text2('Day Phase', {
size: 80,
fill: 0xFFFFFF
});
gameStateText.anchor.set(0.5, 0);
LK.gui.top.addChild(gameStateText);
var timerText = new Text2('30s', {
size: 60,
fill: 0xFFFF00
});
timerText.anchor.set(0.5, 0);
timerText.y = 100;
LK.gui.top.addChild(timerText);
var healthText = new Text2('Health: 100', {
size: 50,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120;
var resourceText = new Text2('Resources: 50', {
size: 50,
fill: 0xFFD700
});
resourceText.anchor.set(0, 0);
resourceText.y = 60;
LK.gui.topLeft.addChild(resourceText);
resourceText.x = 120;
var nightText = new Text2('Night: 0', {
size: 50,
fill: 0x8B3A8B
});
nightText.anchor.set(1, 0);
LK.gui.topRight.addChild(nightText);
// Boss health bar UI elements
var bossHealthBar = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 150,
scaleX: 10,
scaleY: 1
});
bossHealthBar.tint = 0x333333;
bossHealthBar.alpha = 0;
LK.gui.top.addChild(bossHealthBar);
var bossHealthBarFill = LK.getAsset('wall', {
anchorX: 0.0,
anchorY: 0.5,
x: -300,
y: 150,
scaleX: 10,
scaleY: 1
});
bossHealthBarFill.tint = 0xFF0000;
bossHealthBarFill.alpha = 0;
LK.gui.top.addChild(bossHealthBarFill);
var bossHealthText = new Text2('BOSS', {
size: 50,
fill: 0xFF0000
});
bossHealthText.anchor.set(0.5, 0.5);
bossHealthText.x = 0;
bossHealthText.y = 100;
bossHealthText.alpha = 0;
LK.gui.top.addChild(bossHealthText);
// Joystick control elements
var joystickBase = LK.getAsset('corruptedScout', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: -300,
scaleX: 2.5,
scaleY: 2.5
});
joystickBase.alpha = 0.5;
LK.gui.bottomLeft.addChild(joystickBase);
var joystickKnob = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: -300,
scaleX: 1.5,
scaleY: 1.5
});
joystickKnob.tint = 0xFFFFFF;
LK.gui.bottomLeft.addChild(joystickKnob);
var joystickActive = false;
var joystickCenterX = 200;
var joystickCenterY = -300;
var joystickRadius = 60;
var defenseText = new Text2('Defense: Wall (Cost: 10)', {
size: 40,
fill: 0xFFFFFF
});
defenseText.anchor.set(0.5, 1);
defenseText.y = -120;
defenseText.alpha = 0;
LK.gui.bottom.addChild(defenseText);
// Action buttons on the right side
var wallButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -200,
scaleX: 2.5,
scaleY: 2.5
});
LK.gui.bottomRight.addChild(wallButton);
var trapButton = LK.getAsset('trap', {
anchorX: 0.5,
anchorY: 0.5,
x: -150,
y: -200,
scaleX: 2.5,
scaleY: 2.5
});
LK.gui.bottomRight.addChild(trapButton);
var collectButton = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -350,
scaleX: 2.5,
scaleY: 2.5
});
LK.gui.bottomRight.addChild(collectButton);
var wallButtonText = new Text2('W', {
size: 40,
fill: 0xFFFFFF
});
wallButtonText.anchor.set(0.5, 0.5);
wallButtonText.x = -300;
wallButtonText.y = -200;
LK.gui.bottomRight.addChild(wallButtonText);
var trapButtonText = new Text2('T', {
size: 40,
fill: 0xFFFFFF
});
trapButtonText.anchor.set(0.5, 0.5);
trapButtonText.x = -150;
trapButtonText.y = -200;
LK.gui.bottomRight.addChild(trapButtonText);
var collectButtonText = new Text2('C', {
size: 40,
fill: 0xFFFFFF
});
collectButtonText.anchor.set(0.5, 0.5);
collectButtonText.x = -300;
collectButtonText.y = -350;
LK.gui.bottomRight.addChild(collectButtonText);
// Movement control variables
var moveX = 0;
var moveY = 0;
var playerSpeed = 5;
// Pistol graphics
var pistolGraphics = null;
var pistolTimer = 0;
// Game mode state
var gameMode = 'build'; // 'build' or 'collect'
var disablePlacement = false; // Prevents placing objects while a button is pressed
var placementCooldown = 0; // Frames left for placement cooldown (60 = 1s)
// Update UI visibility based on game state
function updateUIVisibility() {
if (gameState === 'mainMenu') {
mainMenuContainer.alpha = 1;
characterMenuContainer.alpha = 0;
gameStateText.alpha = 0;
timerText.alpha = 0;
healthText.alpha = 0;
resourceText.alpha = 0;
nightText.alpha = 0;
joystickBase.alpha = 0;
joystickKnob.alpha = 0;
wallButton.alpha = 0;
trapButton.alpha = 0;
collectButton.alpha = 0;
wallButtonText.alpha = 0;
trapButtonText.alpha = 0;
collectButtonText.alpha = 0;
defenseText.alpha = 0;
healButton.alpha = 0;
healButtonText.alpha = 0;
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
} else if (gameState === 'characterSelect') {
mainMenuContainer.alpha = 0;
characterMenuContainer.alpha = 1;
gameStateText.alpha = 0;
timerText.alpha = 0;
healthText.alpha = 0;
resourceText.alpha = 0;
nightText.alpha = 0;
joystickBase.alpha = 0;
joystickKnob.alpha = 0;
wallButton.alpha = 0;
trapButton.alpha = 0;
collectButton.alpha = 0;
wallButtonText.alpha = 0;
trapButtonText.alpha = 0;
collectButtonText.alpha = 0;
defenseText.alpha = 0;
healButton.alpha = 0;
healButtonText.alpha = 0;
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
} else {
mainMenuContainer.alpha = 0;
characterMenuContainer.alpha = 0;
gameStateText.alpha = 1;
timerText.alpha = 1;
healthText.alpha = 1;
resourceText.alpha = 1;
nightText.alpha = 1;
joystickBase.alpha = 0.5;
joystickKnob.alpha = 1;
wallButton.alpha = 1;
trapButton.alpha = 1;
collectButton.alpha = 1;
wallButtonText.alpha = 1;
trapButtonText.alpha = 1;
collectButtonText.alpha = 1;
defenseText.alpha = gameState === 'day' ? 1 : 0;
}
}
updateUIVisibility();
var placementCooldownText = new Text2('', {
size: 80,
fill: 0xFF0000
});
placementCooldownText.anchor.set(0.5, 0.5);
placementCooldownText.x = 0;
placementCooldownText.y = 0;
placementCooldownText.alpha = 0;
LK.gui.center.addChild(placementCooldownText);
// Spawn initial resources
for (var i = 0; i < 18; i++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 1200;
resources.push(resource);
game.addChild(resource);
}
function spawnMonster(type) {
var monster;
switch (type) {
case 'scout':
monster = new CorruptedScout();
break;
case 'tank':
monster = new CorruptedTank();
break;
case 'swarm':
monster = new CorruptedSwarm();
break;
default:
monster = new CorruptedScout();
}
// Spawn from edges
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
monster.x = Math.random() * 2048;
monster.y = -50;
break;
case 1:
// Right
monster.x = 2098;
monster.y = Math.random() * 2732;
break;
case 2:
// Bottom
monster.x = Math.random() * 2048;
monster.y = 2782;
break;
case 3:
// Left
monster.x = -50;
monster.y = Math.random() * 2732;
break;
}
monsters.push(monster);
game.addChild(monster);
}
function switchToNight() {
gameState = 'night';
currentNight++;
nightTimer = 1800 + (currentNight - 1) * 600; // Base 30s + 10s per night
gameStateText.setText('Night ' + currentNight);
timerText.setText(Math.ceil(nightTimer / 60) + 's');
nightText.setText('Night: ' + currentNight);
// Switch to night background
dayBackground.alpha = 0;
nightBackground.alpha = 1;
LK.playMusic('nightfall');
defenseText.setText('Night Phase - Survive!');
// Show heal button for medic character
if (characterStats.healPerNight > 0 && currentNight > 0) {
healButton.alpha = 1;
healButtonText.alpha = 1;
}
// Spawn initial monsters for the night - start with 6 and increase gradually
var initialMonsters = 6 + Math.floor(currentNight * 0.8); // Start with 6, increase gradually
for (var i = 0; i < initialMonsters; i++) {
spawnMonster('scout'); // Start with scouts for the initial wave
}
// Spawn boss every 3rd night
if (currentNight % 3 === 0 && boss === null) {
boss = new Boss();
// Spawn boss at center
boss.x = 1024;
boss.y = 1366;
game.addChild(boss);
// Show boss health bar
bossHealthBar.alpha = 1;
bossHealthBarFill.alpha = 1;
bossHealthText.alpha = 1;
}
}
function switchToDay() {
gameState = 'day';
dayTimer = 1800; // 30 seconds
gameStateText.setText('Day Phase');
timerText.setText('30s');
// Switch to day background
dayBackground.alpha = 1;
nightBackground.alpha = 0;
LK.stopMusic();
// Reset to default mode
gameMode = 'build';
selectedDefense = 'wall';
defenseText.setText('Defense: Wall (Cost: 10)');
wallButtonText.tint = 0x00FF00;
trapButtonText.tint = 0xFFFFFF;
collectButtonText.tint = 0xFFFFFF;
// Spawn new resources
for (var i = 0; i < 12; i++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 1200;
resources.push(resource);
game.addChild(resource);
}
}
// Joystick movement handler
function updateJoystick(x, y) {
var dx = x - joystickCenterX;
var dy = y - joystickCenterY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > joystickRadius) {
dx = dx / distance * joystickRadius;
dy = dy / distance * joystickRadius;
}
joystickKnob.x = joystickCenterX + dx;
joystickKnob.y = joystickCenterY + dy;
// Calculate movement values (-1 to 1)
moveX = dx / joystickRadius;
moveY = dy / joystickRadius;
}
function resetJoystick() {
joystickKnob.x = joystickCenterX;
joystickKnob.y = joystickCenterY;
moveX = 0;
moveY = 0;
joystickActive = false;
}
// Action button handlers
wallButton.down = function (x, y, obj) {
if (gameState === 'day') {
selectedDefense = 'wall';
gameMode = 'build';
defenseText.setText('Defense: Wall (Cost: 10)');
wallButtonText.tint = 0x00FF00;
trapButtonText.tint = 0xFFFFFF;
collectButtonText.tint = 0xFFFFFF;
}
disablePlacement = true;
placementCooldown = 60;
placementCooldownText.alpha = 1;
placementCooldownText.setText('1');
};
trapButton.down = function (x, y, obj) {
if (gameState === 'day') {
selectedDefense = 'trap';
gameMode = 'build';
defenseText.setText('Defense: Trap (Cost: 15)');
wallButtonText.tint = 0xFFFFFF;
trapButtonText.tint = 0x00FF00;
collectButtonText.tint = 0xFFFFFF;
}
disablePlacement = true;
placementCooldown = 60;
placementCooldownText.alpha = 1;
placementCooldownText.setText('1');
};
collectButton.down = function (x, y, obj) {
if (gameState === 'day') {
gameMode = 'collect';
defenseText.setText('Mode: Resource Collection');
wallButtonText.tint = 0xFFFFFF;
trapButtonText.tint = 0xFFFFFF;
collectButtonText.tint = 0x00FF00;
}
disablePlacement = true;
placementCooldown = 60;
placementCooldownText.alpha = 1;
placementCooldownText.setText('1');
};
// Joystick event handlers
game.down = function (x, y, obj) {
if (gameState === 'mainMenu') {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
// Check play button
if (local.x >= -200 && local.x <= 200 && local.y >= -150 && local.y <= -50) {
gameState = 'day';
updateUIVisibility();
return;
}
// Check characters button
if (local.x >= -200 && local.x <= 200 && local.y >= 0 && local.y <= 100) {
gameState = 'characterSelect';
updateUIVisibility();
return;
}
return;
}
if (gameState === 'characterSelect') {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
// Check character 1
if (local.x >= -400 && local.x <= -200 && local.y >= -200 && local.y <= 0) {
selectedCharacter = 0;
storage.selectedCharacter = 0;
characterStats.damageMultiplier = 1.3;
characterStats.healPerNight = 0;
characterStats.discountMultiplier = 1.0;
// Update character appearance
char1Button.tint = 0xFFFFFF;
char2Button.tint = 0x00FF00;
char3Button.tint = 0x0000FF;
// Apply character color to player
player.tint = 0xFFFFFF; // White for warrior
gameState = 'day';
updateUIVisibility();
return;
}
// Check character 2
if (local.x >= -100 && local.x <= 100 && local.y >= -200 && local.y <= 0) {
selectedCharacter = 1;
storage.selectedCharacter = 1;
characterStats.damageMultiplier = 1.0;
characterStats.healPerNight = 10;
characterStats.discountMultiplier = 1.0;
// Update character appearance
char1Button.tint = 0xFFFFFF;
char2Button.tint = 0x00FF00;
char3Button.tint = 0x0000FF;
// Apply character color to player
player.tint = 0x00FF00; // Green for medic
gameState = 'day';
updateUIVisibility();
return;
}
// Check character 3
if (local.x >= 200 && local.x <= 400 && local.y >= -200 && local.y <= 0) {
selectedCharacter = 2;
storage.selectedCharacter = 2;
characterStats.damageMultiplier = 1.0;
characterStats.healPerNight = 0;
characterStats.discountMultiplier = 0.8;
// Update character appearance
char1Button.tint = 0xFFFFFF;
char2Button.tint = 0x00FF00;
char3Button.tint = 0x0000FF;
// Apply character color to player
player.tint = 0x0000FF; // Blue for engineer
gameState = 'day';
updateUIVisibility();
return;
}
// Check back button
if (local.x >= -150 && local.x <= 150 && local.y >= 250 && local.y <= 350) {
gameState = 'mainMenu';
updateUIVisibility();
return;
}
return;
}
// Check if touch is on joystick base
var local = LK.gui.bottomLeft.toLocal({
x: x,
y: y
}, game);
var dx = local.x - joystickCenterX;
var dy = local.y - joystickCenterY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= joystickRadius + 30) {
joystickActive = true;
updateJoystick(local.x, local.y);
return;
}
// Check if touch is on joystick base
var local = LK.gui.bottomLeft.toLocal({
x: x,
y: y
}, game);
var dx = local.x - joystickCenterX;
var dy = local.y - joystickCenterY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= joystickRadius + 30) {
joystickActive = true;
updateJoystick(local.x, local.y);
return;
}
// Check heal button
if (healButton.alpha > 0) {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
if (local.x >= -370 && local.x <= -130 && local.y >= -120 && local.y <= 120) {
playerHealth = Math.min(100, playerHealth + characterStats.healPerNight);
healthText.setText('Health: ' + playerHealth);
healButton.alpha = 0;
healButtonText.alpha = 0;
LK.getSound('collect').play();
return;
}
}
if (disablePlacement) {
return; // Prevent placing objects while a button is pressed
}
if (gameState === 'day') {
if (gameMode === 'build') {
var baseCost = selectedDefense === 'wall' ? 10 : 15;
var cost = Math.floor(baseCost * characterStats.discountMultiplier);
if (playerResources >= cost) {
var defense;
if (selectedDefense === 'wall') {
defense = new Wall();
} else {
defense = new Trap();
}
defense.x = x;
defense.y = y;
if (selectedDefense === 'wall') {
walls.push(defense);
} else {
traps.push(defense);
}
game.addChild(defense);
playerResources -= cost;
resourceText.setText('Resources: ' + playerResources);
LK.getSound('build').play();
}
} else if (gameMode === 'collect') {
// Enhanced resource collection in collect mode
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
var dx = x - resource.x;
var dy = y - resource.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
playerResources += resource.value;
resourceText.setText('Resources: ' + playerResources);
resource.destroy();
resources.splice(i, 1);
LK.getSound('collect').play();
break;
}
}
}
} else if (gameState === 'night' && playerPistol && !pistolReloading && pistolBullets > 0) {
// Shoot bullet or bomb towards click position
var projectile;
if (selectedCharacter === 1) {
// Medic shoots bombs
projectile = new Bomb();
} else {
// Others shoot bullets
projectile = new Bullet();
}
projectile.x = player.x;
projectile.y = player.y;
// Calculate direction to target
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
projectile.direction.x = dx / distance;
projectile.direction.y = dy / distance;
if (selectedCharacter === 1) {
bombs.push(projectile);
} else {
bullets.push(projectile);
}
game.addChild(projectile);
// Create pistol graphics
if (pistolGraphics) {
pistolGraphics.destroy();
}
pistolGraphics = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.2
}));
pistolGraphics.tint = 0x888888;
pistolGraphics.x = player.x + dx / distance * 40;
pistolGraphics.y = player.y + dy / distance * 40;
pistolGraphics.rotation = Math.atan2(dy, dx);
pistolTimer = 20; // Show pistol for 20 frames
// Animate pistol with tween
tween(pistolGraphics, {
scaleX: 0.7,
scaleY: 0.3
}, {
duration: 100,
easing: tween.easeOut
});
tween(pistolGraphics, {
scaleX: 0.5,
scaleY: 0.2
}, {
duration: 100,
easing: tween.easeIn
});
LK.getSound('shoot').play();
pistolBullets--;
if (pistolBullets === 0) {
pistolReloading = true;
pistolReloadTimer = 180; // 3 seconds at 60fps
pistolReloadText.alpha = 1;
pistolReloadText.setText('Reloading...');
}
}
};
game.move = function (x, y, obj) {
if (joystickActive) {
var local = LK.gui.bottomLeft.toLocal({
x: x,
y: y
}, game);
updateJoystick(local.x, local.y);
}
};
game.up = function (x, y, obj) {
if (joystickActive) {
resetJoystick();
}
};
game.update = function () {
// Skip game logic if in menu states
if (gameState === 'mainMenu' || gameState === 'characterSelect') {
return;
}
// Handle joystick movement
if (Math.abs(moveX) > 0.1 || Math.abs(moveY) > 0.1) {
player.x = Math.max(50, Math.min(1998, player.x + moveX * playerSpeed));
player.y = Math.max(50, Math.min(2682, player.y + moveY * playerSpeed));
// Running animation - scale player slightly and add rotation
tween(player, {
scaleX: 1.1,
scaleY: 0.9,
rotation: moveX * 0.1
}, {
duration: 100,
easing: tween.easeOut
});
tween(player, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 100,
easing: tween.easeIn
});
}
// Handle pistol reload timer
if (pistolReloading) {
pistolReloadTimer--;
pistolReloadText.alpha = 1;
pistolReloadText.setText('Reload: ' + Math.ceil(pistolReloadTimer / 60) + 's');
if (pistolReloadTimer <= 0) {
pistolReloading = false;
pistolBullets = 5;
pistolReloadText.alpha = 0;
}
}
// Handle pistol graphics timer
if (pistolTimer > 0) {
pistolTimer--;
if (pistolTimer <= 0 && pistolGraphics) {
pistolGraphics.destroy();
pistolGraphics = null;
}
}
// Placement cooldown logic
if (placementCooldown > 0) {
placementCooldown--;
if (placementCooldown > 0) {
placementCooldownText.alpha = 1;
placementCooldownText.setText('' + Math.ceil(placementCooldown / 60));
disablePlacement = true;
} else {
placementCooldownText.alpha = 0;
disablePlacement = false;
}
}
if (gameState === 'day') {
dayTimer--;
timerText.setText(Math.ceil(dayTimer / 60) + 's');
if (dayTimer <= 0) {
switchToNight();
}
// Resource collection
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
var dx = player.x - resource.x;
var dy = player.y - resource.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 60) {
playerResources += resource.value;
resourceText.setText('Resources: ' + playerResources);
resource.destroy();
resources.splice(i, 1);
LK.getSound('collect').play();
}
}
} else if (gameState === 'night') {
nightTimer--;
timerText.setText(Math.ceil(nightTimer / 60) + 's');
// Spawn monsters with reduced lag from night 3 onwards
var spawnRate = currentNight >= 3 ? 150 : 90; // Reduce spawn rate after night 3
var maxMonsters = currentNight >= 3 ? Math.min(8, 6 + Math.floor(currentNight * 0.5)) : 10 + Math.floor(currentNight * 1.2); // Cap monsters at 8 from night 3
if (LK.ticks % spawnRate === 0 && monsters.length < maxMonsters) {
var monsterTypes = ['scout', 'tank', 'swarm'];
var type = monsterTypes[Math.floor(Math.random() * monsterTypes.length)];
spawnMonster(type);
}
// Handle slow enemies timer
if (slowEnemiesTimer > 0) {
slowEnemiesTimer--;
if (slowEnemiesTimer <= 0) {
slowEnemiesActive = false;
}
}
// Monster AI and collision
for (var i = monsters.length - 1; i >= 0; i--) {
var monster = monsters[i];
// Skip dead monsters for collision and movement
if (monster.isDead) {
continue;
}
// Apply slow effect if active
var originalSpeed = monster.speed;
if (slowEnemiesActive) {
monster.speed = originalSpeed * 0.3; // 70% slower
}
// Check collision with player
var dx = player.x - monster.x;
var dy = player.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50) {
playerHealth -= monster.damage;
healthText.setText('Health: ' + playerHealth);
monster.destroy();
monsters.splice(i, 1);
LK.getSound('damage').play();
// Check for special abilities when health drops to 30
if (playerHealth <= 30) {
if (selectedCharacter === 0 && !berserkUsed) {
// Warrior berserk mode
berserkMode = true;
berserkUsed = true;
playerSpeed = 8; // Increased speed
characterStats.damageMultiplier = 2.0; // Double damage
slowEnemiesActive = true;
slowEnemiesTimer = 600; // 10 seconds
LK.effects.flashScreen(0xFF0000, 1000); // Red flash
} else if (selectedCharacter === 1 && !medicReviveUsed) {
// Medic auto-heal
playerHealth = 50;
medicReviveUsed = true;
healthText.setText('Health: ' + playerHealth);
LK.effects.flashScreen(0x00FF00, 1000); // Green flash
} else if (selectedCharacter === 2 && !engineerBoostUsed) {
// Engineer boost
engineerBoostActive = true;
engineerBoostUsed = true;
playerSpeed = 7; // Increased speed
LK.effects.flashScreen(0x0000FF, 1000); // Blue flash
}
}
if (playerHealth <= 0) {
LK.showGameOver();
}
continue;
}
// Check collision with walls
var hitWall = false;
for (var j = 0; j < walls.length; j++) {
var wall = walls[j];
if (wall.health > 0 && !monster.isDead && monster.intersects(wall)) {
// Monster only attacks wall every 2 seconds (120 ticks)
// Only if player is within 300px or monster is within 300px of wall (simulate "seeing" wall)
var playerDist = Math.sqrt((player.x - monster.x) * (player.x - monster.x) + (player.y - monster.y) * (player.y - monster.y));
var wallDist = Math.sqrt((wall.x - monster.x) * (wall.x - monster.x) + (wall.y - monster.y) * (wall.y - monster.y));
if (playerDist < 300 || wallDist < 300) {
if (LK.ticks - wall.lastMonsterHitTick >= 120) {
wall.registerMonsterHit();
wall.takeDamage(monster.damage);
LK.effects.flashObject(wall, 0xff0000, 200);
// If wall is destroyed after 3 hits, set health to 0 and alpha to 0.3
if (wall.hitCount >= 3 || wall.health <= 0) {
wall.health = 0;
wall.alpha = 0.3;
}
}
}
// Monster stays and keeps attacking, do not destroy monster
hitWall = true;
break;
}
}
if (hitWall) continue;
// Check collision with traps
for (var k = 0; k < traps.length; k++) {
var trap = traps[k];
if (!monster.isDead && monster.intersects(trap)) {
var trapDamage = trap.activate();
if (trapDamage > 0) {
var isDead = monster.takeDamage(trapDamage);
if (isDead) {
LK.setScore(LK.getScore() + 10);
break;
}
}
}
}
}
// Handle boss combat
if (boss !== null) {
// Update boss health bar
var healthPercent = boss.health / boss.maxHealth;
bossHealthBarFill.scaleX = 10 * healthPercent;
bossHealthText.setText('BOSS: ' + boss.health + '/' + boss.maxHealth);
}
// Handle bomb collisions and explosions
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
var bombHit = false;
// Check collision with monsters
for (var j = monsters.length - 1; j >= 0; j--) {
var monster = monsters[j];
var dx = bomb.x - monster.x;
var dy = bomb.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
// Create explosion effect
LK.effects.flashObject(bomb, 0xFF6600, 500);
// Stun and damage all monsters within explosion radius
for (var k = monsters.length - 1; k >= 0; k--) {
var targetMonster = monsters[k];
var expDx = bomb.x - targetMonster.x;
var expDy = bomb.y - targetMonster.y;
var expDistance = Math.sqrt(expDx * expDx + expDy * expDy);
if (expDistance < bomb.explosionRadius) {
var isDead = targetMonster.takeDamage(2);
// Stun effect - reduce speed temporarily
targetMonster.speed = targetMonster.speed * 0.1;
if (isDead) {
LK.setScore(LK.getScore() + 10);
}
}
}
bomb.destroy();
bombs.splice(i, 1);
bombHit = true;
break;
}
}
// Check collision with boss
if (!bombHit && boss !== null) {
var dx = bomb.x - boss.x;
var dy = bomb.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 60) {
// Explosion damage to boss
var isBossDead = boss.takeDamage(3);
if (isBossDead) {
LK.setScore(LK.getScore() + 100);
boss.destroy();
boss = null;
// Hide boss health bar
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
LK.effects.flashScreen(0x00ff00, 500);
}
bomb.destroy();
bombs.splice(i, 1);
}
}
}
// Handle bullet collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
var bulletHit = false;
// Modify bullet size for engineer
if (engineerBoostActive && selectedCharacter === 2) {
bullet.scaleX = 2.0;
bullet.scaleY = 2.0;
}
// Check collision with monsters
for (var j = monsters.length - 1; j >= 0; j--) {
var monster = monsters[j];
var dx = bullet.x - monster.x;
var dy = bullet.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var hitRadius = engineerBoostActive && selectedCharacter === 2 ? 50 : 30;
if (distance < hitRadius) {
var isDead = monster.takeDamage(bullet.damage);
if (isDead) {
LK.setScore(LK.getScore() + 10);
}
bullet.destroy();
bullets.splice(i, 1);
bulletHit = true;
break;
}
}
// Check collision with boss
if (!bulletHit && boss !== null) {
var dx = bullet.x - boss.x;
var dy = bullet.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 60) {
var isBossDead = boss.takeDamage(bullet.damage);
if (isBossDead) {
LK.setScore(LK.getScore() + 100);
boss.destroy();
boss = null;
// Hide boss health bar
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
LK.effects.flashScreen(0x00ff00, 500); // Green flash for boss kill
}
bullet.destroy();
bullets.splice(i, 1);
}
}
}
if (nightTimer <= 0 && boss === null) {
// Clear remaining monsters
for (var m = monsters.length - 1; m >= 0; m--) {
monsters[m].destroy();
monsters.splice(m, 1);
}
// Clear remaining bullets
for (var b = bullets.length - 1; b >= 0; b--) {
bullets[b].destroy();
bullets.splice(b, 1);
}
// Clear remaining bombs
for (var bomb = bombs.length - 1; bomb >= 0; bomb--) {
bombs[bomb].destroy();
bombs.splice(bomb, 1);
}
switchToDay();
}
}
// Player-monster interaction for attacks
for (var i = monsters.length - 1; i >= 0; i--) {
var monster = monsters[i];
// Skip dead monsters for attack
if (monster.isDead) {
continue;
}
// Check for collision with player to trigger attack
var dx = player.x - monster.x;
var dy = player.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 60) {
// Collision radius for attack
// Monster attacks player
playerHealth -= monster.damage;
healthText.setText('Health: ' + playerHealth);
LK.getSound('damage').play();
if (playerHealth <= 0) {
LK.showGameOver();
}
// Optionally remove monster after attack (or add cooldown)
monster.destroy();
monsters.splice(i, 1);
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -175,9 +175,25 @@
self.maxHealth = 2;
self.speed = 2;
self.damage = 10;
self.type = 'scout';
+ self.isDead = false;
+ self.deadTimer = 0;
self.update = function () {
+ if (self.isDead) {
+ self.deadTimer++;
+ if (self.deadTimer >= 120) {
+ // 2 seconds at 60fps
+ self.destroy();
+ for (var i = monsters.length - 1; i >= 0; i--) {
+ if (monsters[i] === self) {
+ monsters.splice(i, 1);
+ break;
+ }
+ }
+ }
+ return;
+ }
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
@@ -206,8 +222,11 @@
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
+ self.isDead = true;
+ self.alpha = 0.5;
+ scoutGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
@@ -223,9 +242,25 @@
self.maxHealth = 1;
self.speed = 3;
self.damage = 5;
self.type = 'swarm';
+ self.isDead = false;
+ self.deadTimer = 0;
self.update = function () {
+ if (self.isDead) {
+ self.deadTimer++;
+ if (self.deadTimer >= 120) {
+ // 2 seconds at 60fps
+ self.destroy();
+ for (var i = monsters.length - 1; i >= 0; i--) {
+ if (monsters[i] === self) {
+ monsters.splice(i, 1);
+ break;
+ }
+ }
+ }
+ return;
+ }
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
@@ -253,8 +288,11 @@
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
+ self.isDead = true;
+ self.alpha = 0.5;
+ swarmGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
@@ -270,9 +308,25 @@
self.maxHealth = 3;
self.speed = 1;
self.damage = 25;
self.type = 'tank';
+ self.isDead = false;
+ self.deadTimer = 0;
self.update = function () {
+ if (self.isDead) {
+ self.deadTimer++;
+ if (self.deadTimer >= 120) {
+ // 2 seconds at 60fps
+ self.destroy();
+ for (var i = monsters.length - 1; i >= 0; i--) {
+ if (monsters[i] === self) {
+ monsters.splice(i, 1);
+ break;
+ }
+ }
+ }
+ return;
+ }
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
@@ -300,8 +354,11 @@
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
+ self.isDead = true;
+ self.alpha = 0.5;
+ tankGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
@@ -385,8 +442,23 @@
/****
* Game Code
****/
+// Add backgrounds
+var dayBackground = game.addChild(LK.getAsset('dayBackground', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0
+}));
+dayBackground.alpha = 1;
+var nightBackground = game.addChild(LK.getAsset('nightBackground', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0
+}));
+nightBackground.alpha = 0;
var gameState = 'mainMenu'; // Start with main menu
var currentNight = 0;
var dayTimer = 1800; // 30 seconds at 60fps
var nightTimer = 0;
@@ -895,9 +967,11 @@
nightTimer = 1800 + (currentNight - 1) * 600; // Base 30s + 10s per night
gameStateText.setText('Night ' + currentNight);
timerText.setText(Math.ceil(nightTimer / 60) + 's');
nightText.setText('Night: ' + currentNight);
- game.setBackgroundColor(0x0f0f23);
+ // Switch to night background
+ dayBackground.alpha = 0;
+ nightBackground.alpha = 1;
LK.playMusic('nightfall');
defenseText.setText('Night Phase - Survive!');
// Show heal button for medic character
if (characterStats.healPerNight > 0 && currentNight > 0) {
@@ -926,9 +1000,11 @@
gameState = 'day';
dayTimer = 1800; // 30 seconds
gameStateText.setText('Day Phase');
timerText.setText('30s');
- game.setBackgroundColor(0x1a1a2e);
+ // Switch to day background
+ dayBackground.alpha = 1;
+ nightBackground.alpha = 0;
LK.stopMusic();
// Reset to default mode
gameMode = 'build';
selectedDefense = 'wall';
@@ -1354,8 +1430,12 @@
}
// Monster AI and collision
for (var i = monsters.length - 1; i >= 0; i--) {
var monster = monsters[i];
+ // Skip dead monsters for collision and movement
+ if (monster.isDead) {
+ continue;
+ }
// Apply slow effect if active
var originalSpeed = monster.speed;
if (slowEnemiesActive) {
monster.speed = originalSpeed * 0.3; // 70% slower
@@ -1403,9 +1483,9 @@
// Check collision with walls
var hitWall = false;
for (var j = 0; j < walls.length; j++) {
var wall = walls[j];
- if (wall.health > 0 && monster.intersects(wall)) {
+ if (wall.health > 0 && !monster.isDead && monster.intersects(wall)) {
// Monster only attacks wall every 2 seconds (120 ticks)
// Only if player is within 300px or monster is within 300px of wall (simulate "seeing" wall)
var playerDist = Math.sqrt((player.x - monster.x) * (player.x - monster.x) + (player.y - monster.y) * (player.y - monster.y));
var wallDist = Math.sqrt((wall.x - monster.x) * (wall.x - monster.x) + (wall.y - monster.y) * (wall.y - monster.y));
@@ -1429,28 +1509,14 @@
if (hitWall) continue;
// Check collision with traps
for (var k = 0; k < traps.length; k++) {
var trap = traps[k];
- if (monster.intersects(trap)) {
+ if (!monster.isDead && monster.intersects(trap)) {
var trapDamage = trap.activate();
if (trapDamage > 0) {
var isDead = monster.takeDamage(trapDamage);
if (isDead) {
LK.setScore(LK.getScore() + 10);
- // Kill animation - flash and scale down
- tween(monster, {
- scaleX: 1.5,
- scaleY: 1.5,
- alpha: 0.3,
- rotation: Math.PI
- }, {
- duration: 300,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- monster.destroy();
- }
- });
- monsters.splice(i, 1);
break;
}
}
}
@@ -1487,22 +1553,8 @@
// Stun effect - reduce speed temporarily
targetMonster.speed = targetMonster.speed * 0.1;
if (isDead) {
LK.setScore(LK.getScore() + 10);
- // Kill animation
- tween(targetMonster, {
- scaleX: 1.5,
- scaleY: 1.5,
- alpha: 0.3,
- rotation: Math.PI
- }, {
- duration: 300,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- targetMonster.destroy();
- }
- });
- monsters.splice(k, 1);
}
}
}
bomb.destroy();
@@ -1553,22 +1605,8 @@
if (distance < hitRadius) {
var isDead = monster.takeDamage(bullet.damage);
if (isDead) {
LK.setScore(LK.getScore() + 10);
- // Kill animation - flash and scale down
- tween(monster, {
- scaleX: 1.5,
- scaleY: 1.5,
- alpha: 0.3,
- rotation: Math.PI
- }, {
- duration: 300,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- monster.destroy();
- }
- });
- monsters.splice(j, 1);
}
bullet.destroy();
bullets.splice(i, 1);
bulletHit = true;
@@ -1618,8 +1656,12 @@
}
// Player-monster interaction for attacks
for (var i = monsters.length - 1; i >= 0; i--) {
var monster = monsters[i];
+ // Skip dead monsters for attack
+ if (monster.isDead) {
+ continue;
+ }
// Check for collision with player to trigger attack
var dx = player.x - monster.x;
var dy = player.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
Crea picos de madera, que todos estén unidos en una tablilla por abajo y que arriba estén los picos. In-Game asset. 2d. High contrast. No shadows
Crea un botón de color azul pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de lava pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un guerrero pixel, sin armas, y que tenga la cabeza un poco más grande que el cuerpo tipo pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un monstruo corrupto morado de piedra qué no sea tan terrorífico, y que sea pixel.Y qué tenga manos grandes, y torso y que la cabeza no sea tan terrorífico, y no le ponga ojos perturbadores, y que su cabeza sea de un tamaño moderado no muy grande, que algo que si sea grande sea sus brazos, y que tenga algas moradas y que tenga algunas piedras moradas y otras piedras que no sean moradas qué sean grises In-Game asset. 2d. High contrast. No shadows.
Genera una imagen verde solo verde oscuro. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una avispa no terroríficas, pixel y que sean moradas. Que sea corrupta In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un corrupto pixel, y que no sea terrorífico y que sea morado. In-Game asset. 2d. High contrast. No shadows
Genera una imagen morado oscuro solo morado oscuro In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una roca morada sonriente. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un círculo verde pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un destello brillante morado pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una pistola pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una bala pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un médico guerrero pixel, y que su cabeza sea un poco más grande que el cuerpo. Y que no tenga armas In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un albañil guerrero pixel, que su cabeza sea un poco más grande que su cuerpo, y que no tenga armas. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un comerciante pixel y que su cabeza sea un poco más grande que su cuerpo. In-Game asset. 2d. High contrast. No shadows
Crea una imagen de un texto que diga "The corrupt survival" qué sea pixel y en la palabra "i" ponle una espada pixel. In-Game asset. 2d. High contrast. No shadows