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
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
So let's start writing the code.
User prompt
Let's change the sword's feature. Now the sword is not swinging in the direction my character is looking, but towards the closest enemy. Also, since its range is currently very small, we need to increase its range. We should also change the sword buffs as follows: Sword buffs: 1. Boost) Targets the 2nd closest enemy and swings an additional sword. (Number of swung swords increases from 1 to 2) (If there is no 2nd enemy, targets the 1st enemy) 2. Boost) Targets the 3rd closest enemy and swings an additional sword. (Number of swung swords increases from 2 to 3) (If there is no 3rd enemy, targets the 1st enemy) 3. Boost) Targets the 4th closest enemy and swings an additional sword. (Number of swung swords increases from 3 to 4) (If there is no 4th enemy, targets the 1st enemy)
User prompt
I don't think my character has a sword right now. The sword should be swung in the direction my character is looking at every 2 seconds and if it hits an enemy it should deal damage.
User prompt
We are going to make a huge update now! Read carefully and try to analyze and understand thoroughly. There will be nine different weapon types in the game. Each weapon will have its own unique enchantments and upgrades. Whenever my character levels up (except on the level-5 milestones), three random choices will appear, each containing an enchantment for the weapon currently in hand. Whenever my character reaches a multiple of five levels, three random weapon choices will appear; if my character already owns the weapon shown, that choice will count as an upgrade for the existing weapon. Weapon upgrades unlock sequentially—first Upgrade 1, then Upgrade 2, then Upgrade 3. If all possible enchantments or upgrades for that weapon have already been acquired, then on level-up the character’s health is restored by 30%. In addition, each time the character levels up, maximum health increases by +10. My character starts the game with the sword. Below is more detailed information about weapons, enchantments, and upgrades. Sword: The character swings the sword in the direction they are facing at specific intervals (once every 2 seconds). It has a short range. Enemies struck by the swinging sword take damage. Sword Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Sword Upgrades: Upgrade 1) The character also swings the sword behind themselves at the same intervals. Upgrade 2) The character also swings the sword upwards at the same intervals. Upgrade 3) The character also swings the sword downwards at the same intervals. Boomerang: Throws a boomerang at the nearest enemy. The boomerang follows a circular arc and then returns to the character. As it travels, it damages any enemies it hits. It is thrown once every 3 seconds. It has a long range. Boomerang Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Boomerang Upgrades: Upgrade 1) Throws an additional boomerang targeting the second-closest enemy. (Boomerang count increases from 1 to 2.) (If no second enemy exists, the additional boomerang targets the closest enemy.) Upgrade 2) Throws an additional boomerang targeting the third-closest enemy. (Boomerang count increases from 2 to 3.) (If no third enemy exists, the additional boomerang targets the closest enemy.) Upgrade 3) Throws an additional boomerang targeting the fourth-closest enemy. (Boomerang count increases from 3 to 4.) (If no fourth enemy exists, the additional boomerang targets the closest enemy.) Ball: Every 3 seconds, throws a ball at the nearest enemy within its range. The ball can bounce once and deal damage to an enemy, then disappears once it exits the screen. As it travels, it damages any enemies it collides with. It has a long range. Ball Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Ball Upgrades: Upgrade 1) Throws an additional ball at the second-closest enemy. (Ball count increases from 1 to 2.) (If no second enemy exists, the additional ball targets the closest enemy.) Upgrade 2) Throws an additional ball at the third-closest enemy. (Ball count increases from 2 to 3.) (If no third enemy exists, the additional ball targets the closest enemy.) Upgrade 3) Throws an additional ball at the fourth-closest enemy. (Ball count increases from 3 to 4.) (If no fourth enemy exists, the additional ball targets the closest enemy.) Rocket: Every 3 seconds, launches a rocket at the nearest enemy within its range. Range is moderate. When the rocket hits its target, it deals area damage in a circular radius around that enemy (i.e., it is an AoE rocket). Rocket Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Rocket Upgrades: Upgrade 1) Launches an additional rocket at the second-closest enemy. (Rocket count increases from 1 to 2.) (If no second enemy exists, that additional rocket targets the closest enemy.) Upgrade 2) Launches an additional rocket at the third-closest enemy. (Rocket count increases from 2 to 3.) (If no third enemy exists, that additional rocket targets the closest enemy.) Upgrade 3) Launches an additional rocket at the fourth-closest enemy. (Rocket count increases from 3 to 4.) (If no fourth enemy exists, that additional rocket targets the closest enemy.) Brick: Throws a brick at a 75° angle in the direction the character is facing. After the brick is thrown, it falls downward as if affected by gravity, and disappears once it leaves the screen. As it travels, it damages any enemies it collides with. Bricks are thrown once every 3 seconds. Brick Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Brick Upgrades: Upgrade 1) Also throws a second brick at a 75° angle behind the direction the character is facing. (Total of 2 bricks per throw.) Upgrade 2) Also throws a second brick at a 45° angle in the same direction the character is facing. (Total of 3 bricks per throw.) Upgrade 3) Also throws a second brick at a 45° angle behind the direction the character is facing. (Total of 4 bricks per throw.) Lightning: Summons a lightning strike on a random enemy on the screen. Lightning strikes once every 3 seconds. Lightning Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Lightning Upgrades: Upgrade 1) Increases the number of lightning strikes from 1 to 2. (Multiple strikes can hit the same enemy.) Upgrade 2) Increases the number of lightning strikes from 2 to 3. (Multiple strikes can hit the same enemy.) Upgrade 3) Increases the number of lightning strikes from 3 to 4. (Multiple strikes can hit the same enemy.) Aura: Creates a small circular aura that constantly surrounds the character. Any enemy that touches this aura takes damage. Aura Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Aura Upgrades: Upgrade 1) Enemies that enter the aura’s range are slowed by 25%. Upgrade 2) Enemies that enter the aura’s range are slowed by 50%. Upgrade 3) Enemies that enter the aura’s range are slowed by 75%. Molotov: Randomly throws a Molotov cocktail into a circular area. There is a 3-second cooldown. When Molotovs hit the ground, they shatter and ignite a small circular area on fire for 1 second. Any enemy that enters this burning area takes damage. Molotov Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Molotov Upgrades: Upgrade 1) Increases the number of Molotovs thrown from 1 to 2. Upgrade 2) Increases the number of Molotovs thrown from 2 to 3. Upgrade 3) Increases the number of Molotovs thrown from 3 to 4. Shuriken: Within a short radius around the character, two regular-speed shurikens spin for 3 seconds at a time (each shuriken positioned at equal angular separation—if there are two, they are 180° apart). These shurikens rotate around the character and deal damage to any enemy they hit. Shuriken Enchantments: Option 1) +10% Damage Increase Option 2) +10% Attack Speed Increase Option 3) +10% Range Increase Option 4) +10% Size Increase Shuriken Upgrades: Upgrade 1) Increases the shuriken count from 2 to 3. (Shurikens should be evenly spaced—120° apart when there are three.) Upgrade 2) Increases the shuriken count from 3 to 4. (Shurikens should be evenly spaced—90° apart when there are four.) Upgrade 3) Increases the shuriken count from 4 to 5. (Shurikens should be evenly spaced—72° apart when there are five.) I want you to revise the code according to what I explained above. Think carefully.
User prompt
Currently when I level up and choose a upgrade (while choosing a upgrade) the enemies don't stop and keep moving, so when I choose my buff late the enemies get too close to my character and I die. While my character chooses a buff the enemies shouldn't move and shouldn't attack. After my character chooses his buff the enemies can move and attack. Also the magnet and bomb should be much rarer to be created.
User prompt
There should be a bomb that appears randomly on the map and when my character picks up that bomb, all enemies on the current screen (except bosses) should die by eating them one by one. Also, a magnet should appear randomly on the map and when my character picks up that magnet, it should quickly pull all XPs on the current screen towards itself. Also, right now, the game doesn't stop when my character is choosing a power-up and the enemies continue to advance towards my character. Also, don't allow the same power-up to appear more than once when choosing a power-up, I mean when I'm going to choose one of the three power-ups, sometimes two of the three power-ups are the same and I don't want that, each power-up should be different.
User prompt
Do not allow more than 30 enemies on screen at once. There cannot be more than 30 enemies on screen at once.
User prompt
Enemies are currently spawning very close to my character. Enemies should spawn slightly off screen and come towards me. Also enemies are currently spawning very frequently, enemies should spawn less frequently. Also my joystick button is currently too low, I need to move it up a bit.
User prompt
There should be a circle like a joystick button in the middle bottom of the screen. I will control the movement with this joystick button. This joystick button will move in any direction I turn it 360 degrees.
User prompt
Please fix the bug: 'TypeError: self.removeAllChildren is not a function' in or related to this line: 'self.removeAllChildren();' Line Number: 104
Code edit (1 edits merged)
Please save this source code
User prompt
Urban Survivor: Zombie Arena
Initial prompt
Everything I'm about to tell you is very important and detailed. That's why you shouldn't miss even the smallest part. Here we go: We are temporarily naming the game “Urban Survivor”. The genre is mobile-focused top-down arena survival, popularly known as “bullet heaven” or “survivor-like”. The gameplay loop will be tied to a fifteen-minute timer; increasingly crowded zombie variants, explosive mutants and intermediate bosses will rain down on the stage until the time runs out or the player dies. We want Upit to use JavaScript + HTML5-Canvas template as the game engine; files split with ES Modules will be preferred, but Upit should design this detail as modular in its own internal structure. The final output should be playable full-screen on the mobile browser and with mouse-supported joystick emulation on the desktop. The controls are run via a single virtual joystick. The joystick is fixed to the lower-left area on the screen; its back plate is a pale gray circle with a sixty-pixel radius, and the hand-dragged stick inside is a white circle with a thirty-pixel radius. When the user presses their finger, the touchstart event should be assigned to the joystick, the distance and direction from the center should be measured continuously with touchmove, and the direction vector should be reset instantly when touchend occurs. Considering that multi-finger skill buttons will come, touch identifiers should be kept separately, that is, each touch.identifier should be stored. In the desktop test, mouse down, move, up events should mimic the same mechanics. The vector should be normalized and multiplied by the player speed, the joystick ball should not extend to the outer circle; if it is dragged away from the center, the vector should be clipped so that it does not exceed the radius. The player speed is normally two hundred pixels per second, but as long as the joystick distance does not fill the unit circle, it slows down proportionally. Let the main game loop loop in the requestAnimationFrame with the classic delta-time logic. First, dt will be calculated for each frame, and if dt exceeds sixteen milliseconds, a fixed limit of 0.033 seconds will be set so that the physics does not jump in frames with high latency. The core order is as follows: update(dt) does all the logical simulation, then collision() solves the collision and damage checks, and finally render() does the drawing. The player is a single circular combat area. They have a health pool of six hearts; each hit deducts one heart. When hit, the player is granted a half-second invulnerability, indicated by a short alpha flicker effect on the screen. The player's default weapon is a single, straight-firing projectile called the Repeater. It fires once per second at startup, has a range of one and a half times the height of the screen, and takes one zombie's HP per hit. As the player levels up, the weapon's rate of fire, the number of bullets, or the special properties of the projectile can evolve according to the chosen abilities. The basic principle of the weapon system is as follows: active abilities are elements that deal direct damage to the field, passive abilities are the stats that support them. An active ability that reaches level five is automatically promoted to EVO status if the corresponding passive ability is level five; For example, if the Forcefield is level five and the Energy Cube is level five, the Forcefield circle becomes a Super Field that expands by fifty percent. When the EVO transformation occurs, the two slots merge into a single powerful slot, opening up space in the player's skill pool. Let Upit handle this slot management automatically. The bullets should not move randomly but towards the enemy closest to my character. The level system is based on green experience spheres dropped from killing enemies; minion zombies drop one point spheres, elites drop three points. The level threshold is scaled by the formula 5 + L^1.5; that is, each level is a little more difficult. When the player fills the bar, the game immediately pauses, a three-card skill selection opens in the middle of the screen, and very rarely (five percent probability) a fourth secret card appears. Time does not pass until the card block is selected. The text of the skill, the level indicator and the EVO combination, if any, are given in the sub-description. Once the selection is made, the game continues from where it left off. The enemy ecosystem starts with four main types: the walker is slow and fragile, the runner is fast but fragile, the tank is heavily armored and slow, and the exploder explodes on death and deals area damage. We give a fixed table for each type's hp, speed, damage, exp value: walker six hp sixty pixels speed, runner four hp one hundred twenty pixels speed, tank twenty hp forty pixels speed, exploder eight hp seventy pixels speed and two hearts of damage during explosion. The spawn algorithm occurs every second; as the game progresses, the interval shortens like a sine curve, decreasing to three hundred milliseconds. Enemies spawn forty pixels away from the screen without being visible, instantly change their direction to the player center, no pathfinding, only homing vector. Elite versions that drop with a ten percent chance carry quadrupled hp, tripled exp; they also drop loot chests with an eight percent chance. The boss system, which adds color to the difficulty curve, is based on three-minute periods. In the third minute, the Giant Mutant descends onto the field, leaving a poisonous pool around the player like a marshmallow. In the sixth minute, the Chainsaw Brute comes charging forward, in the ninth minute the giant Golem throwing rocks, in the twelfth minute the multi-phase War Mech. Each boss has an introductory scene with a large red warning triangle at the top of the screen, when the boss dies, a yellow chest drops, inside which either a special item that will promote to EVO or a high-level passive is found. The game never stops completely when the boss is killed, only a short "Victory Slow-Mo" is applied for two hundred milliseconds. The map relies on a continuously looping tile overlay to give the feeling of endlessness. Each tile is two hundred and fifty-six pixel squares, a total of sixteen tiles (four-four) are loaded into memory, and the camera shifts to keep the player centered in each frame, unnecessary tiles are not reloaded to the GPU. The ground pattern is gray-purple asphalt, with worn-out road lines in between; a very light parallax cloud layer on the horizon. Screen shaking is activated for high damage and leveling up; amplitude is eight pixels, duration is two hundred milliseconds, easing out-quad. The game map should be endless and repetitive. My character should always be in the exact center of the screen. When my character moves, the ground should move in the opposite direction, so my character moves indirectly because I move the ground under my character, but it is always in the exact center of the screen because it is the ground that is actually moving. My character's attacks (bullets etc.) that go outside the screen should not go back inside from the other side of the screen. Collision calculations are based on the square of the circle-circle distance, so no square root is taken. If the enemy's HP drops to zero in a bullet-enemy collision, it is removed from the enemy pool, an exp sphere is spawned on the ground, and a gold coin is spawned with a fifteen percent chance. I-frame control is performed in player-enemy collisions; if it is not active, health is reduced, and the i-frame is triggered. The same procedure is applied to every object damaged in range in an Exploder explosion. The user interface is a transparent black bar at the top of the screen as the HUD. Heart icons on the left, green level bar in the middle, and score on the top right. The joystick is already visible on the bottom left, and there is a skill button area that is currently left empty on the bottom right, for future expansion. The level-up screen dims the HUD and shows three cards in the middle; cards cannot be selected before their animation is finished, so that they are not clicked unintentionally. The main menu at the beginning of the game is a single page: “Start Game”, “Options”, “How to Play”. Music sound, effect sound, graphic quality, joystick size adjustment, FPS indicator off in Options. “How to Play” is a simple visual-textual explanation. Graphic style is low-poly characters with thick outlines and rounded corners and square bodies. Color palette is saturated, high contrast: zombies are in blue and green tones, player is dark brown body with red scarf, bullets are yellow-orange, force fields are light cyan that looks like glass. Sprite animations are simple walking cycles that rotate in eight frames. Facial expressions have big black eye holes, no mouth. Soundscape is synth-wave based; BPM is around 120 looping tracks. Effects include laser patter of bullet fire, euphoric arpeggio jingle when leveling up, distorted alarm when boss is coming. Performance target is five hundred simultaneous enemies. Object pool technique should be applied; bullets, enemies, expOrbs, particles should be stored in pre-allocated fixed-length arrays, active=false should be given when dead, so that garbage collection is not triggered. Optional QuadTree collision acceleration can be added for higher crowds. Visual assets should be combined in sprite atlas, converted to ImageBitmap during load phase and printed to canvas like that. File structure can be described verbally: under src folder core/loop, core/input, objects folder player, enemy, bullet, systems directory spawn and skills, ui folder hud, modalLevelUp, utilities keep mathHelpers. Main input file main.js imports all modules, creates canvas, boots the game. atlas.png, atlas.json and sfx subfolders under assets folder. index.html contains canvas on a single page, mobile compatibility meta tags and fullscreen manifest. Test scenario list: in thirty-second stress test, FPS should not drop below fifty-five when three hundred enemies spawn; Forcefield + Energy Cube EVO combination tests the power, the old two skill slots should disappear and Super Field should appear in a single slot; joystick vector should give half speed at half radius and full speed at full outside; game time should not pause when chest falls on boss death, only small slow-motion. For extensibility, skill slot count should not be deep frozen const, but six at the beginning but can be changed in the config file; event-bus style publish-subscribe structure will be established to support modders to add new enemies or skills to the system; UI themes can be customized with CSS root variables. Final instructions: Upit will grasp all the systems in this explanation, build them modularly and documented in JavaScript, generate images even as placeholders, add sound stubs, make all mobile controls including joystick fully functional, and convert the result into an export package that works in the browser with a single click. All the information I told and explained to you above is very important, think about and analyze all of them. Program the game accordingly.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ /******************************************************************** * ENEMY CLASSES (unchanged temel) * ********************************************************************/ var Enemy = Container.expand(function () { var self = Container.call(this); var s = Container.call(this); s.hp = 20; s.damage = 10; s.speed = 2; s.expValue = 5; s.type = 'normal'; s.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); s.takeDamage = function (a) { s.hp -= a; LK.effects.flashObject(s, 0xffffff, 60); return s.hp <= 0; }; s.update = function () { if (!player || skillSelect) return; var v = dirTo(s, player); s.x += v.dx * s.speed; s.y += v.dy * s.speed; }; return s; }); 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', { anchorX: 0.5, anchorY: 0.5 }); return z; }); 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', { anchorX: 0.5, anchorY: 0.5 }); return z; }); 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', { anchorX: 0.5, anchorY: 0.5 }); return z; }); /******************************************************************** * EXP ORB & PICKUPS * ********************************************************************/ var ExpOrb = Container.expand(function () { var self = Container.call(this); var o = Container.call(this); o.value = 5; o.magnet = 0; o.attachAsset('expOrb', { anchorX: 0.5, anchorY: 0.5 }); o.update = function () { if (o.magnet) { var v = dirTo(o, player); o.x += v.dx * o.magnet; o.y += v.dy * o.magnet; } }; return o; }); /* Bomb ve Magnet sınıfların eski hâli korunuyor — kod kısaltmak için buraya tekrar yazılmadı. */ /******************************************************************** * JOYSTICK (değişmedi) * ********************************************************************/ var Joystick = Container.expand(function () { var self = Container.call(this); var j = Container.call(this); j.active = false; j.dirX = 0; j.dirY = 0; var base = j.attachAsset('joystickBase', { anchorX: 0.5, anchorY: 0.5 }); var knob = j.attachAsset('joystickKnob', { anchorX: 0.5, anchorY: 0.5 }); j.setPos = function (x, y) { var dx = x - base.x, dy = y - base.y, d = Math.sqrt(dx * dx + dy * dy), m = 60; if (d > m) { dx = dx / d * m; dy = dy / d * m; } knob.x = dx; knob.y = dy; j.dirX = dx / m; j.dirY = dy / m; }; j.reset = function () { knob.x = knob.y = j.dirX = j.dirY = 0; j.active = false; }; return j; }); /******************************************************************** * PLAYER * ********************************************************************/ var Player = Container.expand(function () { var self = Container.call(this); var p = Container.call(this); p.level = 1; p.exp = 0; p.expNext = 10; p.hp = 100; p.hpMax = 100; p.moveSpeed = 5; p.pickRange = 120; p.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); /*--------- Silah envanteri ---------*/ p.weapons = {}; addWeapon('sword'); function addWeapon(k) { if (p.weapons[k]) return; var m = WEAPONS[k]; p.weapons[k] = { cd: m.cd, cdCnt: 0, dmg: 1, range: 1, size: 1, amount: 1, upg: 0, ench: [] }; } /*--------- EXP / Level ---------*/ p.gain = function (v) { p.exp += v; if (p.exp >= p.expNext) levelUp(); }; function levelUp() { p.level++; p.exp = 0; p.expNext = p.level * 15; p.hpMax += 10; p.hp = Math.min(p.hpMax, p.hp + p.hpMax * 0.3); LK.getSound('levelup').play(); openChoice(); } /*--------- Güncelle ---------*/ p.update = function () { for (var key in p.weapons) { var inst = p.weapons[key], meta = WEAPONS[key]; if (--inst.cdCnt <= 0) { fireWeapon(key, inst, meta); inst.cdCnt = inst.cd; } } }; return p; /*===================== LEVEL-UP SEÇİM ==========================*/ function openChoice() { skillSelect = true; var ov = game.addChild(new Container()); ov.x = 1024; ov.y = 1366; var ch = []; if (p.level % 5 === 0) { var pool = Object.keys(WEAPONS); for (var i = 0; i < 3; i++) { ch.push(pool.splice(Math.random() * pool.length | 0, 1)[0]); } } else { var cur = Object.keys(p.weapons)[0], inst = p.weapons[cur], meta = WEAPONS[cur]; var pool = meta.ench.filter(function (e) { return inst.ench.indexOf(e) === -1; }); if (pool.length === 0) { skillSelect = false; ov.destroy(); return; } for (var i = 0; i < 3 && pool.length; i++) ch.push({ w: cur, e: pool.splice(Math.random() * pool.length | 0, 1)[0] }); } ch.forEach(function (c, 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 label; card["do"] = function () {}; if (typeof c === 'string') { // weapon kartı var own = !!p.weapons[c]; if (!own) { label = "Unlock " + c; card["do"] = function () { return addWeapon(c); }; } else if (p.weapons[c].upg < 3) { label = UPG_LABELS[c][p.weapons[c].upg]; card["do"] = function () { p.weapons[c].upg++; p.weapons[c].amount++; }; } else { label = "Heal 30%"; card["do"] = function () { p.hp = Math.min(p.hpMax, p.hp + p.hpMax * 0.3); }; } } else { // enchant kartı label = c.e; card["do"] = function () { var inst = p.weapons[c.w]; inst.ench.push(c.e); if (c.e === ENCH_LABELS[0]) inst.dmg *= 1.1; if (c.e === ENCH_LABELS[1]) inst.cd *= 0.9; if (c.e === ENCH_LABELS[2]) inst.range *= 1.1; if (c.e === ENCH_LABELS[3]) inst.size *= 1.1; }; } var t = new Text2(label, { size: 38, fill: 0xffffff }); t.anchor.set(0.5); card.addChild(t); card.down = function () { this["do"](); ov.destroy(); skillSelect = false; levelTxt.setText("Level " + p.level); }; }); } /*=================================================================*/ }); /**** * Initialize Game ****/ /******************************************************************** * FIRE WEAPON HELPERS (compact) * ********************************************************************/ /******************************************************************** * GAME INITIALISATION * ********************************************************************/ var game = new LK.Game({ backgroundColor: 0x111111 }); /**** * Game Code ****/ /******************************************************************** * GLOBAL HELPERS & DATA * ********************************************************************/ /**** PLUG-INS ****************************************************/ /**** ASSETS ******************************************************/ /******************************************************************** * SURVIVOR-LIKE (Full integrated file — nine weapons, enchants) * ********************************************************************/ function rand(min, max) { return min + Math.random() * (max - min); } function dist2(a, b) { var dx = a.x - b.x, dy = a.y - b.y; return dx * dx + dy * dy; } function dirTo(s, t) { var dx = t.x - s.x, dy = t.y - s.y, d = Math.sqrt(dx * dx + dy * dy); return { dx: dx / d, dy: dy / d }; } var WEAPONS = { sword: { cd: 120, dmg: 10, range: 90, type: 'melee', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, boomerang: { cd: 180, dmg: 10, range: 900, type: 'boomerang', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, ball: { cd: 180, dmg: 12, range: 900, type: 'ball', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, rocket: { cd: 180, dmg: 20, range: 650, type: 'rocket', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, brick: { cd: 180, dmg: 15, range: 800, type: 'brick', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, lightning: { cd: 180, dmg: 25, range: 9999, type: 'lightning', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, aura: { cd: 60, dmg: 5, range: 150, type: 'aura', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, molotov: { cd: 180, dmg: 12, range: 850, type: 'molotov', ench: [0, 1, 2, 3], upg: [0, 1, 2] }, shuriken: { cd: 180, dmg: 8, range: 250, type: 'shuriken', ench: [0, 1, 2, 3], upg: [0, 1, 2] } }; var ENCH_LABELS = ["+10% Damage", "+10% FireRate", "+10% Range", "+10% Size"]; var UPG_LABELS = { sword: ["Back Swing", "Up Swing", "Down Swing"], boomerang: ["Boomerang +1", "Boomerang +1", "Boomerang +1"], ball: ["Ball +1", "Ball +1", "Ball +1"], rocket: ["Rocket +1", "Rocket +1", "Rocket +1"], brick: ["Back 75°", "Front 45°", "Back 45°"], lightning: ["Lightning +1", "Lightning +1", "Lightning +1"], aura: ["Slow 25%", "Slow 50%", "Slow 75%"], molotov: ["Molotov +1", "Molotov +1", "Molotov +1"], shuriken: ["Shuriken +1", "Shuriken +1", "Shuriken +1"] }; /******************************************************************** * GENERIC PROJECTILE FACTORY * ********************************************************************/ function makeProjectile(shapeKey) { return Container.expand(function () { var self = Container.call(this); self.dirX = 0; self.dirY = 0; self.speed = 12; self.dmg = 10; self.life = 300; self.attachAsset(shapeKey, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; if (--self.life <= 0) { self.destroy(); } }; return self; }); } var BoomProj = makeProjectile('boomerang'); var BallProj = makeProjectile('ball'); var RocketProj = makeProjectile('rocket'); var BrickProj = makeProjectile('brick'); var ShuriProj = makeProjectile('shuriken'); /******************************************************************** * FIRE WEAPON HELPERS (compact) * ********************************************************************/ /* Main fireWeapon dispatcher */ function fireWeapon(key, inst, meta) { switch (key) { case 'sword': swingSword(inst); break; case 'boomerang': throwBoomerang(inst); break; case 'ball': throwBall(inst); break; case 'rocket': fireRocket(inst); break; case 'brick': // Brick weapon throws multiple bricks at different angles if upgraded var baseAngles = [180]; if (inst.upg > 0) baseAngles.push(255); if (inst.upg > 1) baseAngles.push(135); if (inst.upg > 2) baseAngles.push(225); for (var i = 0; i < inst.amount; i++) { for (var j = 0; j < baseAngles.length; j++) { throwBrick(inst, baseAngles[j]); } } break; case 'lightning': for (var i = 0; i < inst.amount; i++) { strikeLightning(inst); } break; case 'aura': ensureAura(inst); break; case 'molotov': for (var i = 0; i < inst.amount; i++) { throwMolotov(inst); } break; case 'shuriken': ensureShurikenRing(inst); break; } } function nearest() { var n = null, d = 1e9; for (var i = 0; i < enemies.length; i++) { var e = enemies[i], q = dist2(e, player); if (q < d) { d = q; n = e; } } return n; } function damageEnemy(e, amount) { if (e.takeDamage(amount)) { dropExpOrb(e.x, e.y, e.expValue); e.destroy(); enemies.splice(enemies.indexOf(e), 1); } } /* melee sword */ function swingSword(inst) { var arc = 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 }); arc.life = 10; arc.dmg = 10 * inst.dmg; arc.update = function () { if (--arc.life <= 0) { arc.destroy(); return; } for (var i = enemies.length - 1; i >= 0; i--) { if (dist2(enemies[i], arc) < Math.pow(WEAPONS.sword.range * inst.range, 2)) { damageEnemy(enemies[i], arc.dmg); } } }; gameContainer.addChild(arc); } /* ranged helpers (boomerang, ball, rocket, brick) */ function launchSimple(Cls, inst, setup) { var e = nearest(); if (!e) return; var v = dirTo(player, e); for (var i = 0; i < inst.amount; i++) { var p = new Cls(); p.x = player.x; p.y = player.y; setup(p, v, i); bullets.push(p); gameContainer.addChild(p); } } function throwBoomerang(inst) { launchSimple(BoomProj, inst, function (p, v, i) { p.dirX = v.dx; p.dirY = v.dy; p.dmg = 10 * inst.dmg; p["return"] = false; p.update = function () { if (!p["return"] && --p.life < 180) { p["return"] = true; } if (p["return"]) { var v = dirTo(p, player); p.dirX = v.dx; p.dirY = v.dy; } BoomProj.parent.update.call(p); for (var k = enemies.length - 1; k >= 0; k--) if (p.intersects(enemies[k])) damageEnemy(enemies[k], p.dmg); }; }); } function throwBall(inst) { launchSimple(BallProj, inst, function (p, v) { p.dirX = v.dx; p.dirY = v.dy; p.dmg = 12 * inst.dmg; }); } function fireRocket(inst) { launchSimple(RocketProj, inst, function (p, v) { p.dirX = v.dx; p.dirY = v.dy; p.dmg = 20 * inst.dmg; p.update = function () { RocketProj.parent.update.call(p); for (var k = enemies.length - 1; k >= 0; k--) if (p.intersects(enemies[k])) { LK.getSound('rocketBoom').play(); for (var m = enemies.length - 1; m >= 0; m--) if (dist2(enemies[m], p) < 16000) damageEnemy(enemies[m], p.dmg); p.destroy(); bullets.splice(bullets.indexOf(p), 1); break; } }; }); } function throwBrick(inst, ang) { var rad = ang * Math.PI / 180; var v = { dx: Math.cos(rad), dy: Math.sin(rad) }; var p = new BrickProj(); p.x = player.x; p.y = player.y; p.dirX = v.dx; p.dirY = v.dy; p.speed = 14; p.g = 0.3; p.dmg = 15 * inst.dmg; p.update = function () { p.y += p.g; // Call the base projectile update method directly to avoid undefined parent.update if (typeof makeProjectile('brick').prototype.update === 'function') { makeProjectile('brick').prototype.update.call(p); } if (Math.abs(p.x - player.x) > 1200 || Math.abs(p.y - player.y) > 1600) { p.destroy(); bullets.splice(bullets.indexOf(p), 1); } else for (var k = enemies.length - 1; k >= 0; k--) if (p.intersects(enemies[k])) damageEnemy(enemies[k], p.dmg); }; bullets.push(p); gameContainer.addChild(p); } function strikeLightning(inst) { var e = enemies[Math.random() * enemies.length | 0]; if (!e) return; var l = new Container(); l.attachAsset('lightning', { anchorX: 0.5, anchorY: 1 }); l.x = e.x; l.y = e.y; l.life = 20; l.update = function () { if (--l.life === 19) damageEnemy(e, 25 * inst.dmg); if (l.life <= 0) { l.destroy(); } }; gameContainer.addChild(l); } var auraField = null; function ensureAura(inst) { if (auraField) { auraField.x = player.x; auraField.y = player.y; return; } auraField = new Container(); auraField.attachAsset('auraField', { anchorX: 0.5, anchorY: 0.5, alpha: 0.35 }); auraField.update = function () { auraField.x = player.x; auraField.y = player.y; for (var i = enemies.length - 1; i >= 0; i--) { if (dist2(enemies[i], auraField) < Math.pow(WEAPONS.aura.range * inst.range, 2)) { if (inst.upg > 0) enemies[i].speed = WEAPONS.zombie ? enemies[i].speed : enemies[i].speed * 0.75; damageEnemy(enemies[i], inst.dmg); } } }; gameContainer.addChild(auraField); } 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 = new BrickProj(); p.x = player.x; p.y = player.y; var v = dirTo(p, { x: tx, y: ty }); p.dirX = v.dx; p.dirY = v.dy; p.speed = 16; p.dmg = 0; p.life = 90; p.update = function () { BrickProj.parent.update.call(p); if (p.life < 60) { spawnFlame(tx, ty, inst); p.destroy(); } }; bullets.push(p); gameContainer.addChild(p); } function spawnFlame(x, y, inst) { var f = new Container(); f.attachAsset('molotovFlame', { anchorX: 0.5, anchorY: 0.5, alpha: 0.4 }); f.x = x; f.y = y; f.life = 60; f.update = function () { if (--f.life <= 0) { f.destroy(); return; } for (var i = enemies.length - 1; i >= 0; i--) if (dist2(enemies[i], f) < 4900) damageEnemy(enemies[i], inst.dmg); }; gameContainer.addChild(f); } var shurikenRing = []; function ensureShurikenRing(inst) { if (shurikenRing.length !== inst.amount) { shurikenRing.forEach(function (s) { return s.destroy(); }); shurikenRing = []; var n = inst.amount; for (var i = 0; i < n; i++) { var s = new ShuriProj(); s.speed = 0; s.anchorR = i / n * Math.PI * 2; s.update = function () { this.anchorR += 0.15; this.x = player.x + Math.cos(this.anchorR) * WEAPONS.shuriken.range; this.y = player.y + Math.sin(this.anchorR) * WEAPONS.shuriken.range; for (var k = enemies.length - 1; k >= 0; k--) if (this.intersects(enemies[k])) damageEnemy(enemies[k], inst.dmg); }; shurikenRing.push(s); gameContainer.addChild(s); } } } var player, enemies = [], bullets = [], expOrbs = [], joystick, skillSelect = false; var gameContainer = game.addChild(new Container()); player = gameContainer.addChild(new Player()); player.x = 1024; player.y = 1366; joystick = new Joystick(); joystick.x = 0; joystick.y = -200; LK.gui.bottom.addChild(joystick); /* UI */ var levelTxt = new Text2("Level 1", { size: 60, fill: 0xffff00 }); levelTxt.anchor.set(0, 0); LK.gui.top.addChild(levelTxt); var hpTxt = new Text2("HP", { size: 60, fill: 0xff0000 }); hpTxt.anchor.set(1, 0); hpTxt.y = 100; LK.gui.top.addChild(hpTxt); var timerTxt = new Text2("15:00", { size: 80, fill: 0xffffff }); timerTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timerTxt); /* Waves / spawn */ function spawnEnemy(t, x, y) { var e; switch (t) { case 'fast': e = new FastZombie(); break; case 'tank': e = new TankZombie(); break; case 'boss': e = new Boss(); break; default: e = new Enemy(); } e.x = x; e.y = y; enemies.push(e); gameContainer.addChild(e); } var waveN = 1, gameT = 0; function spawnWave() { var cnt = 5 + waveN * 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; var t = 'normal'; if (waveN > 5 && Math.random() < 0.3) t = 'fast'; if (waveN > 10 && Math.random() < 0.2) t = 'tank'; spawnEnemy(t, x, y); } } spawnWave(); /* EXP orb helper */ function dropExpOrb(x, y, val) { var o = new ExpOrb(); o.x = x; o.y = y; o.value = val; expOrbs.push(o); gameContainer.addChild(o); } /* INPUT */ game.down = function (x, y) { if (skillSelect) return; var l = game.toLocal({ x: x, y: y }); if (l.y > 2000) { joystick.active = true; joystick.setPos(0, 0); } }; game.move = function (x, y) { if (!joystick.active || skillSelect) return; var l = LK.gui.bottom.toLocal({ x: x, y: y }); joystick.setPos(l.x - joystick.x, l.y - joystick.y); }; game.up = function () { joystick.reset(); }; /* MAIN UPDATE */ game.update = function () { if (skillSelect) return; gameT++; /* Timer */ var left = 900 - (gameT / 60 | 0); if (left <= 0) { LK.showYouWin(); return; } timerTxt.setText((left / 60 | 0) + ':' + (left % 60 < 10 ? '0' : '') + left % 60); /* Player movement */ if (joystick.active) { player.x += joystick.dirX * player.moveSpeed; player.y += joystick.dirY * player.moveSpeed; } /* Camera */ gameContainer.x = -(player.x - 1024); gameContainer.y = -(player.y - 1366); /* Waves */ if (gameT % 300 === 0) { waveN++; spawnWave(); } if (gameT % 10800 === 0 && enemies.length < 30) spawnEnemy('boss', player.x + 400, player.y); /* Update arrays */ 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(); }); /* Bullet-enemy collision / off-screen cleanup handled inside bullet helpers */ /* Exp absorb */ for (var i = expOrbs.length - 1; i >= 0; i--) { var o = expOrbs[i]; if (dist2(o, player) < player.pickRange * player.pickRange) o.magnet = 10; if (o.intersects && o.intersects(player)) { player.gain(o.value); o.destroy(); expOrbs.splice(i, 1); LK.getSound('pickup').play(); } } /* UI refresh */ hpTxt.setText('HP: ' + player.hp + '/' + player.hpMax); levelTxt.setText('Level ' + player.level); };
===================================================================
--- original.js
+++ change.js
@@ -604,9 +604,12 @@
p.g = 0.3;
p.dmg = 15 * inst.dmg;
p.update = function () {
p.y += p.g;
- BrickProj.parent.update.call(p);
+ // Call the base projectile update method directly to avoid undefined parent.update
+ if (typeof makeProjectile('brick').prototype.update === 'function') {
+ makeProjectile('brick').prototype.update.call(p);
+ }
if (Math.abs(p.x - player.x) > 1200 || Math.abs(p.y - player.y) > 1600) {
p.destroy();
bullets.splice(bullets.indexOf(p), 1);
} else for (var k = enemies.length - 1; k >= 0; k--) if (p.intersects(enemies[k])) damageEnemy(enemies[k], p.dmg);
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