User prompt
has que el speedyDemon sea un poco mas lento y un poco menos resistente
User prompt
has que las rocas y pasto tengan su propia textura
User prompt
has el texto de los nutrientes mas grandes y cuando consigues un nutriente se vea cuantos tienes que al inicio esten grises opaco y cuando consigues uno, uno de los grises se vuelva morado y tambien añade mas decoracion fuera del jardin, como rocas pasto etc y tambien haz que en la primera fila se vea de color celeste que represente el cielo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que la potatoMine haga daño en 1 casilla y que haga menos daño que el explosiveGolem
User prompt
has que hayan mas Waves y tambien has que cuando mates a un demonio que brille en verde suelte la piedra morada y la tengas que tocar la piedra morada y se acumule en unos slots de 3 y tengas que tocar a los slots para agarrar una piedra morada y ponersela a un golem en especifico ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
has que cuando aparezca un demonio que brilla en verde al matarlo te de un nutriente de pvz pero que sea una piedra morada que haga que los golems activen una habilidad especial por unos segundo( a ecepcion del barrierGolem que mejore su dureza por siempre) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
has que el jardin tenga 12 casillas de largo y 5 de alto
User prompt
has que la potatoMine se tarde 15 segundos en armarse ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
has que cuando toques 2 veces el icono de un golem se deseleccionen todos los iconos
User prompt
has que los iconos de los golems esten mas a la izquierda
Code edit (1 edits merged)
Please save this source code
User prompt
haz que el spikeGolem y potatoMine esten hasta arriba de las casillas
User prompt
haz que el potatoMine y el spikeGolem este al hazta abajo de la casilla
User prompt
haz mas mas abajo a la potatoMine y spikeGolem
User prompt
haz que estos golems aparezcan en una parte mas abajo de las cassillas en donde se colocan: spikeGolem y miniExplodeGolem(quiero que ahora se llame asi la potatoMine)
User prompt
haz que todos los personajes del juego no esten tan centrados en las gridCell, sino que esten un poco mas arriba
User prompt
has que el tankDemon sea igual de fuerte que un zombieStein de pvz
User prompt
agrega a la PotatoMine de pvz original ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que solo recibas Stones cuando se recolecten solas y quita la opcion de que se consigan Stones de conseguir Stones al matar un demonio y tambien añade a las podadoras de pvz original
User prompt
has una barra de cuanto te falta para terminar en nivel y tambien has un sistema de banderas como en el pvz que en cada bandera salgan muchos demonios ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
has que los demonios aparezcan despues del texto de ¡PELEA! y tambien haz que dependiendo del precio de los golems su tiempo de recarga sea mas o mestos rapido ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz el proyectil del crystalGolem mas pequeño para que se note que hace menos daño ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que mientras avanzes en las Wave se vaya haciendo mas dificil
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Demon = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
// Base stats that get modified by wave difficulty
var baseHealth = 450;
var baseSpeed = 0.3;
var baseReward = 10;
// Wave difficulty multiplier - increases health and speed
var waveMultiplier = 1 + (wave - 1) * 0.15; // 15% increase per wave
self.health = Math.floor(baseHealth * waveMultiplier);
self.maxHealth = self.health;
self.speed = baseSpeed * Math.min(waveMultiplier, 2.0); // Cap speed at 2x
self.reward = Math.floor(baseReward * waveMultiplier);
self.biteDamage = 1 + Math.floor((wave - 1) / 3); // Increase bite damage every 3 waves
self.biteDelay = Math.max(15, 30 - wave); // Faster biting as waves progress
self.lastBite = 0;
var assetName = 'basicDemon';
if (self.type === 'fast') {
assetName = 'fastDemon';
baseHealth = 360;
baseSpeed = 1;
baseReward = 15;
self.health = Math.floor(baseHealth * waveMultiplier);
self.maxHealth = self.health;
self.speed = baseSpeed * Math.min(waveMultiplier, 2.5); // Fast demons can go faster
self.reward = Math.floor(baseReward * waveMultiplier);
} else if (self.type === 'tank') {
assetName = 'tankDemon';
baseHealth = 900;
baseSpeed = 0.25;
baseReward = 25;
self.health = Math.floor(baseHealth * waveMultiplier);
self.maxHealth = self.health;
self.speed = baseSpeed * Math.min(waveMultiplier, 1.5); // Tank demons have speed cap
self.reward = Math.floor(baseReward * waveMultiplier);
} else if (self.type === 'zombieAllStar') {
assetName = 'tankDemon'; // Using tank demon sprite
baseHealth = 1200;
baseSpeed = 0.15;
baseReward = 50;
self.health = Math.floor(baseHealth * waveMultiplier);
self.maxHealth = self.health;
self.speed = baseSpeed * Math.min(waveMultiplier, 1.3);
self.reward = Math.floor(baseReward * waveMultiplier);
self.biteDamage = 3 + Math.floor((wave - 1) / 2); // Extra damage scaling
self.biteDelay = Math.max(10, 20 - wave); // Faster biting
} else if (self.type === 'speedy') {
assetName = 'speedyDemon';
baseHealth = 800; // High resistance
baseSpeed = 1.2; // Very fast
baseReward = 40;
self.health = Math.floor(baseHealth * waveMultiplier);
self.maxHealth = self.health;
self.speed = baseSpeed * Math.min(waveMultiplier, 3.0); // Speedy demons can go very fast
self.reward = Math.floor(baseReward * waveMultiplier);
self.biteDamage = 2 + Math.floor((wave - 1) / 3);
self.biteDelay = Math.max(10, 20 - wave); // Fast attacks
} else if (self.type === 'dancing') {
assetName = 'dancingDemon';
baseHealth = 600;
baseSpeed = 0.4;
baseReward = 30;
self.health = Math.floor(baseHealth * waveMultiplier);
self.maxHealth = self.health;
self.speed = baseSpeed * Math.min(waveMultiplier, 2.0);
self.reward = Math.floor(baseReward * waveMultiplier);
self.biteDamage = 2 + Math.floor((wave - 1) / 4);
self.biteDelay = Math.max(15, 25 - wave);
self.isDancing = false;
}
var graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Check for golem collision and bite them
var blocked = false;
var targetGolem = null;
for (var i = 0; i < golems.length; i++) {
var golem = golems[i];
if (golem.type !== 'spike' && self.intersects(golem)) {
blocked = true;
targetGolem = golem;
break;
}
}
if (targetGolem && LK.ticks - self.lastBite > self.biteDelay) {
// Bite the golem
if (!targetGolem.health) {
if (targetGolem.type === 'barrier') {
targetGolem.health = 160; // Barrier golems have 160 health
targetGolem.maxHealth = 160;
} else {
targetGolem.health = 15; // All other golems have 15 health
targetGolem.maxHealth = 15;
}
}
targetGolem.health -= self.biteDamage;
self.lastBite = LK.ticks;
// Visual feedback - flash golem red
tween(targetGolem, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(targetGolem, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
if (targetGolem.health <= 0) {
// Remove golem from grid
var golemGridCol = Math.floor((targetGolem.x - gridStartX + cellSize / 2) / cellSize);
var golemGridRow = Math.floor((targetGolem.y - gridStartY + cellSize / 2) / cellSize);
if (golemGridCol >= 0 && golemGridCol < gridCols && golemGridRow >= 0 && golemGridRow < gridRows) {
gridOccupied[golemGridRow][golemGridCol] = false;
}
// Remove from golems array
for (var j = golems.length - 1; j >= 0; j--) {
if (golems[j] === targetGolem) {
targetGolem.destroy();
golems.splice(j, 1);
break;
}
}
blocked = false; // Can continue moving after eating golem
}
}
if (!blocked) {
self.x -= self.speed;
}
// Special dancing demon effects
if (self.type === 'dancing' && !self.isDancing && Math.random() < 0.01) {
// Start dancing animation
self.isDancing = true;
var originalSpeed = self.speed;
self.speed = 0; // Stop moving while dancing
// Dancing rotation animation
var danceRotations = 0;
var maxRotations = 3;
var _danceRotate2 = function _danceRotate() {
tween(graphics, {
rotation: Math.PI * 2
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
graphics.rotation = 0; // Reset rotation
danceRotations++;
if (danceRotations < maxRotations) {
_danceRotate2();
} else {
// Dance complete, resume movement with speed boost
self.speed = originalSpeed * 1.5; // 50% speed boost after dance
self.isDancing = false;
// Speed boost lasts for 3 seconds
LK.setTimeout(function () {
if (self.health > 0) {
self.speed = originalSpeed; // Return to normal speed
}
}, 3000);
}
}
});
};
_danceRotate2();
// Color flash during dance
tween(graphics, {
tint: 0xFF00FF
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
tint: 0x00FFFF
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFFFF00
}, {
duration: 200,
onFinish: function onFinish() {
tween(graphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
});
}
});
}
// Special zombie all star effects
if (self.type === 'zombieAllStar') {
// Scale pulsing effect when at low health
var healthPercent = self.health / self.maxHealth;
if (healthPercent < 0.5 && !self.isPulsing) {
self.isPulsing = true;
var _pulseScale = function pulseScale() {
tween(graphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(graphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.health > 0 && healthPercent < 0.5) {
_pulseScale();
} else {
self.isPulsing = false;
}
}
});
}
});
};
_pulseScale();
}
}
// Update health bar color
var healthPercent = self.health / self.maxHealth;
if (healthPercent < 0.3) {
graphics.tint = 0xFF0000;
} else if (healthPercent < 0.6) {
graphics.tint = 0xFF6600;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('hit').play();
if (self.health <= 0) {
self.shouldRemove = true;
stones += self.reward;
score += self.reward;
updateUI();
}
};
return self;
});
var Golem = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
self.lastShot = 0;
self.range = 2048; // Full screen width for entire line attack
self.damage = 25;
self.shootDelay = 60; // frames
var assetName = 'basicGolem';
if (self.type === 'heavy') {
assetName = 'heavyGolem';
self.damage = 75;
self.range = 2048; // Full screen width for entire line attack
self.shootDelay = 120;
} else if (self.type === 'crystal') {
assetName = 'crystalGolem';
self.damage = 20;
self.range = 2048; // Full screen width for entire line attack
self.shootDelay = 30;
} else if (self.type === 'barrier') {
assetName = 'barrierGolem';
self.damage = 0;
self.range = 0;
self.shootDelay = 0;
} else if (self.type === 'spike') {
assetName = 'spikeGolem';
self.damage = 10;
self.range = 0;
self.shootDelay = 0;
} else if (self.type === 'stone') {
assetName = 'stoneGolem';
self.damage = 0;
self.range = 0;
self.shootDelay = 450; // Generate stone every 7.5 seconds
} else if (self.type === 'melee') {
assetName = 'meleeGolem';
self.damage = 40;
self.range = cellSize * 2; // 2 cell radius
self.shootDelay = 0; // No projectiles, direct combat
self.meleeDelay = 30; // frames between melee attacks
self.lastMelee = 0;
} else if (self.type === 'explosive') {
assetName = 'explosiveGolem';
self.damage = 80;
self.range = cellSize * 1.5; // 1.5 cell radius for detection
self.shootDelay = 0; // No projectiles, explodes on contact
self.hasExploded = false;
}
var graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (self.type === 'barrier') return;
if (self.type === 'spike') {
// Check for contact damage with cooldown
if (!self.damageCooldown) self.damageCooldown = {};
for (var i = 0; i < demons.length; i++) {
var demon = demons[i];
if (self.intersects(demon)) {
var demonId = demon.id || i; // Use demon id or index as identifier
var currentTime = LK.ticks;
if (!self.damageCooldown[demonId] || currentTime - self.damageCooldown[demonId] > 60) {
demon.takeDamage(self.damage);
self.damageCooldown[demonId] = currentTime;
}
}
}
return;
}
if (self.type === 'stone') {
// Generate stones periodically
if (LK.ticks - self.lastShot > self.shootDelay) {
var stone = new Stone();
stone.x = self.x + (Math.random() - 0.5) * 100; // Spawn near golem
stone.y = self.y + (Math.random() - 0.5) * 100;
stone.value = 25; // Stone golem generates stones worth 25
stones_collectible.push(stone);
game.addChild(stone);
self.lastShot = LK.ticks;
}
return;
}
if (self.type === 'melee') {
// Melee combat - attack demons in 2 cell radius front and back
if (LK.ticks - self.lastMelee > self.meleeDelay) {
var golemRow = Math.floor((self.y - gridStartY + cellSize / 2) / cellSize);
var golemCol = Math.floor((self.x - gridStartX + cellSize / 2) / cellSize);
var attackedDemons = [];
for (var i = 0; i < demons.length; i++) {
var demon = demons[i];
var demonRow = Math.floor((demon.y - gridStartY + cellSize / 2) / cellSize);
var demonCol = Math.floor((demon.x - gridStartX + cellSize / 2) / cellSize);
// Check if demon is in same row and within 2 cells front or back
if (demonRow === golemRow) {
var colDistance = Math.abs(demonCol - golemCol);
if (colDistance <= 2 && colDistance > 0) {
var dx = demon.x - self.x;
var dy = demon.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
attackedDemons.push(demon);
}
}
}
}
if (attackedDemons.length > 0) {
// Attack all demons in range
for (var k = 0; k < attackedDemons.length; k++) {
var targetDemon = attackedDemons[k];
targetDemon.takeDamage(self.damage);
// Visual melee attack effect
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFF4444
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
}
self.lastMelee = LK.ticks;
LK.getSound('hit').play();
}
}
return;
}
if (self.type === 'explosive') {
// Explosive golem - explode when demon gets close
if (!self.hasExploded) {
var golemRow = Math.floor((self.y - gridStartY + cellSize / 2) / cellSize);
var golemCol = Math.floor((self.x - gridStartX + cellSize / 2) / cellSize);
var demonsInRange = [];
for (var i = 0; i < demons.length; i++) {
var demon = demons[i];
var dx = demon.x - self.x;
var dy = demon.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
demonsInRange.push(demon);
}
}
if (demonsInRange.length > 0) {
// Explode in 3x3 area
self.hasExploded = true;
// Visual explosion effect
tween(self, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFF4400,
alpha: 0.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
// Remove golem from grid after explosion
var golemGridCol = Math.floor((self.x - gridStartX + cellSize / 2) / cellSize);
var golemGridRow = Math.floor((self.y - gridStartY + cellSize / 2) / cellSize);
if (golemGridCol >= 0 && golemGridCol < gridCols && golemGridRow >= 0 && golemGridRow < gridRows) {
gridOccupied[golemGridRow][golemGridCol] = false;
}
// Remove from golems array
for (var j = golems.length - 1; j >= 0; j--) {
if (golems[j] === self) {
self.destroy();
golems.splice(j, 1);
break;
}
}
}
});
}
});
// Instantly kill all demons in 3x3 area
for (var i = 0; i < demons.length; i++) {
var demon = demons[i];
var demonRow = Math.floor((demon.y - gridStartY + cellSize / 2) / cellSize);
var demonCol = Math.floor((demon.x - gridStartX + cellSize / 2) / cellSize);
// Check if demon is within 3x3 area centered on golem
var rowDistance = Math.abs(demonRow - golemRow);
var colDistance = Math.abs(demonCol - golemCol);
if (rowDistance <= 1 && colDistance <= 1) {
// Instantly kill the demon by setting health to 0
demon.health = 0;
demon.shouldRemove = true;
stones += demon.reward;
score += demon.reward;
}
}
LK.getSound('hit').play();
}
}
return;
}
if (LK.ticks - self.lastShot > self.shootDelay) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = LK.ticks;
}
}
};
self.findTarget = function () {
var closestDemon = null;
var closestDistance = self.range;
var golemRow = Math.floor((self.y - gridStartY + cellSize / 2) / cellSize);
for (var i = 0; i < demons.length; i++) {
var demon = demons[i];
var demonRow = Math.floor((demon.y - gridStartY + cellSize / 2) / cellSize);
// Only target demons in the same row
if (demonRow !== golemRow) continue;
var dx = demon.x - self.x;
var dy = demon.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestDemon = demon;
}
}
return closestDemon;
};
self.shoot = function (target) {
var projectile = new Projectile(self.type);
projectile.x = self.x;
projectile.y = self.y;
projectile.targetX = target.x;
projectile.targetY = target.y;
projectile.damage = self.damage;
projectiles.push(projectile);
game.addChild(projectile);
LK.getSound('shoot').play();
};
return self;
});
var Projectile = Container.expand(function (golemType) {
var self = Container.call(this);
self.golemType = golemType || 'basic';
var assetName = 'projectile';
if (self.golemType === 'heavy') {
assetName = 'heavyProjectile';
} else if (self.golemType === 'crystal') {
assetName = 'crystalProjectile';
}
var graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 25;
self.speed = 8;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.shouldRemove = true;
return;
}
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
};
return self;
});
var Stone = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.bobOffset = Math.random() * Math.PI * 2;
self.spawnTime = LK.ticks;
self.lifespan = 300; // 5 seconds at 60 FPS
self.isMarkedForCollection = false;
self.collectionMarkTime = 0;
self.collectionDelay = 60; // 1 second at 60 FPS
self.update = function () {
// Bobbing animation
self.y += Math.sin(LK.ticks * 0.05 + self.bobOffset) * 0.3;
// Check if stone should disappear
if (LK.ticks - self.spawnTime > self.lifespan) {
self.shouldRemove = true;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F5233
});
/****
* Game Code
****/
// Game variables
var stones = 100;
var score = 0;
var lives = 10;
var wave = 1;
var nextWaveTimer = 0;
var waveDelay = 300; // frames between waves
// Game arrays
var golems = [];
var demons = [];
var projectiles = [];
var stones_collectible = [];
// Stone spawning - gets slower as waves progress
var lastStoneSpawn = 0;
var baseStoneSpawnDelay = 150;
var stoneSpawnDelay = baseStoneSpawnDelay + (wave - 1) * 20; // Slower stone spawning as waves progress
// Demon spawn cooldown
var demonSpawnCooldown = 300; // 5 seconds between demon spawns
var lastDemonSpawn = 0;
// Initial game delay - demons don't spawn for first 12 seconds
var gameStartDelay = 720; // 12 seconds at 60 FPS
var gameStartTime = 0;
var demonsCanSpawn = false;
// Grid system
var gridCols = 8;
var gridRows = 5;
var gridStartX = 400;
var gridStartY = 800;
var cellSize = 200;
// Golem costs
var golemCosts = {
basic: 100,
heavy: 250,
crystal: 75,
barrier: 80,
spike: 60,
stone: 50,
melee: 120,
explosive: 150,
shovel: 0
};
// Selected golem type
var selectedGolemType = 'basic';
// Golem placement cooldown system
var golemPlacementCooldown = {};
var golemCooldownDuration = 180; // 3 seconds at 60 FPS - base duration
var lastGolemPlacement = 0;
// Function to get cooldown duration based on golem cost
function getGolemCooldownDuration(golemType) {
var cost = golemCosts[golemType];
if (cost === 0) return 0; // No cooldown for free items like shovel
// More expensive golems have longer cooldowns
// Base formula: cost * 1.5 frames (at 60 FPS)
return Math.floor(cost * 1.5);
}
// UI elements
var stonesText = new Text2('Stones: 100', {
size: 40,
fill: 0xFFFFFF
});
stonesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(stonesText);
stonesText.x = 120;
stonesText.y = 20;
var livesText = new Text2('Lives: 10', {
size: 40,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesText);
livesText.x = 120;
livesText.y = 70;
var waveText = new Text2('Wave: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 120;
waveText.y = 120;
var scoreText = new Text2('Score: 0', {
size: 40,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -20;
scoreText.y = 20;
// Cooldown status text
var cooldownText = new Text2('', {
size: 30,
fill: 0xFF6600
});
cooldownText.anchor.set(0.5, 0.5);
cooldownText.x = 2048 / 2;
cooldownText.y = 200;
game.addChild(cooldownText);
// Golem selection buttons
var buttonY = 200;
var buttonSpacing = 150;
var basicButton = LK.getAsset('basicGolem', {
scaleX: 1.2,
scaleY: 1.2
});
basicButton.x = 80;
basicButton.y = buttonY;
LK.gui.topLeft.addChild(basicButton);
var heavyButton = LK.getAsset('heavyGolem', {
scaleX: 1.0,
scaleY: 1.0
});
heavyButton.x = 80;
heavyButton.y = buttonY + buttonSpacing;
LK.gui.topLeft.addChild(heavyButton);
var crystalButton = LK.getAsset('crystalGolem', {
scaleX: 1.1,
scaleY: 1.1
});
crystalButton.x = 80;
crystalButton.y = buttonY + buttonSpacing * 2;
LK.gui.topLeft.addChild(crystalButton);
var barrierButton = LK.getAsset('barrierGolem', {
scaleX: 0.9,
scaleY: 1.0
});
barrierButton.x = 80;
barrierButton.y = buttonY + buttonSpacing * 3;
LK.gui.topLeft.addChild(barrierButton);
var spikeButton = LK.getAsset('spikeGolem', {
scaleX: 1.2,
scaleY: 1.2
});
spikeButton.x = 80;
spikeButton.y = buttonY + buttonSpacing * 4;
LK.gui.topLeft.addChild(spikeButton);
var stoneButton = LK.getAsset('stoneGolem', {
scaleX: 1.0,
scaleY: 1.0
});
stoneButton.x = 80;
stoneButton.y = buttonY + buttonSpacing * 5;
LK.gui.topLeft.addChild(stoneButton);
var meleeButton = LK.getAsset('meleeGolem', {
scaleX: 1.0,
scaleY: 1.0
});
meleeButton.x = 80;
meleeButton.y = buttonY + buttonSpacing * 6;
LK.gui.topLeft.addChild(meleeButton);
var explosiveButton = LK.getAsset('explosiveGolem', {
scaleX: 1.0,
scaleY: 1.0
});
explosiveButton.x = 80;
explosiveButton.y = buttonY + buttonSpacing * 7;
LK.gui.topLeft.addChild(explosiveButton);
var shovelButton = LK.getAsset('shovel', {
scaleX: 1.0,
scaleY: 1.0
});
shovelButton.x = 80;
shovelButton.y = buttonY + buttonSpacing * 8;
LK.gui.topLeft.addChild(shovelButton);
// Cost labels
var basicCostText = new Text2('100', {
size: 24,
fill: 0xFFFF00
});
basicCostText.x = 150;
basicCostText.y = buttonY + 20;
LK.gui.topLeft.addChild(basicCostText);
var heavyCostText = new Text2('250', {
size: 24,
fill: 0xFFFF00
});
heavyCostText.x = 150;
heavyCostText.y = buttonY + buttonSpacing + 20;
LK.gui.topLeft.addChild(heavyCostText);
var crystalCostText = new Text2('75', {
size: 24,
fill: 0xFFFF00
});
crystalCostText.x = 150;
crystalCostText.y = buttonY + buttonSpacing * 2 + 20;
LK.gui.topLeft.addChild(crystalCostText);
var barrierCostText = new Text2('80', {
size: 24,
fill: 0xFFFF00
});
barrierCostText.x = 150;
barrierCostText.y = buttonY + buttonSpacing * 3 + 20;
LK.gui.topLeft.addChild(barrierCostText);
var spikeCostText = new Text2('60', {
size: 24,
fill: 0xFFFF00
});
spikeCostText.x = 150;
spikeCostText.y = buttonY + buttonSpacing * 4 + 20;
LK.gui.topLeft.addChild(spikeCostText);
var stoneCostText = new Text2('50', {
size: 24,
fill: 0xFFFF00
});
stoneCostText.x = 150;
stoneCostText.y = buttonY + buttonSpacing * 5 + 20;
LK.gui.topLeft.addChild(stoneCostText);
var meleeCostText = new Text2('120', {
size: 24,
fill: 0xFFFF00
});
meleeCostText.x = 150;
meleeCostText.y = buttonY + buttonSpacing * 6 + 20;
LK.gui.topLeft.addChild(meleeCostText);
var explosiveCostText = new Text2('150', {
size: 24,
fill: 0xFFFF00
});
explosiveCostText.x = 150;
explosiveCostText.y = buttonY + buttonSpacing * 7 + 20;
LK.gui.topLeft.addChild(explosiveCostText);
var shovelCostText = new Text2('Remove', {
size: 20,
fill: 0xFFFF00
});
shovelCostText.x = 150;
shovelCostText.y = buttonY + buttonSpacing * 8 + 20;
LK.gui.topLeft.addChild(shovelCostText);
// Cooldown text displays for buttons
var basicCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
basicCooldownText.anchor.set(0.5, 0.5);
basicCooldownText.x = 80;
basicCooldownText.y = buttonY - 20;
basicCooldownText.alpha = 0;
LK.gui.topLeft.addChild(basicCooldownText);
var heavyCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
heavyCooldownText.anchor.set(0.5, 0.5);
heavyCooldownText.x = 80;
heavyCooldownText.y = buttonY + buttonSpacing - 20;
heavyCooldownText.alpha = 0;
LK.gui.topLeft.addChild(heavyCooldownText);
var crystalCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
crystalCooldownText.anchor.set(0.5, 0.5);
crystalCooldownText.x = 80;
crystalCooldownText.y = buttonY + buttonSpacing * 2 - 20;
crystalCooldownText.alpha = 0;
LK.gui.topLeft.addChild(crystalCooldownText);
var barrierCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
barrierCooldownText.anchor.set(0.5, 0.5);
barrierCooldownText.x = 80;
barrierCooldownText.y = buttonY + buttonSpacing * 3 - 20;
barrierCooldownText.alpha = 0;
LK.gui.topLeft.addChild(barrierCooldownText);
var spikeCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
spikeCooldownText.anchor.set(0.5, 0.5);
spikeCooldownText.x = 80;
spikeCooldownText.y = buttonY + buttonSpacing * 4 - 20;
spikeCooldownText.alpha = 0;
LK.gui.topLeft.addChild(spikeCooldownText);
var stoneCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
stoneCooldownText.anchor.set(0.5, 0.5);
stoneCooldownText.x = 80;
stoneCooldownText.y = buttonY + buttonSpacing * 5 - 20;
stoneCooldownText.alpha = 0;
LK.gui.topLeft.addChild(stoneCooldownText);
var meleeCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
meleeCooldownText.anchor.set(0.5, 0.5);
meleeCooldownText.x = 80;
meleeCooldownText.y = buttonY + buttonSpacing * 6 - 20;
meleeCooldownText.alpha = 0;
LK.gui.topLeft.addChild(meleeCooldownText);
var explosiveCooldownText = new Text2('', {
size: 30,
fill: 0xFF0000
});
explosiveCooldownText.anchor.set(0.5, 0.5);
explosiveCooldownText.x = 80;
explosiveCooldownText.y = buttonY + buttonSpacing * 7 - 20;
explosiveCooldownText.alpha = 0;
LK.gui.topLeft.addChild(explosiveCooldownText);
// Create grid visualization
var gridCells = [];
for (var row = 0; row < gridRows; row++) {
gridCells[row] = [];
for (var col = 0; col < gridCols; col++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
cell.x = gridStartX + col * cellSize;
cell.y = gridStartY + row * cellSize;
cell.gridX = col;
cell.gridY = row;
gridCells[row][col] = cell;
game.addChild(cell);
}
}
// Grid occupied tracking
var gridOccupied = [];
for (var row = 0; row < gridRows; row++) {
gridOccupied[row] = [];
for (var col = 0; col < gridCols; col++) {
gridOccupied[row][col] = false;
}
}
function updateUI() {
stonesText.setText('Stones: ' + stones);
livesText.setText('Lives: ' + lives);
waveText.setText('Wave: ' + wave);
scoreText.setText('Score: ' + score);
var currentTime = LK.ticks;
// Update button availability based on cost and cooldown
function getButtonAlpha(golemType, cost) {
var hasEnoughStones = stones >= cost;
var cooldownDuration = getGolemCooldownDuration(golemType);
var isOnCooldown = golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < cooldownDuration;
return hasEnoughStones && !isOnCooldown ? 1.0 : 0.5;
}
basicButton.alpha = getButtonAlpha('basic', golemCosts.basic);
heavyButton.alpha = getButtonAlpha('heavy', golemCosts.heavy);
crystalButton.alpha = getButtonAlpha('crystal', golemCosts.crystal);
barrierButton.alpha = getButtonAlpha('barrier', golemCosts.barrier);
spikeButton.alpha = getButtonAlpha('spike', golemCosts.spike);
stoneButton.alpha = getButtonAlpha('stone', golemCosts.stone);
meleeButton.alpha = getButtonAlpha('melee', golemCosts.melee);
explosiveButton.alpha = getButtonAlpha('explosive', golemCosts.explosive);
shovelButton.alpha = 1.0; // Shovel is always available
// Update cooldown displays
function updateCooldownDisplay(golemType, cooldownText) {
var cooldownDuration = getGolemCooldownDuration(golemType);
if (golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < cooldownDuration) {
var remainingTime = Math.ceil((cooldownDuration - (currentTime - golemPlacementCooldown[golemType])) / 60);
cooldownText.setText(remainingTime + 's');
cooldownText.alpha = 1;
} else {
cooldownText.alpha = 0;
}
}
updateCooldownDisplay('basic', basicCooldownText);
updateCooldownDisplay('heavy', heavyCooldownText);
updateCooldownDisplay('crystal', crystalCooldownText);
updateCooldownDisplay('barrier', barrierCooldownText);
updateCooldownDisplay('spike', spikeCooldownText);
updateCooldownDisplay('stone', stoneCooldownText);
updateCooldownDisplay('melee', meleeCooldownText);
updateCooldownDisplay('explosive', explosiveCooldownText);
}
function spawnWave() {
// Don't spawn demons if initial delay hasn't passed
if (!demonsCanSpawn) {
return;
}
// Dramatically increase demons per wave - starts at 3, increases significantly
var demonsToSpawn = Math.max(3, 2 + Math.floor(wave * 1.5)); // More aggressive scaling
var spawnDelay = 300; // 5 seconds delay (300 frames at 60 FPS)
// Decrease spawn delay between demons as waves progress
var delayBetweenSpawns = Math.max(150, 450 - wave * 15); // Faster spawning in later waves
for (var i = 0; i < demonsToSpawn; i++) {
LK.setTimeout(function () {
// Check if enough time has passed since last demon spawn
if (LK.ticks - lastDemonSpawn >= demonSpawnCooldown) {
var demonType = 'basic';
// More aggressive probability scaling based on wave
var waveScaling = Math.min(wave / 10, 1.0); // Scale from 0 to 1 over 10 waves
if (wave > 2 && Math.random() < 0.2 + waveScaling * 0.4) demonType = 'fast'; // Up to 60% chance
if (wave > 3 && Math.random() < 0.15 + waveScaling * 0.3) demonType = 'dancing'; // Up to 45% chance
if (wave > 4 && Math.random() < 0.1 + waveScaling * 0.4) demonType = 'tank'; // Up to 50% chance
if (wave > 5 && Math.random() < 0.05 + waveScaling * 0.3) demonType = 'speedy'; // Up to 35% chance
// Add elite demon spawning for high waves
if (wave > 7 && Math.random() < 0.05 + waveScaling * 0.15) demonType = 'zombieAllStar'; // Up to 20% chance
var demon = new Demon(demonType);
demon.x = 2048;
demon.y = gridStartY + Math.floor(Math.random() * gridRows) * cellSize;
demons.push(demon);
game.addChild(demon);
lastDemonSpawn = LK.ticks;
}
}, spawnDelay);
spawnDelay += delayBetweenSpawns; // Use variable delay that decreases with wave
}
}
function getGridPosition(x, y) {
var col = Math.floor((x - gridStartX + cellSize / 2) / cellSize);
var row = Math.floor((y - gridStartY + cellSize / 2) / cellSize);
if (col >= 0 && col < gridCols && row >= 0 && row < gridRows) {
return {
col: col,
row: row
};
}
return null;
}
// Button click handlers
basicButton.down = function () {
if (stones >= golemCosts.basic) {
selectedGolemType = 'basic';
updateButtonSelection();
}
};
heavyButton.down = function () {
if (stones >= golemCosts.heavy) {
selectedGolemType = 'heavy';
updateButtonSelection();
}
};
crystalButton.down = function () {
if (stones >= golemCosts.crystal) {
selectedGolemType = 'crystal';
updateButtonSelection();
}
};
barrierButton.down = function () {
if (stones >= golemCosts.barrier) {
selectedGolemType = 'barrier';
updateButtonSelection();
}
};
spikeButton.down = function () {
if (stones >= golemCosts.spike) {
selectedGolemType = 'spike';
updateButtonSelection();
}
};
stoneButton.down = function () {
if (stones >= golemCosts.stone) {
selectedGolemType = 'stone';
updateButtonSelection();
}
};
meleeButton.down = function () {
if (stones >= golemCosts.melee) {
selectedGolemType = 'melee';
updateButtonSelection();
}
};
explosiveButton.down = function () {
if (stones >= golemCosts.explosive) {
selectedGolemType = 'explosive';
updateButtonSelection();
}
};
shovelButton.down = function () {
selectedGolemType = 'shovel';
updateButtonSelection();
};
function updateButtonSelection() {
basicButton.tint = selectedGolemType === 'basic' ? 0x00FF00 : 0xFFFFFF;
heavyButton.tint = selectedGolemType === 'heavy' ? 0x00FF00 : 0xFFFFFF;
crystalButton.tint = selectedGolemType === 'crystal' ? 0x00FF00 : 0xFFFFFF;
barrierButton.tint = selectedGolemType === 'barrier' ? 0x00FF00 : 0xFFFFFF;
spikeButton.tint = selectedGolemType === 'spike' ? 0x00FF00 : 0xFFFFFF;
stoneButton.tint = selectedGolemType === 'stone' ? 0x00FF00 : 0xFFFFFF;
meleeButton.tint = selectedGolemType === 'melee' ? 0x00FF00 : 0xFFFFFF;
explosiveButton.tint = selectedGolemType === 'explosive' ? 0x00FF00 : 0xFFFFFF;
shovelButton.tint = selectedGolemType === 'shovel' ? 0x00FF00 : 0xFFFFFF;
}
// Initialize button selection
updateButtonSelection();
// Game click handler
game.down = function (x, y, obj) {
var gridPos = getGridPosition(x, y);
if (gridPos) {
if (selectedGolemType === 'shovel') {
// Remove golem if one exists at this position
if (gridOccupied[gridPos.row][gridPos.col]) {
for (var i = golems.length - 1; i >= 0; i--) {
var golem = golems[i];
var golemGridCol = Math.floor((golem.x - gridStartX + cellSize / 2) / cellSize);
var golemGridRow = Math.floor((golem.y - gridStartY + cellSize / 2) / cellSize);
if (golemGridCol === gridPos.col && golemGridRow === gridPos.row) {
golem.destroy();
golems.splice(i, 1);
gridOccupied[gridPos.row][gridPos.col] = false;
LK.getSound('remove').play();
break;
}
}
}
} else if (!gridOccupied[gridPos.row][gridPos.col]) {
var cost = golemCosts[selectedGolemType];
var currentTime = LK.ticks;
var cooldownKey = selectedGolemType;
var cooldownDuration = getGolemCooldownDuration(selectedGolemType);
// Check if golem type is on cooldown
if (golemPlacementCooldown[cooldownKey] && currentTime - golemPlacementCooldown[cooldownKey] < cooldownDuration) {
var remainingTime = Math.ceil((cooldownDuration - (currentTime - golemPlacementCooldown[cooldownKey])) / 60);
cooldownText.setText('Espera ' + remainingTime + 's para colocar ' + selectedGolemType);
cooldownText.alpha = 1;
tween(cooldownText, {
alpha: 0
}, {
duration: 2000
});
return;
}
if (stones >= cost) {
var golem = new Golem(selectedGolemType);
golem.x = gridStartX + gridPos.col * cellSize;
golem.y = gridStartY + gridPos.row * cellSize;
golems.push(golem);
game.addChild(golem);
gridOccupied[gridPos.row][gridPos.col] = true;
stones -= cost;
golemPlacementCooldown[cooldownKey] = currentTime;
lastGolemPlacement = currentTime;
updateUI();
LK.getSound('place').play();
}
}
}
};
// Countdown sequence before first wave
var countdownText = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 2048 / 2;
countdownText.y = 2732 / 2;
game.addChild(countdownText);
// Show "preparado..." at 4 seconds
LK.setTimeout(function () {
countdownText.setText('preparado...');
countdownText.alpha = 1;
// Fade in effect
tween(countdownText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(countdownText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
}, 4000);
// Show "listo..." at 8 seconds
LK.setTimeout(function () {
countdownText.setText('listo...');
// Scale and color effect
tween(countdownText, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFF00
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(countdownText, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}, 8000);
// Show "¡PELEA!" at 12 seconds and start wave
LK.setTimeout(function () {
countdownText.setText('¡PELEA!');
// Dramatic entrance effect
tween(countdownText, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF0000
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Enable demon spawning after PELEA text is shown
demonsCanSpawn = true;
// Start first wave immediately after PELEA
spawnWave();
// Fade out after showing PELEA
tween(countdownText, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
onFinish: function onFinish() {
countdownText.destroy();
}
});
}
});
}, 12000);
game.update = function () {
// Update golems
for (var i = golems.length - 1; i >= 0; i--) {
var golem = golems[i];
if (golem.update) golem.update();
}
// Update demons
for (var i = demons.length - 1; i >= 0; i--) {
var demon = demons[i];
demon.update();
// Check if demon reached left side
if (demon.x < 300) {
lives--;
demon.destroy();
demons.splice(i, 1);
updateUI();
if (lives <= 0) {
LK.setScore(score);
LK.showGameOver();
return;
}
} else if (demon.shouldRemove) {
demon.destroy();
demons.splice(i, 1);
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
projectile.update();
if (projectile.shouldRemove) {
projectile.destroy();
projectiles.splice(i, 1);
continue;
}
// Check projectile vs demon collision
for (var j = demons.length - 1; j >= 0; j--) {
var demon = demons[j];
if (projectile.intersects(demon)) {
demon.takeDamage(projectile.damage);
// Heavy golem projectiles have 25% chance to push demons backwards
if (projectile.golemType === 'heavy' && Math.random() < 0.25) {
// Push demon backwards (to the right) by 100 pixels
tween(demon, {
x: demon.x + 100
}, {
duration: 300,
easing: tween.easeOut
});
}
projectile.destroy();
projectiles.splice(i, 1);
break;
}
}
}
// Update stones with automatic collection
for (var i = stones_collectible.length - 1; i >= 0; i--) {
var stone = stones_collectible[i];
stone.update();
if (stone.shouldRemove) {
stone.destroy();
stones_collectible.splice(i, 1);
continue;
}
// Check if stone should be marked for collection
if (!stone.isMarkedForCollection) {
var shouldMarkForCollection = false;
// Check proximity to any golem (100 pixel radius)
for (var g = 0; g < golems.length; g++) {
var golem = golems[g];
var dx = stone.x - golem.x;
var dy = stone.y - golem.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
shouldMarkForCollection = true;
break;
}
}
// Also mark stones that have been around for 2 seconds automatically
if (!shouldMarkForCollection && LK.ticks - stone.spawnTime > 120) {
shouldMarkForCollection = true;
}
if (shouldMarkForCollection) {
stone.isMarkedForCollection = true;
stone.collectionMarkTime = LK.ticks;
// Visual indicator - slight glow effect
tween(stone, {
tint: 0xFFFF88
}, {
duration: 200
});
}
}
// Check if marked stone should be collected after delay
if (stone.isMarkedForCollection && LK.ticks - stone.collectionMarkTime >= stone.collectionDelay) {
// Animate stone collection
tween(stone, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
stones += stone.value;
stone.destroy();
updateUI();
}
});
stones_collectible.splice(i, 1);
}
}
// Update stone spawn delay based on current wave
stoneSpawnDelay = baseStoneSpawnDelay + (wave - 1) * 20;
// Spawn stones periodically
if (LK.ticks - lastStoneSpawn > stoneSpawnDelay) {
var stone = new Stone();
stone.x = 400 + Math.random() * (2048 - 800); // Spawn in playable area
stone.y = 600 + Math.random() * 400;
stones_collectible.push(stone);
game.addChild(stone);
lastStoneSpawn = LK.ticks;
}
// Wave management
if (demons.length === 0 && demonsCanSpawn) {
nextWaveTimer++;
if (nextWaveTimer >= waveDelay) {
wave++;
nextWaveTimer = 0;
spawnWave();
updateUI();
// Victory condition
if (wave > 10) {
LK.setScore(score);
LK.showYouWin();
return;
}
}
}
};
// Initialize game start time
gameStartTime = LK.ticks;
// Initialize UI
updateUI(); ===================================================================
--- original.js
+++ change.js
@@ -613,10 +613,18 @@
// Selected golem type
var selectedGolemType = 'basic';
// Golem placement cooldown system
var golemPlacementCooldown = {};
-var golemCooldownDuration = 180; // 3 seconds at 60 FPS
+var golemCooldownDuration = 180; // 3 seconds at 60 FPS - base duration
var lastGolemPlacement = 0;
+// Function to get cooldown duration based on golem cost
+function getGolemCooldownDuration(golemType) {
+ var cost = golemCosts[golemType];
+ if (cost === 0) return 0; // No cooldown for free items like shovel
+ // More expensive golems have longer cooldowns
+ // Base formula: cost * 1.5 frames (at 60 FPS)
+ return Math.floor(cost * 1.5);
+}
// UI elements
var stonesText = new Text2('Stones: 100', {
size: 40,
fill: 0xFFFFFF
@@ -895,9 +903,10 @@
var currentTime = LK.ticks;
// Update button availability based on cost and cooldown
function getButtonAlpha(golemType, cost) {
var hasEnoughStones = stones >= cost;
- var isOnCooldown = golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < golemCooldownDuration;
+ var cooldownDuration = getGolemCooldownDuration(golemType);
+ var isOnCooldown = golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < cooldownDuration;
return hasEnoughStones && !isOnCooldown ? 1.0 : 0.5;
}
basicButton.alpha = getButtonAlpha('basic', golemCosts.basic);
heavyButton.alpha = getButtonAlpha('heavy', golemCosts.heavy);
@@ -909,10 +918,11 @@
explosiveButton.alpha = getButtonAlpha('explosive', golemCosts.explosive);
shovelButton.alpha = 1.0; // Shovel is always available
// Update cooldown displays
function updateCooldownDisplay(golemType, cooldownText) {
- if (golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < golemCooldownDuration) {
- var remainingTime = Math.ceil((golemCooldownDuration - (currentTime - golemPlacementCooldown[golemType])) / 60);
+ var cooldownDuration = getGolemCooldownDuration(golemType);
+ if (golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < cooldownDuration) {
+ var remainingTime = Math.ceil((cooldownDuration - (currentTime - golemPlacementCooldown[golemType])) / 60);
cooldownText.setText(remainingTime + 's');
cooldownText.alpha = 1;
} else {
cooldownText.alpha = 0;
@@ -1061,11 +1071,12 @@
} else if (!gridOccupied[gridPos.row][gridPos.col]) {
var cost = golemCosts[selectedGolemType];
var currentTime = LK.ticks;
var cooldownKey = selectedGolemType;
+ var cooldownDuration = getGolemCooldownDuration(selectedGolemType);
// Check if golem type is on cooldown
- if (golemPlacementCooldown[cooldownKey] && currentTime - golemPlacementCooldown[cooldownKey] < golemCooldownDuration) {
- var remainingTime = Math.ceil((golemCooldownDuration - (currentTime - golemPlacementCooldown[cooldownKey])) / 60);
+ if (golemPlacementCooldown[cooldownKey] && currentTime - golemPlacementCooldown[cooldownKey] < cooldownDuration) {
+ var remainingTime = Math.ceil((cooldownDuration - (currentTime - golemPlacementCooldown[cooldownKey])) / 60);
cooldownText.setText('Espera ' + remainingTime + 's para colocar ' + selectedGolemType);
cooldownText.alpha = 1;
tween(cooldownText, {
alpha: 0
@@ -1153,8 +1164,12 @@
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
+ // Enable demon spawning after PELEA text is shown
+ demonsCanSpawn = true;
+ // Start first wave immediately after PELEA
+ spawnWave();
// Fade out after showing PELEA
tween(countdownText, {
alpha: 0,
scaleX: 0.5,
@@ -1168,12 +1183,8 @@
}
});
}, 12000);
game.update = function () {
- // Check if initial delay has passed
- if (!demonsCanSpawn && LK.ticks - gameStartTime >= gameStartDelay) {
- demonsCanSpawn = true;
- }
// Update golems
for (var i = golems.length - 1; i >= 0; i--) {
var golem = golems[i];
if (golem.update) golem.update();
un demonio bola grande 2d y semi realista con muchos cuernos y que sus ojos sean negros con pupilas blancas. In-Game asset. 2d. High contrast. No shadows
haz a este personaje mas realista
haz a este personaje mucho mas realista
recrea este personaje mucho mas realista
un golem de cristal muy realista con un cañon en la mano. In-Game asset. 2d. High contrast. No shadows
una roca circular muy realista. In-Game asset. 2d. High contrast. No shadows
haz a este personaje mas realista
una pala de madera realista. In-Game asset. 2d. High contrast. No shadows
un golem de piedra con puas plano en horizontal en 3d muy realista. In-Game asset. 2d. High contrast. No shadows
un golem de piedra que parezca un minero y que se vea ultra realista. In-Game asset. 2d. High contrast. No shadows
un demonio bola ultra realista con una peluca y traje de bailarin con lentes de sol y una sonrisa con colmillos afilados. In-Game asset. 2d. High contrast. No shadows
un golem de piedra listo para pelear con puños con puas ultra realista. In-Game asset. 2d. High contrast. No shadows
un golem de piedra ultra realista con una bomba en la espalda. In-Game asset. 2d. High contrast. No shadows
un demonio bola con un casco de jugador de futbol americano ultra realista. In-Game asset. 2d. High contrast. No shadows
haz esta imagen muy, muy, muy, muy, muy realista, es una piedra con ruedas. In-Game asset. 2d. High contrast. No shadows
una piedra con ojos muy realista con una granada encima. In-Game asset. 2d. High contrast. No shadows
un arbusto ultra realista. In-Game asset. 2d. High contrast. No shadows
una roca ultra realista. In-Game asset. 2d. High contrast. No shadows