Code edit (9 edits merged)
Please save this source code
User prompt
flash the CrossWeapon's aimArrow and the FireballWeapon's projectileLaunchers white during the launch function
Code edit (1 edits merged)
Please save this source code
User prompt
Fix Bug: 'ReferenceError: tryUpdateLaunchers is not defined' in this line: 'tryUpdateLaunchers(args);' Line Number: 1024
Code edit (14 edits merged)
Please save this source code
User prompt
Fix Bug: 'TypeError: existingEffect.refresh is not a function' in this line: 'existingEffect.refresh({' Line Number: 803
Code edit (5 edits merged)
Please save this source code
User prompt
when a fireballProjectile explodes, it should attach a BurningEffect class to the nearbyEnemies which deals damage to the enemy every second for 2 seconds. The application should be done in the nearbyEnemy foreach loop.
User prompt
when a fireballProjectile explodes, it should attach a BurningEffect class to the nearbyEnemies which deals damage to the enemy every second for 2 seconds
Code edit (1 edits merged)
Please save this source code
Code edit (13 edits merged)
Please save this source code
User prompt
Fix Bug: 'TypeError: args.effects is undefined' in this line: 'args.effects.push(new FireballExplosion(args.foregroundContainer, self.x, self.y, 100));' Line Number: 771
User prompt
when a FireballProjectile impacts an enemy, add all enemies in 100 range to the hitlist and create a FireballExplosion effect
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
The fireballprojectiles enemy for-loop should use the LinkedList foreach instead
User prompt
fireballprojectiles should check in their update function if they collide with an enemy, and deal damage to it and destroy itself
Code edit (5 edits merged)
Please save this source code
User prompt
Fix Bug: 'TypeError: hero is undefined' in this line: 'hero.rotation += rotationSpeed;' Line Number: 82
User prompt
add a new weapon type called FireballWeapon that slowly rotates, firing FireballProjectiles in the direction it's facing.
Code edit (13 edits merged)
Please save this source code
User prompt
RangedEnemies scale back and forth slightly during their update
User prompt
ranged enemies flash black when they attack
Code edit (1 edits merged)
Please save this source code
Code edit (7 edits merged)
Please save this source code
function Node(data) { this.data = data; this.prev = null; this.next = null; } function LinkedList() { this.head = null; this.tail = null; this.length = 0; } LinkedList.prototype.push = function (data) { var node = new Node(data); if (!this.head) { this.head = node; this.tail = node; } else { node.prev = this.tail; this.tail.next = node; this.tail = node; } this.length++; }; LinkedList.prototype.remove = function (node) { if (node.prev) { node.prev.next = node.next; } else { this.head = node.next; } if (node.next) { node.next.prev = node.prev; } else { this.tail = node.prev; } node.prev = null; node.next = null; this.length--; return node.data; }; LinkedList.prototype.popEach = function (callback) { while (this.head) { callback(this.remove(this.head)); } }; LinkedList.prototype.forEach = function (callback) { var node = this.head; while (node) { var next = node.next; callback(node.data, node); node = next; } }; function updateIteration(list, args) { list.forEach(function (item, node) { if (item.update(args)) { item.destroy(); list.remove(node); } }); } function checkBounds(x, y, borderOrBorderX = 0, borderY) { return x < borderOrBorderX || x > 2048 - borderOrBorderX || y < (borderY || borderOrBorderX) || y > 2732 - (borderY || borderOrBorderX); } var FireballWeapon = Container.expand(function (parent) { var self = Container.call(this); parent.addChild(self); self.x = 0; self.y = 0; var rotationSpeed = 0.05; var cooldown = 0; var initialCooldown = 120; self.update = function (args) { if (cooldown > 0) { cooldown--; } else { var hero = args.hero; var direction = hero.rotation; args.projectiles.push(new FireballProjectile(args.game, hero.x, hero.y, { direction: direction })); cooldown = initialCooldown; } self.rotation += rotationSpeed; }; }); var FireballProjectile = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; var projectileAsset = self.createAsset('fireballProjectile', 'Fireball Projectile', .5, .5); var speed = 5; var direction = args.direction; var speedFactorX = Math.cos(direction); var speedFactorY = Math.sin(direction); self.update = function () { self.x += speed * speedFactorX; self.y += speed * speedFactorY; return checkBounds(self.x, self.y, -50); }; }); var Point = Container.expand(function (parent, x, y) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; var collision = self.createAsset('blank', 'Collision', .5, .5); collision.opacity = 1; collision.tint = 0xff0000; collision.width = 1; collision.height = 1; }); var HealthBar = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; var border = self.createAsset('blank', 'Health Bar Border', .5, .5); var bar = LK.getAsset('blank', 'Health Bar', .5, .5); var defaultTint = 0xffffff; var defaultWidth = 100; var defaultHeight = 10; var defaultWeight = 4; self.addChild(bar); bar.width = args.width || defaultWidth; bar.height = args.height || defaultHeight; bar.tint = args.tint || defaultTint; border.width = bar.width + 2 * (args.weight || defaultWeight); border.height = bar.height + 2 * (args.weight || defaultWeight); border.tint = 0x000000; self.updatePercentage = updatePercentage; function updatePercentage(percentage) { bar.scale.x = Math.max(0, percentage); } }); var SectionalContainer = Container.expand(function (parent) { var self = Container.call(this); self.x = 0; self.y = 0; parent.addChild(self); }); var BorderedText = Container.expand(function (string, settings) { var self = Container.call(this); var textList = []; var defaultFill = '#ffffff'; var defaultBorder = '#000000'; var defaultFont = 'bold monospace'; var defaultSize = 50; var defaultWeight = 2; var offsets = [[-1, -1], [-1, 1], [1, 1], [1, -1], [0, 0]]; var borderSettings = { fill: settings.border || defaultBorder, font: settings.font || defaultFont, size: settings.size || defaultSize }; var textSettings = { fill: settings.fill || defaultFill, font: settings.font || defaultFont, size: settings.size || defaultSize }; self.x = settings.x; self.y = settings.y; for (var i = 0; i < offsets.length; i++) { var localSettings = i === offsets.length - 1 ? textSettings : borderSettings; var text = new Text2(string, localSettings); text.x += offsets[i][0] * defaultWeight; text.y += offsets[i][1] * defaultWeight; if (settings.anchor) { text.anchor.set(settings.anchor.x, settings.anchor.y); } textList.push(text); self.addChild(text); } self.setText = function (string) { for (var i = 0; i < textList.length; i++) { textList[i].setText(string); } }; self.setFill = function (newFill) { textList[textList.length - 1].fill = newFill; }; }); var CountdownTimer = Container.expand(function (initialCountdown) { var self = Container.call(this); var countdown = initialCountdown; var ticker = 60; var countdownTxt = new BorderedText('', { size: 60, anchor: { x: .5, y: 0 } }); self.update = update; self.addChild(countdownTxt); adjustLabel(); function update() { ticker -= 1; if (ticker <= 0) { ticker = 60; countdown--; adjustLabel(); if (countdown == 0) { countdownTxt.setFill('#ff0000'); } } return 1 - countdown / initialCountdown; } function adjustLabel() { var minutes = Math.floor(countdown / 60); var seconds = Math.abs(countdown) % 60; var minutesString = (minutes < 10 ? '0' : '') + minutes; var secondsString = (seconds < 10 ? '0' : '') + seconds; countdownTxt.setText(minutesString + ':' + secondsString); } }); var BoonUpgradeButton = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; var fill = args.fill; var hidden = false; var count = 0; var button = self.createAsset('boonButton', 'Boon Upgrade Button', 0.5, 0.4); var countTxt = new BorderedText('0', { fill: '#ff0000', anchor: { x: .5, y: .5 } }); button.on('down', args.callback); self.addChild(countTxt); self.visible = false; self.setHidden = setHidden; self.setCount = setCount; function setHidden(newHidden) { hidden = newHidden; checkHidden(); } function setCount(newCount) { count = newCount; countTxt.setText(newCount); checkHidden(); } function checkHidden() { self.visible = !hidden && count > 0; } }); var BoonSelection = Container.expand(function (boons, type, count, callback) { var self = Container.call(this); var availableBoons = Object.keys(boons).filter(function (boon) { return boons[boon] < 3; }); var selectedBoons = []; if (availableBoons.length <= 3) { selectedBoons = availableBoons; } else { while (selectedBoons.length < 3 && availableBoons.length > 0) { var boonIndex = Math.floor(Math.random() * availableBoons.length); selectedBoons.push(availableBoons.splice(boonIndex, 1)[0]); } } if (selectedBoons.length < 3) { selectedBoons.push(type === 'Minor' ? 'Minor Heal' : 'Full Heal'); } var background = self.createAsset('boonBackground', 'Boon Selection Popup', 0.5, 0.5); var boonMessageTitle = new BorderedText('Choose ' + count, { y: -220, size: 60, anchor: { x: .5, y: 0 } }); background.y = 50; self.addChild(boonMessageTitle); var boonMessageSubtitle = new BorderedText(type + ' Boon' + (count === 1 ? '' : 's'), { y: -150, anchor: { x: .5, y: 0 } }); self.addChild(boonMessageSubtitle); for (var i = 0; i < selectedBoons.length; i++) { var boon = selectedBoons[i]; var boonButton = self.createAsset('boonButton', 'Boon Button', 0.5, 0.4); boonButton.y = i * 120; boonButton.x = -120; boonButton.boon = boon; boonButton.on('down', function () { self.destroy(); callback(this.boon); }); var boonLevel = new BorderedText(boons[boon] !== undefined ? boons[boon] : '∞', { x: boonButton.x, y: boonButton.y, anchor: { x: .5, y: .5 } }); var boonName = new BorderedText(boon, { x: boonButton.x + 60, y: boonButton.y, anchor: { x: 0, y: .5 } }); self.addChild(boonLevel); self.addChild(boonName); } }); var ExperiencePickup = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; var activeDist = 300; var activeDistSqr = activeDist * activeDist; var collectDistance = 80; var collectDistanceSqr = collectDistance * collectDistance; var combineDist = 150; var combineDistSqr = combineDist * combineDist; var experiencePickups = args.experiencePickups; self.experience = args.experience; experiencePickups.forEach(function (experiencePickup, node) { if (args.experiencePickup !== self) { var dx = experiencePickup.x - self.x; var dy = experiencePickup.y - self.y; var distanceSqr = dx * dx + dy * dy; if (distanceSqr <= combineDistSqr) { self.experience += experiencePickups.remove(node).experience; experiencePickup.destroy(); self.x += dx / 2; self.y += dy / 2; } } }); var size = 'small'; if (self.experience > 5) { size = 'medium'; if (self.experience > 10) { size = 'large'; } } var pickupGraphics = self.createAsset(size + 'ExperiencePickup', 'Experience Pickup', .5, .5); var active = false; var speed = 20; self.update = update; function update(args) { var hero = args.hero; var dx = hero.x - self.x; var dy = hero.y - self.y; var distanceSqr = dx * dx + dy * dy; if (distanceSqr <= activeDistSqr) { self.active = true; if (distanceSqr <= collectDistanceSqr) { hero.addExperience(self.experience); return true; } } if (self.active) { var distance = Math.sqrt(distanceSqr); self.x += dx / distance * speed; self.y += dy / distance * speed; } } }); var CrucifixPickup = Container.expand(function (parent, x, y) { var self = Container.call(this); parent.addChild(self); self.collisionPoint = new Point(self); self.x = x; self.y = y; var pickupGraphics = self.createAsset('crucifixPickup', 'Crucifix Pickup', .5, .5); self.update = update; function update(args) { var hero = args.hero; if (hero.collision.intersects(self.collisionPoint)) { args.enemies.popEach(function (enemy) { enemy.destroy(); }); args.enemyProjectiles.popEach(function (enemyProjectile) { enemyProjectile.destroy(); }); args.experiencePickups.forEach(function (experiencePickup) { experiencePickup.active = true; }); LK.effects.flashScreen(0xffffff, 1000); return true; } } }); var HealingPickup = Container.expand(function (parent, x, y) { var self = Container.call(this); parent.addChild(self); self.collisionPoint = new Point(self); self.x = x; self.y = y; var pickupGraphics = self.createAsset('healingPickup', 'Healing Pickup', .5, .5); var healPercentage = 0.1; self.update = update; function update(args) { var hero = args.hero; if (hero.health < hero.healthMax && hero.collision.intersects(self.collisionPoint)) { hero.onHealPercentage(0.1); return true; } } }); var BasicBloodSplatter = Container.expand(function (parent, x, y) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; var splatterGraphics = self.createAsset('bloodSplatter', 'Blood Splatter', .5, .5); var initialLifetime = Math.floor(0.2 * 60); var remainingLifetime = initialLifetime; self.update = update; function update() { if (--remainingLifetime <= 0) { return true; } var lifetime = remainingLifetime / initialLifetime; var newScale = 2 - lifetime; splatterGraphics.alpha = lifetime; splatterGraphics.scale = { x: newScale, y: newScale }; } }); var EnemyProjectile = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; self.collisionPoint = new Point(self); var direction = args.direction; var damage = args.damage; var projectileAsset = self.createAsset('enemyProjectile', 'Enemy Projectile', .5, .5); var speed = 10; var speedFactorX = Math.cos(direction); var speedFactorY = Math.sin(direction); projectileAsset.rotation = direction - 135 / 180 * Math.PI; self.update = update; function update(args) { var hero = args.hero; self.x += speed * speedFactorX; self.y += speed * speedFactorY; if (hero.collision.intersects(self.collisionPoint)) { hero.onTakeDamage(damage); return true; } if (LK.tick % 5) { self.scale.y *= -1; } return checkBounds(self.x, self.y, -50); } }); var RangedEnemy = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.collision = self.createAsset('rangedEnemy', 'Ranged Enemy', .6, .5); self.id = args.id; self.x = x; self.y = y; var healthBar = null; var creationTick = LK.ticks; var borderMin = 50; var borderX = borderMin * 1.1 + Math.random() * 100; var borderY = borderMin * 1.1 + Math.random() * 100; var attackRange = 500 + Math.random() * 500; var attackRangeSqr = attackRange * attackRange; var scaredRange = attackRange / 2; var scaredRangeSqr = scaredRange * scaredRange; var speed = 1.5; var fleeSpeedFactor = 2; var damage = 5; var initialCooldown = 240; var cooldown = initialCooldown; var healthMax = 20 + 60 * args.difficultyScale; var scaleMagnitude = 0.05; var scalePeriod = 20; var health = healthMax; self.update = update; self.onTakeDamage = onTakeDamage; function update(args) { if (health <= 0) { kill(args); return true; } var foregroundContainer = args.foregroundContainer; var midgroundContainer = args.midgroundContainer; var hero = args.hero; var dx = hero.x - self.x; var dy = hero.y - self.y; var distanceSqr = dx * dx + dy * dy; var state; if (checkBounds(self.x, self.y, borderMin)) { state = 'move'; } else { if (distanceSqr < scaredRangeSqr) { state = checkBounds(self.x, self.y, borderX, borderY) ? 'cornered' : 'flee'; } else { state = distanceSqr <= attackRangeSqr ? 'attack' : 'move'; } } var canAttack = false; var speedFactor = 0; switch (state) { case 'move': cooldown -= 0.5; speedFactor = 1; break; case 'flee': cooldown = initialCooldown; speedFactor = -fleeSpeedFactor; break; case 'attack': cooldown--; canAttack = true; break; case 'cornered': cooldown -= 2; canAttack = true; break; } if (speedFactor !== 0) { var distance = Math.sqrt(distanceSqr); self.x += dx / distance * speed * speedFactor; self.y += dy / distance * speed * speedFactor; } if (canAttack && cooldown <= 0) { cooldown = initialCooldown; LK.effects.flashObject(self.collision, 0x000000, 500); args.projectiles.push(new EnemyProjectile(foregroundContainer, self.x, self.y, { direction: Math.atan2(dy, dx), damage })); } var newScale = 1 + Math.sin((LK.ticks - creationTick) / scalePeriod) * scaleMagnitude; self.collision.scale.x = newScale; self.collision.scale.y = newScale; var newParent = self.y <= hero.y ? midgroundContainer : foregroundContainer; if (parent !== newParent) { newParent.addChild(self); parent = newParent; } } function kill(args) { var backgroundContainer = args.backgroundContainer; var experiencePickups = args.experiencePickups; var hero = args.hero; var droppedExperience = 2; for (var k = 0; k <= hero.minorBoonLevels['Luck']; k++) { if (Math.random() < 0.5) { droppedExperience++; } } if (droppedExperience > 0) { var x = self.x + Math.random() * 100 - 50; var y = self.y + Math.random() * 100 - 50; experiencePickups.push(new ExperiencePickup(backgroundContainer, x, y, { experience: droppedExperience, experiencePickups })); } args.effects.push(new BasicBloodSplatter(parent, self.x, self.y)); } function onTakeDamage(takenDamage) { health -= takenDamage; if (health > 0) { if (!healthBar) { healthBar = new HealthBar(self, 0, -self.collision.height / 2 - 20, { tint: 0xaa0000 }); } healthBar.updatePercentage(health / healthMax); LK.effects.flashObject(self.collision, 0xaa0000, 1000); } } }); var BasicEnemy = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.collision = self.createAsset('enemy', 'Basic Enemy', .5, .5); self.id = args.id; self.x = x; self.y = y; var healthBar = null; var damageDistance = 100; var heightDifference = 25; var speed = 2.5; var damage = 10; var initialCooldown = 10; var cooldown = initialCooldown; var bobMagnitude = 2; var bobPeriod = 10; var creationTick = LK.ticks; var parent = parent; var healthMax = 10 + 50 * args.difficultyScale; var health = healthMax; self.update = update; self.onTakeDamage = onTakeDamage; function update(args) { if (health <= 0) { kill(args); return true; } var hero = args.hero; var midgroundContainer = args.midgroundContainer; var foregroundContainer = args.foregroundContainer; var dx = hero.x - self.x; var dy = hero.y + heightDifference - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > damageDistance) { self.x += dx / distance * speed; self.y += dy / distance * speed + Math.sin((LK.ticks - creationTick) / bobPeriod) * bobMagnitude; cooldown = initialCooldown; } else { cooldown -= 1; if (cooldown <= 0) { cooldown = initialCooldown; hero.onTakeDamage(damage); } } var newParent = self.y <= hero.y + heightDifference ? args.midgroundContainer : args.foregroundContainer; if (parent !== newParent) { newParent.addChild(self); parent = newParent; } } function kill(args) { var hero = args.hero; var healthPickups = args.healthPickups; var crucifixPickups = args.crucifixPickups; var experiencePickups = args.experiencePickups; var backgroundContainer = args.backgroundContainer; if (crucifixPickups.length < 1 && Math.random() < Math.sqrt(hero.minorBoonLevels['Luck']) / 100) { crucifixPickups.push(new CrucifixPickup(backgroundContainer, self.x, self.y)); } else { if (healthPickups.length < 3) { for (var k = 0; k <= 1 + hero.minorBoonLevels['Luck']; k++) { if (Math.random() < 0.02) { healthPickups.push(new HealingPickup(backgroundContainer, self.x, self.y)); break; } } } } var droppedExperience = 0; for (var k = 0; k <= 2 + hero.minorBoonLevels['Luck']; k++) { if (Math.random() < 0.3) { droppedExperience++; } } if (droppedExperience > 0) { var x = self.x + Math.random() * 100 - 50; var y = self.y + Math.random() * 100 - 50; experiencePickups.push(new ExperiencePickup(backgroundContainer, x, y, { experience: droppedExperience, experiencePickups })); } args.effects.push(new BasicBloodSplatter(parent, self.x, self.y)); } function onTakeDamage(takenDamage) { health -= takenDamage; if (health > 0) { if (!healthBar) { healthBar = new HealthBar(self, 0, -self.collision.height / 2 - 30, { tint: 0xaa0000 }); } healthBar.updatePercentage(health / healthMax); LK.effects.flashObject(self.collision, 0xaa0000, 1000); } } }); var EnemySpawner = Container.expand(function (parent) { var self = Container.call(this); parent.addChild(self); var border = -50; var width = 2048; var height = 2732; var borderedWidth = width - 2 * border; var borderedHeight = height - 2 * border; var enemyIdCounter = -1; var spawnRate = 60; var spawnLimit = 40; var spawnTimer = spawnRate; self.update = update; function update(args) { if (args.enemies.length < spawnLimit) { spawnTimer--; if (spawnTimer <= 0) { spawnTimer = Math.max(15, spawnRate - Math.floor(45 * args.difficultyScale)); spawnEnemy(args); } } } function spawnEnemy(args) { var difficultyScale = args.difficultyScale; var side = Math.floor(Math.random() * 4); var distance = Math.random(); var x, y; switch (side) { case 0: x = borderedWidth * distance; y = border; break; case 1: x = width - border; y = borderedHeight * distance; break; case 2: x = borderedWidth * distance; y = height - border; break; case 3: x = border; y = borderedHeight * distance; break; } var enemyType = difficultyScale >= 0.2 && Math.random() < Math.min(0.4, difficultyScale / 2) ? RangedEnemy : BasicEnemy; args.enemies.push(new enemyType(args.midgroundContainer, x, y, { id: (++enemyIdCounter).toString(), difficultyScale })); } }); var CrossProjectile = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.x = x; self.y = y; self.collisionPoint = new Point(self); var direction = args.direction; var damage = args.damage; var linger = args.linger; var range = args.range; var projectileAsset = self.createAsset('crossProjectile', 'Projectile Asset', .5, .5); var hitMap = {}; var initialSpeed = 30; var speed = initialSpeed; var speedFactorX = Math.cos(direction); var speedFactorY = Math.sin(direction); var speedDecrement = 1; var destroyRange = -1000; var growth = 1; var growthRate = args.growthRate; var initialScale = args.scale; var currentScale = initialScale; var scaleDamageFactor = 0.1; self.rotation = Math.random() * Math.PI * 2; self.scale = { x: currentScale, y: currentScale }; self.update = update; function update(args) { var hero = args.hero; var enemies = args.enemies; self.x += speed * speedFactorX; self.y += speed * speedFactorY; self.rotation += 0.2; if (growthRate > 0) { growth += growthRate; currentScale = initialScale * growth; self.scale = { x: currentScale, y: currentScale }; } if (range <= 0) { if (speed > -initialSpeed) { if (speed <= 0 && linger > 0) { speed = 0; linger--; } else { speed -= speedDecrement; } } else { speed = -initialSpeed; } } range -= Math.abs(speed); var tick = LK.ticks; enemies.forEach(function (enemy) { var lastHitTick = hitMap[enemy.id]; if (!lastHitTick || tick - lastHitTick > 10) { if (enemy.collision.intersects(self)) { hitMap[enemy.id] = tick; enemy.onTakeDamage(damage * (1 + (currentScale - 1) * scaleDamageFactor)); } } }); return checkBounds(self.x, self.y, destroyRange) || hero.collision.intersects(self.collisionPoint) && speed < 0; } }); var CrossWeapon = Container.expand(function (parent) { var self = Container.call(this); parent.addChild(self); self.x = 0; self.y = 0; var initialCooldown = 120; var cooldown = self.initialCooldown; var spreadIncrement = 20 * Math.PI / 180; self.update = update; function update(args) { var hero = args.hero; if (cooldown > 0) { cooldown--; } else { launch(args); var attackSpeed = 1 + 0.25 * hero.minorBoonLevels['Rearm']; cooldown = initialCooldown / attackSpeed; } } function launch(args) { var hero = args.hero; var game = args.game; var projectiles = args.projectiles; var scale = 1 + 0.35 * hero.minorBoonLevels['Scale']; var range = 200 + 100 * hero.minorBoonLevels['Range']; var damage = 15 + 10 * hero.minorBoonLevels['Damage']; var linger = 0 + 15 * hero.minorBoonLevels['Duration']; var growthRate = 0.15 * hero.majorBoonLevels['Growth'] / 60; var spreadCount = 1 + hero.majorBoonLevels['Split']; var dx = hero.shootPos.x - hero.x; var dy = hero.shootPos.y - hero.y; var baseAngle = Math.atan2(dy, dx) - spreadCount * spreadIncrement / 2; for (var i = 0; i < spreadCount; i++) { var spreadAngle = spreadIncrement / 2 * (spreadCount <= 1 ? 1 : Math.random() - 0.5); var direction = baseAngle + i * spreadIncrement + spreadAngle; projectiles.push(new CrossProjectile(game, hero.x, hero.y, { linger: linger + Math.floor(10 * Math.random()), range: range * (0.9 + 0.2 * Math.random()), growthRate, direction, damage, scale })); } } }); var Hero = Container.expand(function (parent, x, y, args) { var self = Container.call(this); parent.addChild(self); self.collision = self.createAsset('hero', 'Hero character', .5, .5); self.x = x; self.y = y; var progressBar = args.progressBar; var onLevelUp = args.onLevelUp; self.healthMax = 100; self.health = self.healthMax; var experience = 0; var level = 1; var levelRequirement = 20; var healthBar = new HealthBar(self, 0, -self.height / 2 - 10, { tint: 0x0fa0ff }); self.minorBoonLevels = { 'Luck': 0, 'Scale': 0, 'Range': 0, 'Damage': 0, 'Rearm': 0, 'Duration': 0, 'Health': 0 }; self.majorBoonLevels = { 'Growth': 0, 'Split': 0 }; self.shootPos = { x, y }; self.update = update; self.addExperience = addExperience; self.onTakeDamage = onTakeDamage; self.onHealPercentage = onHealPercentage; function update(args) { var game = args.game; if (self.targetPos) { var dx = self.targetPos.x - self.x; var dy = self.targetPos.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * 10; self.y += dy / distance * 10; } else { self.x = self.targetPos.x; self.y = self.targetPos.y; self.targetPos = null; } } if (self.shootPos.x < self.x) { self.scale.x = -1; } else { self.scale.x = 1; } } function addExperience(amount) { experience += amount; if (experience >= levelRequirement) { level++; experience -= levelRequirement; levelRequirement = Math.floor(levelRequirement * 1.2); onLevelUp(level); } progressBar.scale.x = experience / levelRequirement; } function onTakeDamage(amount) { self.health -= amount; healthBar.updatePercentage(self.health / self.healthMax); LK.effects.flashObject(self.collision, 0xaa0000, 1000); if (self.health <= 0) { LK.effects.flashScreen(0xaa0000, 1000); LK.showGameOver(); } } function onHealPercentage(percentage) { if (percentage > 0) { self.health = Math.min(self.healthMax, self.health + self.healthMax * percentage); LK.effects.flashObject(self.collision, 0x0fa0ff, 1000); } healthBar.updatePercentage(self.health / self.healthMax); } }); var Game = Container.expand(function () { var self = Container.call(this); var isPaused = false; var minorBoonCount = 0; var majorBoonCount = 0; var grass = LK.getAsset('grass', 'Grass Background', 0, 0); var aimArrow = LK.getAsset('arrow', 'Directional Arrow', -2.5, 0.5); var canMove = false; var difficultyScale = 0; var upgradeButton = new BoonUpgradeButton(LK.gui.topRight, -80, 60, { fill: '#ff0000', callback: function () { if (minorBoonCount + majorBoonCount > 0) { showBoonSelection(); } } }); var levelTxt = new BorderedText('Level 1 • XP', { anchor: { x: 1.0, y: 0 }, size: 80 }); var progressBarBorder = LK.getAsset('progressBarBorder', 'Progress Bar Border', 0, .5); var progressBar = LK.getAsset('progressBar', 'Progress Bar', 0, .5); var enemySpawner = new EnemySpawner(self, difficultyScale); var heroProjectiles = new LinkedList(); var enemyProjectiles = new LinkedList(); var weapons = new LinkedList(); var enemies = new LinkedList(); var healthPickups = new LinkedList(); var crucifixPickups = new LinkedList(); var experiencePickups = new LinkedList(); var effects = new LinkedList(); var countdownTimer = new CountdownTimer(300); LK.gui.topCenter.addChild(countdownTimer); LK.gui.topCenter.addChild(progressBarBorder); LK.gui.topCenter.addChild(progressBar); LK.gui.topCenter.addChild(levelTxt); countdownTimer.y = levelTxt.height + 10; progressBarBorder.x = 20; progressBarBorder.y = levelTxt.y + levelTxt.height / 2; progressBar.x = 24; progressBar.y = levelTxt.y + levelTxt.height / 2; progressBar.scale.x = 0; grass.width = 2048; grass.height = 2732; self.addChild(grass); self.addChild(aimArrow); var backgroundContainer = new SectionalContainer(self); var midgroundContainer = new SectionalContainer(self); var hero = new Hero(self, 2048 / 2, 2732 / 2, { progressBar, onLevelUp }); weapons.push(new FireballWeapon(self)); var foregroundContainer = new SectionalContainer(self); stage.on('down', function (obj) { canMove = true; hero.targetPos = obj.event.getLocalPosition(self); }); stage.on('up', function (obj) { canMove = false; hero.targetPos = null; }); stage.on('move', function (obj) { if (!isPaused) { if (canMove) { hero.targetPos = obj.event.getLocalPosition(self); } hero.shootPos = obj.event.getLocalPosition(self); if (hero.shootPos.x < hero.x) { hero.scale.x = -1; } else { hero.scale.x = 1; } } }); LK.on('tick', function () { if (!isPaused) { difficultyScale = countdownTimer.update(); hero.update({ game: self }); aimArrow.x = hero.x; aimArrow.y = hero.y; aimArrow.rotation = Math.atan2(hero.shootPos.y - hero.y, hero.shootPos.x - hero.x); updateIteration(weapons, { projectiles: heroProjectiles, game: self, hero }); updateIteration(heroProjectiles, { enemies, hero }); updateIteration(enemyProjectiles, { hero }); enemySpawner.update({ midgroundContainer, difficultyScale, enemies }); updateIteration(enemies, { projectiles: enemyProjectiles, backgroundContainer, midgroundContainer, foregroundContainer, experiencePickups, crucifixPickups, healthPickups, effects, hero }); updateIteration(effects); updateIteration(experiencePickups, { hero }); updateIteration(healthPickups, { hero }); updateIteration(crucifixPickups, { experiencePickups, enemyProjectiles, enemies, hero }); } }); function showBoonSelection() { var boonSelection; if (minorBoonCount) { boonSelection = new BoonSelection(hero.minorBoonLevels, 'Minor', minorBoonCount, function (boon) { minorBoonCount--; if (!checkBoonActions(boon)) { hero.minorBoonLevels[boon]++; upgradeButton.setCount(minorBoonCount + majorBoonCount); } showBoonSelection(); }); } else { if (majorBoonCount) { boonSelection = new BoonSelection(hero.majorBoonLevels, 'Major', majorBoonCount, function (boon) { majorBoonCount--; if (!checkBoonActions(boon)) { hero.majorBoonLevels[boon]++; upgradeButton.setCount(minorBoonCount + majorBoonCount); } showBoonSelection(); }); } } if (boonSelection) { isPaused = true; LK.gui.center.addChild(boonSelection); } else { isPaused = false; } upgradeButton.setHidden(isPaused); } function checkBoonActions(boon) { if (boon === 'Minor Heal') { hero.onHealPercentage(0.1); return true; } if (boon === 'Full Heal') { hero.onHealPercentage(1); return true; } if (boon === 'Health') { hero.healthMax += 30; hero.onHealPercentage(0); return false; } } function onLevelUp(level) { levelTxt.setText('Level ' + level + ' • XP'); if (level % 5) { minorBoonCount++; } else { majorBoonCount++; } upgradeButton.setCount(minorBoonCount + majorBoonCount); } });
===================================================================
--- original.js
+++ change.js
@@ -78,11 +78,9 @@
direction: direction
}));
cooldown = initialCooldown;
}
- if (hero) {
- hero.rotation += rotationSpeed;
- }
+ self.rotation += rotationSpeed;
};
});
var FireballProjectile = Container.expand(function (parent, x, y, args) {
var self = Container.call(this);
pixel art cross with blue accents Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a white orb. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a white orb with a halo. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a pulsating white heart with a halo. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a dark goo projectile with red highlights. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art tall blue fireball. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of an evil fantasy sword facing downward. Minor red details. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
backgroundAmbient
Sound effect
heroHealed
Sound effect
pickupExperience
Sound effect
heroLeveled
Sound effect
weaponCrossImpact
Sound effect
heroImpact
Sound effect
enemyDeath
Sound effect
pickupWeapon
Sound effect
pickupCrucifix
Sound effect
weaponCrossLaunch
Sound effect
heroDeath
Sound effect
enemyRoar
Sound effect
clockChime
Sound effect