Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: heightDifference is not defined' in or related to this line: 'var dy = hero.y + heightDifference - self.y;' Line Number: 97
Code edit (16 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: self is undefined' in or related to this line: 'var updateBase = self.update;' Line Number: 117
User prompt
Please fix the bug: 'ReferenceError: WeaponFireball is not defined' in or related to this line: 'startingWeapons.push(backgroundContainer.addChild(new PickupWeapon({' Line Number: 525
Code edit (2 edits merged)
Please save this source code
User prompt
add a hero asset with anchor (0.5, 1.0) to the Hero class
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: tint is not defined' in or related to this line: 'var bar = self.attachAsset('shapeBox', {' Line Number: 73
Code edit (7 edits merged)
Please save this source code
User prompt
add an outlineSmall asset to the joystickKnob and an outlineLarge asset to the joystick
Code edit (2 edits merged)
Please save this source code
User prompt
add a new sorting container (inheriting from Container) that has an update function that sorts it's children array by their ascending y value
Code edit (3 edits merged)
Please save this source code
User prompt
Replace all usages of the 'blank' asset with the 'shapeBox' asset
User prompt
Migrate to the latest version of LK
Code edit (1 edits merged)
Please save this source code
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
===================================================================
--- original.js
+++ change.js
@@ -1,104 +1,240 @@
-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;
+/****
+* Classes
+****/
+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.attachAsset('bloodSplatter', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var initialLifetime = Math.floor(0.2 * 60);
+ var remainingLifetime = initialLifetime;
+ self._update_migrated = _update_migrated;
+ function _update_migrated() {
+ if (--remainingLifetime <= 0) {
+ return true;
+ }
+ var lifetime = remainingLifetime / initialLifetime;
+ var newScale = 2 - lifetime;
+ splatterGraphics.alpha = lifetime;
+ splatterGraphics.scale.x = newScale;
+ splatterGraphics.scale.y = newScale;
}
- this.length++;
-};
-LinkedList.prototype.remove = function (node) {
- if (node.prev) {
- node.prev.next = node.next;
- } else {
- this.head = node.next;
+});
+var BasicEnemy = Container.expand(function (parent, x, y, args) {
+ var self = Container.call(this);
+ parent.addChild(self);
+ self.collision = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.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_migrated = _update_migrated;
+ self.onTakeDamage = onTakeDamage;
+ function _update_migrated(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--;
+ 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;
+ }
}
- if (node.next) {
- node.next.prev = node.prev;
- } else {
- this.tail = node.prev;
+ 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: experiencePickups
+ }));
+ }
+ args.effects.push(new BasicBloodSplatter(parent, self.x, self.y));
}
- node.prev = null;
- node.next = null;
- this.length--;
- return node.data;
-};
-LinkedList.prototype.popEach = function (callback) {
- while (this.head) {
- callback(this.remove(this.head));
+ 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);
+ }
}
-};
-LinkedList.prototype.forEach = function (callback) {
- var node = this.head;
- while (node) {
- callback(node.data, node);
- node = node.next;
+});
+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]);
+ }
}
-};
-function updateIteration(list, args) {
- list.forEach(function (item, node) {
- if (item.update(args)) {
- list.remove(node).destroy();
+ if (selectedBoons.length < 3) {
+ selectedBoons.push(type === 'Minor' ? 'Minor Heal' : 'Full Heal');
+ }
+ var background = self.attachAsset('boonBackground', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var boonMessageTitle = new BorderedText('Choose ' + count, {
+ y: -220,
+ size: 60,
+ anchor: {
+ x: .5,
+ y: 0
}
});
-}
-function checkBounds(x, y, borderOrBorderX = 0, borderY) {
- return x < borderOrBorderX || x > 2048 - borderOrBorderX || y < (borderY || borderOrBorderX) || y > 2732 - (borderY || borderOrBorderX);
-}
-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;
+ 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.attachAsset('boonButton', {
+ anchorX: 0.5,
+ anchorY: 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 HealthBar = Container.expand(function (parent, x, y, args) {
+var BoonUpgradeButton = 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 fill = args.fill;
+ var hidden = false;
+ var count = 0;
+ var button = self.attachAsset('boonButton', {
+ anchorX: 0.5,
+ anchorY: 0.4
+ });
+ var countTxt = new BorderedText('0', {
+ fill: '#ff0000',
+ anchor: {
+ x: .5,
+ y: .5
+ }
+ });
+ button.on('down', function (x, y, obj) {
+ obj.event = obj;
+ args.callback(obj);
+ });
+ 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 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';
@@ -138,8 +274,48 @@
self.setFill = function (newFill) {
textList[textList.length - 1].fill = newFill;
};
});
+var BurningEffect = Container.expand(function (parent, x, y, args) {
+ var self = Container.call(this);
+ parent.addChild(self);
+ parent.burningEffect = self;
+ self.refresh = refresh;
+ self._update_migrated = _update_migrated;
+ self.x = x;
+ self.y = y;
+ self.attachAsset('burningGraphics', {
+ anchorX: 0.5,
+ anchorY: 0.65
+ });
+ var interval = args.interval;
+ var duration = args.duration;
+ var damagePerInterval = args.damagePerSecond * interval / 60;
+ var lifetime = 0;
+ var baseAlpha = 0.5;
+ function _update_migrated() {
+ if (parent.health <= 0) {
+ parent.burningEffect = undefined;
+ return true;
+ }
+ lifetime++;
+ var flair = lifetime % interval;
+ if (flair === 0) {
+ parent.onTakeDamage(damagePerInterval);
+ self.scale.x *= 1;
+ }
+ if (lifetime >= duration) {
+ parent.burningEffect = undefined;
+ return true;
+ }
+ self.alpha = (baseAlpha + flair / interval * (1 - baseAlpha)) * baseAlpha;
+ }
+ function refresh(args) {
+ lifetime = 0;
+ damagePerInterval = args.damagePerSecond * interval / 60;
+ duration = args.duration;
+ }
+});
var CountdownTimer = Container.expand(function (initialCountdown) {
var self = Container.call(this);
var countdown = initialCountdown;
var ticker = 60;
@@ -149,12 +325,12 @@
x: .5,
y: 0
}
});
- self.update = update;
+ self._update_migrated = _update_migrated;
self.addChild(countdownTxt);
adjustLabel();
- function update() {
+ function _update_migrated() {
ticker -= 1;
if (ticker <= 0) {
ticker = 60;
countdown--;
@@ -172,173 +348,180 @@
var secondsString = (seconds < 10 ? '0' : '') + seconds;
countdownTxt.setText(minutesString + ':' + secondsString);
}
});
-var BoonUpgradeButton = Container.expand(function (parent, x, y, args) {
+var CrossProjectile = 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
- }
+ self.collisionPoint = new Point(self);
+ var direction = args.direction;
+ var damage = args.damage;
+ var linger = args.linger;
+ var range = args.range;
+ var projectileAsset = self.attachAsset('crossProjectile', {
+ anchorX: 0.5,
+ anchorY: 0.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]);
+ 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_migrated = _update_migrated;
+ function _update_migrated(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;
+ self.scale.y = currentScale;
}
- }
- 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
+ if (range <= 0) {
+ if (speed > -initialSpeed) {
+ if (speed <= 0 && linger > 0) {
+ speed = 0;
+ linger--;
+ } else {
+ speed -= speedDecrement;
+ }
+ } else {
+ speed = -initialSpeed;
+ }
}
- });
- 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
+ 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));
+ }
}
});
- var boonName = new BorderedText(boon, {
- x: boonButton.x + 60,
- y: boonButton.y,
- anchor: {
- x: 0,
- y: .5
- }
- });
- self.addChild(boonLevel);
- self.addChild(boonName);
+ return checkBounds(self.x, self.y, destroyRange) || hero.collision.intersects(self.collisionPoint) && speed < 0;
}
});
-var ExperiencePickup = Container.expand(function (parent, x, y, args) {
+var CrossWeapon = Container.expand(function (parent, x, y, args) {
var self = Container.call(this);
parent.addChild(self);
+ self.activate = activate;
+ self._update_migrated = _update_migrated;
+ self.active = false;
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 weaponGraphics = self.attachAsset('crossProjectile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var collisionPoint = new Point(self);
+ var aimArrow;
+ var initialCooldown = 120;
+ var cooldown = initialCooldown;
+ var splitIncrement = 20 * Math.PI / 180;
+ weaponGraphics.scale.x = 1.25;
+ weaponGraphics.scale.y = 1.25;
+ weaponGraphics.rotation = 0.1;
+ function _update_migrated(args) {
+ var hero = args.hero;
+ if (self.active) {
+ if (cooldown > 0) {
+ cooldown--;
+ } else {
+ launch(args);
+ var attackSpeed = 1 + 0.25 * hero.minorBoonLevels['Rearm'];
+ cooldown = initialCooldown / attackSpeed;
}
+ aimArrow.x = hero.x;
+ aimArrow.y = hero.y;
+ aimArrow.rotation = Math.atan2(hero.shootPos.y - hero.y, hero.shootPos.x - hero.x);
+ } else {
+ var weaponScale = 1.25 + Math.sin(LK.ticks / 10) * 0.1;
+ weaponGraphics.scale.x = weaponScale;
+ weaponGraphics.scale.y = weaponScale;
+ if (hero.collision.intersects(collisionPoint)) {
+ activate(args);
+ }
}
- });
- 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) {
+ function activate(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;
+ var weapons = args.weapons;
+ aimArrow = args.foregroundContainer.createAsset('arrow', 'Directional Arrow', -2.5, 0.5);
+ hero.addChild(self);
+ self.active = true;
+ self.x = 0;
+ self.y = 0;
+ weaponGraphics.y = 20;
+ weaponGraphics.scale.x = 0.5;
+ weaponGraphics.scale.y = 0.5;
+ weaponGraphics.rotation = 1.2;
+ collisionPoint.destroy();
+ weapons.forEach(function (weapon, node) {
+ if (!weapon.active) {
+ weapons.remove(node).destroy();
}
+ });
+ }
+ 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 splitCount = 1 + hero.majorBoonLevels['Split'];
+ var dx = hero.shootPos.x - hero.x;
+ var dy = hero.shootPos.y - hero.y;
+ var baseAngle = Math.atan2(dy, dx) - splitCount * splitIncrement / 2;
+ LK.effects.flashObject(aimArrow, 0x0fa0ff, 1000);
+ LK.effects.flashObject(weaponGraphics, 0x0fa0ff, 1000);
+ for (var i = 0; i < splitCount; i++) {
+ var splitAngle = splitIncrement / 2 * (splitCount <= 1 ? 1 : Math.random() - 0.5);
+ var direction = baseAngle + i * splitIncrement + splitAngle;
+ 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: growthRate,
+ direction: direction,
+ damage: damage,
+ scale: scale
+ }));
}
- 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 pickupGraphics = self.attachAsset('crucifixPickup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self._update_migrated = _update_migrated;
+ function _update_migrated(args) {
var hero = args.hero;
if (hero.collision.intersects(self.collisionPoint)) {
args.enemies.popEach(function (enemy) {
enemy.destroy();
@@ -353,60 +536,26 @@
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;
- splatterGraphics.scale.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 projectileAsset = self.attachAsset('enemyProjectile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
var speed = 10;
var speedFactorX = Math.cos(direction);
var speedFactorY = Math.sin(direction);
projectileAsset.rotation = direction - 45 / 180 * Math.PI;
- self.update = update;
- function update(args) {
+ self._update_migrated = _update_migrated;
+ function _update_migrated(args) {
var hero = args.hero;
self.x += speed * speedFactorX;
self.y += speed * speedFactorY;
if (hero.collision.intersects(self.collisionPoint)) {
@@ -420,224 +569,8 @@
}
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 = 1.5;
- 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--;
- 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;
@@ -648,10 +581,10 @@
var enemyIdCounter = -1;
var spawnRate = 60;
var spawnLimit = 40;
var spawnTimer = spawnRate;
- self.update = update;
- function update(args) {
+ self._update_migrated = _update_migrated;
+ function _update_migrated(args) {
if (args.enemies.length < spawnLimit) {
spawnTimer--;
if (spawnTimer <= 0) {
spawnTimer = Math.max(15, spawnRate - Math.floor(45 * args.difficultyScale));
@@ -684,62 +617,87 @@
}
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
+ difficultyScale: difficultyScale
}));
}
});
-var BurningEffect = Container.expand(function (parent, x, y, args) {
+var ExperiencePickup = Container.expand(function (parent, x, y, args) {
var self = Container.call(this);
parent.addChild(self);
- parent.burningEffect = self;
- self.refresh = refresh;
- self.update = update;
self.x = x;
self.y = y;
- self.createAsset('burningGraphics', 'Burning Graphics', .5, .65);
- var interval = args.interval;
- var duration = args.duration;
- var damagePerInterval = args.damagePerSecond * interval / 60;
- var lifetime = 0;
- var baseAlpha = 0.5;
- function update() {
- if (parent.health <= 0) {
- parent.burningEffect = undefined;
- return true;
+ 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;
+ }
}
- lifetime++;
- var flair = lifetime % interval;
- if (flair === 0) {
- parent.onTakeDamage(damagePerInterval);
- self.scale.x *= 1;
+ });
+ var size = 'small';
+ if (self.experience > 5) {
+ size = 'medium';
+ if (self.experience > 10) {
+ size = 'large';
}
- if (lifetime >= duration) {
- parent.burningEffect = undefined;
- return true;
+ }
+ var pickupGraphics = self.createAsset(size + 'ExperiencePickup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var active = false;
+ var speed = 20;
+ self._update_migrated = _update_migrated;
+ function _update_migrated(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;
+ }
}
- self.alpha = (baseAlpha + flair / interval * (1 - baseAlpha)) * baseAlpha;
+ if (self.active) {
+ var distance = Math.sqrt(distanceSqr);
+ self.x += dx / distance * speed;
+ self.y += dy / distance * speed;
+ }
}
- function refresh(args) {
- lifetime = 0;
- damagePerInterval = args.damagePerSecond * interval / 60;
- duration = args.duration;
- }
});
var FireballExplosion = Container.expand(function (parent, x, y, args) {
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
- var explosionGraphics = self.createAsset('fireballExplosion', 'Fireball Explosion', .5, .5);
+ var explosionGraphics = self.attachAsset('fireballExplosion', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
var initialScale = args.scale;
var scale = initialScale;
var maxScale = initialScale + 1;
var scaleRate = 0.075;
- self.update = update;
+ self._update_migrated = _update_migrated;
self.rotation = args.rotation;
- function update() {
+ function _update_migrated() {
scale += scaleRate;
if (scale >= maxScale) {
self.destroy();
return true;
@@ -753,9 +711,12 @@
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
- var projectileAsset = self.createAsset('fireballProjectile', 'Fireball Projectile', .5, .5);
+ var projectileAsset = self.attachAsset('fireballProjectile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
var hitMap = {};
var speed = 15;
var baseRadius = 150;
var burnInterval = 15;
@@ -773,9 +734,9 @@
self.scale = {
x: currentScale,
y: currentScale
};
- self.update = function (args) {
+ self._update_migrated = function (args) {
var enemies = args.enemies;
var effects = args.effects;
self.x += speed * speedFactorX;
self.y += speed * speedFactorY;
@@ -801,16 +762,16 @@
hitMap[nearbyEnemy.id] = true;
var existingEffect = nearbyEnemy.burningEffect;
if (existingEffect) {
existingEffect.refresh({
- damagePerSecond,
- duration
+ damagePerSecond: damagePerSecond,
+ duration: duration
});
} else {
effects.push(new BurningEffect(nearbyEnemy, 0, 0, {
interval: burnInterval,
- damagePerSecond,
- duration
+ damagePerSecond: damagePerSecond,
+ duration: duration
}));
}
}
}
@@ -832,9 +793,12 @@
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
- var weaponGraphics = self.createAsset('fireballWeapon', 'Weapon Asset', .5, .5);
+ var weaponGraphics = self.attachAsset('fireballWeapon', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
var collisionPoint = new Point(self);
var projectileLaunchers = [];
var initialCooldown = 120;
var cooldown = initialCooldown;
@@ -844,10 +808,10 @@
var projectileOffset = 150;
weaponGraphics.scale.x = 1.25;
weaponGraphics.scale.y = 1.25;
self.active = false;
- self.update = update;
- function update(args) {
+ self._update_migrated = _update_migrated;
+ function _update_migrated(args) {
var hero = args.hero;
if (self.active) {
tryUpdateLaunchers(args);
self.x = hero.x;
@@ -858,9 +822,9 @@
launch(args);
cooldown = initialCooldown - 20 * hero.minorBoonLevels['Rearm'];
}
} else {
- var weaponScale = 1.25 + Math.sin((LK.ticks + 2.5) / 10) * 0.1;
+ var weaponScale = 1.25 + Math.sin(LK.ticks / 10) * -0.1;
weaponGraphics.scale.x = weaponScale;
weaponGraphics.scale.y = weaponScale;
if (hero.collision.intersects(collisionPoint)) {
activate(args);
@@ -892,20 +856,20 @@
var duration = 60 + 45 * hero.minorBoonLevels['Duration'];
var growthRate = 0.15 * hero.majorBoonLevels['Growth'] / 60;
var angle = 2 * Math.PI / projectileLaunchers.length;
var angleOffset = rotationTicks % (2 * cooldown) === 0 ? 0 : angle / 2;
- for (let i = 0; i < projectileLaunchers.length; i++) {
+ for (var i = 0; i < projectileLaunchers.length; i++) {
LK.effects.flashObject(projectileLaunchers[i], 0x0fa0ff, 1000);
var direction = angleOffset + angle * i - Math.PI / 2;
var projectileX = hero.x + Math.cos(direction) * projectileOffset;
var projectileY = hero.y + Math.sin(direction) * projectileOffset;
projectiles.push(new FireballProjectile(game, projectileX, projectileY, {
- growthRate,
- direction,
- duration,
- damage,
- pierce,
- scale
+ growthRate: growthRate,
+ direction: direction,
+ duration: duration,
+ damage: damage,
+ pierce: pierce,
+ scale: scale
}));
}
}
function tryUpdateLaunchers(args) {
@@ -915,173 +879,74 @@
rotationTicks = 0;
var angle = 2 * Math.PI / count;
for (var i = 0; i < count; i++) {
if (i == projectileLaunchers.length) {
- projectileLaunchers.push(self.createAsset('fireballWeapon', 'Weapon Asset', 0.5, 2));
+ projectileLaunchers.push(self.attachAsset('fireballWeapon', {
+ anchorX: 0.5,
+ anchorY: 2
+ }));
}
projectileLaunchers[i].rotation = angle * i;
}
}
}
});
-var CrossProjectile = Container.expand(function (parent, x, y, args) {
+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;
- 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 pickupGraphics = self.attachAsset('healingPickup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var healPercentage = 0.1;
+ self._update_migrated = _update_migrated;
+ function _update_migrated(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;
- self.scale.y = currentScale;
+ if (hero.health < hero.healthMax && hero.collision.intersects(self.collisionPoint)) {
+ hero.onHealPercentage(0.1);
+ return true;
}
- 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, x, y, args) {
+var HealthBar = Container.expand(function (parent, x, y, args) {
var self = Container.call(this);
parent.addChild(self);
- self.activate = activate;
- self.update = update;
- self.active = false;
self.x = x;
self.y = y;
- var weaponGraphics = self.createAsset('crossProjectile', 'Cross Weapon Asset', .5, .5);
- var collisionPoint = new Point(self);
- var aimArrow;
- var initialCooldown = 120;
- var cooldown = initialCooldown;
- var splitIncrement = 20 * Math.PI / 180;
- weaponGraphics.scale.x = 1.25;
- weaponGraphics.scale.y = 1.25;
- weaponGraphics.rotation = 0.1;
- function update(args) {
- var hero = args.hero;
- if (self.active) {
- if (cooldown > 0) {
- cooldown--;
- } else {
- launch(args);
- var attackSpeed = 1 + 0.25 * hero.minorBoonLevels['Rearm'];
- cooldown = initialCooldown / attackSpeed;
- }
- aimArrow.x = hero.x;
- aimArrow.y = hero.y;
- aimArrow.rotation = Math.atan2(hero.shootPos.y - hero.y, hero.shootPos.x - hero.x);
- } else {
- var weaponScale = 1.25 + Math.sin(LK.ticks / 10) * 0.1;
- weaponGraphics.scale.x = weaponScale;
- weaponGraphics.scale.y = weaponScale;
- if (hero.collision.intersects(collisionPoint)) {
- activate(args);
- }
- }
+ var border = self.attachAsset('blank', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var bar = LK.getAsset('blank', {
+ anchorX: 0.5,
+ anchorY: 0.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);
}
- function activate(args) {
- var hero = args.hero;
- var weapons = args.weapons;
- aimArrow = args.foregroundContainer.createAsset('arrow', 'Directional Arrow', -2.5, 0.5);
- hero.addChild(self);
- self.active = true;
- self.x = 0;
- self.y = 0;
- weaponGraphics.y = 20;
- weaponGraphics.scale.x = 0.5;
- weaponGraphics.scale.y = 0.5;
- weaponGraphics.rotation = 1.2;
- collisionPoint.destroy();
- weapons.forEach(function (weapon, node) {
- if (!weapon.active) {
- weapons.remove(node).destroy();
- }
- });
- }
- 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 splitCount = 1 + hero.majorBoonLevels['Split'];
- var dx = hero.shootPos.x - hero.x;
- var dy = hero.shootPos.y - hero.y;
- var baseAngle = Math.atan2(dy, dx) - splitCount * splitIncrement / 2;
- LK.effects.flashObject(aimArrow, 0x0fa0ff, 1000);
- LK.effects.flashObject(weaponGraphics, 0x0fa0ff, 1000);
- for (var i = 0; i < splitCount; i++) {
- var splitAngle = splitIncrement / 2 * (splitCount <= 1 ? 1 : Math.random() - 0.5);
- var direction = baseAngle + i * splitIncrement + splitAngle;
- 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.collision = self.attachAsset('hero', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
self.x = x;
self.y = y;
var progressBar = args.progressBar;
var onLevelUp = args.onLevelUp;
@@ -1106,16 +971,16 @@
'Growth': 0,
'Split': 0
};
self.shootPos = {
- x,
- y
+ x: x,
+ y: y
};
- self.update = update;
+ self._update_migrated = _update_migrated;
self.addExperience = addExperience;
self.onTakeDamage = onTakeDamage;
self.onHealPercentage = onHealPercentage;
- function update(args) {
+ function _update_migrated(args) {
var game = args.game;
if (self.targetPos) {
var dx = self.targetPos.x - self.x;
var dy = self.targetPos.y - self.y;
@@ -1161,187 +1026,405 @@
}
healthBar.updatePercentage(self.health / self.healthMax);
}
});
-var Game = Container.expand(function () {
+var Point = Container.expand(function (parent, x, y) {
var self = Container.call(this);
- var isPaused = false;
- var minorBoonCount = 0;
- var majorBoonCount = 0;
- var grass = LK.getAsset('grass', 'Grass Background', 0, 0);
- var canMove = false;
- var difficultyScale = 0;
- var upgradeButton = new BoonUpgradeButton(LK.gui.topRight, -80, 60, {
- fill: '#ff0000',
- callback: function () {
- if (minorBoonCount + majorBoonCount > 0) {
- showBoonSelection();
- }
- }
+ parent.addChild(self);
+ self.x = x;
+ self.y = y;
+ var collision = self.attachAsset('blank', {
+ anchorX: 0.5,
+ anchorY: 0.5
});
- var levelTxt = new BorderedText('Level 1 • XP', {
- anchor: {
- x: 1.0,
- y: 0
- },
- size: 80
+ collision.opacity = 1;
+ collision.tint = 0xff0000;
+ collision.width = 1;
+ collision.height = 1;
+});
+var RangedEnemy = Container.expand(function (parent, x, y, args) {
+ var self = Container.call(this);
+ parent.addChild(self);
+ self.collision = self.attachAsset('rangedEnemy', {
+ anchorX: 0.6,
+ anchorY: 0.5
});
- 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);
- var backgroundContainer = new SectionalContainer(self);
- var midgroundContainer = new SectionalContainer(self);
- var hero = new Hero(self, 2048 / 2, 2732 / 2, {
- progressBar,
- onLevelUp
- });
- var foregroundContainer = new SectionalContainer(self);
- weapons.push(new FireballWeapon(backgroundContainer, 2048 / 4 * 2, 2732 / 4 * 1));
- weapons.push(new CrossWeapon(foregroundContainer, 2048 / 4 * 2, 2732 / 4 * 3));
- 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);
- hero.scale.x = hero.shootPos.x < hero.x ? -1 : 1;
+ 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 = 1.5;
+ 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_migrated = _update_migrated;
+ self.onTakeDamage = onTakeDamage;
+ function _update_migrated(args) {
+ if (health <= 0) {
+ kill(args);
+ return true;
}
- });
- LK.on('tick', function () {
- if (!isPaused) {
- difficultyScale = countdownTimer.update();
- hero.update({
- game: self
- });
- enemySpawner.update({
- midgroundContainer,
- difficultyScale,
- enemies
- });
- updateIteration(weapons, {
- projectiles: heroProjectiles,
- game: self,
- backgroundContainer,
- foregroundContainer,
- midgroundContainer,
- weapons,
- hero
- });
- updateIteration(heroProjectiles, {
- game: self,
- effects,
- enemies,
- hero
- });
- updateIteration(enemyProjectiles, {
- hero
- });
- 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
- });
+ 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';
}
- });
- 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();
- });
+ 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 (boonSelection) {
- isPaused = true;
- LK.gui.center.addChild(boonSelection);
- } else {
- isPaused = false;
+ if (speedFactor !== 0) {
+ var distance = Math.sqrt(distanceSqr);
+ self.x += dx / distance * speed * speedFactor;
+ self.y += dy / distance * speed * speedFactor;
}
- upgradeButton.setHidden(isPaused);
+ 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: 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 checkBoonActions(boon) {
- if (boon === 'Minor Heal') {
- hero.onHealPercentage(0.1);
- return true;
+ 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 (boon === 'Full Heal') {
- hero.onHealPercentage(1);
- return true;
+ 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: experiencePickups
+ }));
}
- if (boon === 'Health') {
- hero.healthMax += 30;
- hero.onHealPercentage(0);
- return false;
+ 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);
}
}
- function onLevelUp(level) {
- levelTxt.setText('Level ' + level + ' • XP');
- if (level % 5) {
- minorBoonCount++;
- } else {
- majorBoonCount++;
+});
+var SectionalContainer = Container.expand(function (parent) {
+ var self = Container.call(this);
+ self.x = 0;
+ self.y = 0;
+ parent.addChild(self);
+});
+
+/****
+* Initialize Game
+****/
+var game = new LK.Game({
+ backgroundColor: 0x000000
+});
+
+/****
+* Game 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) {
+ callback(node.data, node);
+ node = node.next;
+ }
+};
+function updateIteration(list, args) {
+ list.forEach(function (item, node) {
+ if (item._update_migrated(args)) {
+ list.remove(node).destroy();
}
- upgradeButton.setCount(minorBoonCount + majorBoonCount);
+ });
+}
+function checkBounds(x, y) {
+ var borderOrBorderX = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
+ var borderY = arguments.length > 3 ? arguments[3] : undefined;
+ return x < borderOrBorderX || x > 2048 - borderOrBorderX || y < (borderY || borderOrBorderX) || y > 2732 - (borderY || borderOrBorderX);
+}
+var isPaused = false;
+var minorBoonCount = 0;
+var majorBoonCount = 0;
+var grass = LK.getAsset('grass', {});
+var canMove = false;
+var difficultyScale = 0;
+var upgradeButton = new BoonUpgradeButton(LK.gui.topRight, -80, 60, {
+ fill: '#ff0000',
+ callback: function callback() {
+ 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', {
+ anchorY: 0.5
+});
+var progressBar = LK.getAsset('progressBar', {
+ anchorY: 0.5
+});
+var enemySpawner = new EnemySpawner(game, 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.top.addChild(countdownTimer);
+LK.gui.top.addChild(progressBarBorder);
+LK.gui.top.addChild(progressBar);
+LK.gui.top.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;
+game.addChild(grass);
+var backgroundContainer = new SectionalContainer(game);
+var midgroundContainer = new SectionalContainer(game);
+var hero = new Hero(game, 2048 / 2, 2732 / 2, {
+ progressBar: progressBar,
+ onLevelUp: onLevelUp
+});
+var foregroundContainer = new SectionalContainer(game);
+weapons.push(new FireballWeapon(backgroundContainer, 2048 / 4 * 2, 2732 / 8 * 3));
+weapons.push(new CrossWeapon(foregroundContainer, 2048 / 4 * 2, 2732 / 8 * 5));
+game.on('down', function (x, y, obj) {
+ canMove = true;
+ hero.targetPos = game.toLocal(obj.global);
+});
+game.on('up', function (x, y, obj) {
+ canMove = false;
+ hero.targetPos = null;
+});
+game.on('move', function (x, y, obj) {
+ if (!isPaused) {
+ if (canMove) {
+ hero.targetPos = game.toLocal(obj.global);
+ }
+ hero.shootPos = game.toLocal(obj.global);
+ hero.scale.x = hero.shootPos.x < hero.x ? -1 : 1;
+ }
+});
+LK.on('tick', function () {
+ if (!isPaused) {
+ difficultyScale = countdownTimer._update_migrated();
+ hero._update_migrated({
+ __game: game
+ });
+ enemySpawner._update_migrated({
+ midgroundContainer: midgroundContainer,
+ difficultyScale: difficultyScale,
+ enemies: enemies
+ });
+ updateIteration(weapons, {
+ projectiles: heroProjectiles,
+ __game: game,
+ backgroundContainer: backgroundContainer,
+ foregroundContainer: foregroundContainer,
+ midgroundContainer: midgroundContainer,
+ weapons: weapons,
+ hero: hero
+ });
+ updateIteration(heroProjectiles, {
+ __game: game,
+ effects: effects,
+ enemies: enemies,
+ hero: hero
+ });
+ updateIteration(enemyProjectiles, {
+ hero: hero
+ });
+ updateIteration(enemies, {
+ projectiles: enemyProjectiles,
+ backgroundContainer: backgroundContainer,
+ midgroundContainer: midgroundContainer,
+ foregroundContainer: foregroundContainer,
+ experiencePickups: experiencePickups,
+ crucifixPickups: crucifixPickups,
+ healthPickups: healthPickups,
+ effects: effects,
+ hero: hero
+ });
+ updateIteration(effects);
+ updateIteration(experiencePickups, {
+ hero: hero
+ });
+ updateIteration(healthPickups, {
+ hero: hero
+ });
+ updateIteration(crucifixPickups, {
+ experiencePickups: experiencePickups,
+ enemyProjectiles: enemyProjectiles,
+ enemies: enemies,
+ hero: 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);
+}
\ No newline at end of file
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