User prompt
Elimina las texturas del suelo
User prompt
Ponerles texturas al suelo también
User prompt
Aumenta la velocidad de movimiento del jugador
User prompt
Hacer un perro ciborg aliado q nos va a ayudar a eliminar a los enemigos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Elimina algunas estructuras si es necesario para que el rendimiento no se vea afectado
User prompt
Aumenta la velocidad del jugador y has que sea cómodo de controlar y puedas moverte y disparar a la vez ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Mejorar el rendimiento del jugador y su velocidad, añadir un botón circular para el moverlo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Mejorar el movimiento del jugador ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Elimina alguna estructuras del mapa
User prompt
Optimizar el rendimiento
User prompt
Vamos a añadir estructuras al mapa con colisiones y texturas, añadir cosas como árboles, coches destruidos, rocas y así
User prompt
Agregar las texturas para los nuevo tipos de enemigos también
User prompt
Vamos a agregar mayor variedad de enemigos 2 o 3 más
Code edit (1 edits merged)
Please save this source code
User prompt
Cyborg Vengeance: Crystal Defense
Initial prompt
Un mundo **posapocalíptico** donde las máquinas se revelaron para acabar con los humanos, controlamos a un ciborg el cual quiere vengarse de las máquinas, entonces tendremos que sobrevivir a oleadas de enemigos diversos todos con características y patrones de ataques únicos, en un entorno interactivo inspirado en una ciudad en ruinas. Al morir los enemigos nos darán engranaje y algunos darán partes como: brazos, piernas y otras cosas que el jugador se podrá equipar pagando engranajes. Estas piezas mejorarán cosas como el ataque, la defensa, velocidad entre otras cosas. Todo esto mientras defiende un cristal en el centro de la ciudad el cual tiene una barrera y usaremos las baterías de los enemigos que nos atacan para recuperar la energía de la barrera, también estando cerca del cristal podremos curarnos
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Barrier = Container.expand(function () {
var self = Container.call(this);
var barrierGraphics = self.attachAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Update barrier visibility based on energy
var energyPercent = crystal.barrierEnergy / crystal.maxBarrierEnergy;
barrierGraphics.alpha = energyPercent * 0.3;
if (energyPercent > 0.5) {
barrierGraphics.tint = 0x00FFFF;
} else if (energyPercent > 0.25) {
barrierGraphics.tint = 0xFFFF00;
} else {
barrierGraphics.tint = 0xFF4500;
}
};
return self;
});
var Battery = Container.expand(function () {
var self = Container.call(this);
var batteryGraphics = self.attachAsset('battery', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Check if cyborg is close enough to collect
var distToCyborg = Math.sqrt(Math.pow(self.x - cyborg.x, 2) + Math.pow(self.y - cyborg.y, 2));
if (distToCyborg < 40) {
crystal.restoreBarrier(20);
LK.getSound('collect').play();
// Remove from batteries array
for (var i = batteries.length - 1; i >= 0; i--) {
if (batteries[i] === self) {
batteries.splice(i, 1);
break;
}
}
returnBatteryToPool(self);
}
};
return self;
});
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 = 25;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (self.intersects(enemy)) {
enemy.takeDamage(self.damage);
// Remove bullet
for (var j = bullets.length - 1; j >= 0; j--) {
if (bullets[j] === self) {
bullets.splice(j, 1);
break;
}
}
returnBulletToPool(self);
return;
}
}
// Check collision with structures
for (var s = structures.length - 1; s >= 0; s--) {
if (self.intersects(structures[s])) {
// Remove bullet
for (var p = bullets.length - 1; p >= 0; p--) {
if (bullets[p] === self) {
bullets.splice(p, 1);
break;
}
}
returnBulletToPool(self);
return;
}
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
for (var k = bullets.length - 1; k >= 0; k--) {
if (bullets[k] === self) {
bullets.splice(k, 1);
break;
}
}
returnBulletToPool(self);
}
};
return self;
});
var Crystal = Container.expand(function () {
var self = Container.call(this);
var crystalGraphics = self.attachAsset('crystal', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 500;
self.maxHealth = 500;
self.barrierEnergy = 100;
self.maxBarrierEnergy = 100;
self.takeDamage = function (damage) {
if (self.barrierEnergy > 0) {
self.barrierEnergy -= damage;
if (self.barrierEnergy < 0) {
var overflow = -self.barrierEnergy;
self.barrierEnergy = 0;
self.health -= overflow;
}
} else {
self.health -= damage;
}
crystalHealthText.setText('Crystal: ' + Math.floor(self.health));
barrierText.setText('Barrier: ' + Math.floor(self.barrierEnergy));
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
LK.showGameOver();
}
};
self.restoreBarrier = function (amount) {
self.barrierEnergy += amount;
if (self.barrierEnergy > self.maxBarrierEnergy) {
self.barrierEnergy = self.maxBarrierEnergy;
}
barrierText.setText('Barrier: ' + Math.floor(self.barrierEnergy));
};
return self;
});
var Cyborg = Container.expand(function () {
var self = Container.call(this);
var cyborgGraphics = self.attachAsset('cyborg', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 12; // Increased from 8 to 12 for even faster movement
self.attackDamage = 25;
self.shootCooldown = 0;
self.isNearCrystal = false;
self.update = function () {
// Store previous position for rotation calculation
if (self.lastX === undefined) self.lastX = self.x;
if (self.lastY === undefined) self.lastY = self.y;
// Handle movement button input with improved responsiveness
if (isMoving && (Math.abs(movementDirection.x) > 0.05 || Math.abs(movementDirection.y) > 0.05)) {
var speedMultiplier = 2.0; // Boost speed when using movement button
var newX = self.x + movementDirection.x * self.speed * speedMultiplier;
var newY = self.y + movementDirection.y * self.speed * speedMultiplier;
// Check bounds
newX = Math.max(40, Math.min(2008, newX));
newY = Math.max(40, Math.min(2692, newY));
// Check structure collision
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
}
}
// Calculate movement direction for smooth rotation
var dx = self.x - self.lastX;
var dy = self.y - self.lastY;
var movementDistance = Math.sqrt(dx * dx + dy * dy);
// Only rotate if actually moving
if (movementDistance > 0.5) {
var targetRotation = Math.atan2(dy, dx) + Math.PI / 2;
// Smooth rotation towards movement direction
var currentRotation = cyborgGraphics.rotation;
var rotationDiff = targetRotation - currentRotation;
// Handle rotation wrap-around
if (rotationDiff > Math.PI) rotationDiff -= 2 * Math.PI;
if (rotationDiff < -Math.PI) rotationDiff += 2 * Math.PI;
// Apply smooth rotation
cyborgGraphics.rotation += rotationDiff * 0.3; // Increased from 0.2 to 0.3 for even faster rotation
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
// Check if near crystal for healing
var distToCrystal = Math.sqrt(Math.pow(self.x - crystal.x, 2) + Math.pow(self.y - crystal.y, 2));
self.isNearCrystal = distToCrystal < 150;
// Heal when near crystal
if (self.isNearCrystal && self.health < self.maxHealth) {
self.health += 0.5;
if (self.health > self.maxHealth) self.health = self.maxHealth;
healthText.setText('Health: ' + Math.floor(self.health));
}
// Reduce shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Visual feedback when near crystal with smooth color transitions
if (self.isNearCrystal) {
tween(cyborgGraphics, {
tint: 0x90EE90
}, {
duration: 200,
easing: tween.easeOut
});
} else {
tween(cyborgGraphics, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
};
self.shoot = function (targetX, targetY) {
if (self.shootCooldown <= 0) {
var bullet = getPooledBullet();
bullet.x = self.x;
bullet.y = self.y;
var angle = Math.atan2(targetY - self.y, targetX - self.x);
bullet.velocityX = Math.cos(angle) * 8;
bullet.velocityY = Math.sin(angle) * 8;
bullets.push(bullet);
game.addChild(bullet);
self.shootCooldown = 10; // Reduced from 15 to 10 for even faster shooting
LK.getSound('shoot').play();
// Add subtle recoil animation that doesn't interfere with movement
var recoilDistance = 4; // Reduced from 8 to 4 for less movement interference
var recoilX = self.x - Math.cos(angle) * recoilDistance;
var recoilY = self.y - Math.sin(angle) * recoilDistance;
var originalX = self.x;
var originalY = self.y;
// Quick recoil back - only if not actively moving
if (!isMoving) {
tween(self, {
x: recoilX,
y: recoilY
}, {
duration: 50,
// Reduced from 80 to 50
easing: tween.easeOut,
onFinish: function onFinish() {
// Spring back to original position
tween(self, {
x: originalX,
y: originalY
}, {
duration: 80,
// Reduced from 120 to 80
easing: tween.easeOut
});
}
});
}
// Add shooting flash effect
tween(cyborgGraphics, {
tint: 0xFFFFAA
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(cyborgGraphics, {
tint: self.isNearCrystal ? 0x90EE90 : 0xFFFFFF
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
};
self.takeDamage = function (damage) {
self.health -= damage;
healthText.setText('Health: ' + Math.floor(self.health));
LK.effects.flashObject(self, 0xFF0000, 300);
// Add impact animation
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Add screen shake effect by briefly moving the cyborg
var shakeIntensity = damage * 0.3;
var originalX = self.x;
var originalY = self.y;
tween(self, {
x: originalX + shakeIntensity,
y: originalY + shakeIntensity
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
x: originalX - shakeIntensity,
y: originalY - shakeIntensity
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
x: originalX,
y: originalY
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
if (self.health <= 0) {
LK.showGameOver();
}
};
return self;
});
var CyborgDog = Container.expand(function () {
var self = Container.call(this);
var dogGraphics = self.attachAsset('cyborgDog', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 80;
self.maxHealth = 80;
self.speed = 6;
self.attackDamage = 20;
self.shootCooldown = 0;
self.followDistance = 100;
self.lastX = 0;
self.lastY = 0;
self.targetEnemy = null;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Find closest enemy to attack
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var distance = Math.sqrt(Math.pow(self.x - enemy.x, 2) + Math.pow(self.y - enemy.y, 2));
if (distance < closestDistance && distance < 400) {
closestDistance = distance;
closestEnemy = enemy;
}
}
self.targetEnemy = closestEnemy;
// Movement behavior
if (self.targetEnemy) {
// Combat mode: move towards enemy but maintain some distance
var enemyAngle = Math.atan2(self.targetEnemy.y - self.y, self.targetEnemy.x - self.x);
var targetDistance = 120; // Preferred combat distance
if (closestDistance > targetDistance + 20) {
// Move closer to enemy
var newX = self.x + Math.cos(enemyAngle) * self.speed;
var newY = self.y + Math.sin(enemyAngle) * self.speed;
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
}
} else if (closestDistance < targetDistance - 20) {
// Move away from enemy (too close)
var newX = self.x - Math.cos(enemyAngle) * self.speed * 0.5;
var newY = self.y - Math.sin(enemyAngle) * self.speed * 0.5;
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
}
}
// Shoot at enemy
if (self.shootCooldown <= 0 && closestDistance < 300) {
self.shootAtEnemy(self.targetEnemy);
self.shootCooldown = 25;
}
} else {
// Follow mode: stay near cyborg
var distToCyborg = Math.sqrt(Math.pow(self.x - cyborg.x, 2) + Math.pow(self.y - cyborg.y, 2));
if (distToCyborg > self.followDistance) {
var followAngle = Math.atan2(cyborg.y - self.y, cyborg.x - self.x);
var newX = self.x + Math.cos(followAngle) * self.speed;
var newY = self.y + Math.sin(followAngle) * self.speed;
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
}
}
}
// Rotation towards movement direction
var dx = self.x - self.lastX;
var dy = self.y - self.lastY;
var movementDistance = Math.sqrt(dx * dx + dy * dy);
if (movementDistance > 0.5) {
var targetRotation = Math.atan2(dy, dx) + Math.PI / 2;
var currentRotation = dogGraphics.rotation;
var rotationDiff = targetRotation - currentRotation;
if (rotationDiff > Math.PI) rotationDiff -= 2 * Math.PI;
if (rotationDiff < -Math.PI) rotationDiff += 2 * Math.PI;
dogGraphics.rotation += rotationDiff * 0.25;
}
// Reduce shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Visual feedback based on mode
if (self.targetEnemy) {
// Combat mode - red tint
tween(dogGraphics, {
tint: 0xFFAAAA
}, {
duration: 200,
easing: tween.easeOut
});
} else {
// Follow mode - green tint
tween(dogGraphics, {
tint: 0xAAFFAA
}, {
duration: 200,
easing: tween.easeOut
});
}
};
self.shootAtEnemy = function (enemy) {
var bullet = getPooledBullet();
bullet.x = self.x;
bullet.y = self.y;
var angle = Math.atan2(enemy.y - self.y, enemy.x - self.x);
bullet.velocityX = Math.cos(angle) * 7;
bullet.velocityY = Math.sin(angle) * 7;
bullet.damage = self.attackDamage;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
// Muzzle flash effect
tween(dogGraphics, {
tint: 0xFFFFAA
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(dogGraphics, {
tint: self.targetEnemy ? 0xFFAAAA : 0xAAFFAA
}, {
duration: 100,
easing: tween.easeIn
});
}
});
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 300);
// Impact animation
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Visual death effect
tween(dogGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
// Respawn after 10 seconds
LK.setTimeout(function () {
self.health = self.maxHealth;
self.x = cyborg.x + 50;
self.y = cyborg.y + 50;
dogGraphics.alpha = 1;
dogGraphics.scaleX = 1;
dogGraphics.scaleY = 1;
}, 10000);
}
});
};
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 = 50;
self.speed = 1;
self.attackDamage = 15;
self.attackCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Move towards crystal
var angle = Math.atan2(crystal.y - self.y, crystal.x - self.x);
var newX = self.x + Math.cos(angle) * self.speed;
var newY = self.y + Math.sin(angle) * self.speed;
// Check structure collision
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
} else {
// Try to move around obstacle
var sideAngle = angle + Math.PI / 2;
var sideX = self.x + Math.cos(sideAngle) * self.speed;
var sideY = self.y + Math.sin(sideAngle) * self.speed;
if (!checkStructureCollision(self, sideX, sideY)) {
self.x = sideX;
self.y = sideY;
}
}
// Attack crystal if close enough
var distToCrystal = Math.sqrt(Math.pow(self.x - crystal.x, 2) + Math.pow(self.y - crystal.y, 2));
if (distToCrystal < 160 && self.attackCooldown <= 0) {
crystal.takeDamage(self.attackDamage);
self.attackCooldown = 60;
LK.effects.flashObject(self, 0xFFFFFF, 200);
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Drop gear
var gear = getPooledGear();
gear.x = self.x;
gear.y = self.y;
gears.push(gear);
game.addChild(gear);
// Sometimes drop battery
if (Math.random() < 0.3) {
var battery = getPooledBattery();
battery.x = self.x + (Math.random() - 0.5) * 40;
battery.y = self.y + (Math.random() - 0.5) * 40;
batteries.push(battery);
game.addChild(battery);
}
LK.getSound('enemyHit').play();
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.tint = 0xFF0000; // Red tint for enemy bullets
self.velocityX = 0;
self.velocityY = 0;
self.damage = 20;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with cyborg
if (self.intersects(cyborg)) {
cyborg.takeDamage(self.damage);
// Remove bullet
for (var i = enemyBullets.length - 1; i >= 0; i--) {
if (enemyBullets[i] === self) {
enemyBullets.splice(i, 1);
break;
}
}
returnEnemyBulletToPool(self);
return;
}
// Check collision with cyborg dog
if (self.intersects(cyborgDog)) {
cyborgDog.takeDamage(self.damage);
// Remove bullet
for (var i = enemyBullets.length - 1; i >= 0; i--) {
if (enemyBullets[i] === self) {
enemyBullets.splice(i, 1);
break;
}
}
returnEnemyBulletToPool(self);
return;
}
// Check collision with structures
for (var s = structures.length - 1; s >= 0; s--) {
if (self.intersects(structures[s])) {
// Remove bullet
for (var p = enemyBullets.length - 1; p >= 0; p--) {
if (enemyBullets[p] === self) {
enemyBullets.splice(p, 1);
break;
}
}
returnEnemyBulletToPool(self);
return;
}
}
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
for (var j = enemyBullets.length - 1; j >= 0; j--) {
if (enemyBullets[j] === self) {
enemyBullets.splice(j, 1);
break;
}
}
returnEnemyBulletToPool(self);
}
};
return self;
});
var FastEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('fastEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.speed = 2.5;
self.attackDamage = 10;
self.attackCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Move towards crystal with erratic movement
var angle = Math.atan2(crystal.y - self.y, crystal.x - self.x);
var wobble = Math.sin(LK.ticks * 0.1) * 0.5;
var newX = self.x + Math.cos(angle + wobble) * self.speed;
var newY = self.y + Math.sin(angle + wobble) * self.speed;
// Check structure collision
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
} else {
// Try to move around obstacle
var sideAngle = angle + Math.PI / 2;
var sideX = self.x + Math.cos(sideAngle) * self.speed;
var sideY = self.y + Math.sin(sideAngle) * self.speed;
if (!checkStructureCollision(self, sideX, sideY)) {
self.x = sideX;
self.y = sideY;
}
}
// Attack crystal if close enough
var distToCrystal = Math.sqrt(Math.pow(self.x - crystal.x, 2) + Math.pow(self.y - crystal.y, 2));
if (distToCrystal < 160 && self.attackCooldown <= 0) {
crystal.takeDamage(self.attackDamage);
self.attackCooldown = 40;
LK.effects.flashObject(self, 0xFFFFFF, 200);
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Drop gear
var gear = new Gear();
gear.x = self.x;
gear.y = self.y;
gears.push(gear);
game.addChild(gear);
// Sometimes drop battery
if (Math.random() < 0.25) {
var battery = new Battery();
battery.x = self.x + (Math.random() - 0.5) * 40;
battery.y = self.y + (Math.random() - 0.5) * 40;
batteries.push(battery);
game.addChild(battery);
}
LK.getSound('enemyHit').play();
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
var Gear = Container.expand(function () {
var self = Container.call(this);
var gearGraphics = self.attachAsset('gear', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
gearGraphics.rotation += 0.1;
// Check if cyborg is close enough to collect
var distToCyborg = Math.sqrt(Math.pow(self.x - cyborg.x, 2) + Math.pow(self.y - cyborg.y, 2));
if (distToCyborg < 40) {
gearCount++;
gearsText.setText('Gears: ' + gearCount);
LK.getSound('collect').play();
// Remove from gears array
for (var i = gears.length - 1; i >= 0; i--) {
if (gears[i] === self) {
gears.splice(i, 1);
break;
}
}
returnGearToPool(self);
}
};
return self;
});
var MovementButton = Container.expand(function () {
var self = Container.call(this);
// Outer circle (background)
var outerCircle = self.attachAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
alpha: 0.3
});
// Inner circle (knob)
var innerCircle = self.attachAsset('cyborg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.outerRadius = 60;
self.innerRadius = 25;
self.centerX = 0;
self.centerY = 0;
self.isDragging = false;
self.down = function (x, y, obj) {
self.isDragging = true;
isMoving = true;
self.updateKnob(x, y);
};
self.up = function (x, y, obj) {
self.isDragging = false;
isMoving = false;
movementDirection.x = 0;
movementDirection.y = 0;
// Animate knob back to center
tween(innerCircle, {
x: 0,
y: 0
}, {
duration: 200,
easing: tween.easeOut
});
};
self.move = function (x, y, obj) {
if (self.isDragging) {
self.updateKnob(x, y);
}
};
self.updateKnob = function (x, y) {
var dx = x - self.centerX;
var dy = y - self.centerY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.outerRadius) {
dx = dx / distance * self.outerRadius;
dy = dy / distance * self.outerRadius;
distance = self.outerRadius;
}
innerCircle.x = dx;
innerCircle.y = dy;
// Calculate normalized movement direction with improved sensitivity
var strength = Math.min(distance / self.outerRadius, 1.0);
var sensitivity = 1.5; // Increase sensitivity for better control
movementDirection.x = dx / self.outerRadius * strength * sensitivity;
movementDirection.y = dy / self.outerRadius * strength * sensitivity;
};
return self;
});
var RangedEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('rangedEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 40;
self.speed = 1.2;
self.attackDamage = 12;
self.attackCooldown = 0;
self.shootCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Stay at medium distance from crystal
var distToCrystal = Math.sqrt(Math.pow(self.x - crystal.x, 2) + Math.pow(self.y - crystal.y, 2));
var angle = Math.atan2(crystal.y - self.y, crystal.x - self.x);
if (distToCrystal > 400) {
// Move closer
var newX = self.x + Math.cos(angle) * self.speed;
var newY = self.y + Math.sin(angle) * self.speed;
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
}
} else if (distToCrystal < 300) {
// Move away
var newX = self.x - Math.cos(angle) * self.speed;
var newY = self.y - Math.sin(angle) * self.speed;
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
}
}
// Shoot at cyborg
if (self.shootCooldown <= 0) {
var distToCyborg = Math.sqrt(Math.pow(self.x - cyborg.x, 2) + Math.pow(self.y - cyborg.y, 2));
if (distToCyborg < 500) {
self.shootAtCyborg();
self.shootCooldown = 120;
}
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Attack crystal if close enough
if (distToCrystal < 160 && self.attackCooldown <= 0) {
crystal.takeDamage(self.attackDamage);
self.attackCooldown = 60;
LK.effects.flashObject(self, 0xFFFFFF, 200);
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
};
self.shootAtCyborg = function () {
var bullet = getPooledEnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var angle = Math.atan2(cyborg.y - self.y, cyborg.x - self.x);
bullet.velocityX = Math.cos(angle) * 4;
bullet.velocityY = Math.sin(angle) * 4;
enemyBullets.push(bullet);
game.addChild(bullet);
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Drop gear
var gear = new Gear();
gear.x = self.x;
gear.y = self.y;
gears.push(gear);
game.addChild(gear);
// Sometimes drop battery
if (Math.random() < 0.3) {
var battery = new Battery();
battery.x = self.x + (Math.random() - 0.5) * 40;
battery.y = self.y + (Math.random() - 0.5) * 40;
batteries.push(battery);
game.addChild(battery);
}
LK.getSound('enemyHit').play();
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
var Structure = Container.expand(function (type) {
var self = Container.call(this);
var structureGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.structureType = type;
return self;
});
var TankEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('tankEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 120;
self.speed = 0.7;
self.attackDamage = 30;
self.attackCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Move towards crystal steadily
var angle = Math.atan2(crystal.y - self.y, crystal.x - self.x);
var newX = self.x + Math.cos(angle) * self.speed;
var newY = self.y + Math.sin(angle) * self.speed;
// Check structure collision
if (!checkStructureCollision(self, newX, newY)) {
self.x = newX;
self.y = newY;
} else {
// Try to move around obstacle
var sideAngle = angle + Math.PI / 2;
var sideX = self.x + Math.cos(sideAngle) * self.speed;
var sideY = self.y + Math.sin(sideAngle) * self.speed;
if (!checkStructureCollision(self, sideX, sideY)) {
self.x = sideX;
self.y = sideY;
}
}
// Attack crystal if close enough
var distToCrystal = Math.sqrt(Math.pow(self.x - crystal.x, 2) + Math.pow(self.y - crystal.y, 2));
if (distToCrystal < 160 && self.attackCooldown <= 0) {
crystal.takeDamage(self.attackDamage);
self.attackCooldown = 90;
LK.effects.flashObject(self, 0xFFFFFF, 300);
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
};
self.takeDamage = function (damage) {
self.health -= Math.floor(damage * 0.7); // Reduced damage
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// Drop more gear
var gear = new Gear();
gear.x = self.x;
gear.y = self.y;
gears.push(gear);
game.addChild(gear);
// Drop extra gear
if (Math.random() < 0.6) {
var gear2 = new Gear();
gear2.x = self.x + (Math.random() - 0.5) * 30;
gear2.y = self.y + (Math.random() - 0.5) * 30;
gears.push(gear2);
game.addChild(gear2);
}
// Sometimes drop battery
if (Math.random() < 0.4) {
var battery = new Battery();
battery.x = self.x + (Math.random() - 0.5) * 40;
battery.y = self.y + (Math.random() - 0.5) * 40;
batteries.push(battery);
game.addChild(battery);
}
LK.getSound('enemyHit').play();
// Remove from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F2F2F
});
/****
* Game Code
****/
// Game variables
var cyborg;
var cyborgDog;
var crystal;
var barrier;
var enemies = [];
var bullets = [];
var enemyBullets = [];
var gears = [];
var batteries = [];
var structures = [];
var gearCount = 0;
var waveNumber = 1;
var enemySpawnTimer = 0;
var enemiesPerWave = 5;
var waveTimer = 0;
var waveDelay = 300;
// Object pools for performance
var bulletPool = [];
var enemyBulletPool = [];
var gearPool = [];
var batteryPool = [];
var maxPoolSize = 50;
// Movement control variables
var movementButton;
var isMoving = false;
var movementDirection = {
x: 0,
y: 0
};
// UI elements
var healthText = new Text2('Health: 100', {
size: 40,
fill: 0xFFFFFF
});
healthText.anchor.set(0, 0);
healthText.x = 120;
healthText.y = 50;
LK.gui.topLeft.addChild(healthText);
var crystalHealthText = new Text2('Crystal: 500', {
size: 40,
fill: 0x00FFFF
});
crystalHealthText.anchor.set(0.5, 0);
crystalHealthText.x = 1024;
crystalHealthText.y = 50;
LK.gui.top.addChild(crystalHealthText);
var barrierText = new Text2('Barrier: 100', {
size: 40,
fill: 0x00FFFF
});
barrierText.anchor.set(1, 0);
barrierText.x = 1928;
barrierText.y = 50;
LK.gui.topRight.addChild(barrierText);
var gearsText = new Text2('Gears: 0', {
size: 40,
fill: 0xFFD700
});
gearsText.anchor.set(0, 0);
gearsText.x = 120;
gearsText.y = 100;
LK.gui.topLeft.addChild(gearsText);
var waveText = new Text2('Wave: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
waveText.x = 1024;
waveText.y = 100;
LK.gui.top.addChild(waveText);
// Initialize game objects
crystal = game.addChild(new Crystal());
crystal.x = 1024;
crystal.y = 1366;
barrier = game.addChild(new Barrier());
barrier.x = crystal.x;
barrier.y = crystal.y;
cyborg = game.addChild(new Cyborg());
cyborg.x = 1024;
cyborg.y = 1200;
// Create cyborg dog ally
cyborgDog = game.addChild(new CyborgDog());
cyborgDog.x = cyborg.x + 80;
cyborgDog.y = cyborg.y + 80;
// Create movement button
movementButton = new MovementButton();
movementButton.x = 180;
movementButton.y = 2400; // Moved up slightly for better thumb reach
movementButton.centerX = movementButton.x;
movementButton.centerY = movementButton.y;
LK.gui.bottomLeft.addChild(movementButton);
// Create map structures
createMapStructures();
// Event handlers
game.down = function (x, y, obj) {
cyborg.shoot(x, y);
};
game.move = function (x, y, obj) {
// Only handle tap-to-move if not using movement button
if (!isMoving) {
var dx = x - cyborg.x;
var dy = y - cyborg.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 10) {
// Calculate target position with bounds checking
var targetX = Math.max(40, Math.min(2008, x));
var targetY = Math.max(40, Math.min(2692, y));
// Check if target position would collide with structures
var tempX = cyborg.x;
var tempY = cyborg.y;
cyborg.x = targetX;
cyborg.y = targetY;
var wouldCollide = false;
for (var i = 0; i < structures.length; i++) {
if (cyborg.intersects(structures[i])) {
wouldCollide = true;
break;
}
}
cyborg.x = tempX;
cyborg.y = tempY;
if (!wouldCollide) {
// Stop any existing movement tween
tween.stop(cyborg, {
x: true,
y: true
});
// Create smooth movement tween with faster speed
tween(cyborg, {
x: targetX,
y: targetY
}, {
duration: distance * 8,
// Reduced from 15 to 8 for even faster movement
// Dynamic duration based on distance
easing: tween.easeOut,
onFinish: function onFinish() {
// Optional: Add a subtle bounce effect when reaching destination
tween(cyborg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(cyborg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
});
}
}
}
};
function createMapStructures() {
// Create trees
var treePositions = [{
x: 300,
y: 400
}, {
x: 1700,
y: 1100
}];
for (var i = 0; i < treePositions.length; i++) {
var tree = new Structure('tree');
tree.x = treePositions[i].x;
tree.y = treePositions[i].y;
structures.push(tree);
game.addChild(tree);
}
// Create destroyed cars
var carPositions = [{
x: 600,
y: 500
}, {
x: 1400,
y: 700
}];
for (var j = 0; j < carPositions.length; j++) {
var car = new Structure('destroyedCar');
car.x = carPositions[j].x;
car.y = carPositions[j].y;
structures.push(car);
game.addChild(car);
}
// Create rocks
var rockPositions = [{
x: 700,
y: 900
}, {
x: 1300,
y: 1200
}];
for (var k = 0; k < rockPositions.length; k++) {
var rock = new Structure('rock');
rock.x = rockPositions[k].x;
rock.y = rockPositions[k].y;
structures.push(rock);
game.addChild(rock);
}
}
function spawnEnemy() {
var enemy;
// Randomly choose enemy type based on wave number
var enemyType = Math.random();
if (enemyType < 0.4) {
enemy = new Enemy();
} else if (enemyType < 0.7) {
enemy = new FastEnemy();
} else if (enemyType < 0.9) {
enemy = new RangedEnemy();
} else {
enemy = new TankEnemy();
}
// Spawn from random edge
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -30;
break;
case 1:
// Right
enemy.x = 2078;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2762;
break;
case 3:
// Left
enemy.x = -30;
enemy.y = Math.random() * 2732;
break;
}
enemies.push(enemy);
game.addChild(enemy);
}
function checkStructureCollision(obj, newX, newY) {
var tempX = obj.x;
var tempY = obj.y;
obj.x = newX;
obj.y = newY;
for (var i = 0; i < structures.length; i++) {
if (obj.intersects(structures[i])) {
obj.x = tempX;
obj.y = tempY;
return true;
}
}
return false;
}
function getPooledBullet() {
if (bulletPool.length > 0) {
return bulletPool.pop();
}
return new Bullet();
}
function returnBulletToPool(bullet) {
if (bulletPool.length < maxPoolSize) {
bulletPool.push(bullet);
game.removeChild(bullet);
} else {
bullet.destroy();
}
}
function getPooledEnemyBullet() {
if (enemyBulletPool.length > 0) {
return enemyBulletPool.pop();
}
return new EnemyBullet();
}
function returnEnemyBulletToPool(bullet) {
if (enemyBulletPool.length < maxPoolSize) {
enemyBulletPool.push(bullet);
game.removeChild(bullet);
} else {
bullet.destroy();
}
}
function getPooledGear() {
if (gearPool.length > 0) {
return gearPool.pop();
}
return new Gear();
}
function returnGearToPool(gear) {
if (gearPool.length < maxPoolSize) {
gearPool.push(gear);
game.removeChild(gear);
} else {
gear.destroy();
}
}
function getPooledBattery() {
if (batteryPool.length > 0) {
return batteryPool.pop();
}
return new Battery();
}
function returnBatteryToPool(battery) {
if (batteryPool.length < maxPoolSize) {
batteryPool.push(battery);
game.removeChild(battery);
} else {
battery.destroy();
}
}
function startNewWave() {
waveNumber++;
waveText.setText('Wave: ' + waveNumber);
enemiesPerWave = Math.floor(5 + waveNumber * 1.5);
waveTimer = 0;
// Spawn enemies for this wave
for (var i = 0; i < enemiesPerWave; i++) {
LK.setTimeout(function () {
spawnEnemy();
}, i * 1000);
}
}
// Main game loop
game.update = function () {
// Update wave timer
waveTimer++;
// Check if wave is complete (no enemies left and enough time passed)
if (enemies.length === 0 && waveTimer > waveDelay) {
startNewWave();
}
// Update all bullets (optimized loop)
var i = bullets.length;
while (i--) {
bullets[i].update();
}
// Update all enemy bullets (optimized loop)
var m = enemyBullets.length;
while (m--) {
enemyBullets[m].update();
}
// Update all enemies (optimized loop)
var j = enemies.length;
while (j--) {
enemies[j].update();
}
// Update all gears (optimized loop)
var k = gears.length;
while (k--) {
gears[k].update();
}
// Update all batteries (optimized loop)
var l = batteries.length;
while (l--) {
batteries[l].update();
}
// Update cyborg
cyborg.update();
// Update cyborg dog
cyborgDog.update();
// Update barrier
barrier.update();
};
// Start first wave
LK.setTimeout(function () {
startNewWave();
}, 2000); ===================================================================
--- original.js
+++ change.js
@@ -149,9 +149,9 @@
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
- self.speed = 8; // Increased from 5 to 8 for much faster movement
+ self.speed = 12; // Increased from 8 to 12 for even faster movement
self.attackDamage = 25;
self.shootCooldown = 0;
self.isNearCrystal = false;
self.update = function () {
@@ -159,9 +159,9 @@
if (self.lastX === undefined) self.lastX = self.x;
if (self.lastY === undefined) self.lastY = self.y;
// Handle movement button input with improved responsiveness
if (isMoving && (Math.abs(movementDirection.x) > 0.05 || Math.abs(movementDirection.y) > 0.05)) {
- var speedMultiplier = 1.5; // Boost speed when using movement button
+ var speedMultiplier = 2.0; // Boost speed when using movement button
var newX = self.x + movementDirection.x * self.speed * speedMultiplier;
var newY = self.y + movementDirection.y * self.speed * speedMultiplier;
// Check bounds
newX = Math.max(40, Math.min(2008, newX));
@@ -821,9 +821,9 @@
innerCircle.x = dx;
innerCircle.y = dy;
// Calculate normalized movement direction with improved sensitivity
var strength = Math.min(distance / self.outerRadius, 1.0);
- var sensitivity = 1.2; // Increase sensitivity for better control
+ var sensitivity = 1.5; // Increase sensitivity for better control
movementDirection.x = dx / self.outerRadius * strength * sensitivity;
movementDirection.y = dy / self.outerRadius * strength * sensitivity;
};
return self;
@@ -1167,10 +1167,10 @@
tween(cyborg, {
x: targetX,
y: targetY
}, {
- duration: distance * 15,
- // Reduced from 30 to 15 for much faster movement
+ duration: distance * 8,
+ // Reduced from 15 to 8 for even faster movement
// Dynamic duration based on distance
easing: tween.easeOut,
onFinish: function onFinish() {
// Optional: Add a subtle bounce effect when reaching destination
Un cibor visto desde arriba con una escopeta en las manos. In-Game asset. 2d. High contrast. No shadows
Cristal magico visto desde arriba. In-Game asset. 2d. High contrast. No shadows
Roca vista desde arriba. In-Game asset. 2d. High contrast. No shadows
Arbol visto desde arriba algo oscuro. In-Game asset. 2d. High contrast. No shadows
Coche destruido, algo retro visto desde arriba y en posición horizontal. In-Game asset. 2d. High contrast. No shadows
Perro ciborg visto desde arriba. In-Game asset. 2d. High contrast. No shadows