User prompt
haz un nuevo demonio que sea rapido y resistente
User prompt
haz el texto que dice cuanto tiempo falta para que los golems vuelvan a ser colocados mas grande
User prompt
haz que en las imagenes para colocar a los golems aparezca un tiempo de recarga cuando los coloques ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los proyectiles del heavyGolem sean mas grandes y tengan una provabilidad del 25% de empujar para atras a los demonios ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que los demonios no aparezcan al inicio de la partida, sino que se tarden 12 segundos en que aparezcan los primeros demonios
User prompt
haz que los golem y demonios tengan un tiempo de recarga para aparecer o ser colocados ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que el explosiveGolem mate al instante a todos los demonios de su area de 3x3
User prompt
haz que las Stones se tarden 1 segundo en ser recojidas automaticamente ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz un golem que explote en un area de 3x3 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz que las Stones se recojan automaticamente
User prompt
haz que el jugador tenga 12 segundos para prepararse antes de que vengan los demonios y haz que el stoneGolem se tarde 7.5 segundos en producir cada Stone ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
añade un nuevo golem que ataque cuerpo a cuerpo en un radio de 2 casillas delante y detras de el ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
añade que los demonios se tarden 5 segundos en aparecer
User prompt
añade el texto de:listo... preparado... ¡PLANTA!, pero que en ves de eso diga: preparado... listo... ¡PELEA! ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz un tiempo de espera de 3 segundos para que aparezcan los primeros demonios
User prompt
añade un nuevo demonio que sea como el zombie bailon de pvz ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz a los demonios mas resistentes y añade un demonio que sea como el zombie all star de pvz ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz a los iconos de colocar a los golems mucho mas separados
User prompt
haz mas grande los gridcells y que los golems puedan atacar en toda su linea
User prompt
haz que el heavyGolem dispare mas lento que el BasicGolem pero haga mas daño
User prompt
haz que el StoneGolem se tarde 4 segundos en generar cada Stone y que los basicDemon sean mas lentos
User prompt
crea un golem que genere Stones con un precio de 25 Stones y que este golem cueste 50 Stones
User prompt
haz mas resistente al barrierGolem, que aguante 160 mordidas
User prompt
haz que las Stones den 10 Stones en ves de 5
User prompt
At the beginning only 2 demons appear but as you advance between waves more demons appear
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Demon = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
self.health = 450;
self.maxHealth = 450;
self.speed = 0.3;
self.reward = 10;
self.biteDamage = 1;
self.biteDelay = 30; // frames between bites
self.lastBite = 0;
var assetName = 'basicDemon';
if (self.type === 'fast') {
assetName = 'fastDemon';
self.health = 360;
self.maxHealth = 360;
self.speed = 1;
self.reward = 15;
} else if (self.type === 'tank') {
assetName = 'tankDemon';
self.health = 900;
self.maxHealth = 900;
self.speed = 0.25;
self.reward = 25;
} else if (self.type === 'zombieAllStar') {
assetName = 'tankDemon'; // Using tank demon sprite
self.health = 1200;
self.maxHealth = 1200;
self.speed = 0.15;
self.reward = 50;
self.biteDamage = 3;
self.biteDelay = 20; // Faster biting
} else if (self.type === 'dancing') {
assetName = 'dancingDemon';
self.health = 600;
self.maxHealth = 600;
self.speed = 0.4;
self.reward = 30;
self.biteDamage = 2;
self.biteDelay = 25;
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();
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 () {
var self = Container.call(this);
var graphics = self.attachAsset('projectile', {
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
var lastStoneSpawn = 0;
var stoneSpawnDelay = 150; // frames between stone spawns (faster spawning)
// 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
var lastGolemPlacement = 0;
// 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);
// 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 isOnCooldown = golemPlacementCooldown[golemType] && currentTime - golemPlacementCooldown[golemType] < golemCooldownDuration;
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
}
function spawnWave() {
// Don't spawn demons if initial delay hasn't passed
if (!demonsCanSpawn) {
return;
}
var demonsToSpawn = 2 + Math.floor((wave - 1) * 0.8); // Start with 2, gradually increase
var spawnDelay = 300; // 5 seconds delay (300 frames at 60 FPS)
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';
if (wave > 2 && Math.random() < 0.3) demonType = 'fast';
if (wave > 3 && Math.random() < 0.25) demonType = 'dancing';
if (wave > 4 && Math.random() < 0.2) demonType = 'tank';
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 += 450; // Spread spawns over 60 seconds total (450 frames = 7.5 seconds between spawns)
}
}
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;
// Check if golem type is on cooldown
if (golemPlacementCooldown[cooldownKey] && currentTime - golemPlacementCooldown[cooldownKey] < golemCooldownDuration) {
var remainingTime = Math.ceil((golemCooldownDuration - (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() {
// 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 () {
// 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();
}
// 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);
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);
}
}
// 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
@@ -550,8 +550,12 @@
var stoneSpawnDelay = 150; // frames between stone spawns (faster spawning)
// 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;
@@ -795,8 +799,12 @@
explosiveButton.alpha = getButtonAlpha('explosive', golemCosts.explosive);
shovelButton.alpha = 1.0; // Shovel is always available
}
function spawnWave() {
+ // Don't spawn demons if initial delay hasn't passed
+ if (!demonsCanSpawn) {
+ return;
+ }
var demonsToSpawn = 2 + Math.floor((wave - 1) * 0.8); // Start with 2, gradually increase
var spawnDelay = 300; // 5 seconds delay (300 frames at 60 FPS)
for (var i = 0; i < demonsToSpawn; i++) {
LK.setTimeout(function () {
@@ -1022,12 +1030,14 @@
}
});
}
});
- // Start the first wave
- spawnWave();
}, 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();
@@ -1137,9 +1147,9 @@
game.addChild(stone);
lastStoneSpawn = LK.ticks;
}
// Wave management
- if (demons.length === 0) {
+ if (demons.length === 0 && demonsCanSpawn) {
nextWaveTimer++;
if (nextWaveTimer >= waveDelay) {
wave++;
nextWaveTimer = 0;
@@ -1153,6 +1163,8 @@
}
}
}
};
+// Initialize game start time
+gameStartTime = LK.ticks;
// Initialize UI
updateUI();
\ No newline at end of file
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