User prompt
Make the enemies move slow
User prompt
Make my health more
User prompt
Make the enemies move
User prompt
More enemies that come towards you
User prompt
Make the water shoot farther
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'waterMaster.activateShield();' Line Number: 531
User prompt
Please fix the bug: 'tween.create is not a function. (In 'tween.create(sourceGraphics.scale)', 'tween.create' is undefined)' in or related to this line: 'tween.create(sourceGraphics.scale).to({' Line Number: 270 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
More code
User prompt
Aqua Master: Elemental Flow
Initial prompt
A person that shoots our water from their hands and controls water
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); // Create enemy graphic var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); // Enemy properties self.health = 100; self.speedX = 0; self.speedY = 0; self.attackRange = 300; self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; self.enemyType = 'normal'; // Enemy type: normal, fast, heavy self.maxSpeed = 2; // Default speed for normal enemies // Initialize enemy with properties self.init = function (health, speedX, speedY, type) { self.health = health || 100; self.speedX = speedX || 0; self.speedY = speedY || 0; // Set enemy type and properties self.enemyType = type || ['normal', 'fast', 'heavy'][Math.floor(Math.random() * 3)]; // Set properties based on type switch (self.enemyType) { case 'fast': self.maxSpeed = 1.8; // Slowed down from 3.5 self.health = health * 0.7 || 70; enemyGraphics.tint = 0xFF00FF; // Pink enemyGraphics.scale.set(0.8, 0.8); // Smaller break; case 'heavy': self.maxSpeed = 0.5; // Slowed down from 1.2 self.health = health * 1.8 || 180; enemyGraphics.tint = 0x880000; // Dark red enemyGraphics.scale.set(1.3, 1.3); // Larger break; default: // normal self.maxSpeed = 0.8; // Slowed down from 2 enemyGraphics.tint = 0xFF6347; // Default color break; } }; // Take damage from water self.takeDamage = function (amount) { self.health -= amount; // Visual feedback LK.effects.flashObject(self, 0xFF0000, 500); // Play sound LK.getSound('enemyHit').play(); // Check if enemy is defeated if (self.health <= 0) { return true; } return false; }; // Move toward target self.moveToward = function (targetX, targetY, speed) { // Calculate direction vector var dirX = targetX - self.x; var dirY = targetY - self.y; // Calculate distance var distance = Math.sqrt(dirX * dirX + dirY * dirY); // Only move if not too close if (distance > 10) { // Normalize direction vector dirX /= distance; dirY /= distance; // Adjust speed based on enemy type var actualSpeed = speed * self.maxSpeed; // Add some randomness to movement for normal and fast enemies if (self.enemyType !== 'heavy') { // Add slight oscillation or randomness to movement var time = LK.ticks / 30; var randomFactor = 0.2; if (self.enemyType === 'fast') { // Fast enemies zigzag more aggressively dirX += Math.sin(time) * randomFactor; dirY += Math.cos(time) * randomFactor; // Renormalize direction var newLen = Math.sqrt(dirX * dirX + dirY * dirY); dirX /= newLen; dirY /= newLen; } } // Set velocity self.speedX = dirX * actualSpeed; self.speedY = dirY * actualSpeed; } else { // Stop if close enough self.speedX = 0; self.speedY = 0; } }; // Update method called every tick self.update = function () { // Store last position self.lastX = self.x; self.lastY = self.y; // Move enemy self.x += self.speedX; self.y += self.speedY; // Keep enemy within game bounds if (self.x < 50) self.x = 50; if (self.x > 2048 - 50) self.x = 2048 - 50; if (self.y < 50) self.y = 50; if (self.y > 2732 - 50) self.y = 2732 - 50; // Find waterMaster and move toward it if not already moving if (waterMaster && self.speedX === 0 && self.speedY === 0) { // Move toward player automatically self.moveToward(waterMaster.x, waterMaster.y, 1); } }; return self; }); var WaterMaster = Container.expand(function () { var self = Container.call(this); // Create character graphic var characterGraphics = self.attachAsset('waterMaster', { anchorX: 0.5, anchorY: 0.5 }); // Water power properties self.waterReserve = 300; // Maximum water reserve (increased from 100) self.currentWater = 300; // Current water level (increased from 100) self.waterRegenRate = 0.5; // Water regeneration rate per tick (increased) self.shootCost = 15; // Cost of shooting water (adjusted for higher reserve) self.lastShootTime = 0; // Track last shoot time for cooldown self.shootCooldown = 15; // Cooldown between shots in ticks self.isCharging = false; // Track if charging a water shot self.chargeAmount = 0; // Current charge amount self.chargeMax = 60; // Maximum charge amount self.lastX = 0; self.lastY = 0; // Create water shield self.shield = self.addChild(LK.getAsset('waterShield', { anchorX: 0.5, anchorY: 0.5, alpha: 0 })); // Event handlers for touch interactions self.down = function (x, y, obj) { self.isCharging = true; self.chargeAmount = 0; }; self.up = function (x, y, obj) { if (self.isCharging && self.currentWater >= self.shootCost) { // Calculate direction based on charge time var chargeRatio = Math.min(self.chargeAmount / self.chargeMax, 1); var power = 5 + 15 * chargeRatio * chargeRatio; // Exponential power increase based on charge // Create water projectile self.shootWater(power); // Reset charging self.isCharging = false; self.chargeAmount = 0; } }; // Shoot water in direction self.shootWater = function (power) { if (LK.ticks - self.lastShootTime < self.shootCooldown || self.currentWater < self.shootCost) { return; } // Create water projectile if (typeof game !== 'undefined' && game.createWaterProjectile) { // Determine direction vector from center to touch point var touchX = game.lastTouchX || self.x; var touchY = game.lastTouchY || self.y; // Calculate direction vector var dirX = touchX - self.x; var dirY = touchY - self.y; // Normalize direction vector var length = Math.sqrt(dirX * dirX + dirY * dirY); if (length > 0) { dirX /= length; dirY /= length; } else { dirX = 0; dirY = -1; // Default direction up } // Create projectile with increased power (2x) game.createWaterProjectile(self.x, self.y, dirX * power * 2, dirY * power * 2); // Reduce water reserve self.currentWater -= self.shootCost; // Play sound LK.getSound('waterShoot').play(); // Track last shoot time self.lastShootTime = LK.ticks; } }; // Activate shield self.activateShield = function () { if (self.currentWater >= 40) { self.shield.alpha = 0.7; self.currentWater -= 40; // Auto-disable shield after 3 seconds LK.setTimeout(function () { self.shield.alpha = 0; }, 3000); } }; // Refill water reserve self.refillWater = function (amount) { self.currentWater = Math.min(self.currentWater + amount, self.waterReserve); }; // Update method called every tick self.update = function () { // Store last position self.lastX = self.x; self.lastY = self.y; // Slowly regenerate water if (self.currentWater < self.waterReserve) { self.currentWater += self.waterRegenRate; if (self.currentWater > self.waterReserve) { self.currentWater = self.waterReserve; } } // Update charging if (self.isCharging) { self.chargeAmount++; if (self.chargeAmount > self.chargeMax) { self.chargeAmount = self.chargeMax; } } }; return self; }); var WaterProjectile = Container.expand(function () { var self = Container.call(this); // Create projectile graphic var projectileGraphics = self.attachAsset('waterProjectile', { anchorX: 0.5, anchorY: 0.5 }); // Projectile properties self.speedX = 0; self.speedY = 0; self.power = 1; self.lifespan = 240; // Extended projectile lifespan in ticks self.age = 0; self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Initialize projectile with direction and speed self.init = function (speedX, speedY, power) { self.speedX = speedX; self.speedY = speedY; self.power = power || 1; // Scale based on power var scale = 0.5 + self.power * 0.1; projectileGraphics.scale.set(scale, scale); }; // Update method called every tick self.update = function () { // Store last position self.lastX = self.x; self.lastY = self.y; // Move projectile self.x += self.speedX; self.y += self.speedY; // Age the projectile self.age++; // Make projectile gradually fade out if (self.age > self.lifespan * 0.7) { var fadeRatio = 1 - (self.age - self.lifespan * 0.7) / (self.lifespan * 0.3); self.alpha = Math.max(fadeRatio, 0); } }; return self; }); var WaterSource = Container.expand(function () { var self = Container.call(this); // Create water source graphic var sourceGraphics = self.attachAsset('waterSource', { anchorX: 0.5, anchorY: 0.5 }); // Water source properties self.refillAmount = 150; self.refillCooldown = 180; // 3 seconds at 60 FPS self.lastRefillTime = 0; self.lastWasIntersecting = false; // Pulsating animation function startPulsating() { tween(sourceGraphics.scale, { x: 1.1, y: 1.1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(sourceGraphics.scale, { x: 0.9, y: 0.9 }, { duration: 1000, easing: tween.easeInOut, onFinish: startPulsating }); } }); } // Start pulsating animation startPulsating(); // Provide water to player self.refillPlayerWater = function () { if (LK.ticks - self.lastRefillTime > self.refillCooldown) { self.lastRefillTime = LK.ticks; LK.getSound('waterRefill').play(); return self.refillAmount; } return 0; }; return self; }); /**** * Initialize Game ****/ // Set water-themed background color var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Import tween plugin for animations // Initialize assets for the water elementalist game // Set water-themed background color game.setBackgroundColor(0x1A75FF); // Game variables var waterMaster; var waterProjectiles = []; var enemies = []; var waterSources = []; var score = 0; var level = 1; var gameActive = true; // UI elements var waterBar; var scoreText; var levelText; // Initialize game UI function initializeUI() { // Create water bar background var waterBarBg = new Container(); var waterBarBgGraphic = waterBarBg.addChild(LK.getAsset('bullet', { anchorX: 0, anchorY: 0, width: 400, height: 40, tint: 0x555555 })); // Create water bar waterBar = new Container(); var waterBarGraphic = waterBar.addChild(LK.getAsset('bullet', { anchorX: 0, anchorY: 0, width: 396, height: 36, tint: 0x00BFFF })); // Position water bar waterBarBg.x = 20; waterBarBg.y = 20; waterBar.x = 22; waterBar.y = 22; // Add to GUI LK.gui.topLeft.addChild(waterBarBg); LK.gui.topLeft.addChild(waterBar); // Create score text scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); scoreText.x = -20; scoreText.y = 20; LK.gui.topRight.addChild(scoreText); // Create level text levelText = new Text2('Level: 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); levelText.y = 20; LK.gui.top.addChild(levelText); } // Initialize player character function initializePlayer() { waterMaster = game.addChild(new WaterMaster()); waterMaster.x = 2048 / 2; waterMaster.y = 2732 - 300; } // Initialize water sources function initializeWaterSources() { // Add water sources at different locations var positions = [{ x: 300, y: 500 }, { x: 1700, y: 500 }, { x: 1000, y: 1500 }]; for (var i = 0; i < positions.length; i++) { var waterSource = new WaterSource(); waterSource.x = positions[i].x; waterSource.y = positions[i].y; waterSource.lastWasIntersecting = false; waterSources.push(waterSource); game.addChild(waterSource); } } // Create a water projectile game.createWaterProjectile = function (x, y, speedX, speedY) { var projectile = new WaterProjectile(); projectile.x = x; projectile.y = y; projectile.lastX = x; projectile.lastY = y; projectile.init(speedX, speedY, 1.5 + level * 0.4); projectile.lastWasIntersecting = false; waterProjectiles.push(projectile); game.addChild(projectile); }; // Spawn enemies function spawnEnemies() { // Determine number of enemies based on level var enemyCount = Math.min(2 + level, 8); // Clear any existing enemies for (var i = 0; i < enemies.length; i++) { if (enemies[i].parent) { enemies[i].parent.removeChild(enemies[i]); } } enemies = []; // Create new enemies for (var i = 0; i < enemyCount; i++) { var enemy = new Enemy(); // Position enemy randomly but not too close to player do { enemy.x = Math.random() * 1848 + 100; enemy.y = Math.random() * 1500 + 100; } while (Math.sqrt(Math.pow(enemy.x - waterMaster.x, 2) + Math.pow(enemy.y - waterMaster.y, 2)) < 500); enemy.lastX = enemy.x; enemy.lastY = enemy.y; // Determine enemy type distribution based on level var normalProb = Math.max(0.8 - level * 0.1, 0.3); // Decrease normal enemies as level increases var fastProb = Math.min(0.1 + level * 0.05, 0.4); // Increase fast enemies as level increases var heavyProb = Math.min(0.1 + level * 0.05, 0.3); // Increase heavy enemies as level increases var rand = Math.random(); var enemyType; if (rand < normalProb) { enemyType = 'normal'; } else if (rand < normalProb + fastProb) { enemyType = 'fast'; } else { enemyType = 'heavy'; } enemy.init(80 + level * 20, 0, 0, enemyType); enemy.lastWasIntersecting = false; enemies.push(enemy); game.addChild(enemy); } } // Update score and level function updateScore(points) { score += points; scoreText.setText('Score: ' + score); // Check for level up if (score >= level * 100) { levelUp(); } } // Level up function levelUp() { level++; levelText.setText('Level: ' + level); // Flash screen to indicate level up LK.effects.flashScreen(0x00FFFF, 500); // Spawn new enemies for the level spawnEnemies(); } // Game initialization initializeUI(); initializePlayer(); initializeWaterSources(); spawnEnemies(); // Game touch handling game.lastTouchX = 0; game.lastTouchY = 0; // Dragging functionality var isDragging = false; // Touch down event game.down = function (x, y, obj) { // Store touch position game.lastTouchX = x; game.lastTouchY = y; // Check if touching water master if (waterMaster) { var touchPoint = { x: x, y: y }; var distance = Math.sqrt(Math.pow(touchPoint.x - waterMaster.x, 2) + Math.pow(touchPoint.y - waterMaster.y, 2)); if (distance < 100) { // Start dragging player isDragging = true; } else { // Start charging water shot waterMaster.down(x, y, obj); } } }; // Touch move event game.move = function (x, y, obj) { // Store touch position game.lastTouchX = x; game.lastTouchY = y; if (isDragging && waterMaster) { // Move water master with touch waterMaster.x = x; waterMaster.y = y; // Keep within game bounds if (waterMaster.x < 100) waterMaster.x = 100; if (waterMaster.x > 2048 - 100) waterMaster.x = 2048 - 100; if (waterMaster.y < 100) waterMaster.y = 100; if (waterMaster.y > 2732 - 100) waterMaster.y = 2732 - 100; } }; // Touch up event game.up = function (x, y, obj) { // If was charging water shot if (!isDragging && waterMaster) { waterMaster.up(x, y, obj); } // Stop dragging isDragging = false; }; // Double tap to activate shield var lastTapTime = 0; var originalDown = game.down; // Store the original down handler game.down = function (x, y, obj) { var currentTime = Date.now(); // Check for double tap (within 300ms) if (currentTime - lastTapTime < 300) { if (waterMaster) { waterMaster.activateShield(); } } lastTapTime = currentTime; // Call the original down handler instead of recursively calling itself if (originalDown) { // Store touch position and handle dragging game.lastTouchX = x; game.lastTouchY = y; // Check if touching water master if (waterMaster) { var touchPoint = { x: x, y: y }; var distance = Math.sqrt(Math.pow(touchPoint.x - waterMaster.x, 2) + Math.pow(touchPoint.y - waterMaster.y, 2)); if (distance < 100) { // Start dragging player isDragging = true; } else { // Start charging water shot waterMaster.down(x, y, obj); } } } }; // Timer for spawning additional enemies var lastEnemySpawnTime = 0; var enemySpawnInterval = 600; // 10 seconds at 60 FPS // Game update loop game.update = function () { if (!gameActive) return; // Spawn additional enemies every 10 seconds if (LK.ticks - lastEnemySpawnTime > enemySpawnInterval && enemies.length < 10 + level) { lastEnemySpawnTime = LK.ticks; // Create a new enemy var enemy = new Enemy(); // Position enemy randomly on the edges of the screen var side = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left switch (side) { case 0: // Top enemy.x = Math.random() * 1848 + 100; enemy.y = -50; break; case 1: // Right enemy.x = 2048 + 50; enemy.y = Math.random() * 2532 + 100; break; case 2: // Bottom enemy.x = Math.random() * 1848 + 100; enemy.y = 2732 + 50; break; case 3: // Left enemy.x = -50; enemy.y = Math.random() * 2532 + 100; break; } enemy.lastX = enemy.x; enemy.lastY = enemy.y; enemy.init(80 + level * 20, 0, 0); enemy.lastWasIntersecting = false; enemies.push(enemy); game.addChild(enemy); } // Update water master if (waterMaster) { waterMaster.update(); // Update water bar UI if (waterBar) { var waterRatio = waterMaster.currentWater / waterMaster.waterReserve; waterBar.children[0].width = 396 * waterRatio; } // Check water master collisions with water sources for (var i = 0; i < waterSources.length; i++) { var source = waterSources[i]; var isIntersecting = waterMaster.intersects(source); // Refill water if touching a water source for the first time if (!source.lastWasIntersecting && isIntersecting) { var refillAmount = source.refillPlayerWater(); if (refillAmount > 0) { waterMaster.refillWater(refillAmount); // Visual feedback LK.effects.flashObject(source, 0x00FFFF, 500); } } source.lastWasIntersecting = isIntersecting; } } // Update water projectiles for (var i = waterProjectiles.length - 1; i >= 0; i--) { var projectile = waterProjectiles[i]; projectile.update(); // Check if projectile is out of bounds or expired if (projectile.x < -100 || projectile.x > 2148 || projectile.y < -100 || projectile.y > 2832 || projectile.age > projectile.lifespan) { if (projectile.parent) { projectile.parent.removeChild(projectile); } waterProjectiles.splice(i, 1); continue; } // Check collisions with enemies for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; var isIntersecting = projectile.intersects(enemy); // Handle collision if not already intersecting if (!projectile.lastWasIntersecting && isIntersecting) { // Enemy takes damage based on projectile power var isDefeated = enemy.takeDamage(20 * projectile.power); // Remove projectile if (projectile.parent) { projectile.parent.removeChild(projectile); } waterProjectiles.splice(i, 1); // Play hit sound LK.getSound('waterHit').play(); // If enemy was defeated if (isDefeated) { if (enemy.parent) { enemy.parent.removeChild(enemy); } enemies.splice(j, 1); updateScore(10); } break; } if (projectile.lastWasIntersecting !== undefined) { projectile.lastWasIntersecting = isIntersecting; } } } // Update enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Move toward player if in range var distanceToPlayer = Math.sqrt(Math.pow(enemy.x - waterMaster.x, 2) + Math.pow(enemy.y - waterMaster.y, 2)); if (distanceToPlayer < 800) { enemy.moveToward(waterMaster.x, waterMaster.y, 1 + level * 0.2); } enemy.update(); // Check collision with player var isIntersecting = enemy.intersects(waterMaster); // Handle collision if not already intersecting and shield is not active if (!enemy.lastWasIntersecting && isIntersecting && waterMaster.shield.alpha < 0.1) { // Game over if no shield LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); gameActive = false; } else if (!enemy.lastWasIntersecting && isIntersecting && waterMaster.shield.alpha >= 0.1) { // Push enemy away if shield is active var dirX = enemy.x - waterMaster.x; var dirY = enemy.y - waterMaster.y; var length = Math.sqrt(dirX * dirX + dirY * dirY); if (length > 0) { dirX /= length; dirY /= length; } enemy.x += dirX * 200; enemy.y += dirY * 200; enemy.takeDamage(10); } enemy.lastWasIntersecting = isIntersecting; } // Check if all enemies are defeated if (enemies.length === 0) { // Spawn more enemies spawnEnemies(); updateScore(level * 20); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Create enemy graphic
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Enemy properties
self.health = 100;
self.speedX = 0;
self.speedY = 0;
self.attackRange = 300;
self.lastX = 0;
self.lastY = 0;
self.lastWasIntersecting = false;
self.enemyType = 'normal'; // Enemy type: normal, fast, heavy
self.maxSpeed = 2; // Default speed for normal enemies
// Initialize enemy with properties
self.init = function (health, speedX, speedY, type) {
self.health = health || 100;
self.speedX = speedX || 0;
self.speedY = speedY || 0;
// Set enemy type and properties
self.enemyType = type || ['normal', 'fast', 'heavy'][Math.floor(Math.random() * 3)];
// Set properties based on type
switch (self.enemyType) {
case 'fast':
self.maxSpeed = 1.8; // Slowed down from 3.5
self.health = health * 0.7 || 70;
enemyGraphics.tint = 0xFF00FF; // Pink
enemyGraphics.scale.set(0.8, 0.8); // Smaller
break;
case 'heavy':
self.maxSpeed = 0.5; // Slowed down from 1.2
self.health = health * 1.8 || 180;
enemyGraphics.tint = 0x880000; // Dark red
enemyGraphics.scale.set(1.3, 1.3); // Larger
break;
default:
// normal
self.maxSpeed = 0.8; // Slowed down from 2
enemyGraphics.tint = 0xFF6347; // Default color
break;
}
};
// Take damage from water
self.takeDamage = function (amount) {
self.health -= amount;
// Visual feedback
LK.effects.flashObject(self, 0xFF0000, 500);
// Play sound
LK.getSound('enemyHit').play();
// Check if enemy is defeated
if (self.health <= 0) {
return true;
}
return false;
};
// Move toward target
self.moveToward = function (targetX, targetY, speed) {
// Calculate direction vector
var dirX = targetX - self.x;
var dirY = targetY - self.y;
// Calculate distance
var distance = Math.sqrt(dirX * dirX + dirY * dirY);
// Only move if not too close
if (distance > 10) {
// Normalize direction vector
dirX /= distance;
dirY /= distance;
// Adjust speed based on enemy type
var actualSpeed = speed * self.maxSpeed;
// Add some randomness to movement for normal and fast enemies
if (self.enemyType !== 'heavy') {
// Add slight oscillation or randomness to movement
var time = LK.ticks / 30;
var randomFactor = 0.2;
if (self.enemyType === 'fast') {
// Fast enemies zigzag more aggressively
dirX += Math.sin(time) * randomFactor;
dirY += Math.cos(time) * randomFactor;
// Renormalize direction
var newLen = Math.sqrt(dirX * dirX + dirY * dirY);
dirX /= newLen;
dirY /= newLen;
}
}
// Set velocity
self.speedX = dirX * actualSpeed;
self.speedY = dirY * actualSpeed;
} else {
// Stop if close enough
self.speedX = 0;
self.speedY = 0;
}
};
// Update method called every tick
self.update = function () {
// Store last position
self.lastX = self.x;
self.lastY = self.y;
// Move enemy
self.x += self.speedX;
self.y += self.speedY;
// Keep enemy within game bounds
if (self.x < 50) self.x = 50;
if (self.x > 2048 - 50) self.x = 2048 - 50;
if (self.y < 50) self.y = 50;
if (self.y > 2732 - 50) self.y = 2732 - 50;
// Find waterMaster and move toward it if not already moving
if (waterMaster && self.speedX === 0 && self.speedY === 0) {
// Move toward player automatically
self.moveToward(waterMaster.x, waterMaster.y, 1);
}
};
return self;
});
var WaterMaster = Container.expand(function () {
var self = Container.call(this);
// Create character graphic
var characterGraphics = self.attachAsset('waterMaster', {
anchorX: 0.5,
anchorY: 0.5
});
// Water power properties
self.waterReserve = 300; // Maximum water reserve (increased from 100)
self.currentWater = 300; // Current water level (increased from 100)
self.waterRegenRate = 0.5; // Water regeneration rate per tick (increased)
self.shootCost = 15; // Cost of shooting water (adjusted for higher reserve)
self.lastShootTime = 0; // Track last shoot time for cooldown
self.shootCooldown = 15; // Cooldown between shots in ticks
self.isCharging = false; // Track if charging a water shot
self.chargeAmount = 0; // Current charge amount
self.chargeMax = 60; // Maximum charge amount
self.lastX = 0;
self.lastY = 0;
// Create water shield
self.shield = self.addChild(LK.getAsset('waterShield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}));
// Event handlers for touch interactions
self.down = function (x, y, obj) {
self.isCharging = true;
self.chargeAmount = 0;
};
self.up = function (x, y, obj) {
if (self.isCharging && self.currentWater >= self.shootCost) {
// Calculate direction based on charge time
var chargeRatio = Math.min(self.chargeAmount / self.chargeMax, 1);
var power = 5 + 15 * chargeRatio * chargeRatio; // Exponential power increase based on charge
// Create water projectile
self.shootWater(power);
// Reset charging
self.isCharging = false;
self.chargeAmount = 0;
}
};
// Shoot water in direction
self.shootWater = function (power) {
if (LK.ticks - self.lastShootTime < self.shootCooldown || self.currentWater < self.shootCost) {
return;
}
// Create water projectile
if (typeof game !== 'undefined' && game.createWaterProjectile) {
// Determine direction vector from center to touch point
var touchX = game.lastTouchX || self.x;
var touchY = game.lastTouchY || self.y;
// Calculate direction vector
var dirX = touchX - self.x;
var dirY = touchY - self.y;
// Normalize direction vector
var length = Math.sqrt(dirX * dirX + dirY * dirY);
if (length > 0) {
dirX /= length;
dirY /= length;
} else {
dirX = 0;
dirY = -1; // Default direction up
}
// Create projectile with increased power (2x)
game.createWaterProjectile(self.x, self.y, dirX * power * 2, dirY * power * 2);
// Reduce water reserve
self.currentWater -= self.shootCost;
// Play sound
LK.getSound('waterShoot').play();
// Track last shoot time
self.lastShootTime = LK.ticks;
}
};
// Activate shield
self.activateShield = function () {
if (self.currentWater >= 40) {
self.shield.alpha = 0.7;
self.currentWater -= 40;
// Auto-disable shield after 3 seconds
LK.setTimeout(function () {
self.shield.alpha = 0;
}, 3000);
}
};
// Refill water reserve
self.refillWater = function (amount) {
self.currentWater = Math.min(self.currentWater + amount, self.waterReserve);
};
// Update method called every tick
self.update = function () {
// Store last position
self.lastX = self.x;
self.lastY = self.y;
// Slowly regenerate water
if (self.currentWater < self.waterReserve) {
self.currentWater += self.waterRegenRate;
if (self.currentWater > self.waterReserve) {
self.currentWater = self.waterReserve;
}
}
// Update charging
if (self.isCharging) {
self.chargeAmount++;
if (self.chargeAmount > self.chargeMax) {
self.chargeAmount = self.chargeMax;
}
}
};
return self;
});
var WaterProjectile = Container.expand(function () {
var self = Container.call(this);
// Create projectile graphic
var projectileGraphics = self.attachAsset('waterProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
// Projectile properties
self.speedX = 0;
self.speedY = 0;
self.power = 1;
self.lifespan = 240; // Extended projectile lifespan in ticks
self.age = 0;
self.lastX = 0;
self.lastY = 0;
self.lastWasIntersecting = false;
// Initialize projectile with direction and speed
self.init = function (speedX, speedY, power) {
self.speedX = speedX;
self.speedY = speedY;
self.power = power || 1;
// Scale based on power
var scale = 0.5 + self.power * 0.1;
projectileGraphics.scale.set(scale, scale);
};
// Update method called every tick
self.update = function () {
// Store last position
self.lastX = self.x;
self.lastY = self.y;
// Move projectile
self.x += self.speedX;
self.y += self.speedY;
// Age the projectile
self.age++;
// Make projectile gradually fade out
if (self.age > self.lifespan * 0.7) {
var fadeRatio = 1 - (self.age - self.lifespan * 0.7) / (self.lifespan * 0.3);
self.alpha = Math.max(fadeRatio, 0);
}
};
return self;
});
var WaterSource = Container.expand(function () {
var self = Container.call(this);
// Create water source graphic
var sourceGraphics = self.attachAsset('waterSource', {
anchorX: 0.5,
anchorY: 0.5
});
// Water source properties
self.refillAmount = 150;
self.refillCooldown = 180; // 3 seconds at 60 FPS
self.lastRefillTime = 0;
self.lastWasIntersecting = false;
// Pulsating animation
function startPulsating() {
tween(sourceGraphics.scale, {
x: 1.1,
y: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(sourceGraphics.scale, {
x: 0.9,
y: 0.9
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: startPulsating
});
}
});
}
// Start pulsating animation
startPulsating();
// Provide water to player
self.refillPlayerWater = function () {
if (LK.ticks - self.lastRefillTime > self.refillCooldown) {
self.lastRefillTime = LK.ticks;
LK.getSound('waterRefill').play();
return self.refillAmount;
}
return 0;
};
return self;
});
/****
* Initialize Game
****/
// Set water-themed background color
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Import tween plugin for animations
// Initialize assets for the water elementalist game
// Set water-themed background color
game.setBackgroundColor(0x1A75FF);
// Game variables
var waterMaster;
var waterProjectiles = [];
var enemies = [];
var waterSources = [];
var score = 0;
var level = 1;
var gameActive = true;
// UI elements
var waterBar;
var scoreText;
var levelText;
// Initialize game UI
function initializeUI() {
// Create water bar background
var waterBarBg = new Container();
var waterBarBgGraphic = waterBarBg.addChild(LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0,
width: 400,
height: 40,
tint: 0x555555
}));
// Create water bar
waterBar = new Container();
var waterBarGraphic = waterBar.addChild(LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0,
width: 396,
height: 36,
tint: 0x00BFFF
}));
// Position water bar
waterBarBg.x = 20;
waterBarBg.y = 20;
waterBar.x = 22;
waterBar.y = 22;
// Add to GUI
LK.gui.topLeft.addChild(waterBarBg);
LK.gui.topLeft.addChild(waterBar);
// Create score text
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
scoreText.x = -20;
scoreText.y = 20;
LK.gui.topRight.addChild(scoreText);
// Create level text
levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.y = 20;
LK.gui.top.addChild(levelText);
}
// Initialize player character
function initializePlayer() {
waterMaster = game.addChild(new WaterMaster());
waterMaster.x = 2048 / 2;
waterMaster.y = 2732 - 300;
}
// Initialize water sources
function initializeWaterSources() {
// Add water sources at different locations
var positions = [{
x: 300,
y: 500
}, {
x: 1700,
y: 500
}, {
x: 1000,
y: 1500
}];
for (var i = 0; i < positions.length; i++) {
var waterSource = new WaterSource();
waterSource.x = positions[i].x;
waterSource.y = positions[i].y;
waterSource.lastWasIntersecting = false;
waterSources.push(waterSource);
game.addChild(waterSource);
}
}
// Create a water projectile
game.createWaterProjectile = function (x, y, speedX, speedY) {
var projectile = new WaterProjectile();
projectile.x = x;
projectile.y = y;
projectile.lastX = x;
projectile.lastY = y;
projectile.init(speedX, speedY, 1.5 + level * 0.4);
projectile.lastWasIntersecting = false;
waterProjectiles.push(projectile);
game.addChild(projectile);
};
// Spawn enemies
function spawnEnemies() {
// Determine number of enemies based on level
var enemyCount = Math.min(2 + level, 8);
// Clear any existing enemies
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].parent) {
enemies[i].parent.removeChild(enemies[i]);
}
}
enemies = [];
// Create new enemies
for (var i = 0; i < enemyCount; i++) {
var enemy = new Enemy();
// Position enemy randomly but not too close to player
do {
enemy.x = Math.random() * 1848 + 100;
enemy.y = Math.random() * 1500 + 100;
} while (Math.sqrt(Math.pow(enemy.x - waterMaster.x, 2) + Math.pow(enemy.y - waterMaster.y, 2)) < 500);
enemy.lastX = enemy.x;
enemy.lastY = enemy.y;
// Determine enemy type distribution based on level
var normalProb = Math.max(0.8 - level * 0.1, 0.3); // Decrease normal enemies as level increases
var fastProb = Math.min(0.1 + level * 0.05, 0.4); // Increase fast enemies as level increases
var heavyProb = Math.min(0.1 + level * 0.05, 0.3); // Increase heavy enemies as level increases
var rand = Math.random();
var enemyType;
if (rand < normalProb) {
enemyType = 'normal';
} else if (rand < normalProb + fastProb) {
enemyType = 'fast';
} else {
enemyType = 'heavy';
}
enemy.init(80 + level * 20, 0, 0, enemyType);
enemy.lastWasIntersecting = false;
enemies.push(enemy);
game.addChild(enemy);
}
}
// Update score and level
function updateScore(points) {
score += points;
scoreText.setText('Score: ' + score);
// Check for level up
if (score >= level * 100) {
levelUp();
}
}
// Level up
function levelUp() {
level++;
levelText.setText('Level: ' + level);
// Flash screen to indicate level up
LK.effects.flashScreen(0x00FFFF, 500);
// Spawn new enemies for the level
spawnEnemies();
}
// Game initialization
initializeUI();
initializePlayer();
initializeWaterSources();
spawnEnemies();
// Game touch handling
game.lastTouchX = 0;
game.lastTouchY = 0;
// Dragging functionality
var isDragging = false;
// Touch down event
game.down = function (x, y, obj) {
// Store touch position
game.lastTouchX = x;
game.lastTouchY = y;
// Check if touching water master
if (waterMaster) {
var touchPoint = {
x: x,
y: y
};
var distance = Math.sqrt(Math.pow(touchPoint.x - waterMaster.x, 2) + Math.pow(touchPoint.y - waterMaster.y, 2));
if (distance < 100) {
// Start dragging player
isDragging = true;
} else {
// Start charging water shot
waterMaster.down(x, y, obj);
}
}
};
// Touch move event
game.move = function (x, y, obj) {
// Store touch position
game.lastTouchX = x;
game.lastTouchY = y;
if (isDragging && waterMaster) {
// Move water master with touch
waterMaster.x = x;
waterMaster.y = y;
// Keep within game bounds
if (waterMaster.x < 100) waterMaster.x = 100;
if (waterMaster.x > 2048 - 100) waterMaster.x = 2048 - 100;
if (waterMaster.y < 100) waterMaster.y = 100;
if (waterMaster.y > 2732 - 100) waterMaster.y = 2732 - 100;
}
};
// Touch up event
game.up = function (x, y, obj) {
// If was charging water shot
if (!isDragging && waterMaster) {
waterMaster.up(x, y, obj);
}
// Stop dragging
isDragging = false;
};
// Double tap to activate shield
var lastTapTime = 0;
var originalDown = game.down; // Store the original down handler
game.down = function (x, y, obj) {
var currentTime = Date.now();
// Check for double tap (within 300ms)
if (currentTime - lastTapTime < 300) {
if (waterMaster) {
waterMaster.activateShield();
}
}
lastTapTime = currentTime;
// Call the original down handler instead of recursively calling itself
if (originalDown) {
// Store touch position and handle dragging
game.lastTouchX = x;
game.lastTouchY = y;
// Check if touching water master
if (waterMaster) {
var touchPoint = {
x: x,
y: y
};
var distance = Math.sqrt(Math.pow(touchPoint.x - waterMaster.x, 2) + Math.pow(touchPoint.y - waterMaster.y, 2));
if (distance < 100) {
// Start dragging player
isDragging = true;
} else {
// Start charging water shot
waterMaster.down(x, y, obj);
}
}
}
};
// Timer for spawning additional enemies
var lastEnemySpawnTime = 0;
var enemySpawnInterval = 600; // 10 seconds at 60 FPS
// Game update loop
game.update = function () {
if (!gameActive) return;
// Spawn additional enemies every 10 seconds
if (LK.ticks - lastEnemySpawnTime > enemySpawnInterval && enemies.length < 10 + level) {
lastEnemySpawnTime = LK.ticks;
// Create a new enemy
var enemy = new Enemy();
// Position enemy randomly on the edges of the screen
var side = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
switch (side) {
case 0:
// Top
enemy.x = Math.random() * 1848 + 100;
enemy.y = -50;
break;
case 1:
// Right
enemy.x = 2048 + 50;
enemy.y = Math.random() * 2532 + 100;
break;
case 2:
// Bottom
enemy.x = Math.random() * 1848 + 100;
enemy.y = 2732 + 50;
break;
case 3:
// Left
enemy.x = -50;
enemy.y = Math.random() * 2532 + 100;
break;
}
enemy.lastX = enemy.x;
enemy.lastY = enemy.y;
enemy.init(80 + level * 20, 0, 0);
enemy.lastWasIntersecting = false;
enemies.push(enemy);
game.addChild(enemy);
}
// Update water master
if (waterMaster) {
waterMaster.update();
// Update water bar UI
if (waterBar) {
var waterRatio = waterMaster.currentWater / waterMaster.waterReserve;
waterBar.children[0].width = 396 * waterRatio;
}
// Check water master collisions with water sources
for (var i = 0; i < waterSources.length; i++) {
var source = waterSources[i];
var isIntersecting = waterMaster.intersects(source);
// Refill water if touching a water source for the first time
if (!source.lastWasIntersecting && isIntersecting) {
var refillAmount = source.refillPlayerWater();
if (refillAmount > 0) {
waterMaster.refillWater(refillAmount);
// Visual feedback
LK.effects.flashObject(source, 0x00FFFF, 500);
}
}
source.lastWasIntersecting = isIntersecting;
}
}
// Update water projectiles
for (var i = waterProjectiles.length - 1; i >= 0; i--) {
var projectile = waterProjectiles[i];
projectile.update();
// Check if projectile is out of bounds or expired
if (projectile.x < -100 || projectile.x > 2148 || projectile.y < -100 || projectile.y > 2832 || projectile.age > projectile.lifespan) {
if (projectile.parent) {
projectile.parent.removeChild(projectile);
}
waterProjectiles.splice(i, 1);
continue;
}
// Check collisions with enemies
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
var isIntersecting = projectile.intersects(enemy);
// Handle collision if not already intersecting
if (!projectile.lastWasIntersecting && isIntersecting) {
// Enemy takes damage based on projectile power
var isDefeated = enemy.takeDamage(20 * projectile.power);
// Remove projectile
if (projectile.parent) {
projectile.parent.removeChild(projectile);
}
waterProjectiles.splice(i, 1);
// Play hit sound
LK.getSound('waterHit').play();
// If enemy was defeated
if (isDefeated) {
if (enemy.parent) {
enemy.parent.removeChild(enemy);
}
enemies.splice(j, 1);
updateScore(10);
}
break;
}
if (projectile.lastWasIntersecting !== undefined) {
projectile.lastWasIntersecting = isIntersecting;
}
}
}
// Update enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Move toward player if in range
var distanceToPlayer = Math.sqrt(Math.pow(enemy.x - waterMaster.x, 2) + Math.pow(enemy.y - waterMaster.y, 2));
if (distanceToPlayer < 800) {
enemy.moveToward(waterMaster.x, waterMaster.y, 1 + level * 0.2);
}
enemy.update();
// Check collision with player
var isIntersecting = enemy.intersects(waterMaster);
// Handle collision if not already intersecting and shield is not active
if (!enemy.lastWasIntersecting && isIntersecting && waterMaster.shield.alpha < 0.1) {
// Game over if no shield
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
gameActive = false;
} else if (!enemy.lastWasIntersecting && isIntersecting && waterMaster.shield.alpha >= 0.1) {
// Push enemy away if shield is active
var dirX = enemy.x - waterMaster.x;
var dirY = enemy.y - waterMaster.y;
var length = Math.sqrt(dirX * dirX + dirY * dirY);
if (length > 0) {
dirX /= length;
dirY /= length;
}
enemy.x += dirX * 200;
enemy.y += dirY * 200;
enemy.takeDamage(10);
}
enemy.lastWasIntersecting = isIntersecting;
}
// Check if all enemies are defeated
if (enemies.length === 0) {
// Spawn more enemies
spawnEnemies();
updateScore(level * 20);
}
};