User prompt
Each exp orb should give a fixed 1 EXP. It doesn't seem to be the case right now. We need to fix that.
User prompt
You need to change the leveling system. In order to move to the next level, I need to have the same amount of exp orbs as my current level. (So if I started at level 1, I need 1 exp orb to move to level 2, 2 exp orbs to move to level 3, 3 exp orbs to move to level 4.)
User prompt
"Death" sound when killing an enemy. I want to play a "hit" sound when hitting an enemy. Right now, the hit sound plays when an enemy dies, but the hit sound should play when I hit the enemy, not when the enemy dies. The death sound should play when the enemy dies.
User prompt
Do it for me.
Code edit (2 edits merged)
Please save this source code
User prompt
I want to use the image named "seamlessBackGround" in the background.
Code edit (6 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: e.takeDamage is not a function' in or related to this line: 'if (e.takeDamage(dmg)) {' Line Number: 594
Code edit (8 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Graphics is not a constructor' in or related to this line: 'var gfx = new Graphics();' Line Number: 778
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'cdCnt')' in or related to this line: 'if (--inst.cdCnt <= 0) {' Line Number: 302
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'cdCnt')' in or related to this line: 'if (--inst.cdCnt <= 0) {' Line Number: 304
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'update')' in or related to this line: 'BrickProj.parent.update.call(b);' Line Number: 680
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'update')' in or related to this line: 'BrickProj.parent.update.call(p);' Line Number: 754
User prompt
Please fix the bug: 'ReferenceError: fireWeapon is not defined' in or related to this line: 'fireWeapon(key, inst, meta);' Line Number: 223
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: meta is not defined' in or related to this line: 'if (e.intersectsCircle(arc.x, arc.y, meta.range * inst.rngMul) && e.takeDamage(arc.dmg)) {' Line Number: 383
User prompt
Please fix the bug: 'spawnWave is not defined' in or related to this line: 'spawnWave();' Line Number: 1076
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: dropExpOrb is not defined' in or related to this line: 'dropExpOrb(en.x, en.y, en.expValue);' Line Number: 593
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bomb = Container.expand(function () { var self = Container.call(this); self.active = true; var bombGraphics = self.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5, width: 60, height: 60, tint: 0xff0000 }); self.update = function () { if (!player || !self.active) { return; } var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.active = false; // Kill all non-boss enemies on screen for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.type !== 'boss') { var screenDx = Math.abs(enemy.x - player.x); var screenDy = Math.abs(enemy.y - player.y); if (screenDx < 1024 && screenDy < 1366) { dropExpOrb(enemy.x, enemy.y, enemy.expValue); enemy.destroy(); enemies.splice(i, 1); } } } LK.effects.flashScreen(0xff0000, 300); self.destroy(); return true; } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); self.damage = 10; self.speed = 15; self.dirX = 0; self.dirY = 0; self.piercing = 1; self.hitEnemies = []; var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); self.hp = 20; self.maxHp = 20; self.damage = 10; self.speed = 2; self.expValue = 5; self.type = 'normal'; var enemyGraphics = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.takeDamage = function (amount) { self.hp -= amount; LK.effects.flashObject(self, 0xffffff, 100); if (self.hp <= 0) { dropExpOrb(self.x, self.y, self.expValue); return true; } return false; }; self.update = function () { if (!player || skillSelectionActive) { return; } var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); var TankZombie = Enemy.expand(function () { var self = Enemy.call(this); self.hp = 60; self.maxHp = 60; self.damage = 20; self.speed = 1; self.expValue = 15; self.type = 'tank'; var graphics = self.attachAsset('tankZombie', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var FastZombie = Enemy.expand(function () { var self = Enemy.call(this); self.hp = 15; self.maxHp = 15; self.damage = 8; self.speed = 4; self.expValue = 8; self.type = 'fast'; var graphics = self.attachAsset('fastZombie', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var Boss = Enemy.expand(function () { var self = Enemy.call(this); self.hp = 500; self.maxHp = 500; self.damage = 30; self.speed = 1.5; self.expValue = 100; self.type = 'boss'; var graphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var ExpOrb = Container.expand(function () { var self = Container.call(this); self.value = 5; self.magnetSpeed = 0; var orbGraphics = self.attachAsset('expOrb', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (!player || self.magnetSpeed === 0) { return; } var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.magnetSpeed; self.y += dy / dist * self.magnetSpeed; } }; return self; }); var Joystick = Container.expand(function () { var self = Container.call(this); self.active = false; self.dirX = 0; self.dirY = 0; var base = self.attachAsset('joystickBase', { anchorX: 0.5, anchorY: 0.5 }); base.alpha = 0.5; var knob = self.attachAsset('joystickKnob', { anchorX: 0.5, anchorY: 0.5 }); knob.alpha = 0.7; self.setKnobPosition = function (x, y) { var dx = x - base.x; var dy = y - base.y; var dist = Math.sqrt(dx * dx + dy * dy); var maxDist = 60; if (dist > maxDist) { dx = dx / dist * maxDist; dy = dy / dist * maxDist; } knob.x = dx; knob.y = dy; self.dirX = dx / maxDist; self.dirY = dy / maxDist; }; self.reset = function () { knob.x = 0; knob.y = 0; self.dirX = 0; self.dirY = 0; self.active = false; }; return self; }); var Magnet = Container.expand(function () { var self = Container.call(this); self.active = true; var magnetGraphics = self.attachAsset('magnet', { anchorX: 0.5, anchorY: 0.5, width: 60, height: 60, tint: 0x0099ff }); self.update = function () { if (!player || !self.active) { return; } var dx = player.x - self.x; var dy = player.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.active = false; // Magnetize all exp orbs on screen for (var i = 0; i < expOrbs.length; i++) { var orb = expOrbs[i]; var orbDx = Math.abs(orb.x - player.x); var orbDy = Math.abs(orb.y - player.y); if (orbDx < 1024 && orbDy < 1366) { orb.magnetSpeed = 20; } } self.destroy(); return true; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); self.level = 1; self.exp = 0; self.expToNext = 10; self.hp = 100; self.maxHp = 100; self.damage = 10; self.fireRate = 30; self.bulletSpeed = 15; self.moveSpeed = 5; self.pickupRange = 100; self.lastFire = 0; /* ===== WEAPON INVENTORY ===== */ self.weapons = {}; // key → instance addWeapon('sword'); // başlangıç function addWeapon(key) { if (self.weapons[key]) return; var m = WEAPONS[key]; self.weapons[key] = { cd: m.cd, cdCnt: 0, dmgMul: 1, rngMul: 1, sizeMul: 1, amount: 1, upgrade: 0, enchTaken: [] }; } var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.takeDamage = function (amount) { self.hp -= amount; LK.effects.flashObject(self, 0xff0000, 300); if (self.hp <= 0) { LK.showGameOver(); } }; self.gainExp = function (amount) { self.exp += amount; if (self.exp >= self.expToNext) { self.levelUp(); } }; self.levelUp = function () { self.level++; self.exp = 0; self.expToNext = self.level * 15; self.maxHp += 10; self.hp = self.maxHp; LK.getSound('levelup').play(); showSkillSelection(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x111111 }); /**** * Game Code ****/ /* ==== UNIVERSAL HELPERS ==== */ function rand(min, max) { return min + Math.random() * (max - min); } function distSq(a, b) { var dx = a.x - b.x, dy = a.y - b.y; return dx * dx + dy * dy; } function unitDir(from, to) { var dx = to.x - from.x, dy = to.y - from.y, d = Math.sqrt(dx * dx + dy * dy); return { dx: dx / d, dy: dy / d, len: d }; } /* ==== WEAPON META TABLE ==== */ var WEAPONS = { sword: { cd: 120, dmg: 10, range: 90, type: 'melee', ench: ["Sword Damage+", "Sword Attack Speed+", "Sword Range+", "Sword Size+"], up: ["Sword +1", "Sword +2", "Sword +3"] }, boomerang: { cd: 180, dmg: 10, range: 900, type: 'boomerang', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Boomerang +1", "Boomerang +2", "Boomerang +3"] }, ball: { cd: 180, dmg: 12, range: 900, type: 'ball', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Ball +1", "Ball +2", "Ball +3"] }, rocket: { cd: 240, dmg: 20, range: 650, type: 'rocket', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Rocket +1", "Rocket +2", "Rocket +3"] }, brick: { cd: 180, dmg: 15, range: 800, type: 'brick', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Back 75°", "Front 45°", "Back 45°"] }, lightning: { cd: 180, dmg: 25, range: 9999, type: 'lightning', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Lightning +1", "Lightning +2", "Lightning +3"] }, aura: { cd: 60, dmg: 5, range: 150, type: 'aura', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Slow 25%", "Slow 50%", "Slow 75%"] }, molotov: { cd: 180, dmg: 12, range: 850, type: 'molotov', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Molotov +1", "Molotov +2", "Molotov +3"] }, shuriken: { cd: 180, dmg: 8, range: 250, type: 'shuriken', ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"], up: ["Shuriken +1", "Shuriken +2", "Shuriken +3"] } }; var player; var enemies = []; var bullets = []; var expOrbs = []; var joystick; var gameTime = 0; var waveNumber = 1; var bossSpawned = false; var selectedSkills = []; var camera = { x: 0, y: 0 }; var gameContainer; var skillSelectionActive = false; var pickups = []; var lastPickupSpawn = 0; // Initialize game world gameContainer = game.addChild(new Container()); // Create player player = gameContainer.addChild(new Player()); player.x = 1024; player.y = 1366; // Create joystick joystick = new Joystick(); joystick.x = 0; joystick.y = -200; LK.gui.bottom.addChild(joystick); // UI Elements var timerText = new Text2('15:00', { size: 80, fill: 0xFFFFFF }); timerText.anchor.set(0.5, 0); LK.gui.top.addChild(timerText); var levelText = new Text2('Level 1', { size: 60, fill: 0xFFFF00 }); levelText.anchor.set(0, 0); levelText.y = 100; LK.gui.top.addChild(levelText); var hpText = new Text2('HP: 100/100', { size: 60, fill: 0xFF0000 }); hpText.anchor.set(1, 0); hpText.y = 100; LK.gui.top.addChild(hpText); // Spawn functions function spawnEnemy(type, x, y) { var enemy; switch (type) { case 'fast': enemy = new FastZombie(); break; case 'tank': enemy = new TankZombie(); break; case 'boss': enemy = new Boss(); break; default: enemy = new Enemy(); } enemy.x = x; enemy.y = y; enemies.push(enemy); gameContainer.addChild(enemy); } function spawnWave() { var spawnCount = 5 + waveNumber * 2; var spawnRadius = 1500; for (var i = 0; i < spawnCount; i++) { // Check if we've reached the enemy limit if (enemies.length >= 30) { break; } var angle = Math.random() * Math.PI * 2; var x = player.x + Math.cos(angle) * spawnRadius; var y = player.y + Math.sin(angle) * spawnRadius; var type = 'normal'; if (waveNumber > 5 && Math.random() < 0.3) { type = 'fast'; } if (waveNumber > 10 && Math.random() < 0.2) { type = 'tank'; } spawnEnemy(type, x, y); } } function dropExpOrb(x, y, value) { var orb = new ExpOrb(); orb.x = x; orb.y = y; orb.value = value; expOrbs.push(orb); gameContainer.addChild(orb); } function fireBullet() { if (enemies.length === 0) { return; } // Find nearest enemy var nearestEnemy = null; var nearestDist = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - player.x; var dy = enemy.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < nearestDist) { nearestDist = dist; nearestEnemy = enemy; } } if (nearestEnemy) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y; bullet.damage = player.damage; bullet.speed = player.bulletSpeed; var dx = nearestEnemy.x - player.x; var dy = nearestEnemy.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); bullet.dirX = dx / dist; bullet.dirY = dy / dist; bullets.push(bullet); gameContainer.addChild(bullet); LK.getSound('shoot').play(); } } /* =============================================================== */ /* NINE-WEAPON FIRE / PROJECTILES */ /* =============================================================== */ function nearestEnemy() { var best = null, bestD = 1e9; for (var i = 0; i < enemies.length; i++) { var d = distSq(player, enemies[i]); if (d < bestD) { best = enemies[i]; bestD = d; } } return best; } function damageEnemy(e, dmg) { if (e.takeDamage(dmg)) { var idx = enemies.indexOf(e); enemies.splice(idx, 1); e.destroy(); LK.getSound('hit').play(); } } /* ---- sword (melee slash) ---- */ function swingSword(inst) { var target = nearestEnemy(); if (!target) return; var dir = unitDir(player, target); var arc = gameContainer.addChild(new Container()); arc.x = player.x; arc.y = player.y; arc.attachAsset('swordHit', { anchorX: 0, anchorY: 0.5, rotation: Math.atan2(dir.dy, dir.dx), scaleX: inst.sizeMul, scaleY: inst.sizeMul }); arc.life = 10; arc.dmg = 10 * inst.dmgMul; arc.update = function () { if (--arc.life <= 0) { arc.destroy(); return; } for (var i = enemies.length - 1; i >= 0; i--) { if (distSq(arc, enemies[i]) < Math.pow(WEAPONS.sword.range * inst.rngMul, 2)) damageEnemy(enemies[i], arc.dmg); } }; } /* ---- boomerang ---- */ function fireBoomerang(inst) { var target = nearestEnemy(); if (!target) return; var dir = unitDir(player, target); for (var n = 0; n < inst.amount; n++) { var p = gameContainer.addChild(new Container()); p.attachAsset('boomerang', { anchorX: 0.5, anchorY: 0.5 }); p.x = player.x; p.y = player.y; p.dirX = dir.dx; p.dirY = dir.dy; p.speed = 12; p.dmg = 10 * inst.dmgMul; p.life = 300; p.update = function () { this.x += this.dirX * this.speed; this.y += this.dirY * this.speed; if (--this.life === 150) { /* dönüş */ var u = unitDir(this, player); this.dirX = u.dx; this.dirY = u.dy; } for (var i = enemies.length - 1; i >= 0; i--) if (this.intersects(enemies[i])) damageEnemy(enemies[i], this.dmg); if (this.life <= 0) this.destroy(); }; bullets.push(p); } } /* ---- top (rebound ball) ---- */ function fireBall(inst) { var target = nearestEnemy(); if (!target) return; var dir = unitDir(player, target); for (var n = 0; n < inst.amount; n++) { var p = new Bullet(); /* var olan Bullet sınıfını kullan */ p.x = player.x; p.y = player.y; p.dirX = dir.dx; p.dirY = dir.dy; p.damage = 12 * inst.dmgMul; p.speed = 14; bullets.push(p); gameContainer.addChild(p); } } /* ---- rocket ---- */ function fireRocket(inst) { var target = nearestEnemy(); if (!target) return; var dir = unitDir(player, target); for (var n = 0; n < inst.amount; n++) { var p = gameContainer.addChild(new Container()); p.attachAsset('rocket', { anchorX: 0.5, anchorY: 0.5 }); p.x = player.x; p.y = player.y; p.dirX = dir.dx; p.dirY = dir.dy; p.speed = 10; p.dmg = 20 * inst.dmgMul; p.update = function () { this.x += this.dirX * this.speed; this.y += this.dirY * this.speed; for (var i = enemies.length - 1; i >= 0; i--) { if (this.intersects(enemies[i])) { LK.getSound('rocketBoom').play(); /* küçük AoE */ for (var k = enemies.length - 1; k >= 0; k--) if (distSq(this, enemies[k]) < 16000) damageEnemy(enemies[k], this.dmg); this.destroy(); return; } } }; bullets.push(p); } } /* ---- brick ---- */ function throwBrick(inst, angDeg) { var rad = angDeg * Math.PI / 180; var p = gameContainer.addChild(new Container()); p.attachAsset('brick', { anchorX: 0.5, anchorY: 0.5 }); p.x = player.x; p.y = player.y; p.vx = Math.cos(rad) * 14; p.vy = Math.sin(rad) * 14; p.g = 0.3; p.dmg = 15 * inst.dmgMul; p.update = function () { this.vy += this.g; this.x += this.vx; this.y += this.vy; for (var i = enemies.length - 1; i >= 0; i--) if (this.intersects(enemies[i])) damageEnemy(enemies[i], this.dmg); if (Math.abs(this.x - player.x) > 1200 || Math.abs(this.y - player.y) > 1600) this.destroy(); }; } /* ---- lightning ---- */ function castLightning(inst) { var victim = enemies[Math.random() * enemies.length | 0]; if (!victim) return; var l = gameContainer.addChild(new Container()); l.attachAsset('lightning', { anchorX: 0.5, anchorY: 1 }); l.x = victim.x; l.y = victim.y; l.life = 15; l.update = function () { if (--this.life === 14) damageEnemy(victim, 25 * inst.dmgMul); if (this.life <= 0) this.destroy(); }; } /* ---- aura ---- */ var auraField = null; function ensureAura(inst) { if (!auraField) { auraField = gameContainer.addChild(new Container()); auraField.attachAsset('auraField', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); } auraField.x = player.x; auraField.y = player.y; var r = WEAPONS.aura.range * inst.rngMul; for (var i = enemies.length - 1; i >= 0; i--) { if (distSq(auraField, enemies[i]) < r * r) damageEnemy(enemies[i], inst.dmgMul * 5); } } /* ---- molotov ---- */ function throwMolotov(inst) { var a = Math.random() * Math.PI * 2, d = rand(300, 600), tx = player.x + Math.cos(a) * d, ty = player.y + Math.sin(a) * d; var p = gameContainer.addChild(new Container()); p.attachAsset('molotov', { anchorX: 0.5, anchorY: 0.5 }); p.x = player.x; p.y = player.y; var u = unitDir(p, { x: tx, y: ty }); p.dirX = u.dx; p.dirY = u.dy; p.speed = 16; p.life = 60; p.update = function () { this.x += this.dirX * this.speed; this.y += this.dirY * this.speed; if (--this.life <= 0) { spawnFlame(tx, ty, inst); this.destroy(); } }; bullets.push(p); } function spawnFlame(x, y, inst) { var f = gameContainer.addChild(new Container()); f.attachAsset('molotovFlame', { anchorX: 0.5, anchorY: 0.5, alpha: 0.4 }); f.x = x; f.y = y; f.life = 60; f.dmg = inst.dmgMul * 12; f.update = function () { for (var i = enemies.length - 1; i >= 0; i--) if (distSq(f, enemies[i]) < 4900) damageEnemy(enemies[i], this.dmg); if (--this.life <= 0) this.destroy(); }; } /* ---- shuriken ring ---- */ var shurikenObjs = []; function maintainShurikens(inst) { if (shurikenObjs.length !== inst.amount) { shurikenObjs.forEach(function (s) { return s.destroy(); }); shurikenObjs = []; var n = inst.amount, r = WEAPONS.shuriken.range * inst.rngMul; for (var i = 0; i < n; i++) { var s = gameContainer.addChild(new Container()); s.attachAsset('shuriken', { anchorX: 0.5, anchorY: 0.5 }); s.angle = i / n * Math.PI * 2; s.update = function () { this.angle += 0.15; this.x = player.x + Math.cos(this.angle) * r; this.y = player.y + Math.sin(this.angle) * r; for (var k = enemies.length - 1; k >= 0; k--) if (this.intersects(enemies[k])) damageEnemy(enemies[k], 8 * inst.dmgMul); }; shurikenObjs.push(s); } } } /* ---- ana fireWeapon anahtarı ---- */ function fireWeapon(key, inst, meta) { switch (meta.type) { case 'melee': swingSword(inst); break; case 'boomerang': fireBoomerang(inst); break; case 'ball': fireBall(inst); break; case 'rocket': fireRocket(inst); break; case 'brick': throwBrick(inst, 75); if (inst.upgrade > 0) throwBrick(inst, -75); if (inst.upgrade > 1) throwBrick(inst, 45); if (inst.upgrade > 2) throwBrick(inst, -45); break; case 'lightning': for (var n = 0; n < inst.amount; n++) castLightning(inst); break; case 'aura': ensureAura(inst); break; case 'molotov': for (var n = 0; n < inst.amount; n++) throwMolotov(inst); break; case 'shuriken': maintainShurikens(inst); break; } } function showSkillSelection() { skillSelectionActive = true; var ov = game.addChild(new Container()); ov.x = 1024; ov.y = 1366; var choices = []; if (player.level % 5 === 0) { /* ---- Silah Kartları ---- */ var pool = Object.keys(WEAPONS); while (choices.length < 3) choices.push(pool.splice(Math.random() * pool.length | 0, 1)[0]); } else { /* ---- Efsun Kartları ---- */ var cur = Object.keys(player.weapons)[0], inst = player.weapons[cur], available = WEAPONS[cur].ench.filter(function (e) { return inst.enchTaken.indexOf(e) === -1; }); if (!available.length) { /* her şey alındıysa 30 % heal */ player.hp = Math.min(player.maxHp, player.hp + player.maxHp * 0.3); skillSelectionActive = false; ov.destroy(); return; } while (choices.length < 3) choices.push({ w: cur, e: available.splice(Math.random() * available.length | 0, 1)[0] }); } choices.forEach(function (c, idx) { var card = ov.addChild(new Container()); card.attachAsset('skillCard', { anchorX: 0.5, anchorY: 0.5 }); card.x = (idx - 1) * 450; card.y = 0; var label, fn; if (typeof c === 'string') { /* Silah */ var own = !!player.weapons[c]; if (!own) { label = "Unlock " + c; fn = function fn() { return player.weapons[c] = player.weapons[c] || addWeapon(c); }; } else if (player.weapons[c].upgrade < 3) { label = WEAPONS[c].up[player.weapons[c].upgrade]; fn = function fn() { player.weapons[c].upgrade++; player.weapons[c].amount++; }; } else { label = "Heal 30%"; fn = function fn() { return player.hp = Math.min(player.maxHp, player.hp + player.maxHp * 0.3); }; } } else { /* Efsun */ label = c.e; fn = function fn() { var inst = player.weapons[c.w]; inst.enchTaken.push(c.e); if (c.e === "+10% Damage") inst.dmgMul *= 1.1; if (c.e === "+10% Atk Spd") inst.cd *= 0.9; if (c.e === "+10% Range") inst.rngMul *= 1.1; if (c.e === "+10% Size") inst.sizeMul *= 1.1; }; } var txt = new Text2(label, { size: 40, fill: 0xffffff }); txt.anchor.set(0.5); card.addChild(txt); card.down = function () { fn(); ov.destroy(); skillSelectionActive = false; levelText.setText('Level ' + player.level); }; }); } // Input handling game.down = function (x, y, obj) { if (skillSelectionActive) { return; } var localPos = game.toLocal({ x: x, y: y }); if (localPos.y > 2000) { joystick.active = true; joystick.setKnobPosition(0, 0); } }; game.move = function (x, y, obj) { if (!joystick.active || skillSelectionActive) { return; } var localPos = LK.gui.bottom.toLocal({ x: x, y: y }); var dx = localPos.x - joystick.x; var dy = localPos.y - joystick.y; joystick.setKnobPosition(dx, dy); }; game.up = function (x, y, obj) { joystick.reset(); }; // Game update game.update = function () { if (skillSelectionActive) { return; } gameTime++; // Update timer var timeLeft = 900 - Math.floor(gameTime / 60); if (timeLeft <= 0) { LK.showYouWin(); return; } var minutes = Math.floor(timeLeft / 60); var seconds = timeLeft % 60; timerText.setText(minutes + ':' + (seconds < 10 ? '0' : '') + seconds); // Update UI hpText.setText('HP: ' + player.hp + '/' + player.maxHp); // Player movement if (joystick.active) { player.x += joystick.dirX * player.moveSpeed; player.y += joystick.dirY * player.moveSpeed; } // Camera follow player camera.x = player.x - 1024; camera.y = player.y - 1366; gameContainer.x = -camera.x; gameContainer.y = -camera.y; // Spawn waves if (gameTime % 300 === 0) { waveNumber++; spawnWave(); } // Spawn boss every 3 minutes if (gameTime % (180 * 60) === 0 && !bossSpawned && enemies.length < 30) { spawnEnemy('boss', player.x + 400, player.y); bossSpawned = true; } // Auto fire if (gameTime - player.lastFire > player.fireRate) { fireBullet(); player.lastFire = gameTime; } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Check if off screen var dx = Math.abs(bullet.x - player.x); var dy = Math.abs(bullet.y - player.y); if (dx > 1200 || dy > 1600) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check collisions with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.hitEnemies.indexOf(enemy) === -1 && bullet.intersects(enemy)) { bullet.hitEnemies.push(enemy); if (enemy.takeDamage(bullet.damage)) { enemy.destroy(); enemies.splice(j, 1); LK.getSound('hit').play(); } if (bullet.hitEnemies.length >= bullet.piercing) { bullet.destroy(); bullets.splice(i, 1); break; } } } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.intersects(player)) { player.takeDamage(enemy.damage); enemy.destroy(); enemies.splice(i, 1); } } // Update exp orbs for (var i = expOrbs.length - 1; i >= 0; i--) { var orb = expOrbs[i]; var dx = orb.x - player.x; var dy = orb.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.pickupRange) { orb.magnetSpeed = 10; } if (orb.intersects(player)) { player.gainExp(orb.value); orb.destroy(); expOrbs.splice(i, 1); LK.getSound('pickup').play(); } } // Spawn pickups randomly if (gameTime - lastPickupSpawn > 1800 && Math.random() < 0.1) { lastPickupSpawn = gameTime; var pickup; var angle = Math.random() * Math.PI * 2; var distance = 300 + Math.random() * 500; var pickupX = player.x + Math.cos(angle) * distance; var pickupY = player.y + Math.sin(angle) * distance; if (Math.random() < 0.5) { pickup = new Bomb(); } else { pickup = new Magnet(); } pickup.x = pickupX; pickup.y = pickupY; pickups.push(pickup); gameContainer.addChild(pickup); } // Update pickups for (var i = pickups.length - 1; i >= 0; i--) { var pickup = pickups[i]; if (!pickup.active) { pickups.splice(i, 1); } } }; // Initial spawn spawnWave();
===================================================================
--- original.js
+++ change.js
@@ -6,854 +6,1063 @@
/****
* Classes
****/
-/****-----------------------------------------------------------------
-* 4. ENEMY TÜREVLERİ
-*------------------------------------------------------------------*/
+var Bomb = Container.expand(function () {
+ var self = Container.call(this);
+ self.active = true;
+ var bombGraphics = self.attachAsset('bomb', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 60,
+ height: 60,
+ tint: 0xff0000
+ });
+ self.update = function () {
+ if (!player || !self.active) {
+ return;
+ }
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 80) {
+ self.active = false;
+ // Kill all non-boss enemies on screen
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ if (enemy.type !== 'boss') {
+ var screenDx = Math.abs(enemy.x - player.x);
+ var screenDy = Math.abs(enemy.y - player.y);
+ if (screenDx < 1024 && screenDy < 1366) {
+ dropExpOrb(enemy.x, enemy.y, enemy.expValue);
+ enemy.destroy();
+ enemies.splice(i, 1);
+ }
+ }
+ }
+ LK.effects.flashScreen(0xff0000, 300);
+ self.destroy();
+ return true;
+ }
+ };
+ return self;
+});
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ self.damage = 10;
+ self.speed = 15;
+ self.dirX = 0;
+ self.dirY = 0;
+ self.piercing = 1;
+ self.hitEnemies = [];
+ var bulletGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.update = function () {
+ self.x += self.dirX * self.speed;
+ self.y += self.dirY * self.speed;
+ };
+ return self;
+});
var Enemy = Container.expand(function () {
var self = Container.call(this);
- var e = Container.call(this);
- e.hp = 20;
- e.damage = 10;
- e.speed = 2;
- e.exp = 5;
- e.type = 'normal';
- e.attachAsset('zombie', {
+ self.hp = 20;
+ self.maxHp = 20;
+ self.damage = 10;
+ self.speed = 2;
+ self.expValue = 5;
+ self.type = 'normal';
+ var enemyGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
- e.take = function (d) {
- e.hp -= d;
- LK.effects.flashObject(e, 0xffffff, 60);
- return e.hp <= 0;
+ self.takeDamage = function (amount) {
+ self.hp -= amount;
+ LK.effects.flashObject(self, 0xffffff, 100);
+ if (self.hp <= 0) {
+ dropExpOrb(self.x, self.y, self.expValue);
+ return true;
+ }
+ return false;
};
- e.update = function () {
- if (!player || skillSel) return;
- var v = dirUnit(e, player);
- e.x += v.dx * e.speed;
- e.y += v.dy * e.speed;
+ self.update = function () {
+ if (!player || skillSelectionActive) {
+ return;
+ }
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
+ }
};
- return e;
+ return self;
});
var TankZombie = Enemy.expand(function () {
var self = Enemy.call(this);
- var z = Enemy.call(this);
- z.hp = 60;
- z.damage = 20;
- z.speed = 1;
- z.attachAsset('tankZombie', {
+ self.hp = 60;
+ self.maxHp = 60;
+ self.damage = 20;
+ self.speed = 1;
+ self.expValue = 15;
+ self.type = 'tank';
+ var graphics = self.attachAsset('tankZombie', {
anchorX: 0.5,
anchorY: 0.5
});
- return z;
+ return self;
});
var FastZombie = Enemy.expand(function () {
var self = Enemy.call(this);
- var z = Enemy.call(this);
- z.hp = 15;
- z.damage = 8;
- z.speed = 4;
- z.attachAsset('fastZombie', {
+ self.hp = 15;
+ self.maxHp = 15;
+ self.damage = 8;
+ self.speed = 4;
+ self.expValue = 8;
+ self.type = 'fast';
+ var graphics = self.attachAsset('fastZombie', {
anchorX: 0.5,
anchorY: 0.5
});
- return z;
+ return self;
});
var Boss = Enemy.expand(function () {
var self = Enemy.call(this);
- var z = Enemy.call(this);
- z.hp = 500;
- z.damage = 30;
- z.speed = 1.5;
- z.type = 'boss';
- z.attachAsset('boss', {
+ self.hp = 500;
+ self.maxHp = 500;
+ self.damage = 30;
+ self.speed = 1.5;
+ self.expValue = 100;
+ self.type = 'boss';
+ var graphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
- return z;
+ return self;
});
-/****-----------------------------------------------------------------
-* 5. EXP ORB
-*------------------------------------------------------------------*/
var ExpOrb = Container.expand(function () {
var self = Container.call(this);
- var o = Container.call(this);
- o.val = 5;
- o.mag = 0;
- o.attachAsset('expOrb', {
+ self.value = 5;
+ self.magnetSpeed = 0;
+ var orbGraphics = self.attachAsset('expOrb', {
anchorX: 0.5,
anchorY: 0.5
});
- o.update = function () {
- if (o.mag) {
- var v = dirUnit(o, player);
- o.x += v.dx * o.mag;
- o.y += v.dy * o.mag;
+ self.update = function () {
+ if (!player || self.magnetSpeed === 0) {
+ return;
}
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ self.x += dx / dist * self.magnetSpeed;
+ self.y += dy / dist * self.magnetSpeed;
+ }
};
- return o;
+ return self;
});
-/****-----------------------------------------------------------------
-* 6. JOYSTICK
-*------------------------------------------------------------------*/
var Joystick = Container.expand(function () {
var self = Container.call(this);
- var j = Container.call(this);
- j.act = false;
- j.dx = 0;
- j.dy = 0;
- var base = j.attachAsset('joystickBase', {
+ self.active = false;
+ self.dirX = 0;
+ self.dirY = 0;
+ var base = self.attachAsset('joystickBase', {
anchorX: 0.5,
anchorY: 0.5
});
- var knob = j.attachAsset('joystickKnob', {
+ base.alpha = 0.5;
+ var knob = self.attachAsset('joystickKnob', {
anchorX: 0.5,
anchorY: 0.5
});
- j.set = function (x, y) {
- var d = Math.sqrt(x * x + y * y),
- m = 60;
- if (d > m) {
- x = x / d * m;
- y = y / d * m;
+ knob.alpha = 0.7;
+ self.setKnobPosition = function (x, y) {
+ var dx = x - base.x;
+ var dy = y - base.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var maxDist = 60;
+ if (dist > maxDist) {
+ dx = dx / dist * maxDist;
+ dy = dy / dist * maxDist;
}
- knob.x = x;
- knob.y = y;
- j.dx = x / m;
- j.dy = y / m;
+ knob.x = dx;
+ knob.y = dy;
+ self.dirX = dx / maxDist;
+ self.dirY = dy / maxDist;
};
- j.reset = function () {
- knob.x = knob.y = j.dx = j.dy = 0;
- j.act = false;
+ self.reset = function () {
+ knob.x = 0;
+ knob.y = 0;
+ self.dirX = 0;
+ self.dirY = 0;
+ self.active = false;
};
- return j;
+ return self;
});
-/****-----------------------------------------------------------------
-* 7. PLAYER (+ Silah Envanteri)
-*------------------------------------------------------------------*/
-var Player = Container.expand(function () {
+var Magnet = Container.expand(function () {
var self = Container.call(this);
- var p = Container.call(this);
- p.level = 1;
- p.exp = 0;
- p.expNeed = 10;
- p.hp = 100;
- p.hpMax = 100;
- p.spd = 5;
- p.pick = 120;
- p.attachAsset('player', {
+ self.active = true;
+ var magnetGraphics = self.attachAsset('magnet', {
anchorX: 0.5,
- anchorY: 0.5
+ anchorY: 0.5,
+ width: 60,
+ height: 60,
+ tint: 0x0099ff
});
- /*---- Silah Envanteri ----*/
- p.wep = {};
- addWeapon('sword');
- function addWeapon(k) {
- if (p.wep[k]) return;
- var m = WEAPONS[k];
- p.wep[k] = {
+ self.update = function () {
+ if (!player || !self.active) {
+ return;
+ }
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 80) {
+ self.active = false;
+ // Magnetize all exp orbs on screen
+ for (var i = 0; i < expOrbs.length; i++) {
+ var orb = expOrbs[i];
+ var orbDx = Math.abs(orb.x - player.x);
+ var orbDy = Math.abs(orb.y - player.y);
+ if (orbDx < 1024 && orbDy < 1366) {
+ orb.magnetSpeed = 20;
+ }
+ }
+ self.destroy();
+ return true;
+ }
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ self.level = 1;
+ self.exp = 0;
+ self.expToNext = 10;
+ self.hp = 100;
+ self.maxHp = 100;
+ self.damage = 10;
+ self.fireRate = 30;
+ self.bulletSpeed = 15;
+ self.moveSpeed = 5;
+ self.pickupRange = 100;
+ self.lastFire = 0;
+ /* ===== WEAPON INVENTORY ===== */
+ self.weapons = {}; // key → instance
+ addWeapon('sword'); // başlangıç
+ function addWeapon(key) {
+ if (self.weapons[key]) return;
+ var m = WEAPONS[key];
+ self.weapons[key] = {
cd: m.cd,
cdCnt: 0,
- dmg: 1,
- rng: 1,
- size: 1,
- amt: 1,
- up: 0,
- ench: []
+ dmgMul: 1,
+ rngMul: 1,
+ sizeMul: 1,
+ amount: 1,
+ upgrade: 0,
+ enchTaken: []
};
}
- /*---- EXP / Seviye ----*/
- p.gain = function (v) {
- p.exp += v;
- if (p.exp >= p.expNeed) lvlUp();
- };
- function lvlUp() {
- p.level++;
- p.exp = 0;
- p.expNeed = p.level * 15;
- p.hpMax += 10;
- p.hp = Math.min(p.hpMax, p.hp + p.hpMax * 0.3); // +10 max + %30 heal
- LK.getSound('levelup').play();
- openChoice();
- }
- /*---- Update ----*/
- p.update = function () {
- for (var k in p.wep) {
- var i = p.wep[k],
- m = WEAPONS[k];
- if (--i.cdCnt <= 0) {
- fireWeapon(k, i, m);
- i.cdCnt = i.cd;
- }
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.takeDamage = function (amount) {
+ self.hp -= amount;
+ LK.effects.flashObject(self, 0xff0000, 300);
+ if (self.hp <= 0) {
+ LK.showGameOver();
}
};
- return p;
- /*=========== Seçim Ekranı (Efsun / Silah) ============*/
- function openChoice() {
- skillSel = true;
- var ov = game.addChild(new Container());
- ov.x = 1024;
- ov.y = 1366;
- var opts = [];
- if (p.level % 5 === 0) {
- var pool = Object.keys(WEAPONS);
- while (opts.length < 3) opts.push(pool.splice(Math.random() * pool.length | 0, 1)[0]);
- } else {
- var cur = Object.keys(p.wep)[0],
- inst = p.wep[cur],
- m = WEAPONS[cur];
- var pool = m.ench.filter(function (idx) {
- return inst.ench.indexOf(idx) === -1;
- });
- if (pool.length === 0) {
- skillSel = false;
- ov.destroy();
- return;
- }
- while (opts.length < 3) opts.push({
- w: cur,
- e: pool.splice(Math.random() * pool.length | 0, 1)[0]
- });
+ self.gainExp = function (amount) {
+ self.exp += amount;
+ if (self.exp >= self.expToNext) {
+ self.levelUp();
}
- opts.forEach(function (o, i) {
- var card = ov.addChild(new Container());
- card.attachAsset('skillCard', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- card.x = (i - 1) * 450;
- card.y = 0;
- var txt;
- card["do"] = function () {};
- if (typeof o === 'string') {
- // Silah kartı
- var own = !!p.wep[o];
- if (!own) {
- txt = "Unlock " + o;
- card["do"] = function () {
- return addWeapon(o);
- };
- } else if (p.wep[o].up < 3) {
- txt = WEAPONS[o].up[p.wep[o].up];
- card["do"] = function () {
- p.wep[o].up++;
- if (WEAPONS[o].type !== 'sword') p.wep[o].amt++;
- };
- } else {
- txt = "Heal 30%";
- card["do"] = function () {
- p.hp = Math.min(p.hpMax, p.hp + p.hpMax * 0.3);
- };
- }
- } else {
- // Efsun kartı
- txt = ENCH_LABEL[o.e];
- card["do"] = function () {
- var inst = p.wep[o.w];
- inst.ench.push(o.e);
- if (o.e === 0) inst.dmg *= 1.1;
- if (o.e === 1) inst.cd *= 0.9;
- if (o.e === 2) inst.rng *= 1.1;
- if (o.e === 3) inst.size *= 1.1;
- };
- }
- var t = new Text2(txt, {
- size: 38,
- fill: 0xffffff
- });
- t.anchor.set(0.5);
- card.addChild(t);
- card.overlay = ov;
- card.down = function () {
- this["do"]();
- this.overlay.destroy();
- skillSel = false;
- lTxt.setText('Level ' + p.level);
- };
- });
- }
- /*=======================================================*/
+ };
+ self.levelUp = function () {
+ self.level++;
+ self.exp = 0;
+ self.expToNext = self.level * 15;
+ self.maxHp += 10;
+ self.hp = self.maxHp;
+ LK.getSound('levelup').play();
+ showSkillSelection();
+ };
+ return self;
});
/****
* Initialize Game
****/
-/****-----------------------------------------------------------------
-* 8. SİLAH ATEŞLEME YARDIMCILARI
-*------------------------------------------------------------------*/
-/****-----------------------------------------------------------------
-* 9. GAME BOOTSTRAP & GLOBALS
-*------------------------------------------------------------------*/
var game = new LK.Game({
backgroundColor: 0x111111
});
/****
* Game Code
****/
-/****-----------------------------------------------------------------
-* 2. KÜRESEL YARDIMCILAR + SİLAH METADATASI
-*------------------------------------------------------------------*/
-/****-----------------------------------------------------------------
-* 1. PLUG-INS
-*------------------------------------------------------------------*/
-// roket patlaması
-/* sesler */
-/****-----------------------------------------------------------------
-* 0. ASSETS (ESKİ + YENİ) *
-*------------------------------------------------------------------*/
-/********************************************************************
-* SURVIVOR-LIKE – FULL SINGLE-FILE BUILD (Nine weapons, enchants) *
-* Yapıştır > Run *
-********************************************************************/
+/* ==== UNIVERSAL HELPERS ==== */
function rand(min, max) {
return min + Math.random() * (max - min);
}
-function dist2(a, b) {
+function distSq(a, b) {
var dx = a.x - b.x,
dy = a.y - b.y;
return dx * dx + dy * dy;
}
-function dirUnit(src, dst) {
- var dx = dst.x - src.x,
- dy = dst.y - src.y,
+function unitDir(from, to) {
+ var dx = to.x - from.x,
+ dy = to.y - from.y,
d = Math.sqrt(dx * dx + dy * dy);
return {
dx: dx / d,
- dy: dy / d
+ dy: dy / d,
+ len: d
};
}
-/* Silah veritabanı – cooldown (frame), base dmg, range(px), tür */
+/* ==== WEAPON META TABLE ==== */
var WEAPONS = {
sword: {
cd: 120,
dmg: 10,
range: 90,
type: 'melee',
- ench: [0, 1, 2, 3],
- up: ["Back Swing", "Up Swing", "Down Swing"]
+ ench: ["Sword Damage+", "Sword Attack Speed+", "Sword Range+", "Sword Size+"],
+ up: ["Sword +1", "Sword +2", "Sword +3"]
},
boomerang: {
cd: 180,
dmg: 10,
range: 900,
type: 'boomerang',
- ench: [0, 1, 2, 3],
- up: ["Boomerang +1", "Boomerang +1", "Boomerang +1"]
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
+ up: ["Boomerang +1", "Boomerang +2", "Boomerang +3"]
},
ball: {
cd: 180,
dmg: 12,
range: 900,
type: 'ball',
- ench: [0, 1, 2, 3],
- up: ["Ball +1", "Ball +1", "Ball +1"]
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
+ up: ["Ball +1", "Ball +2", "Ball +3"]
},
rocket: {
- cd: 180,
+ cd: 240,
dmg: 20,
range: 650,
type: 'rocket',
- ench: [0, 1, 2, 3],
- up: ["Rocket +1", "Rocket +1", "Rocket +1"]
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
+ up: ["Rocket +1", "Rocket +2", "Rocket +3"]
},
brick: {
cd: 180,
dmg: 15,
range: 800,
type: 'brick',
- ench: [0, 1, 2, 3],
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
up: ["Back 75°", "Front 45°", "Back 45°"]
},
lightning: {
cd: 180,
dmg: 25,
range: 9999,
type: 'lightning',
- ench: [0, 1, 2, 3],
- up: ["Lightning +1", "Lightning +1", "Lightning +1"]
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
+ up: ["Lightning +1", "Lightning +2", "Lightning +3"]
},
aura: {
cd: 60,
dmg: 5,
range: 150,
type: 'aura',
- ench: [0, 1, 2, 3],
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
up: ["Slow 25%", "Slow 50%", "Slow 75%"]
},
molotov: {
cd: 180,
dmg: 12,
range: 850,
type: 'molotov',
- ench: [0, 1, 2, 3],
- up: ["Molotov +1", "Molotov +1", "Molotov +1"]
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
+ up: ["Molotov +1", "Molotov +2", "Molotov +3"]
},
shuriken: {
cd: 180,
dmg: 8,
range: 250,
type: 'shuriken',
- ench: [0, 1, 2, 3],
- up: ["Shuriken +1", "Shuriken +1", "Shuriken +1"]
+ ench: ["+10% Damage", "+10% Atk Spd", "+10% Range", "+10% Size"],
+ up: ["Shuriken +1", "Shuriken +2", "Shuriken +3"]
}
};
-var ENCH_LABEL = ["+10% Damage", "+10% FireRate", "+10% Range", "+10% Size"];
-/****-----------------------------------------------------------------
-* 3. GENEL PROJEKTİL FABRİKASI
-*------------------------------------------------------------------*/
-function makeProj(shape) {
- return Container.expand(function () {
- var o = Container.call(this);
- o.dirX = 0;
- o.dirY = 0;
- o.speed = 12;
- o.dmg = 10;
- o.life = 300;
- o.attachAsset(shape, {
- anchorX: 0.5,
- anchorY: 0.5
- });
- o.update = function () {
- o.x += o.dirX * o.speed;
- o.y += o.dirY * o.speed;
- if (--o.life <= 0) o.destroy();
- };
- return o;
- });
+var player;
+var enemies = [];
+var bullets = [];
+var expOrbs = [];
+var joystick;
+var gameTime = 0;
+var waveNumber = 1;
+var bossSpawned = false;
+var selectedSkills = [];
+var camera = {
+ x: 0,
+ y: 0
+};
+var gameContainer;
+var skillSelectionActive = false;
+var pickups = [];
+var lastPickupSpawn = 0;
+// Initialize game world
+gameContainer = game.addChild(new Container());
+// Create player
+player = gameContainer.addChild(new Player());
+player.x = 1024;
+player.y = 1366;
+// Create joystick
+joystick = new Joystick();
+joystick.x = 0;
+joystick.y = -200;
+LK.gui.bottom.addChild(joystick);
+// UI Elements
+var timerText = new Text2('15:00', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+timerText.anchor.set(0.5, 0);
+LK.gui.top.addChild(timerText);
+var levelText = new Text2('Level 1', {
+ size: 60,
+ fill: 0xFFFF00
+});
+levelText.anchor.set(0, 0);
+levelText.y = 100;
+LK.gui.top.addChild(levelText);
+var hpText = new Text2('HP: 100/100', {
+ size: 60,
+ fill: 0xFF0000
+});
+hpText.anchor.set(1, 0);
+hpText.y = 100;
+LK.gui.top.addChild(hpText);
+// Spawn functions
+function spawnEnemy(type, x, y) {
+ var enemy;
+ switch (type) {
+ case 'fast':
+ enemy = new FastZombie();
+ break;
+ case 'tank':
+ enemy = new TankZombie();
+ break;
+ case 'boss':
+ enemy = new Boss();
+ break;
+ default:
+ enemy = new Enemy();
+ }
+ enemy.x = x;
+ enemy.y = y;
+ enemies.push(enemy);
+ gameContainer.addChild(enemy);
}
-var BoomProj = makeProj('boomerang');
-var BallProj = makeProj('ball');
-var RocketProj = makeProj('rocket');
-var BrickProj = makeProj('brick');
-var ShuriProj = makeProj('shuriken');
-/****-----------------------------------------------------------------
-* 8. SİLAH ATEŞLEME YARDIMCILARI
-*------------------------------------------------------------------*/
-function nearest() {
- var n = null,
- d = 1e9;
- for (var i = 0; i < enemies.length; i++) {
- var q = dist2(player, enemies[i]);
- if (q < d) {
- d = q;
- n = enemies[i];
+function spawnWave() {
+ var spawnCount = 5 + waveNumber * 2;
+ var spawnRadius = 1500;
+ for (var i = 0; i < spawnCount; i++) {
+ // Check if we've reached the enemy limit
+ if (enemies.length >= 30) {
+ break;
}
+ var angle = Math.random() * Math.PI * 2;
+ var x = player.x + Math.cos(angle) * spawnRadius;
+ var y = player.y + Math.sin(angle) * spawnRadius;
+ var type = 'normal';
+ if (waveNumber > 5 && Math.random() < 0.3) {
+ type = 'fast';
+ }
+ if (waveNumber > 10 && Math.random() < 0.2) {
+ type = 'tank';
+ }
+ spawnEnemy(type, x, y);
}
- return n;
}
-function killEnemy(idx) {
- var e = enemies[idx];
- dropExp(e.x, e.y, e.exp);
- e.destroy();
- enemies.splice(idx, 1);
+function dropExpOrb(x, y, value) {
+ var orb = new ExpOrb();
+ orb.x = x;
+ orb.y = y;
+ orb.value = value;
+ expOrbs.push(orb);
+ gameContainer.addChild(orb);
}
-function dropExp(x, y, v) {
- var o = new ExpOrb();
- o.x = x;
- o.y = y;
- o.val = v;
- expOrbs.push(o);
- gameContainer.addChild(o);
+function fireBullet() {
+ if (enemies.length === 0) {
+ return;
+ }
+ // Find nearest enemy
+ var nearestEnemy = null;
+ var nearestDist = Infinity;
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ var dx = enemy.x - player.x;
+ var dy = enemy.y - player.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < nearestDist) {
+ nearestDist = dist;
+ nearestEnemy = enemy;
+ }
+ }
+ if (nearestEnemy) {
+ var bullet = new Bullet();
+ bullet.x = player.x;
+ bullet.y = player.y;
+ bullet.damage = player.damage;
+ bullet.speed = player.bulletSpeed;
+ var dx = nearestEnemy.x - player.x;
+ var dy = nearestEnemy.y - player.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ bullet.dirX = dx / dist;
+ bullet.dirY = dy / dist;
+ bullets.push(bullet);
+ gameContainer.addChild(bullet);
+ LK.getSound('shoot').play();
+ }
}
-function damage(e, amt) {
- if (e.take(amt)) killEnemy(enemies.indexOf(e));
+/* =============================================================== */
+/* NINE-WEAPON FIRE / PROJECTILES */
+/* =============================================================== */
+function nearestEnemy() {
+ var best = null,
+ bestD = 1e9;
+ for (var i = 0; i < enemies.length; i++) {
+ var d = distSq(player, enemies[i]);
+ if (d < bestD) {
+ best = enemies[i];
+ bestD = d;
+ }
+ }
+ return best;
}
-function fireWeapon(k, inst, meta) {
- if (enemies.length === 0) return;
- switch (meta.type) {
- case 'melee':
- swing(inst);
- break;
- case 'boomerang':
- for (var i = 0; i < inst.amt; i++) throwBoom(inst);
- break;
- case 'ball':
- for (var i = 0; i < inst.amt; i++) throwBall(inst);
- break;
- case 'rocket':
- for (var i = 0; i < inst.amt; i++) fireRock(inst);
- break;
- case 'brick':
- throwBrick(inst, 75);
- if (inst.up > 0) throwBrick(inst, -75);
- if (inst.up > 1) throwBrick(inst, 45);
- if (inst.up > 2) throwBrick(inst, -45);
- break;
- case 'lightning':
- for (var i = 0; i < inst.amt; i++) lightning(inst);
- break;
- case 'aura':
- aura(inst);
- break;
- case 'molotov':
- for (var i = 0; i < inst.amt; i++) molotov(inst);
- break;
- case 'shuriken':
- shurikenRing(inst);
- break;
+function damageEnemy(e, dmg) {
+ if (e.takeDamage(dmg)) {
+ var idx = enemies.indexOf(e);
+ enemies.splice(idx, 1);
+ e.destroy();
+ LK.getSound('hit').play();
}
}
-/*-------------------------------------------------------*/
-/* Tek tek mini-fonksiyonlar */
-/*-------------------------------------------------------*/
-function swing(inst) {
- var arc = new Container();
+/* ---- sword (melee slash) ---- */
+function swingSword(inst) {
+ var target = nearestEnemy();
+ if (!target) return;
+ var dir = unitDir(player, target);
+ var arc = gameContainer.addChild(new Container());
arc.x = player.x;
arc.y = player.y;
arc.attachAsset('swordHit', {
anchorX: 0,
anchorY: 0.5,
- rotation: player.rotation,
- scaleX: inst.size,
- scaleY: inst.size
+ rotation: Math.atan2(dir.dy, dir.dx),
+ scaleX: inst.sizeMul,
+ scaleY: inst.sizeMul
});
arc.life = 10;
- arc.dmg = 10 * inst.dmg;
+ arc.dmg = 10 * inst.dmgMul;
arc.update = function () {
if (--arc.life <= 0) {
arc.destroy();
return;
}
- for (var i = enemies.length - 1; i >= 0; i--) if (dist2(arc, enemies[i]) < Math.pow(WEAPONS.sword.range * inst.rng, 2)) damage(enemies[i], arc.dmg);
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ if (distSq(arc, enemies[i]) < Math.pow(WEAPONS.sword.range * inst.rngMul, 2)) damageEnemy(enemies[i], arc.dmg);
+ }
};
- gameContainer.addChild(arc);
}
-function launchSimple(Cls, inst, setup) {
- var t = nearest();
- if (!t) return;
- var v = dirUnit(player, t);
- for (var i = 0; i < inst.amt; i++) {
- var p = new Cls();
+/* ---- boomerang ---- */
+function fireBoomerang(inst) {
+ var target = nearestEnemy();
+ if (!target) return;
+ var dir = unitDir(player, target);
+ for (var n = 0; n < inst.amount; n++) {
+ var p = gameContainer.addChild(new Container());
+ p.attachAsset('boomerang', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
p.x = player.x;
p.y = player.y;
- setup(p, v, i);
- bullets.push(p);
- gameContainer.addChild(p);
- }
-}
-function throwBoom(inst) {
- launchSimple(BoomProj, inst, function (p, v) {
- p.dirX = v.dx;
- p.dirY = v.dy;
- p.dmg = 10 * inst.dmg;
- p["return"] = false;
+ p.dirX = dir.dx;
+ p.dirY = dir.dy;
+ p.speed = 12;
+ p.dmg = 10 * inst.dmgMul;
+ p.life = 300;
p.update = function () {
- if (!p["return"] && --p.life < 180) p["return"] = true;
- if (p["return"]) {
- var v = dirUnit(p, player);
- p.dirX = v.dx;
- p.dirY = v.dy;
+ this.x += this.dirX * this.speed;
+ this.y += this.dirY * this.speed;
+ if (--this.life === 150) {
+ /* dönüş */
+ var u = unitDir(this, player);
+ this.dirX = u.dx;
+ this.dirY = u.dy;
}
- BoomProj.parent.update.call(p);
- for (var i = enemies.length - 1; i >= 0; i--) if (p.intersects(enemies[i])) damage(enemies[i], p.dmg);
+ for (var i = enemies.length - 1; i >= 0; i--) if (this.intersects(enemies[i])) damageEnemy(enemies[i], this.dmg);
+ if (this.life <= 0) this.destroy();
};
- });
+ bullets.push(p);
+ }
}
-function throwBall(inst) {
- launchSimple(BallProj, inst, function (p, v) {
- p.dirX = v.dx;
- p.dirY = v.dy;
- p.dmg = 12 * inst.dmg;
- });
+/* ---- top (rebound ball) ---- */
+function fireBall(inst) {
+ var target = nearestEnemy();
+ if (!target) return;
+ var dir = unitDir(player, target);
+ for (var n = 0; n < inst.amount; n++) {
+ var p = new Bullet(); /* var olan Bullet sınıfını kullan */
+ p.x = player.x;
+ p.y = player.y;
+ p.dirX = dir.dx;
+ p.dirY = dir.dy;
+ p.damage = 12 * inst.dmgMul;
+ p.speed = 14;
+ bullets.push(p);
+ gameContainer.addChild(p);
+ }
}
-function fireRock(inst) {
- launchSimple(RocketProj, inst, function (p, v) {
- p.dirX = v.dx;
- p.dirY = v.dy;
- p.dmg = 20 * inst.dmg;
+/* ---- rocket ---- */
+function fireRocket(inst) {
+ var target = nearestEnemy();
+ if (!target) return;
+ var dir = unitDir(player, target);
+ for (var n = 0; n < inst.amount; n++) {
+ var p = gameContainer.addChild(new Container());
+ p.attachAsset('rocket', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ p.x = player.x;
+ p.y = player.y;
+ p.dirX = dir.dx;
+ p.dirY = dir.dy;
+ p.speed = 10;
+ p.dmg = 20 * inst.dmgMul;
p.update = function () {
- RocketProj.parent.update.call(p);
- for (var i = enemies.length - 1; i >= 0; i--) if (p.intersects(enemies[i])) {
- LK.getSound('rocketBoom').play();
- for (var k = enemies.length - 1; k >= 0; k--) if (dist2(p, enemies[k]) < 16000) damage(enemies[k], p.dmg);
- p.destroy();
- bullets.splice(bullets.indexOf(p), 1);
- break;
+ this.x += this.dirX * this.speed;
+ this.y += this.dirY * this.speed;
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ if (this.intersects(enemies[i])) {
+ LK.getSound('rocketBoom').play();
+ /* küçük AoE */
+ for (var k = enemies.length - 1; k >= 0; k--) if (distSq(this, enemies[k]) < 16000) damageEnemy(enemies[k], this.dmg);
+ this.destroy();
+ return;
+ }
}
};
- });
+ bullets.push(p);
+ }
}
-function throwBrick(inst, ang) {
- var rad = ang * Math.PI / 180,
- dirX = Math.cos(rad),
- dirY = Math.sin(rad);
- var b = new BrickProj();
- b.x = player.x;
- b.y = player.y;
- b.dirX = dirX;
- b.dirY = dirY;
- b.speed = 14;
- b.gravity = 0.4;
- b.dmg = 15 * inst.dmg;
- b.update = function () {
- b.y += b.gravity;
- // Defensive: Only call parent update if it exists
- if (BrickProj.parent && typeof BrickProj.parent.update === "function") {
- BrickProj.parent.update.call(b);
- }
- for (var i = enemies.length - 1; i >= 0; i--) if (b.intersects(enemies[i])) damage(enemies[i], b.dmg);
- if (Math.abs(b.x - player.x) > 1200 || Math.abs(b.y - player.y) > 1600) {
- b.destroy();
- bullets.splice(bullets.indexOf(b), 1);
- }
+/* ---- brick ---- */
+function throwBrick(inst, angDeg) {
+ var rad = angDeg * Math.PI / 180;
+ var p = gameContainer.addChild(new Container());
+ p.attachAsset('brick', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ p.x = player.x;
+ p.y = player.y;
+ p.vx = Math.cos(rad) * 14;
+ p.vy = Math.sin(rad) * 14;
+ p.g = 0.3;
+ p.dmg = 15 * inst.dmgMul;
+ p.update = function () {
+ this.vy += this.g;
+ this.x += this.vx;
+ this.y += this.vy;
+ for (var i = enemies.length - 1; i >= 0; i--) if (this.intersects(enemies[i])) damageEnemy(enemies[i], this.dmg);
+ if (Math.abs(this.x - player.x) > 1200 || Math.abs(this.y - player.y) > 1600) this.destroy();
};
- bullets.push(b);
- gameContainer.addChild(b);
}
-function lightning(inst) {
- var e = enemies[Math.random() * enemies.length | 0];
- if (!e) return;
- var l = new Container();
+/* ---- lightning ---- */
+function castLightning(inst) {
+ var victim = enemies[Math.random() * enemies.length | 0];
+ if (!victim) return;
+ var l = gameContainer.addChild(new Container());
l.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 1
});
- l.x = e.x;
- l.y = e.y;
- l.life = 20;
+ l.x = victim.x;
+ l.y = victim.y;
+ l.life = 15;
l.update = function () {
- if (--l.life === 19) damage(e, 25 * inst.dmg);
- if (l.life <= 0) l.destroy();
+ if (--this.life === 14) damageEnemy(victim, 25 * inst.dmgMul);
+ if (this.life <= 0) this.destroy();
};
- gameContainer.addChild(l);
}
-var aField = null;
-function aura(inst) {
- if (aField) {
- aField.inst = inst;
- return;
+/* ---- aura ---- */
+var auraField = null;
+function ensureAura(inst) {
+ if (!auraField) {
+ auraField = gameContainer.addChild(new Container());
+ auraField.attachAsset('auraField', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.3
+ });
}
- aField = new Container();
- aField.attachAsset('auraField', {
- anchorX: 0.5,
- anchorY: 0.5,
- alpha: 0.35
- });
- aField.inst = inst;
- aField.update = function () {
- aField.x = player.x;
- aField.y = player.y;
- var r = WEAPONS.aura.range * aField.inst.rng;
- for (var i = enemies.length - 1; i >= 0; i--) if (dist2(aField, enemies[i]) < r * r) damage(enemies[i], aField.inst.dmg);
- };
- gameContainer.addChild(aField);
+ auraField.x = player.x;
+ auraField.y = player.y;
+ var r = WEAPONS.aura.range * inst.rngMul;
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ if (distSq(auraField, enemies[i]) < r * r) damageEnemy(enemies[i], inst.dmgMul * 5);
+ }
}
-function molotov(inst) {
+/* ---- molotov ---- */
+function throwMolotov(inst) {
var a = Math.random() * Math.PI * 2,
d = rand(300, 600),
tx = player.x + Math.cos(a) * d,
ty = player.y + Math.sin(a) * d;
- var m = new BrickProj();
- m.x = player.x;
- m.y = player.y;
- var v = dirUnit(m, {
+ var p = gameContainer.addChild(new Container());
+ p.attachAsset('molotov', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ p.x = player.x;
+ p.y = player.y;
+ var u = unitDir(p, {
x: tx,
y: ty
});
- m.dirX = v.dx;
- m.dirY = v.dy;
- m.speed = 16;
- m.life = 90;
- m.update = function () {
- BrickProj.parent.update.call(m);
- if (--m.life < 60) {
+ p.dirX = u.dx;
+ p.dirY = u.dy;
+ p.speed = 16;
+ p.life = 60;
+ p.update = function () {
+ this.x += this.dirX * this.speed;
+ this.y += this.dirY * this.speed;
+ if (--this.life <= 0) {
spawnFlame(tx, ty, inst);
- m.destroy();
+ this.destroy();
}
};
- bullets.push(m);
- gameContainer.addChild(m);
+ bullets.push(p);
}
function spawnFlame(x, y, inst) {
- var f = new Container();
+ var f = gameContainer.addChild(new Container());
f.attachAsset('molotovFlame', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.4
});
f.x = x;
f.y = y;
f.life = 60;
+ f.dmg = inst.dmgMul * 12;
f.update = function () {
- if (--f.life <= 0) {
- f.destroy();
- return;
- }
- for (var i = enemies.length - 1; i >= 0; i--) if (dist2(f, enemies[i]) < 4900) damage(enemies[i], inst.dmg);
+ for (var i = enemies.length - 1; i >= 0; i--) if (distSq(f, enemies[i]) < 4900) damageEnemy(enemies[i], this.dmg);
+ if (--this.life <= 0) this.destroy();
};
- gameContainer.addChild(f);
}
-var ring = [];
-function shurikenRing(inst) {
- if (ring.length === inst.amt) return;
- ring.forEach(function (s) {
- return s.destroy();
- });
- ring = [];
- var n = inst.amt,
- r = WEAPONS.shuriken.range * inst.rng;
- for (var i = 0; i < n; i++) {
- var s = new ShuriProj();
- s.speed = 0;
- s.angle = i / n * Math.PI * 2;
- s.update = function () {
- this.angle += 0.15;
- this.x = player.x + Math.cos(this.angle) * r;
- this.y = player.y + Math.sin(this.angle) * r;
- for (var k = enemies.length - 1; k >= 0; k--) if (this.intersects(enemies[k])) damage(enemies[k], inst.dmg);
- };
- ring.push(s);
- gameContainer.addChild(s);
+/* ---- shuriken ring ---- */
+var shurikenObjs = [];
+function maintainShurikens(inst) {
+ if (shurikenObjs.length !== inst.amount) {
+ shurikenObjs.forEach(function (s) {
+ return s.destroy();
+ });
+ shurikenObjs = [];
+ var n = inst.amount,
+ r = WEAPONS.shuriken.range * inst.rngMul;
+ for (var i = 0; i < n; i++) {
+ var s = gameContainer.addChild(new Container());
+ s.attachAsset('shuriken', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ s.angle = i / n * Math.PI * 2;
+ s.update = function () {
+ this.angle += 0.15;
+ this.x = player.x + Math.cos(this.angle) * r;
+ this.y = player.y + Math.sin(this.angle) * r;
+ for (var k = enemies.length - 1; k >= 0; k--) if (this.intersects(enemies[k])) damageEnemy(enemies[k], 8 * inst.dmgMul);
+ };
+ shurikenObjs.push(s);
+ }
}
}
-var gameContainer = game.addChild(new Container());
-var player = gameContainer.addChild(new Player());
-player.x = 1024;
-player.y = 1366;
-var joystick = new Joystick();
-joystick.x = 0;
-joystick.y = -200;
-LK.gui.bottom.addChild(joystick);
-var enemies = [],
- bullets = [],
- expOrbs = [],
- skillSel = false;
-var lTxt = new Text2("Level 1", {
- size: 60,
- fill: 0xffff00
-});
-lTxt.anchor.set(0, 0);
-LK.gui.top.addChild(lTxt);
-var hpTxt = new Text2("HP", {
- size: 60,
- fill: 0xff0000
-});
-hpTxt.anchor.set(1, 0);
-hpTxt.y = 100;
-LK.gui.top.addChild(hpTxt);
-var tTxt = new Text2("15:00", {
- size: 80,
- fill: 0xffffff
-});
-tTxt.anchor.set(0.5, 0);
-LK.gui.top.addChild(tTxt);
-var wave = 1,
- time = 0;
-spawnWave();
-function spawnWave() {
- var cnt = 5 + wave * 2,
- rad = 1500;
- for (var i = 0; i < cnt && enemies.length < 30; i++) {
- var a = Math.random() * Math.PI * 2,
- x = player.x + Math.cos(a) * rad,
- y = player.y + Math.sin(a) * rad,
- t = 'normal';
- if (wave > 5 && Math.random() < 0.3) t = 'fast';
- if (wave > 10 && Math.random() < 0.2) t = 'tank';
- spawnEnemy(t, x, y);
- }
-}
-function spawnEnemy(type, x, y) {
- var e;
- switch (type) {
- case 'fast':
- e = new FastZombie();
+/* ---- ana fireWeapon anahtarı ---- */
+function fireWeapon(key, inst, meta) {
+ switch (meta.type) {
+ case 'melee':
+ swingSword(inst);
break;
- case 'tank':
- e = new TankZombie();
+ case 'boomerang':
+ fireBoomerang(inst);
break;
- case 'boss':
- e = new Boss();
+ case 'ball':
+ fireBall(inst);
break;
- default:
- e = new Enemy();
+ case 'rocket':
+ fireRocket(inst);
+ break;
+ case 'brick':
+ throwBrick(inst, 75);
+ if (inst.upgrade > 0) throwBrick(inst, -75);
+ if (inst.upgrade > 1) throwBrick(inst, 45);
+ if (inst.upgrade > 2) throwBrick(inst, -45);
+ break;
+ case 'lightning':
+ for (var n = 0; n < inst.amount; n++) castLightning(inst);
+ break;
+ case 'aura':
+ ensureAura(inst);
+ break;
+ case 'molotov':
+ for (var n = 0; n < inst.amount; n++) throwMolotov(inst);
+ break;
+ case 'shuriken':
+ maintainShurikens(inst);
+ break;
}
- e.x = x;
- e.y = y;
- enemies.push(e);
- gameContainer.addChild(e);
}
-/*--- input ---*/
-game.down = function (x, y) {
- if (skillSel) return;
- var l = game.toLocal({
+function showSkillSelection() {
+ skillSelectionActive = true;
+ var ov = game.addChild(new Container());
+ ov.x = 1024;
+ ov.y = 1366;
+ var choices = [];
+ if (player.level % 5 === 0) {
+ /* ---- Silah Kartları ---- */
+ var pool = Object.keys(WEAPONS);
+ while (choices.length < 3) choices.push(pool.splice(Math.random() * pool.length | 0, 1)[0]);
+ } else {
+ /* ---- Efsun Kartları ---- */
+ var cur = Object.keys(player.weapons)[0],
+ inst = player.weapons[cur],
+ available = WEAPONS[cur].ench.filter(function (e) {
+ return inst.enchTaken.indexOf(e) === -1;
+ });
+ if (!available.length) {
+ /* her şey alındıysa 30 % heal */
+ player.hp = Math.min(player.maxHp, player.hp + player.maxHp * 0.3);
+ skillSelectionActive = false;
+ ov.destroy();
+ return;
+ }
+ while (choices.length < 3) choices.push({
+ w: cur,
+ e: available.splice(Math.random() * available.length | 0, 1)[0]
+ });
+ }
+ choices.forEach(function (c, idx) {
+ var card = ov.addChild(new Container());
+ card.attachAsset('skillCard', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ card.x = (idx - 1) * 450;
+ card.y = 0;
+ var label, fn;
+ if (typeof c === 'string') {
+ /* Silah */
+ var own = !!player.weapons[c];
+ if (!own) {
+ label = "Unlock " + c;
+ fn = function fn() {
+ return player.weapons[c] = player.weapons[c] || addWeapon(c);
+ };
+ } else if (player.weapons[c].upgrade < 3) {
+ label = WEAPONS[c].up[player.weapons[c].upgrade];
+ fn = function fn() {
+ player.weapons[c].upgrade++;
+ player.weapons[c].amount++;
+ };
+ } else {
+ label = "Heal 30%";
+ fn = function fn() {
+ return player.hp = Math.min(player.maxHp, player.hp + player.maxHp * 0.3);
+ };
+ }
+ } else {
+ /* Efsun */
+ label = c.e;
+ fn = function fn() {
+ var inst = player.weapons[c.w];
+ inst.enchTaken.push(c.e);
+ if (c.e === "+10% Damage") inst.dmgMul *= 1.1;
+ if (c.e === "+10% Atk Spd") inst.cd *= 0.9;
+ if (c.e === "+10% Range") inst.rngMul *= 1.1;
+ if (c.e === "+10% Size") inst.sizeMul *= 1.1;
+ };
+ }
+ var txt = new Text2(label, {
+ size: 40,
+ fill: 0xffffff
+ });
+ txt.anchor.set(0.5);
+ card.addChild(txt);
+ card.down = function () {
+ fn();
+ ov.destroy();
+ skillSelectionActive = false;
+ levelText.setText('Level ' + player.level);
+ };
+ });
+}
+// Input handling
+game.down = function (x, y, obj) {
+ if (skillSelectionActive) {
+ return;
+ }
+ var localPos = game.toLocal({
x: x,
y: y
});
- if (l.y > 2000) {
- joystick.act = true;
- joystick.set(0, 0);
+ if (localPos.y > 2000) {
+ joystick.active = true;
+ joystick.setKnobPosition(0, 0);
}
};
-game.move = function (x, y) {
- if (!joystick.act || skillSel) return;
- var l = LK.gui.bottom.toLocal({
+game.move = function (x, y, obj) {
+ if (!joystick.active || skillSelectionActive) {
+ return;
+ }
+ var localPos = LK.gui.bottom.toLocal({
x: x,
y: y
});
- joystick.set(l.x - joystick.x, l.y - joystick.y);
+ var dx = localPos.x - joystick.x;
+ var dy = localPos.y - joystick.y;
+ joystick.setKnobPosition(dx, dy);
};
-game.up = function () {
+game.up = function (x, y, obj) {
joystick.reset();
};
-/*--- main update ---*/
+// Game update
game.update = function () {
- if (skillSel) return;
- time++;
- /* timer */
- var left = 900 - (time / 60 | 0);
- if (left <= 0) {
+ if (skillSelectionActive) {
+ return;
+ }
+ gameTime++;
+ // Update timer
+ var timeLeft = 900 - Math.floor(gameTime / 60);
+ if (timeLeft <= 0) {
LK.showYouWin();
return;
}
- tTxt.setText((left / 60 | 0) + ':' + (left % 60 < 10 ? '0' : '') + left % 60);
- /* hareket */
- if (joystick.act) {
- player.x += joystick.dx * player.spd;
- player.y += joystick.dy * player.spd;
+ var minutes = Math.floor(timeLeft / 60);
+ var seconds = timeLeft % 60;
+ timerText.setText(minutes + ':' + (seconds < 10 ? '0' : '') + seconds);
+ // Update UI
+ hpText.setText('HP: ' + player.hp + '/' + player.maxHp);
+ // Player movement
+ if (joystick.active) {
+ player.x += joystick.dirX * player.moveSpeed;
+ player.y += joystick.dirY * player.moveSpeed;
}
- /* kamera */
- gameContainer.x = -(player.x - 1024);
- gameContainer.y = -(player.y - 1366);
- /* dalgalar */
- if (time % 300 === 0) {
- wave++;
+ // Camera follow player
+ camera.x = player.x - 1024;
+ camera.y = player.y - 1366;
+ gameContainer.x = -camera.x;
+ gameContainer.y = -camera.y;
+ // Spawn waves
+ if (gameTime % 300 === 0) {
+ waveNumber++;
spawnWave();
}
- if (time % 10800 === 0 && enemies.length < 30) spawnEnemy('boss', player.x + 400, player.y);
- /* update */
- player.update();
- bullets.forEach(function (b) {
- return b.update && b.update();
- });
- enemies.forEach(function (e) {
- return e.update && e.update();
- });
- expOrbs.forEach(function (o) {
- return o.update && o.update();
- });
- /* çarpışma */
+ // Spawn boss every 3 minutes
+ if (gameTime % (180 * 60) === 0 && !bossSpawned && enemies.length < 30) {
+ spawnEnemy('boss', player.x + 400, player.y);
+ bossSpawned = true;
+ }
+ // Auto fire
+ if (gameTime - player.lastFire > player.fireRate) {
+ fireBullet();
+ player.lastFire = gameTime;
+ }
+ // Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
- if (!bullets[i].parent) bullets.splice(i, 1);
+ var bullet = bullets[i];
+ // Check if off screen
+ var dx = Math.abs(bullet.x - player.x);
+ var dy = Math.abs(bullet.y - player.y);
+ if (dx > 1200 || dy > 1600) {
+ bullet.destroy();
+ bullets.splice(i, 1);
+ continue;
+ }
+ // Check collisions with enemies
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (bullet.hitEnemies.indexOf(enemy) === -1 && bullet.intersects(enemy)) {
+ bullet.hitEnemies.push(enemy);
+ if (enemy.takeDamage(bullet.damage)) {
+ enemy.destroy();
+ enemies.splice(j, 1);
+ LK.getSound('hit').play();
+ }
+ if (bullet.hitEnemies.length >= bullet.piercing) {
+ bullet.destroy();
+ bullets.splice(i, 1);
+ break;
+ }
+ }
+ }
}
+ // Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
- if (dist2(enemies[i], player) < 2600) {
- player.hp -= enemies[i].damage;
- killEnemy(i);
+ var enemy = enemies[i];
+ if (enemy.intersects(player)) {
+ player.takeDamage(enemy.damage);
+ enemy.destroy();
+ enemies.splice(i, 1);
}
}
+ // Update exp orbs
for (var i = expOrbs.length - 1; i >= 0; i--) {
- var o = expOrbs[i];
- if (dist2(o, player) < player.pick * player.pick) o.mag = 10;
- if (o.intersects && o.intersects(player)) {
- player.gain(o.val);
- o.destroy();
+ var orb = expOrbs[i];
+ var dx = orb.x - player.x;
+ var dy = orb.y - player.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < player.pickupRange) {
+ orb.magnetSpeed = 10;
+ }
+ if (orb.intersects(player)) {
+ player.gainExp(orb.value);
+ orb.destroy();
expOrbs.splice(i, 1);
LK.getSound('pickup').play();
}
}
- /* UI */
- hpTxt.setText('HP: ' + player.hp + '/' + player.hpMax);
- lTxt.setText('Level ' + player.level);
-};
\ No newline at end of file
+ // Spawn pickups randomly
+ if (gameTime - lastPickupSpawn > 1800 && Math.random() < 0.1) {
+ lastPickupSpawn = gameTime;
+ var pickup;
+ var angle = Math.random() * Math.PI * 2;
+ var distance = 300 + Math.random() * 500;
+ var pickupX = player.x + Math.cos(angle) * distance;
+ var pickupY = player.y + Math.sin(angle) * distance;
+ if (Math.random() < 0.5) {
+ pickup = new Bomb();
+ } else {
+ pickup = new Magnet();
+ }
+ pickup.x = pickupX;
+ pickup.y = pickupY;
+ pickups.push(pickup);
+ gameContainer.addChild(pickup);
+ }
+ // Update pickups
+ for (var i = pickups.length - 1; i >= 0; i--) {
+ var pickup = pickups[i];
+ if (!pickup.active) {
+ pickups.splice(i, 1);
+ }
+ }
+};
+// Initial spawn
+spawnWave();
\ No newline at end of file
Survivor.io style 2D sword swing effect made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows. It should only have a slash effect, no swords. The slash effect should also be in the shape of a half moon.
Survivor.io style 2D round soccer ball made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
A 2D Survivor.io style lightning strike from a cloud in the sky to the ground, made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
A red and blue Survivor.io style 2D U-shaped (with N and S) magnet made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
Survivor.io style 2D shuriken made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
Survivor.io style 2D brick made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
Survivor.io style 2D missile rocket made by HABBY PTE. LTD.
A 2D green radiating circular aura in the Survivor.io style made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
A 2D bomb in the style of Survivor.io, made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
A 2D circular burning effect in Survivor.io style made by HABBY PTE. LTD. (not only the surroundings but also the inside burns) In-Game asset. 2d. High contrast. No shadows
A 2D molotov in the Survivor.io style made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
Survivor.io style 2D greenish exp sphere made by HABBY PTE. LTD. No exp written on it. In-Game asset. 2d. High contrast. No shadows
Survivor.io style 2D half-moon orange boomerang made by HABBY PTE. LTD. In-Game asset. 2d. High contrast. No shadows
Survivor.io style 2D 1 chicken leg.. In-Game asset. 2d. High contrast. No shadows
2D survivor.io game style atomic boom effect front view. No text written on it.
2D. Ranged zombie. attacks with poisonous saliva. In-Game asset. 2d. High contrast. No shadows
2D. Child (small) zombie. He has a small saw in his hand.. In-Game asset. 2d. High contrast. No shadows
2D. Fat zombie. His hands are too big.. In-Game asset. 2d. High contrast. No shadows
Poisonous green circular saliva. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
Small green claw slash effect. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
Giant boss angry reddish zombie. 2D.. In-Game asset. 2d. High contrast. No shadows
Small saw slash effect. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
Big red fist slash effect. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
Kanlı kemik 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
2D character that looks like a prophet and holds a holy book in his hand.. In-Game asset. 2d. High contrast. No shadows
A background image (wallpaper) representing an old prophet-like man with white hair and beard, wearing a priest's robe (hooded) and holding a holy book (christianity, cross) in his hand, fighting against zombies.. In-Game asset. 2d. High contrast. No shadows
Zombie flesh and bone themed 2D cardboard hollow (without text) horizontal rectangular button.. In-Game asset. 2d. High contrast. No shadows
2D. Healer zombie. Like a female zombie in a healer costume.. In-Game asset. 2d. High contrast. No shadows
2D. Brain illustrated healing potion.. In-Game asset. 2d. High contrast. No shadows
A healing blood pool with circular zombie brain and bone particles. Green + (healing) symbols on top. 2D.. In-Game asset. 2d. High contrast. No shadows
2D. Survivor.io game style skill card. No text written on it. No symbols on it. Just the blank card. Green.. In-Game asset. 2d. High contrast. No shadows
2D. Cartoon. The rise of the zombie ghost spirit from the ground.. In-Game asset. 2d. High contrast. No shadows
levelup
Sound effect
hit
Sound effect
rocketBoom
Sound effect
pickup
Sound effect
backGroundMusic
Music
death
Sound effect
damageTaken
Sound effect
mainMenuMusic
Music
deathScreenMusic
Music
swordSoundEffect
Sound effect
bumerangSoundEffect
Sound effect
brickSoundEffect
Sound effect
lightningSoundEffect
Sound effect
ballSoundEffect
Sound effect
rocketSoundEffect
Sound effect
auraSoundEffect
Sound effect
molotovSoundEffect
Sound effect
molotovBoom
Sound effect
introSpeech
Sound effect
bombBoomSound
Sound effect