Code edit (5 edits merged)
Please save this source code
User prompt
Farklı düşmanlar olsun. Bazen can iksiri düşsün. Daha kapsamlı bir shop olsun
Code edit (6 edits merged)
Please save this source code
User prompt
düşen altınlar otomatik toplansın. range çizgisi gözüksün. Oyun tasarımını modern hale getir.
Code edit (1 edits merged)
Please save this source code
User prompt
Idle Hero: Auto Battle RPG
Initial prompt
Create an idle action RPG game. The main character stands in the center of the screen, while waves of enemies spawn and approach from all directions. The character automatically shoots projectiles at the nearest enemies from a distance. As enemies are defeated, they drop gold and items. Players can spend collected gold in the shop to upgrade their stats (damage, attack speed, range, etc.) and buy new abilities. Add a skill tree or ability selection system where players can unlock and upgrade powerful skills — like area damage, freezing enemies, or summoning turrets. Items can also be upgraded (e.g., Sword +0 → Sword +1), improving their stats just like in traditional RPGs. Include visual effects for upgrades and skill activations. The game should have a simple and intuitive interface, with automatic combat but deep upgrade and progression mechanics. Make sure the difficulty increases gradually with stronger enemy waves.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.damage = 10;
self.lifetime = 120; // frames
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
// Check collision with enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (self.intersects(enemy)) {
enemy.takeDamage(self.damage);
self.destroy();
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
return;
}
}
// Remove if lifetime expired or off screen
if (self.lifetime <= 0 || self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.destroy();
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.maxHealth = 20;
self.damage = 5;
self.speed = 1;
self.goldReward = 5;
self.update = function () {
// Move towards hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Check collision with hero
if (distance < 50) {
hero.takeDamage(self.damage);
self.destroy();
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Drop gold
var gold = new Gold();
gold.x = self.x;
gold.y = self.y;
goldItems.push(gold);
game.addChild(gold);
// Occasionally drop equipment
if (Math.random() < 0.1) {
var equipment = new Equipment();
equipment.x = self.x;
equipment.y = self.y;
equipmentItems.push(equipment);
game.addChild(equipment);
}
self.destroy();
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
LK.getSound('enemyHit').play();
};
return self;
});
var Equipment = Container.expand(function () {
var self = Container.call(this);
var equipmentGraphics = self.attachAsset('equipment', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'sword';
self.level = 0;
self.magnetRange = 200;
self.magnetSpeed = 3;
self.update = function () {
// Magnetic pull towards hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.magnetRange) {
self.x += dx / distance * self.magnetSpeed;
self.y += dy / distance * self.magnetSpeed;
}
// Automatic collection when close
if (distance < 60) {
playerEquipment.push(self.type);
self.destroy();
var index = equipmentItems.indexOf(self);
if (index > -1) {
equipmentItems.splice(index, 1);
}
LK.getSound('pickup').play();
}
};
return self;
});
var Gold = Container.expand(function () {
var self = Container.call(this);
var goldGraphics = self.attachAsset('goldCoin', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 5;
self.magnetRange = 250;
self.magnetSpeed = 4;
self.update = function () {
// Magnetic pull towards hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.magnetRange) {
self.x += dx / distance * self.magnetSpeed;
self.y += dy / distance * self.magnetSpeed;
}
// Automatic collection when close
if (distance < 60) {
playerGold += self.value;
goldText.setText('Gold: ' + playerGold);
self.destroy();
var index = goldItems.indexOf(self);
if (index > -1) {
goldItems.splice(index, 1);
}
LK.getSound('pickup').play();
}
};
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
var rangeCircle = self.attachAsset('rangeCircle', {
anchorX: 0.5,
anchorY: 0.5
});
rangeCircle.alpha = 0.1;
rangeCircle.scaleX = 0.5;
rangeCircle.scaleY = 0.5;
self.rangeCircle = rangeCircle;
self.health = 100;
self.maxHealth = 100;
self.damage = 40;
self.attackSpeed = 60; // frames between shots
self.range = 1200;
self.shootTimer = 0;
self.target = null;
self.update = function () {
self.shootTimer--;
// Update range circle scale
var scale = self.range / 1200;
self.rangeCircle.scaleX = scale * 0.5;
self.rangeCircle.scaleY = scale * 0.5;
// Find nearest enemy in range
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
self.target = nearestEnemy;
// Shoot at target
if (self.target && self.shootTimer <= 0) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.velocityX = dx / distance * 8;
bullet.velocityY = dy / distance * 8;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
self.shootTimer = self.attackSpeed;
LK.getSound('shoot').play();
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0d1117
});
/****
* Game Code
****/
// Game variables
var hero;
var enemies = [];
var bullets = [];
var goldItems = [];
var equipmentItems = [];
var playerGold = 0;
var playerEquipment = [];
var waveNumber = 1;
var enemySpawnTimer = 0;
var enemiesPerWave = 3;
// UI Elements
var goldText = new Text2('Gold: 0', {
size: 40,
fill: '#FFD700'
});
goldText.anchor.set(0, 0);
goldText.x = 120;
goldText.y = 50;
LK.gui.topLeft.addChild(goldText);
var waveText = new Text2('Wave: 1', {
size: 40,
fill: '#FFFFFF'
});
waveText.anchor.set(0.5, 0);
waveText.x = 0;
waveText.y = 50;
LK.gui.top.addChild(waveText);
var healthText = new Text2('Health: 100', {
size: 40,
fill: '#FF0000'
});
healthText.anchor.set(1, 0);
healthText.x = 0;
healthText.y = 50;
LK.gui.topRight.addChild(healthText);
// Upgrade buttons
var damageUpgradeBtn = new Text2('Damage +10 (Cost: 50)', {
size: 35,
fill: '#FFFFFF'
});
damageUpgradeBtn.anchor.set(0.5, 1);
damageUpgradeBtn.x = 0;
damageUpgradeBtn.y = -200;
LK.gui.bottom.addChild(damageUpgradeBtn);
var speedUpgradeBtn = new Text2('Speed +10 (Cost: 75)', {
size: 35,
fill: '#FFFFFF'
});
speedUpgradeBtn.anchor.set(0.5, 1);
speedUpgradeBtn.x = 0;
speedUpgradeBtn.y = -150;
LK.gui.bottom.addChild(speedUpgradeBtn);
var rangeUpgradeBtn = new Text2('Range +50 (Cost: 100)', {
size: 35,
fill: '#FFFFFF'
});
rangeUpgradeBtn.anchor.set(0.5, 1);
rangeUpgradeBtn.x = 0;
rangeUpgradeBtn.y = -100;
LK.gui.bottom.addChild(rangeUpgradeBtn);
// Initialize hero at center
hero = new Hero();
hero.x = 1024;
hero.y = 1366;
game.addChild(hero);
// Upgrade costs
var damageCost = 50;
var speedCost = 75;
var rangeCost = 100;
// Upgrade button handlers
damageUpgradeBtn.down = function () {
if (playerGold >= damageCost) {
playerGold -= damageCost;
hero.damage += 10;
damageCost = Math.floor(damageCost * 1.5);
goldText.setText('Gold: ' + playerGold);
damageUpgradeBtn.setText('Damage +10 (Cost: ' + damageCost + ')');
LK.getSound('upgrade').play();
}
};
speedUpgradeBtn.down = function () {
if (playerGold >= speedCost) {
playerGold -= speedCost;
hero.attackSpeed = Math.max(10, hero.attackSpeed - 5);
speedCost = Math.floor(speedCost * 1.5);
goldText.setText('Gold: ' + playerGold);
speedUpgradeBtn.setText('Speed +10 (Cost: ' + speedCost + ')');
LK.getSound('upgrade').play();
}
};
rangeUpgradeBtn.down = function () {
if (playerGold >= rangeCost) {
playerGold -= rangeCost;
hero.range += 50;
rangeCost = Math.floor(rangeCost * 1.5);
goldText.setText('Gold: ' + playerGold);
rangeUpgradeBtn.setText('Range +50 (Cost: ' + rangeCost + ')');
LK.getSound('upgrade').play();
}
};
function spawnEnemy() {
var enemy = new Enemy();
// Random spawn position at screen edges
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
// Scale enemy stats with wave number
enemy.health = 20 + (waveNumber - 1) * 5;
enemy.maxHealth = enemy.health;
enemy.speed = 1 + (waveNumber - 1) * 0.2;
enemy.goldReward = 5 + (waveNumber - 1) * 2;
enemies.push(enemy);
game.addChild(enemy);
}
game.update = function () {
// Update health display
healthText.setText('Health: ' + hero.health);
// Enemy spawning
enemySpawnTimer++;
var spawnRate = Math.max(30, 120 - waveNumber * 5);
if (enemySpawnTimer >= spawnRate) {
if (enemies.length < enemiesPerWave + Math.floor(waveNumber / 2)) {
spawnEnemy();
enemySpawnTimer = 0;
}
}
// Check for wave completion
if (LK.ticks % 1800 === 0) {
// Every 30 seconds
waveNumber++;
enemiesPerWave = Math.min(15, 3 + Math.floor(waveNumber / 2));
waveText.setText('Wave: ' + waveNumber);
}
// Update all game objects
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].update) {
bullets[i].update();
}
}
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].update) {
enemies[i].update();
}
}
for (var i = goldItems.length - 1; i >= 0; i--) {
if (goldItems[i].update) {
goldItems[i].update();
}
}
for (var i = equipmentItems.length - 1; i >= 0; i--) {
if (equipmentItems[i].update) {
equipmentItems[i].update();
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -50,9 +50,9 @@
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
- self.health = 20;
+ self.health = 10;
self.maxHealth = 20;
self.damage = 5;
self.speed = 1;
self.goldReward = 5;
@@ -112,10 +112,10 @@
anchorY: 0.5
});
self.type = 'sword';
self.level = 0;
- self.magnetRange = 100;
- self.magnetSpeed = 2;
+ self.magnetRange = 200;
+ self.magnetSpeed = 3;
self.update = function () {
// Magnetic pull towards hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
@@ -123,10 +123,10 @@
if (distance < self.magnetRange) {
self.x += dx / distance * self.magnetSpeed;
self.y += dy / distance * self.magnetSpeed;
}
- // Check collection
- if (distance < 30) {
+ // Automatic collection when close
+ if (distance < 60) {
playerEquipment.push(self.type);
self.destroy();
var index = equipmentItems.indexOf(self);
if (index > -1) {
@@ -143,10 +143,10 @@
anchorX: 0.5,
anchorY: 0.5
});
self.value = 5;
- self.magnetRange = 150;
- self.magnetSpeed = 3;
+ self.magnetRange = 250;
+ self.magnetSpeed = 4;
self.update = function () {
// Magnetic pull towards hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
@@ -154,10 +154,10 @@
if (distance < self.magnetRange) {
self.x += dx / distance * self.magnetSpeed;
self.y += dy / distance * self.magnetSpeed;
}
- // Check collection
- if (distance < 30) {
+ // Automatic collection when close
+ if (distance < 60) {
playerGold += self.value;
goldText.setText('Gold: ' + playerGold);
self.destroy();
var index = goldItems.indexOf(self);
@@ -174,17 +174,29 @@
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
+ var rangeCircle = self.attachAsset('rangeCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ rangeCircle.alpha = 0.1;
+ rangeCircle.scaleX = 0.5;
+ rangeCircle.scaleY = 0.5;
+ self.rangeCircle = rangeCircle;
self.health = 100;
self.maxHealth = 100;
- self.damage = 10;
+ self.damage = 40;
self.attackSpeed = 60; // frames between shots
- self.range = 300;
+ self.range = 1200;
self.shootTimer = 0;
self.target = null;
self.update = function () {
self.shootTimer--;
+ // Update range circle scale
+ var scale = self.range / 1200;
+ self.rangeCircle.scaleX = scale * 0.5;
+ self.rangeCircle.scaleY = scale * 0.5;
// Find nearest enemy in range
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
@@ -227,9 +239,9 @@
/****
* Initialize Game
****/
var game = new LK.Game({
- backgroundColor: 0x1a1a2e
+ backgroundColor: 0x0d1117
});
/****
* Game Code