User prompt
all demons appear in 60 seconds
User prompt
los demonios aparezcan dentro de 12 segundos
User prompt
los demonios se tarden 12 segundos en aparecer
User prompt
haz que los demonios aparezcan en 12 segundo y aumenta en 1 casilla en rango de todos los golems y que el heavy golem cueste 250 Stones y que las Stones aparezcan mas rapido
User prompt
haz que los demonios ignoren al spikeGolem y que los golems solo puedan atacar en su propia fila y que los demonios aparezcan en 12 segundos y que el basicGolem cueste 100 Stones y que las Stones desaparescan en 5 segundos despues de aparecer ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
mejor haz que los demonios aguanten 12 disparos
User prompt
haz que los demonios puedan comerse a los golems mordiendolos 15 veces y que los demonios tarden 12 segundos en aparecer y que salgan Stones del suelo que los puedas recoger y te den 5 Stones ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
haz el rango del basicGolem sea de 3 casillas y los demonios aguanten 10 disparos
User prompt
haz que el spikeGolem no mate al instante a los demonios
User prompt
haz que el spikeGolem haga poco daño y que los zombies lo ignoren
User prompt
añade a un golem que sea como la pincho hierba de pvz y que los demonios sean mas resistentes
User prompt
haz que el crystalGolem haga menos daño, pero dispare mas rapido y tenga mas rango
User prompt
haz las casillas de pasto mas grandes y aumenta un poco el rango de los golems
User prompt
haz a los iconos de colocar golems mucho mas grandes y mas separados
User prompt
haz el icono de los golems mas grandes y añade una pala para quitar a los golems
User prompt
reduce la velocidad de los demonios y aumenta el rango de los golems
Code edit (1 edits merged)
Please save this source code
User prompt
Stone Guardians vs Demons
Initial prompt
puedes hacer un juego estilo plantas versus zombies, pero que sea golems de piedra versus demonio
/****
* 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 = 300;
self.maxHealth = 300;
self.speed = 0.5;
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 = 240;
self.maxHealth = 240;
self.speed = 1;
self.reward = 15;
} else if (self.type === 'tank') {
assetName = 'tankDemon';
self.health = 600;
self.maxHealth = 600;
self.speed = 0.25;
self.reward = 25;
}
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) {
targetGolem.health = 15; // All 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;
}
// 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 = 640; // Increased by 160 pixels (1 cell)
self.damage = 25;
self.shootDelay = 60; // frames
var assetName = 'basicGolem';
if (self.type === 'heavy') {
assetName = 'heavyGolem';
self.damage = 50;
self.range = 390; // Increased by 160 pixels (1 cell)
self.shootDelay = 90;
} else if (self.type === 'crystal') {
assetName = 'crystalGolem';
self.damage = 20;
self.range = 510; // Increased by 160 pixels (1 cell)
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;
}
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 (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 = 5;
self.bobOffset = Math.random() * Math.PI * 2;
self.spawnTime = LK.ticks;
self.lifespan = 300; // 5 seconds 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)
// Grid system
var gridCols = 8;
var gridRows = 5;
var gridStartX = 400;
var gridStartY = 800;
var cellSize = 160;
// Golem costs
var golemCosts = {
basic: 100,
heavy: 250,
crystal: 75,
barrier: 80,
spike: 60,
shovel: 0
};
// Selected golem type
var selectedGolemType = 'basic';
// 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;
// Golem selection buttons
var buttonY = 200;
var buttonSpacing = 100;
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 shovelButton = LK.getAsset('shovel', {
scaleX: 1.0,
scaleY: 1.0
});
shovelButton.x = 80;
shovelButton.y = buttonY + buttonSpacing * 5;
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 shovelCostText = new Text2('Remove', {
size: 20,
fill: 0xFFFF00
});
shovelCostText.x = 150;
shovelCostText.y = buttonY + buttonSpacing * 5 + 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);
// Update button availability
basicButton.alpha = stones >= golemCosts.basic ? 1.0 : 0.5;
heavyButton.alpha = stones >= golemCosts.heavy ? 1.0 : 0.5;
crystalButton.alpha = stones >= golemCosts.crystal ? 1.0 : 0.5;
barrierButton.alpha = stones >= golemCosts.barrier ? 1.0 : 0.5;
spikeButton.alpha = stones >= golemCosts.spike ? 1.0 : 0.5;
shovelButton.alpha = 1.0; // Shovel is always available
}
function spawnWave() {
var demonsToSpawn = Math.min(3 + Math.floor(wave / 2), 8);
var spawnDelay = 0;
for (var i = 0; i < demonsToSpawn; i++) {
LK.setTimeout(function () {
var demonType = 'basic';
if (wave > 2 && Math.random() < 0.3) demonType = 'fast';
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);
}, spawnDelay);
spawnDelay += 720; // 12 seconds between spawns (720 frames at 60 FPS)
}
}
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();
}
};
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;
shovelButton.tint = selectedGolemType === 'shovel' ? 0x00FF00 : 0xFFFFFF;
}
// Initialize button selection
updateButtonSelection();
// Game click handler
game.down = function (x, y, obj) {
// Check if clicked on a stone first
for (var i = stones_collectible.length - 1; i >= 0; i--) {
var stone = stones_collectible[i];
var dx = x - stone.x;
var dy = y - stone.y;
if (Math.sqrt(dx * dx + dy * dy) < 30) {
// 30 pixel collection radius
stones += stone.value;
stone.destroy();
stones_collectible.splice(i, 1);
updateUI();
return; // Don't process grid placement if we collected a stone
}
}
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];
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;
updateUI();
LK.getSound('place').play();
}
}
}
};
// Initial wave spawn
LK.setTimeout(function () {
spawnWave();
}, 2000);
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);
projectile.destroy();
projectiles.splice(i, 1);
break;
}
}
}
// Update stones
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);
}
}
// 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) {
nextWaveTimer++;
if (nextWaveTimer >= waveDelay) {
wave++;
nextWaveTimer = 0;
spawnWave();
updateUI();
// Victory condition
if (wave > 10) {
LK.setScore(score);
LK.showYouWin();
return;
}
}
}
};
// Initialize UI
updateUI(); ===================================================================
--- original.js
+++ change.js
@@ -458,9 +458,9 @@
demon.y = gridStartY + Math.floor(Math.random() * gridRows) * cellSize;
demons.push(demon);
game.addChild(demon);
}, spawnDelay);
- spawnDelay += 12000; // 12 seconds between spawns
+ spawnDelay += 720; // 12 seconds between spawns (720 frames at 60 FPS)
}
}
function getGridPosition(x, y) {
var col = Math.floor((x - gridStartX + cellSize / 2) / cellSize);
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