User prompt
The parry of the level 10 weapon should charge in 4.5 seconds and give a 1.5 second shield that will block all damage until it runs out.
User prompt
Instead of the parry of the level 10 weapon filling our health, let it give a 2.5-second shield that blocks 1 damage and the cooldown of this weapon's parry should be 4. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (6 edits merged)
Please save this source code
User prompt
make bosses harder
User prompt
Have 3 parry instead of 2
Code edit (3 edits merged)
Please save this source code
User prompt
Remove the parry button and instead add text like Tap! to the head of the character with a background, click on it and the text will go and parry, so that he will understand how to parry. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (4 edits merged)
Please save this source code
User prompt
Reduce the powerup spawn rate, reduce the perry spawn rate even more and add a button that says parry when you click on the character instead of parrying, and also change the level text background and parry text background and Make the opacity of the weapon name background 100 and make the background of the weapon names longer.
User prompt
add a button to use perry when clicking on the character.
User prompt
Add a background to the weapon name and perry text with assetle then add a background to the level text with assetle
Code edit (1 edits merged)
Please save this source code
User prompt
Increase the bullets (including the enemies' kide) of the "hero" character
Initial prompt
Make the player character's hand, bosses and enemies bigger so they can be seen easily by the eye. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.bossLevel = 1; self.health = 20; self.maxHealth = 20; self.speed = 2; self.direction = 1; self.shootCooldown = 0; self.shootInterval = 60; self.phase = 1; self.points = 1000; self.setBossLevel = function (level) { self.bossLevel = Math.floor(level / 10); self.health = 20 + self.bossLevel * 10; self.maxHealth = self.health; self.points = 1000 * (self.bossLevel + 1); bossGraphics.scale.x = 1 + self.bossLevel * 0.2; bossGraphics.scale.y = 1 + self.bossLevel * 0.2; }; self.update = function () { // Boss movement pattern self.y += self.speed * self.direction; if (self.y > 600 || self.y < 300) { self.direction *= -1; } // More complex movement for higher level bosses if (self.bossLevel >= 2) { self.x += Math.sin(LK.ticks * 0.02) * 2; } self.shootCooldown++; // Different attack patterns based on phase if (self.health < self.maxHealth * 0.5 && self.phase === 1) { self.phase = 2; self.shootInterval = 40; } if (self.health < self.maxHealth * 0.25 && self.phase === 2 && self.bossLevel >= 3) { self.phase = 3; self.shootInterval = 30; } if (self.shootCooldown >= self.shootInterval) { self.shootCooldown = 0; return self.phase; // Return phase for different bullet patterns } return 0; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { return true; // Boss destroyed } tween(bossGraphics, { tint: 0xffffff }, { duration: 100, onFinish: function onFinish() { bossGraphics.tint = 0xffffff; } }); bossGraphics.tint = 0xff0000; return false; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.enemyType = 'basic'; self.health = 2; self.speed = -2; self.shootCooldown = 0; self.shootInterval = 120; self.points = 100; self.pattern = 0; self.setType = function (type) { self.enemyType = type; var stats = enemyTypesPerLevel[type]; self.health = stats.health; self.speed = stats.speed; self.shootInterval = stats.shootInterval; enemyGraphics.tint = stats.color; self.points = stats.health * 50; }; self.update = function () { self.x += self.speed; // Different movement patterns for different enemy types if (self.enemyType === 'fast') { self.y += Math.sin(self.x * 0.01) * 2; } else if (self.enemyType === 'sniper' && self.x < 1500) { self.speed = 0; } self.shootCooldown++; if (self.shootCooldown >= self.shootInterval) { self.shootCooldown = 0; return true; // Signal to shoot } return false; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { return true; // Enemy destroyed } tween(enemyGraphics, { tint: 0xffffff }, { duration: 100, onFinish: function onFinish() { enemyGraphics.tint = enemyTypesPerLevel[self.enemyType].color; } }); enemyGraphics.tint = 0xff0000; return false; }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = -8; self.speedY = 0; self.canBeParried = false; self.parried = false; self.update = function () { self.x += self.speedX; self.y += self.speedY; // Make bullets parryable when they're pink if (!self.canBeParried && Math.random() < 0.3) { self.canBeParried = true; bulletGraphics.tint = 0xff00ff; } }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.hand = self.attachAsset('hand', { anchorX: 0.5, anchorY: 0.5, x: 60, y: -5 }); self.handBaseY = -15; self.handAnimating = false; self.health = 3; self.maxHealth = 3; self.shootCooldown = 0; self.shootInterval = 20; self.invulnerable = 0; self.powerupTime = 0; self.powerupType = null; self.weaponType = 0; self.chargeTime = 0; self.isParrying = false; self.parryIndicator = null; self.originalTint = 0xffffff; self.isPowerupFlashing = false; self.perryCharges = 2; // Start with 2 perrys self.perryEffect = null; self.perryActive = false; self.perryCooldown = 0; self.perryMaxCooldown = 300; // 5 seconds at 60fps self.update = function () { if (self.invulnerable > 0) { self.invulnerable--; self.alpha = Math.sin(self.invulnerable * 0.3) > 0 ? 1 : 0.5; } else { self.alpha = 1; } if (self.powerupTime > 0) { self.powerupTime--; // Flash between powerup color and original color in the last 2 seconds if (self.powerupTime <= 120 && !self.isPowerupFlashing) { self.isPowerupFlashing = true; self.startPowerupFlash(); } if (self.powerupTime === 0) { self.powerupType = null; self.shootInterval = 20; heroGraphics.tint = self.originalTint; self.isPowerupFlashing = false; } } self.shootCooldown++; // Update charge for charge weapon if (self.weaponType === 2 && self.chargeTime > 0) { self.chargeTime--; } // Update perry cooldown if (self.perryCooldown > 0) { self.perryCooldown--; } }; self.takeDamage = function () { if (self.invulnerable > 0) { return false; } self.health--; self.invulnerable = 120; // 2 seconds of invulnerability if (self.health <= 0) { return true; // Hero destroyed } LK.effects.flashObject(self, 0xff0000, 500); return false; }; self.canShoot = function () { var weapon = weaponTypes[self.weaponType]; var interval = self.shootInterval; if (weapon.fireRate) { interval = weapon.fireRate; } if (self.shootCooldown >= interval) { self.shootCooldown = 0; return true; } return false; }; self.applyPowerup = function (type) { self.powerupType = type; self.powerupTime = 600; // 10 seconds self.isPowerupFlashing = false; // Change hero color based on powerup type var powerupColor = type === 'rapid' ? 0xff00ff : 0x00ffff; heroGraphics.tint = powerupColor; if (type === 'rapid') { self.shootInterval = 10; } }; self.startPowerupFlash = function () { var flashCount = 0; var flashInterval = LK.setInterval(function () { flashCount++; if (flashCount % 2 === 0) { heroGraphics.tint = self.originalTint; } else { var powerupColor = self.powerupType === 'rapid' ? 0xff00ff : 0x00ffff; heroGraphics.tint = powerupColor; } if (self.powerupTime === 0) { LK.clearInterval(flashInterval); heroGraphics.tint = self.originalTint; } }, 200); // Flash every 200ms }; self.setWeapon = function (weaponIndex) { self.weaponType = weaponIndex; }; self.startParry = function () { if (!self.isParrying && !self.parryIndicator) { self.isParrying = true; self.parryIndicator = self.attachAsset('parryIndicator', { anchorX: 0.5, anchorY: 0.5 }); self.parryIndicator.alpha = 0.5; self.parryIndicator.tint = weaponTypes[self.weaponType].parryColor; } }; self.endParry = function () { self.isParrying = false; if (self.parryIndicator) { self.parryIndicator.destroy(); self.parryIndicator = null; } }; self.animateHandShoot = function () { if (!self.handAnimating) { self.handAnimating = true; tween(self.hand, { y: self.handBaseY - 20 }, { duration: 100, onFinish: function onFinish() { tween(self.hand, { y: self.handBaseY }, { duration: 100, onFinish: function onFinish() { self.handAnimating = false; } }); } }); } }; self.activatePerry = function () { if (self.perryCharges > 0 && !self.perryActive && self.perryCooldown === 0) { self.perryCharges--; self.perryActive = true; self.perryCooldown = self.perryMaxCooldown; // Set cooldown var weapon = weaponTypes[self.weaponType]; // Create perry effect visual self.perryEffect = self.attachAsset('perryEffect', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.perryEffect.tint = weapon.parryColor; // Weapon-specific animations and effects if (weapon.name === 'Spread') { // Freeze all enemies briefly self.performSpreadPerry(); } else if (weapon.name === 'Rapid') { // Multi-hit explosion self.performRapidPerry(); } else if (weapon.name === 'Charge') { // Piercing beam attack self.performChargePerry(); } else if (weapon.name === 'Homing') { // Healing wave self.performHomingPerry(); } else if (weapon.name === 'Bounce') { // Multi-directional attack self.performBouncePerry(); } // Animate perry effect tween(self.perryEffect, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { if (self.perryEffect) { self.perryEffect.destroy(); self.perryEffect = null; } self.perryActive = false; } }); // Hand animation for perry tween(self.hand, { scaleX: 1.5, scaleY: 1.5, rotation: Math.PI / 4 }, { duration: 200, onFinish: function onFinish() { tween(self.hand, { scaleX: 1, scaleY: 1, rotation: 0 }, { duration: 200 }); } }); } }; self.performSpreadPerry = function () { // Freeze all enemies for 2 seconds for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var originalSpeed = enemy.speed; enemy.speed = 0; tween(enemy, { tint: 0x00ffff }, { duration: 2000, onFinish: function onFinish() { enemy.speed = originalSpeed; enemy.tint = enemyTypesPerLevel[enemy.enemyType].color; } }); } if (boss) { var originalSpeed = boss.speed; boss.speed = 0; tween(boss, { tint: 0x00ffff }, { duration: 2000, onFinish: function onFinish() { boss.speed = originalSpeed; boss.tint = 0xffffff; } }); } }; self.performRapidPerry = function () { // Damage all enemies with explosion effect LK.effects.flashScreen(0xff00ff, 500); for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.takeDamage(3)) { LK.setScore(LK.getScore() + enemy.points * 2); spawnPowerup(enemy.x, enemy.y); enemy.destroy(); enemies.splice(i, 1); } } if (boss) { boss.takeDamage(5); } }; self.performChargePerry = function () { // Create piercing beam that hits all enemies in line var beamY = self.y; for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (Math.abs(enemy.y - beamY) < 50) { if (enemy.takeDamage(4)) { LK.setScore(LK.getScore() + enemy.points * 2); spawnPowerup(enemy.x, enemy.y); enemy.destroy(); enemies.splice(i, 1); } } } if (boss && Math.abs(boss.y - beamY) < 75) { boss.takeDamage(8); } // Visual beam effect LK.effects.flashScreen(0xffff00, 300); }; self.performHomingPerry = function () { // Heal hero and create healing wave if (self.health < self.maxHealth) { self.health = Math.min(self.maxHealth, self.health + 2); } // Damage nearby enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2)); if (distance < 300) { if (enemy.takeDamage(2)) { LK.setScore(LK.getScore() + enemy.points); spawnPowerup(enemy.x, enemy.y); enemy.destroy(); enemies.splice(i, 1); } } } if (boss) { var distance = Math.sqrt(Math.pow(boss.x - self.x, 2) + Math.pow(boss.y - self.y, 2)); if (distance < 400) { boss.takeDamage(3); } } }; self.performBouncePerry = function () { // Create multiple bouncing attacks for (var angle = 0; angle < Math.PI * 2; angle += Math.PI / 4) { var bullet = new HeroBullet(); bullet.x = self.x; bullet.y = self.y; bullet.speed = 12; bullet.damage = 3; bullet.bounces = 3; bullet.speedX = Math.cos(angle) * bullet.speed; bullet.speedY = Math.sin(angle) * bullet.speed; bullet.setWeaponType(4, weaponTypes[4]); heroBullets.push(bullet); game.addChild(bullet); } }; self.collectPerry = function () { self.perryCharges++; }; return self; }); var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('heroBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = 1; self.weaponType = 0; self.target = null; self.bounces = 0; self.pierce = false; self.setWeaponType = function (type, weapon) { self.weaponType = type; bulletGraphics.tint = weapon.parryColor; if (type === 2) { // Charge weapon self.damage = 2; bulletGraphics.scale.x = 1.5; bulletGraphics.scale.y = 1.5; } else if (type === 4) { // Bounce weapon self.bounces = weapon.bounceCount; } }; self.update = function () { if (self.weaponType === 3 && self.target && !self.target.destroyed) { // Homing var angle = Math.atan2(self.target.y - self.y, self.target.x - self.x); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } else if (self.speedX !== undefined && self.speedY !== undefined) { // Perry bouncing bullets self.x += self.speedX; self.y += self.speedY; // Bounce off screen edges if (self.bounces > 0 && (self.y < 100 || self.y > 2632)) { self.speedY *= -1; self.bounces--; } } else { self.x += self.speed; } }; return self; }); var PerryCollectible = Container.expand(function () { var self = Container.call(this); var perryGraphics = self.attachAsset('perryEffect', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3 }); self.speed = -3; self.update = function () { self.x += self.speed; self.rotation += 0.03; // Floating animation self.y += Math.sin(LK.ticks * 0.05) * 0.5; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.random() > 0.5 ? 'rapid' : 'triple'; self.speed = -3; self.update = function () { self.x += self.speed; self.rotation += 0.05; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ game.setBackgroundColor(0x1a1a2e); // Background layers var backgroundLayer1 = LK.getAsset('background1', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 1.0 }); game.addChild(backgroundLayer1); var backgroundLayer2 = LK.getAsset('background2', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 1.0 }); game.addChild(backgroundLayer2); // Clouds array for parallax effect var clouds = []; for (var i = 0; i < 8; i++) { var cloud = LK.getAsset('cloud', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 2048, y: 200 + Math.random() * 1000, alpha: 0.1 + Math.random() * 0.1 }); clouds.push(cloud); game.addChild(cloud); } // Game variables var hero; var heroBullets = []; var enemies = []; var enemyBullets = []; var powerups = []; var perryCollectibles = []; var boss = null; var currentLevel = 1; var enemiesSpawned = 0; var enemiesPerLevel = 10; var spawnCooldown = 0; var gameStarted = false; var isDragging = false; var dragOffsetY = 0; var parryWindow = false; var parryWindowTimer = 0; // Weapon types with different parry mechanics var weaponTypes = [{ name: 'Spread', bulletCount: 3, fireRate: 25, parryColor: 0x00ffff, parryEffect: 'freeze' }, { name: 'Rapid', fireRate: 15, parryColor: 0xff00ff, parryEffect: 'explode' }, { name: 'Charge', chargeTime: 45, fireRate: 60, parryColor: 0xffff00, parryEffect: 'pierce' }, { name: 'Homing', homingStrength: 0.1, fireRate: 30, parryColor: 0x00ff00, parryEffect: 'heal' }, { name: 'Bounce', bounceCount: 2, fireRate: 35, parryColor: 0xff0000, parryEffect: 'multi' }]; var currentWeapon = 0; // Enemy types per level range (base values) var enemyTypesBase = { basic: { health: 2, speed: -2, shootInterval: 120, color: 0xff4444 }, fast: { health: 1, speed: -4, shootInterval: 80, color: 0xff8844 }, heavy: { health: 4, speed: -1, shootInterval: 150, color: 0x884444 }, sniper: { health: 2, speed: -1.5, shootInterval: 180, color: 0x4444ff }, burst: { health: 3, speed: -2.5, shootInterval: 100, color: 0xff44ff } }; // Current enemy stats (will be modified based on weapon changes) var enemyTypesPerLevel = { basic: { health: 2, speed: -2, shootInterval: 120, color: 0xff4444 }, fast: { health: 1, speed: -4, shootInterval: 80, color: 0xff8844 }, heavy: { health: 4, speed: -1, shootInterval: 150, color: 0x884444 }, sniper: { health: 2, speed: -1.5, shootInterval: 180, color: 0x4444ff }, burst: { health: 3, speed: -2.5, shootInterval: 100, color: 0xff44ff } }; // Ground var ground = LK.getAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: 2732 - 100 }); game.addChild(ground); // Hero hero = new Hero(); hero.x = 200; hero.y = 2732 - 200; game.addChild(hero); // UI Elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 20; LK.gui.top.addChild(scoreTxt); // Health display var healthContainer = new Container(); LK.gui.topRight.addChild(healthContainer); healthContainer.x = -120; healthContainer.y = 40; var healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); healthContainer.addChild(healthBarBg); var healthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5, x: -100 }); healthContainer.addChild(healthBar); // Level text var levelTxt = new Text2('Level 1', { size: 80, fill: 0xFFFF00 }); levelTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(levelTxt); levelTxt.alpha = 0; // Weapon text var weaponTxt = new Text2('Weapon: Spread', { size: 50, fill: 0xFFFFFF }); weaponTxt.anchor.set(0, 0); weaponTxt.x = 20; weaponTxt.y = 120; LK.gui.topLeft.addChild(weaponTxt); // Perry charges text var perryTxt = new Text2('Perry: 2', { size: 45, fill: 0xff6600 }); perryTxt.anchor.set(0, 0); perryTxt.x = 20; perryTxt.y = 180; LK.gui.topLeft.addChild(perryTxt); // Perry cooldown text var perryCooldownTxt = new Text2('', { size: 35, fill: 0xffaa00 }); perryCooldownTxt.anchor.set(0, 0); perryCooldownTxt.x = 20; perryCooldownTxt.y = 230; LK.gui.topLeft.addChild(perryCooldownTxt); // Touch controls game.down = function (x, y, obj) { var heroGlobalPos = hero.toGlobal({ x: 0, y: 0 }); var localPos = game.toLocal(heroGlobalPos); if (Math.abs(x - localPos.x) < 100 && Math.abs(y - localPos.y) < 100) { isDragging = true; dragOffsetY = y - hero.y; gameStarted = true; } else if (x > 1024) { // Right side tap for parry parryWindow = true; parryWindowTimer = 20; // 1/3 second parry window hero.startParry(); } else if (x < 200 && y > 1000) { // Bottom left tap for perry special attack hero.activatePerry(); perryTxt.setText('Perry: ' + hero.perryCharges); } }; game.up = function (x, y, obj) { isDragging = false; }; game.move = function (x, y, obj) { if (isDragging) { hero.y = Math.max(300, Math.min(2732 - 200, y - dragOffsetY)); } }; // Helper functions function spawnEnemy() { var enemy = new Enemy(); enemy.x = 2048 + 50; enemy.y = 300 + Math.random() * (2732 - 600); // Choose enemy type based on level var types = ['basic']; if (currentLevel >= 5) { types.push('fast'); } if (currentLevel >= 10) { types.push('heavy'); } if (currentLevel >= 15) { types.push('sniper'); } if (currentLevel >= 20) { types.push('burst'); } var randomType = types[Math.floor(Math.random() * types.length)]; enemy.setType(randomType); enemies.push(enemy); game.addChild(enemy); } function spawnBoss() { boss = new Boss(); boss.x = 2048 - 200; boss.y = 450; boss.setBossLevel(currentLevel); game.addChild(boss); // Show boss warning levelTxt.setText('BOSS LEVEL ' + currentLevel + '!'); levelTxt.alpha = 1; tween(levelTxt, { alpha: 0 }, { duration: 2000 }); } function spawnPowerup(x, y) { if (Math.random() < 0.15) { // 15% chance for perry collectible var perryCollectible = new PerryCollectible(); perryCollectible.x = x; perryCollectible.y = y; perryCollectibles.push(perryCollectible); game.addChild(perryCollectible); } else if (Math.random() < 0.2) { // 20% chance for regular powerup var powerup = new PowerUp(); powerup.x = x; powerup.y = y; powerups.push(powerup); game.addChild(powerup); } } function shootHeroBullet() { var weapon = weaponTypes[hero.weaponType]; hero.animateHandShoot(); var bulletStartX = hero.x + hero.hand.x; var bulletStartY = hero.y + hero.hand.y; if (hero.weaponType === 0 || hero.powerupType === 'triple') { // Spread weapon // Triple shot for (var i = -1; i <= 1; i++) { var bullet = new HeroBullet(); bullet.x = bulletStartX; bullet.y = bulletStartY + i * 30; bullet.setWeaponType(hero.weaponType, weapon); if (hero.weaponType === 3) { // Homing bullet.target = enemies.length > 0 ? enemies[0] : boss; } heroBullets.push(bullet); game.addChild(bullet); } } else if (hero.weaponType === 2) { // Charge weapon if (hero.chargeTime <= 0) { var bullet = new HeroBullet(); bullet.x = bulletStartX; bullet.y = bulletStartY; bullet.setWeaponType(hero.weaponType, weapon); heroBullets.push(bullet); game.addChild(bullet); hero.chargeTime = weapon.chargeTime; } } else { // Normal shot var bullet = new HeroBullet(); bullet.x = bulletStartX; bullet.y = bulletStartY; bullet.setWeaponType(hero.weaponType, weapon); if (hero.weaponType === 3) { // Homing bullet.target = enemies.length > 0 ? enemies[0] : boss; } heroBullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot').play(); } function shootEnemyBullet(enemy) { var bullet = new EnemyBullet(); bullet.x = enemy.x - 30; bullet.y = enemy.y; enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('enemyShoot').play(); } function shootBossBullet(phase) { if (phase === 1) { // Single aimed shot var bullet = new EnemyBullet(); bullet.x = boss.x - 75; bullet.y = boss.y; var angle = Math.atan2(hero.y - boss.y, hero.x - boss.x); bullet.speedX = Math.cos(angle) * 10; bullet.speedY = Math.sin(angle) * 10; enemyBullets.push(bullet); game.addChild(bullet); } else if (phase === 2) { // Spread shot for (var i = -2; i <= 2; i++) { var bullet = new EnemyBullet(); bullet.x = boss.x - 75; bullet.y = boss.y; bullet.speedX = -8; bullet.speedY = i * 2; enemyBullets.push(bullet); game.addChild(bullet); } } LK.getSound('enemyShoot').play(); } // Game update game.update = function () { if (!gameStarted) { return; } // Update health bar healthBar.scale.x = hero.health / hero.maxHealth; // Update perry cooldown display if (hero.perryCooldown > 0) { var cooldownSeconds = Math.ceil(hero.perryCooldown / 60); perryCooldownTxt.setText('Cooldown: ' + cooldownSeconds + 's'); } else { perryCooldownTxt.setText(''); } // Update background clouds for (var i = 0; i < clouds.length; i++) { clouds[i].x -= 0.5; if (clouds[i].x < -100) { clouds[i].x = 2048 + 100; clouds[i].y = 200 + Math.random() * 1000; } } // Spawn enemies if (!boss && enemiesSpawned < enemiesPerLevel) { spawnCooldown++; var spawnRate = Math.max(60, 120 - currentLevel * 2); // Faster spawns at higher levels if (spawnCooldown >= spawnRate) { spawnCooldown = 0; spawnEnemy(); enemiesSpawned++; } } // Update parry window if (parryWindow && parryWindowTimer > 0) { parryWindowTimer--; if (parryWindowTimer === 0) { parryWindow = false; hero.endParry(); } } // Check for next level if (!boss && enemiesSpawned >= enemiesPerLevel && enemies.length === 0) { currentLevel++; enemiesSpawned = 0; enemiesPerLevel = Math.min(20, 10 + Math.floor(currentLevel / 5)); // Change weapon every 3 levels if ((currentLevel - 1) % 3 === 0 && currentLevel > 1) { var newWeaponIndex = Math.floor((currentLevel - 1) / 3) % weaponTypes.length; hero.setWeapon(newWeaponIndex); weaponTxt.setText('Weapon: ' + weaponTypes[hero.weaponType].name); // Make enemies stronger when weapon changes var strengthMultiplier = 1 + Math.floor((currentLevel - 1) / 3) * 0.3; for (var enemyType in enemyTypesPerLevel) { enemyTypesPerLevel[enemyType].health = Math.floor(enemyTypesPerLevel[enemyType].health * strengthMultiplier); enemyTypesPerLevel[enemyType].speed = enemyTypesPerLevel[enemyType].speed * (1 + strengthMultiplier * 0.1); } } if (currentLevel > 50) { // Win condition LK.showYouWin(); } else if (currentLevel % 10 === 0) { // Boss level spawnBoss(); } else { // Normal level levelTxt.setText('Level ' + currentLevel); levelTxt.alpha = 1; tween(levelTxt, { alpha: 0 }, { duration: 2000 }); } } // Hero shooting if (hero.canShoot()) { shootHeroBullet(); } // Update hero bullets for (var i = heroBullets.length - 1; i >= 0; i--) { var bullet = heroBullets[i]; if (bullet.x > 2048 + 50) { bullet.destroy(); heroBullets.splice(i, 1); continue; } // Check enemy collisions for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { if (enemy.takeDamage(bullet.damage)) { // Enemy destroyed LK.setScore(LK.getScore() + enemy.points); scoreTxt.setText('Score: ' + LK.getScore()); spawnPowerup(enemy.x, enemy.y); enemy.destroy(); enemies.splice(j, 1); LK.getSound('enemyDestroy').play(); } bullet.destroy(); heroBullets.splice(i, 1); break; } } // Check boss collision if (boss && bullet.intersects(boss)) { if (boss.takeDamage(bullet.damage)) { // Boss destroyed LK.setScore(LK.getScore() + boss.points); scoreTxt.setText('Score: ' + LK.getScore()); spawnPowerup(boss.x, boss.y); boss.destroy(); boss = null; LK.getSound('enemyDestroy').play(); } bullet.destroy(); heroBullets.splice(i, 1); } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.x < -50) { enemy.destroy(); enemies.splice(i, 1); continue; } if (enemy.update()) { shootEnemyBullet(enemy); } // Check collision with hero if (enemy.intersects(hero)) { if (hero.takeDamage()) { LK.showGameOver(); } enemy.destroy(); enemies.splice(i, 1); LK.getSound('hit').play(); } } // Update boss if (boss) { var phase = boss.update(); if (phase > 0) { shootBossBullet(phase); } // Check collision with hero if (boss.intersects(hero)) { if (hero.takeDamage()) { LK.showGameOver(); } LK.getSound('hit').play(); } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; if (bullet.x < -50 || bullet.x > 2048 + 50 || bullet.y < -50 || bullet.y > 2732 + 50) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } // Check collision with hero if (bullet.intersects(hero)) { if (parryWindow && bullet.canBeParried && !bullet.parried) { // Successful parry! bullet.parried = true; bullet.speedX *= -2; bullet.speedY *= -0.5; bullet.tint = weaponTypes[hero.weaponType].parryColor; LK.setScore(LK.getScore() + 50); scoreTxt.setText('Score: ' + LK.getScore()); // Apply parry effect var effect = weaponTypes[hero.weaponType].parryEffect; if (effect === 'heal' && hero.health < hero.maxHealth) { hero.health++; } else if (effect === 'explode') { LK.effects.flashScreen(weaponTypes[hero.weaponType].parryColor, 200); // Damage all enemies for (var j = 0; j < enemies.length; j++) { enemies[j].takeDamage(1); } } else if (effect === 'freeze') { // Slow all enemies temporarily for (var j = 0; j < enemies.length; j++) { enemies[j].speed *= 0.5; } } } else if (!bullet.parried) { if (hero.takeDamage()) { LK.showGameOver(); } bullet.destroy(); enemyBullets.splice(i, 1); LK.getSound('hit').play(); } } // Check parried bullets hitting enemies if (bullet.parried) { for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { if (enemy.takeDamage(2)) { LK.setScore(LK.getScore() + enemy.points * 2); scoreTxt.setText('Score: ' + LK.getScore()); spawnPowerup(enemy.x, enemy.y); enemy.destroy(); enemies.splice(j, 1); LK.getSound('enemyDestroy').play(); } bullet.destroy(); enemyBullets.splice(i, 1); break; } } // Check boss collision if (boss && bullet.intersects(boss)) { if (boss.takeDamage(2)) { LK.setScore(LK.getScore() + boss.points); scoreTxt.setText('Score: ' + LK.getScore()); spawnPowerup(boss.x, boss.y); boss.destroy(); boss = null; LK.getSound('enemyDestroy').play(); } bullet.destroy(); enemyBullets.splice(i, 1); } } } // Update powerups for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (powerup.x < -50) { powerup.destroy(); powerups.splice(i, 1); continue; } // Check collision with hero if (powerup.intersects(hero)) { hero.applyPowerup(powerup.type); powerup.destroy(); powerups.splice(i, 1); LK.getSound('powerupCollect').play(); } } // Update perry collectibles for (var i = perryCollectibles.length - 1; i >= 0; i--) { var perryCollectible = perryCollectibles[i]; if (perryCollectible.x < -50) { perryCollectible.destroy(); perryCollectibles.splice(i, 1); continue; } // Check collision with hero if (perryCollectible.intersects(hero)) { hero.collectPerry(); perryTxt.setText('Perry: ' + hero.perryCharges); perryCollectible.destroy(); perryCollectibles.splice(i, 1); LK.getSound('powerupCollect').play(); } } }; // Start music LK.playMusic('bgMusic');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.bossLevel = 1;
self.health = 20;
self.maxHealth = 20;
self.speed = 2;
self.direction = 1;
self.shootCooldown = 0;
self.shootInterval = 60;
self.phase = 1;
self.points = 1000;
self.setBossLevel = function (level) {
self.bossLevel = Math.floor(level / 10);
self.health = 20 + self.bossLevel * 10;
self.maxHealth = self.health;
self.points = 1000 * (self.bossLevel + 1);
bossGraphics.scale.x = 1 + self.bossLevel * 0.2;
bossGraphics.scale.y = 1 + self.bossLevel * 0.2;
};
self.update = function () {
// Boss movement pattern
self.y += self.speed * self.direction;
if (self.y > 600 || self.y < 300) {
self.direction *= -1;
}
// More complex movement for higher level bosses
if (self.bossLevel >= 2) {
self.x += Math.sin(LK.ticks * 0.02) * 2;
}
self.shootCooldown++;
// Different attack patterns based on phase
if (self.health < self.maxHealth * 0.5 && self.phase === 1) {
self.phase = 2;
self.shootInterval = 40;
}
if (self.health < self.maxHealth * 0.25 && self.phase === 2 && self.bossLevel >= 3) {
self.phase = 3;
self.shootInterval = 30;
}
if (self.shootCooldown >= self.shootInterval) {
self.shootCooldown = 0;
return self.phase; // Return phase for different bullet patterns
}
return 0;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true; // Boss destroyed
}
tween(bossGraphics, {
tint: 0xffffff
}, {
duration: 100,
onFinish: function onFinish() {
bossGraphics.tint = 0xffffff;
}
});
bossGraphics.tint = 0xff0000;
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.enemyType = 'basic';
self.health = 2;
self.speed = -2;
self.shootCooldown = 0;
self.shootInterval = 120;
self.points = 100;
self.pattern = 0;
self.setType = function (type) {
self.enemyType = type;
var stats = enemyTypesPerLevel[type];
self.health = stats.health;
self.speed = stats.speed;
self.shootInterval = stats.shootInterval;
enemyGraphics.tint = stats.color;
self.points = stats.health * 50;
};
self.update = function () {
self.x += self.speed;
// Different movement patterns for different enemy types
if (self.enemyType === 'fast') {
self.y += Math.sin(self.x * 0.01) * 2;
} else if (self.enemyType === 'sniper' && self.x < 1500) {
self.speed = 0;
}
self.shootCooldown++;
if (self.shootCooldown >= self.shootInterval) {
self.shootCooldown = 0;
return true; // Signal to shoot
}
return false;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
return true; // Enemy destroyed
}
tween(enemyGraphics, {
tint: 0xffffff
}, {
duration: 100,
onFinish: function onFinish() {
enemyGraphics.tint = enemyTypesPerLevel[self.enemyType].color;
}
});
enemyGraphics.tint = 0xff0000;
return false;
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = -8;
self.speedY = 0;
self.canBeParried = false;
self.parried = false;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
// Make bullets parryable when they're pink
if (!self.canBeParried && Math.random() < 0.3) {
self.canBeParried = true;
bulletGraphics.tint = 0xff00ff;
}
};
return self;
});
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroGraphics = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
self.hand = self.attachAsset('hand', {
anchorX: 0.5,
anchorY: 0.5,
x: 60,
y: -5
});
self.handBaseY = -15;
self.handAnimating = false;
self.health = 3;
self.maxHealth = 3;
self.shootCooldown = 0;
self.shootInterval = 20;
self.invulnerable = 0;
self.powerupTime = 0;
self.powerupType = null;
self.weaponType = 0;
self.chargeTime = 0;
self.isParrying = false;
self.parryIndicator = null;
self.originalTint = 0xffffff;
self.isPowerupFlashing = false;
self.perryCharges = 2; // Start with 2 perrys
self.perryEffect = null;
self.perryActive = false;
self.perryCooldown = 0;
self.perryMaxCooldown = 300; // 5 seconds at 60fps
self.update = function () {
if (self.invulnerable > 0) {
self.invulnerable--;
self.alpha = Math.sin(self.invulnerable * 0.3) > 0 ? 1 : 0.5;
} else {
self.alpha = 1;
}
if (self.powerupTime > 0) {
self.powerupTime--;
// Flash between powerup color and original color in the last 2 seconds
if (self.powerupTime <= 120 && !self.isPowerupFlashing) {
self.isPowerupFlashing = true;
self.startPowerupFlash();
}
if (self.powerupTime === 0) {
self.powerupType = null;
self.shootInterval = 20;
heroGraphics.tint = self.originalTint;
self.isPowerupFlashing = false;
}
}
self.shootCooldown++;
// Update charge for charge weapon
if (self.weaponType === 2 && self.chargeTime > 0) {
self.chargeTime--;
}
// Update perry cooldown
if (self.perryCooldown > 0) {
self.perryCooldown--;
}
};
self.takeDamage = function () {
if (self.invulnerable > 0) {
return false;
}
self.health--;
self.invulnerable = 120; // 2 seconds of invulnerability
if (self.health <= 0) {
return true; // Hero destroyed
}
LK.effects.flashObject(self, 0xff0000, 500);
return false;
};
self.canShoot = function () {
var weapon = weaponTypes[self.weaponType];
var interval = self.shootInterval;
if (weapon.fireRate) {
interval = weapon.fireRate;
}
if (self.shootCooldown >= interval) {
self.shootCooldown = 0;
return true;
}
return false;
};
self.applyPowerup = function (type) {
self.powerupType = type;
self.powerupTime = 600; // 10 seconds
self.isPowerupFlashing = false;
// Change hero color based on powerup type
var powerupColor = type === 'rapid' ? 0xff00ff : 0x00ffff;
heroGraphics.tint = powerupColor;
if (type === 'rapid') {
self.shootInterval = 10;
}
};
self.startPowerupFlash = function () {
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
flashCount++;
if (flashCount % 2 === 0) {
heroGraphics.tint = self.originalTint;
} else {
var powerupColor = self.powerupType === 'rapid' ? 0xff00ff : 0x00ffff;
heroGraphics.tint = powerupColor;
}
if (self.powerupTime === 0) {
LK.clearInterval(flashInterval);
heroGraphics.tint = self.originalTint;
}
}, 200); // Flash every 200ms
};
self.setWeapon = function (weaponIndex) {
self.weaponType = weaponIndex;
};
self.startParry = function () {
if (!self.isParrying && !self.parryIndicator) {
self.isParrying = true;
self.parryIndicator = self.attachAsset('parryIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
self.parryIndicator.alpha = 0.5;
self.parryIndicator.tint = weaponTypes[self.weaponType].parryColor;
}
};
self.endParry = function () {
self.isParrying = false;
if (self.parryIndicator) {
self.parryIndicator.destroy();
self.parryIndicator = null;
}
};
self.animateHandShoot = function () {
if (!self.handAnimating) {
self.handAnimating = true;
tween(self.hand, {
y: self.handBaseY - 20
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.hand, {
y: self.handBaseY
}, {
duration: 100,
onFinish: function onFinish() {
self.handAnimating = false;
}
});
}
});
}
};
self.activatePerry = function () {
if (self.perryCharges > 0 && !self.perryActive && self.perryCooldown === 0) {
self.perryCharges--;
self.perryActive = true;
self.perryCooldown = self.perryMaxCooldown; // Set cooldown
var weapon = weaponTypes[self.weaponType];
// Create perry effect visual
self.perryEffect = self.attachAsset('perryEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.perryEffect.tint = weapon.parryColor;
// Weapon-specific animations and effects
if (weapon.name === 'Spread') {
// Freeze all enemies briefly
self.performSpreadPerry();
} else if (weapon.name === 'Rapid') {
// Multi-hit explosion
self.performRapidPerry();
} else if (weapon.name === 'Charge') {
// Piercing beam attack
self.performChargePerry();
} else if (weapon.name === 'Homing') {
// Healing wave
self.performHomingPerry();
} else if (weapon.name === 'Bounce') {
// Multi-directional attack
self.performBouncePerry();
}
// Animate perry effect
tween(self.perryEffect, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
if (self.perryEffect) {
self.perryEffect.destroy();
self.perryEffect = null;
}
self.perryActive = false;
}
});
// Hand animation for perry
tween(self.hand, {
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI / 4
}, {
duration: 200,
onFinish: function onFinish() {
tween(self.hand, {
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 200
});
}
});
}
};
self.performSpreadPerry = function () {
// Freeze all enemies for 2 seconds
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var originalSpeed = enemy.speed;
enemy.speed = 0;
tween(enemy, {
tint: 0x00ffff
}, {
duration: 2000,
onFinish: function onFinish() {
enemy.speed = originalSpeed;
enemy.tint = enemyTypesPerLevel[enemy.enemyType].color;
}
});
}
if (boss) {
var originalSpeed = boss.speed;
boss.speed = 0;
tween(boss, {
tint: 0x00ffff
}, {
duration: 2000,
onFinish: function onFinish() {
boss.speed = originalSpeed;
boss.tint = 0xffffff;
}
});
}
};
self.performRapidPerry = function () {
// Damage all enemies with explosion effect
LK.effects.flashScreen(0xff00ff, 500);
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.takeDamage(3)) {
LK.setScore(LK.getScore() + enemy.points * 2);
spawnPowerup(enemy.x, enemy.y);
enemy.destroy();
enemies.splice(i, 1);
}
}
if (boss) {
boss.takeDamage(5);
}
};
self.performChargePerry = function () {
// Create piercing beam that hits all enemies in line
var beamY = self.y;
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (Math.abs(enemy.y - beamY) < 50) {
if (enemy.takeDamage(4)) {
LK.setScore(LK.getScore() + enemy.points * 2);
spawnPowerup(enemy.x, enemy.y);
enemy.destroy();
enemies.splice(i, 1);
}
}
}
if (boss && Math.abs(boss.y - beamY) < 75) {
boss.takeDamage(8);
}
// Visual beam effect
LK.effects.flashScreen(0xffff00, 300);
};
self.performHomingPerry = function () {
// Heal hero and create healing wave
if (self.health < self.maxHealth) {
self.health = Math.min(self.maxHealth, self.health + 2);
}
// Damage nearby enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
if (distance < 300) {
if (enemy.takeDamage(2)) {
LK.setScore(LK.getScore() + enemy.points);
spawnPowerup(enemy.x, enemy.y);
enemy.destroy();
enemies.splice(i, 1);
}
}
}
if (boss) {
var distance = Math.sqrt(Math.pow(boss.x - self.x, 2) + Math.pow(boss.y - self.y, 2));
if (distance < 400) {
boss.takeDamage(3);
}
}
};
self.performBouncePerry = function () {
// Create multiple bouncing attacks
for (var angle = 0; angle < Math.PI * 2; angle += Math.PI / 4) {
var bullet = new HeroBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.speed = 12;
bullet.damage = 3;
bullet.bounces = 3;
bullet.speedX = Math.cos(angle) * bullet.speed;
bullet.speedY = Math.sin(angle) * bullet.speed;
bullet.setWeaponType(4, weaponTypes[4]);
heroBullets.push(bullet);
game.addChild(bullet);
}
};
self.collectPerry = function () {
self.perryCharges++;
};
return self;
});
var HeroBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('heroBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.damage = 1;
self.weaponType = 0;
self.target = null;
self.bounces = 0;
self.pierce = false;
self.setWeaponType = function (type, weapon) {
self.weaponType = type;
bulletGraphics.tint = weapon.parryColor;
if (type === 2) {
// Charge weapon
self.damage = 2;
bulletGraphics.scale.x = 1.5;
bulletGraphics.scale.y = 1.5;
} else if (type === 4) {
// Bounce weapon
self.bounces = weapon.bounceCount;
}
};
self.update = function () {
if (self.weaponType === 3 && self.target && !self.target.destroyed) {
// Homing
var angle = Math.atan2(self.target.y - self.y, self.target.x - self.x);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
} else if (self.speedX !== undefined && self.speedY !== undefined) {
// Perry bouncing bullets
self.x += self.speedX;
self.y += self.speedY;
// Bounce off screen edges
if (self.bounces > 0 && (self.y < 100 || self.y > 2632)) {
self.speedY *= -1;
self.bounces--;
}
} else {
self.x += self.speed;
}
};
return self;
});
var PerryCollectible = Container.expand(function () {
var self = Container.call(this);
var perryGraphics = self.attachAsset('perryEffect', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
self.speed = -3;
self.update = function () {
self.x += self.speed;
self.rotation += 0.03;
// Floating animation
self.y += Math.sin(LK.ticks * 0.05) * 0.5;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.random() > 0.5 ? 'rapid' : 'triple';
self.speed = -3;
self.update = function () {
self.x += self.speed;
self.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
game.setBackgroundColor(0x1a1a2e);
// Background layers
var backgroundLayer1 = LK.getAsset('background1', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1.0
});
game.addChild(backgroundLayer1);
var backgroundLayer2 = LK.getAsset('background2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1.0
});
game.addChild(backgroundLayer2);
// Clouds array for parallax effect
var clouds = [];
for (var i = 0; i < 8; i++) {
var cloud = LK.getAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: 200 + Math.random() * 1000,
alpha: 0.1 + Math.random() * 0.1
});
clouds.push(cloud);
game.addChild(cloud);
}
// Game variables
var hero;
var heroBullets = [];
var enemies = [];
var enemyBullets = [];
var powerups = [];
var perryCollectibles = [];
var boss = null;
var currentLevel = 1;
var enemiesSpawned = 0;
var enemiesPerLevel = 10;
var spawnCooldown = 0;
var gameStarted = false;
var isDragging = false;
var dragOffsetY = 0;
var parryWindow = false;
var parryWindowTimer = 0;
// Weapon types with different parry mechanics
var weaponTypes = [{
name: 'Spread',
bulletCount: 3,
fireRate: 25,
parryColor: 0x00ffff,
parryEffect: 'freeze'
}, {
name: 'Rapid',
fireRate: 15,
parryColor: 0xff00ff,
parryEffect: 'explode'
}, {
name: 'Charge',
chargeTime: 45,
fireRate: 60,
parryColor: 0xffff00,
parryEffect: 'pierce'
}, {
name: 'Homing',
homingStrength: 0.1,
fireRate: 30,
parryColor: 0x00ff00,
parryEffect: 'heal'
}, {
name: 'Bounce',
bounceCount: 2,
fireRate: 35,
parryColor: 0xff0000,
parryEffect: 'multi'
}];
var currentWeapon = 0;
// Enemy types per level range (base values)
var enemyTypesBase = {
basic: {
health: 2,
speed: -2,
shootInterval: 120,
color: 0xff4444
},
fast: {
health: 1,
speed: -4,
shootInterval: 80,
color: 0xff8844
},
heavy: {
health: 4,
speed: -1,
shootInterval: 150,
color: 0x884444
},
sniper: {
health: 2,
speed: -1.5,
shootInterval: 180,
color: 0x4444ff
},
burst: {
health: 3,
speed: -2.5,
shootInterval: 100,
color: 0xff44ff
}
};
// Current enemy stats (will be modified based on weapon changes)
var enemyTypesPerLevel = {
basic: {
health: 2,
speed: -2,
shootInterval: 120,
color: 0xff4444
},
fast: {
health: 1,
speed: -4,
shootInterval: 80,
color: 0xff8844
},
heavy: {
health: 4,
speed: -1,
shootInterval: 150,
color: 0x884444
},
sniper: {
health: 2,
speed: -1.5,
shootInterval: 180,
color: 0x4444ff
},
burst: {
health: 3,
speed: -2.5,
shootInterval: 100,
color: 0xff44ff
}
};
// Ground
var ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - 100
});
game.addChild(ground);
// Hero
hero = new Hero();
hero.x = 200;
hero.y = 2732 - 200;
game.addChild(hero);
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
// Health display
var healthContainer = new Container();
LK.gui.topRight.addChild(healthContainer);
healthContainer.x = -120;
healthContainer.y = 40;
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthContainer.addChild(healthBarBg);
var healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: -100
});
healthContainer.addChild(healthBar);
// Level text
var levelTxt = new Text2('Level 1', {
size: 80,
fill: 0xFFFF00
});
levelTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelTxt);
levelTxt.alpha = 0;
// Weapon text
var weaponTxt = new Text2('Weapon: Spread', {
size: 50,
fill: 0xFFFFFF
});
weaponTxt.anchor.set(0, 0);
weaponTxt.x = 20;
weaponTxt.y = 120;
LK.gui.topLeft.addChild(weaponTxt);
// Perry charges text
var perryTxt = new Text2('Perry: 2', {
size: 45,
fill: 0xff6600
});
perryTxt.anchor.set(0, 0);
perryTxt.x = 20;
perryTxt.y = 180;
LK.gui.topLeft.addChild(perryTxt);
// Perry cooldown text
var perryCooldownTxt = new Text2('', {
size: 35,
fill: 0xffaa00
});
perryCooldownTxt.anchor.set(0, 0);
perryCooldownTxt.x = 20;
perryCooldownTxt.y = 230;
LK.gui.topLeft.addChild(perryCooldownTxt);
// Touch controls
game.down = function (x, y, obj) {
var heroGlobalPos = hero.toGlobal({
x: 0,
y: 0
});
var localPos = game.toLocal(heroGlobalPos);
if (Math.abs(x - localPos.x) < 100 && Math.abs(y - localPos.y) < 100) {
isDragging = true;
dragOffsetY = y - hero.y;
gameStarted = true;
} else if (x > 1024) {
// Right side tap for parry
parryWindow = true;
parryWindowTimer = 20; // 1/3 second parry window
hero.startParry();
} else if (x < 200 && y > 1000) {
// Bottom left tap for perry special attack
hero.activatePerry();
perryTxt.setText('Perry: ' + hero.perryCharges);
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
game.move = function (x, y, obj) {
if (isDragging) {
hero.y = Math.max(300, Math.min(2732 - 200, y - dragOffsetY));
}
};
// Helper functions
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = 2048 + 50;
enemy.y = 300 + Math.random() * (2732 - 600);
// Choose enemy type based on level
var types = ['basic'];
if (currentLevel >= 5) {
types.push('fast');
}
if (currentLevel >= 10) {
types.push('heavy');
}
if (currentLevel >= 15) {
types.push('sniper');
}
if (currentLevel >= 20) {
types.push('burst');
}
var randomType = types[Math.floor(Math.random() * types.length)];
enemy.setType(randomType);
enemies.push(enemy);
game.addChild(enemy);
}
function spawnBoss() {
boss = new Boss();
boss.x = 2048 - 200;
boss.y = 450;
boss.setBossLevel(currentLevel);
game.addChild(boss);
// Show boss warning
levelTxt.setText('BOSS LEVEL ' + currentLevel + '!');
levelTxt.alpha = 1;
tween(levelTxt, {
alpha: 0
}, {
duration: 2000
});
}
function spawnPowerup(x, y) {
if (Math.random() < 0.15) {
// 15% chance for perry collectible
var perryCollectible = new PerryCollectible();
perryCollectible.x = x;
perryCollectible.y = y;
perryCollectibles.push(perryCollectible);
game.addChild(perryCollectible);
} else if (Math.random() < 0.2) {
// 20% chance for regular powerup
var powerup = new PowerUp();
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
game.addChild(powerup);
}
}
function shootHeroBullet() {
var weapon = weaponTypes[hero.weaponType];
hero.animateHandShoot();
var bulletStartX = hero.x + hero.hand.x;
var bulletStartY = hero.y + hero.hand.y;
if (hero.weaponType === 0 || hero.powerupType === 'triple') {
// Spread weapon
// Triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new HeroBullet();
bullet.x = bulletStartX;
bullet.y = bulletStartY + i * 30;
bullet.setWeaponType(hero.weaponType, weapon);
if (hero.weaponType === 3) {
// Homing
bullet.target = enemies.length > 0 ? enemies[0] : boss;
}
heroBullets.push(bullet);
game.addChild(bullet);
}
} else if (hero.weaponType === 2) {
// Charge weapon
if (hero.chargeTime <= 0) {
var bullet = new HeroBullet();
bullet.x = bulletStartX;
bullet.y = bulletStartY;
bullet.setWeaponType(hero.weaponType, weapon);
heroBullets.push(bullet);
game.addChild(bullet);
hero.chargeTime = weapon.chargeTime;
}
} else {
// Normal shot
var bullet = new HeroBullet();
bullet.x = bulletStartX;
bullet.y = bulletStartY;
bullet.setWeaponType(hero.weaponType, weapon);
if (hero.weaponType === 3) {
// Homing
bullet.target = enemies.length > 0 ? enemies[0] : boss;
}
heroBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shoot').play();
}
function shootEnemyBullet(enemy) {
var bullet = new EnemyBullet();
bullet.x = enemy.x - 30;
bullet.y = enemy.y;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('enemyShoot').play();
}
function shootBossBullet(phase) {
if (phase === 1) {
// Single aimed shot
var bullet = new EnemyBullet();
bullet.x = boss.x - 75;
bullet.y = boss.y;
var angle = Math.atan2(hero.y - boss.y, hero.x - boss.x);
bullet.speedX = Math.cos(angle) * 10;
bullet.speedY = Math.sin(angle) * 10;
enemyBullets.push(bullet);
game.addChild(bullet);
} else if (phase === 2) {
// Spread shot
for (var i = -2; i <= 2; i++) {
var bullet = new EnemyBullet();
bullet.x = boss.x - 75;
bullet.y = boss.y;
bullet.speedX = -8;
bullet.speedY = i * 2;
enemyBullets.push(bullet);
game.addChild(bullet);
}
}
LK.getSound('enemyShoot').play();
}
// Game update
game.update = function () {
if (!gameStarted) {
return;
}
// Update health bar
healthBar.scale.x = hero.health / hero.maxHealth;
// Update perry cooldown display
if (hero.perryCooldown > 0) {
var cooldownSeconds = Math.ceil(hero.perryCooldown / 60);
perryCooldownTxt.setText('Cooldown: ' + cooldownSeconds + 's');
} else {
perryCooldownTxt.setText('');
}
// Update background clouds
for (var i = 0; i < clouds.length; i++) {
clouds[i].x -= 0.5;
if (clouds[i].x < -100) {
clouds[i].x = 2048 + 100;
clouds[i].y = 200 + Math.random() * 1000;
}
}
// Spawn enemies
if (!boss && enemiesSpawned < enemiesPerLevel) {
spawnCooldown++;
var spawnRate = Math.max(60, 120 - currentLevel * 2); // Faster spawns at higher levels
if (spawnCooldown >= spawnRate) {
spawnCooldown = 0;
spawnEnemy();
enemiesSpawned++;
}
}
// Update parry window
if (parryWindow && parryWindowTimer > 0) {
parryWindowTimer--;
if (parryWindowTimer === 0) {
parryWindow = false;
hero.endParry();
}
}
// Check for next level
if (!boss && enemiesSpawned >= enemiesPerLevel && enemies.length === 0) {
currentLevel++;
enemiesSpawned = 0;
enemiesPerLevel = Math.min(20, 10 + Math.floor(currentLevel / 5));
// Change weapon every 3 levels
if ((currentLevel - 1) % 3 === 0 && currentLevel > 1) {
var newWeaponIndex = Math.floor((currentLevel - 1) / 3) % weaponTypes.length;
hero.setWeapon(newWeaponIndex);
weaponTxt.setText('Weapon: ' + weaponTypes[hero.weaponType].name);
// Make enemies stronger when weapon changes
var strengthMultiplier = 1 + Math.floor((currentLevel - 1) / 3) * 0.3;
for (var enemyType in enemyTypesPerLevel) {
enemyTypesPerLevel[enemyType].health = Math.floor(enemyTypesPerLevel[enemyType].health * strengthMultiplier);
enemyTypesPerLevel[enemyType].speed = enemyTypesPerLevel[enemyType].speed * (1 + strengthMultiplier * 0.1);
}
}
if (currentLevel > 50) {
// Win condition
LK.showYouWin();
} else if (currentLevel % 10 === 0) {
// Boss level
spawnBoss();
} else {
// Normal level
levelTxt.setText('Level ' + currentLevel);
levelTxt.alpha = 1;
tween(levelTxt, {
alpha: 0
}, {
duration: 2000
});
}
}
// Hero shooting
if (hero.canShoot()) {
shootHeroBullet();
}
// Update hero bullets
for (var i = heroBullets.length - 1; i >= 0; i--) {
var bullet = heroBullets[i];
if (bullet.x > 2048 + 50) {
bullet.destroy();
heroBullets.splice(i, 1);
continue;
}
// Check enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(bullet.damage)) {
// Enemy destroyed
LK.setScore(LK.getScore() + enemy.points);
scoreTxt.setText('Score: ' + LK.getScore());
spawnPowerup(enemy.x, enemy.y);
enemy.destroy();
enemies.splice(j, 1);
LK.getSound('enemyDestroy').play();
}
bullet.destroy();
heroBullets.splice(i, 1);
break;
}
}
// Check boss collision
if (boss && bullet.intersects(boss)) {
if (boss.takeDamage(bullet.damage)) {
// Boss destroyed
LK.setScore(LK.getScore() + boss.points);
scoreTxt.setText('Score: ' + LK.getScore());
spawnPowerup(boss.x, boss.y);
boss.destroy();
boss = null;
LK.getSound('enemyDestroy').play();
}
bullet.destroy();
heroBullets.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.x < -50) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
if (enemy.update()) {
shootEnemyBullet(enemy);
}
// Check collision with hero
if (enemy.intersects(hero)) {
if (hero.takeDamage()) {
LK.showGameOver();
}
enemy.destroy();
enemies.splice(i, 1);
LK.getSound('hit').play();
}
}
// Update boss
if (boss) {
var phase = boss.update();
if (phase > 0) {
shootBossBullet(phase);
}
// Check collision with hero
if (boss.intersects(hero)) {
if (hero.takeDamage()) {
LK.showGameOver();
}
LK.getSound('hit').play();
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.x < -50 || bullet.x > 2048 + 50 || bullet.y < -50 || bullet.y > 2732 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with hero
if (bullet.intersects(hero)) {
if (parryWindow && bullet.canBeParried && !bullet.parried) {
// Successful parry!
bullet.parried = true;
bullet.speedX *= -2;
bullet.speedY *= -0.5;
bullet.tint = weaponTypes[hero.weaponType].parryColor;
LK.setScore(LK.getScore() + 50);
scoreTxt.setText('Score: ' + LK.getScore());
// Apply parry effect
var effect = weaponTypes[hero.weaponType].parryEffect;
if (effect === 'heal' && hero.health < hero.maxHealth) {
hero.health++;
} else if (effect === 'explode') {
LK.effects.flashScreen(weaponTypes[hero.weaponType].parryColor, 200);
// Damage all enemies
for (var j = 0; j < enemies.length; j++) {
enemies[j].takeDamage(1);
}
} else if (effect === 'freeze') {
// Slow all enemies temporarily
for (var j = 0; j < enemies.length; j++) {
enemies[j].speed *= 0.5;
}
}
} else if (!bullet.parried) {
if (hero.takeDamage()) {
LK.showGameOver();
}
bullet.destroy();
enemyBullets.splice(i, 1);
LK.getSound('hit').play();
}
}
// Check parried bullets hitting enemies
if (bullet.parried) {
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(2)) {
LK.setScore(LK.getScore() + enemy.points * 2);
scoreTxt.setText('Score: ' + LK.getScore());
spawnPowerup(enemy.x, enemy.y);
enemy.destroy();
enemies.splice(j, 1);
LK.getSound('enemyDestroy').play();
}
bullet.destroy();
enemyBullets.splice(i, 1);
break;
}
}
// Check boss collision
if (boss && bullet.intersects(boss)) {
if (boss.takeDamage(2)) {
LK.setScore(LK.getScore() + boss.points);
scoreTxt.setText('Score: ' + LK.getScore());
spawnPowerup(boss.x, boss.y);
boss.destroy();
boss = null;
LK.getSound('enemyDestroy').play();
}
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.x < -50) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with hero
if (powerup.intersects(hero)) {
hero.applyPowerup(powerup.type);
powerup.destroy();
powerups.splice(i, 1);
LK.getSound('powerupCollect').play();
}
}
// Update perry collectibles
for (var i = perryCollectibles.length - 1; i >= 0; i--) {
var perryCollectible = perryCollectibles[i];
if (perryCollectible.x < -50) {
perryCollectible.destroy();
perryCollectibles.splice(i, 1);
continue;
}
// Check collision with hero
if (perryCollectible.intersects(hero)) {
hero.collectPerry();
perryTxt.setText('Perry: ' + hero.perryCharges);
perryCollectible.destroy();
perryCollectibles.splice(i, 1);
LK.getSound('powerupCollect').play();
}
}
};
// Start music
LK.playMusic('bgMusic');