Code edit (3 edits merged)
Please save this source code
User prompt
change the slightly brown tint to #FFEADB instead
User prompt
change the slightly brown tint to #FFD9BD instead
User prompt
change the slightly brown tint to #f5cfb3 instead
User prompt
change the slightly brown tint to C7AD99
Code edit (1 edits merged)
Please save this source code
User prompt
tint the uiBoonBackground and uiBoonUpgrade assets of the UiBoonSelection class slightly brown
Code edit (2 edits merged)
Please save this source code
User prompt
Rename the uiBoonButton asset to uiBoonSelection and update all usages in the code
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: ENEMY_RANGED_ATTACK_COOLDOWN is not defined' in or related to this line: 'self.attackCooldown = ENEMY_RANGED_ATTACK_COOLDOWN;' Line Number: 855
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: self.updatePercentage is not a function' in or related to this line: 'self.updatePercentage(config.percentage);' Line Number: 282
User prompt
rename the progressBar class's updatePercentage function to setPercentage and update all usages in other classes
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: self.intersectRadius is not a function' in or related to this line: 'if (self.activated) {' Line Number: 609
Code edit (1 edits merged)
Please save this source code
Code edit (9 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: midFrontContainer is not defined' in or related to this line: 'midFrontContainer.addChild(new ProjectileCross({' Line Number: 111
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
if a closest enemy was found, increase the baseAngle by the angle from the hero to the closestEnemy
User prompt
In the weaponCross class replace the TODO comment by finding the closest (square distance) child in the midgroundContainer, making sure that the child has tag TAG_ENEMY and not TAG_PROJECTILE
Code edit (2 edits merged)
Please save this source code
User prompt
Rename the midBackContainer to midgroundContainer
/**** * Classes ****/ var ConfigContainer = Container.expand(function (config) { var self = Container.call(this); config = config || {}; // Private variables var destroyCalled = false; // Public variables self.tags = {}; self.id = id++; self.x = config.x || 0; self.y = config.y || 0; self.rotation = config.rotation || 0; self.alpha = config.alpha !== undefined ? config.alpha : 1.0; if (config.scale !== undefined || config.scaleX !== undefined || config.scaleY !== undefined) { var scaleX = config.scaleX !== undefined ? config.scaleX : config.scale !== undefined ? config.scale : 1; var scaleY = config.scaleY !== undefined ? config.scaleY : config.scale !== undefined ? config.scale : 1; self.scale.set(scaleX, scaleY); } // Public functions self.callDestroy = function () { if (!destroyCalled) { destroyCalled = true; self.onDestroy(); self.destroy(); } }; self.onDestroy = function () {}; // Enable inheritance return self; }); var Weapon = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); self.cooldown = 0; self.update = function () { if (!isPaused) { if (--self.cooldown <= 0) { self.launchProjectiles(); } self.onUpdate(); } }; self.onUpdate = function () {}; self.launchProjectiles = function () {}; return self; }); var WeaponCross = Weapon.expand(function (config) { var self = Weapon.call(this, config); self.cooldown = WEAPON_CROSS_COOLDOWN_BASE; self.launchProjectiles = function () { var attackSpeed = 1 + WEAPON_CROSS_COOLDOWN_SCALING * minorBoonLevels[BOON_REARM]; var scale = 1 + WEAPON_CROSS_SCALE_SCALING * minorBoonLevels[BOON_SCALE]; var range = WEAPON_CROSS_RANGE_BASE + WEAPON_CROSS_RANGE_SCALING * minorBoonLevels[BOON_RANGE]; var damage = WEAPON_CROSS_DAMAGE_BASE + WEAPON_CROSS_DAMAGE_SCALING * minorBoonLevels[BOON_DAMAGE]; var linger = WEAPON_CROSS_LINGER_BASE + WEAPON_CROSS_LINGER_SCALING * minorBoonLevels[BOON_DURATION]; var growthRate = WEAPON_CROSS_GROWTH_SCALING * majorBoonLevels[BOON_GROWTH]; var splitCount = 1 + majorBoonLevels[BOON_SPLIT]; var baseAngle = splitCount * WEAPON_CROSS_SPLIT_INCREMENT / 2; var closestEnemy = null; var minDistanceSqr = Infinity; for (var i = 0; i < midgroundContainer.children.length; i++) { var child = midgroundContainer.children[i]; if (child.tags[TAG_ENEMY] && !child.tags[TAG_PROJECTILE]) { var dx = hero.x - child.x; var dy = hero.y - child.y; var distanceSqr = dx * dx + dy * dy; if (distanceSqr < minDistanceSqr) { minDistanceSqr = distanceSqr; closestEnemy = child; } } } if (closestEnemy) { var angleToEnemy = Math.atan2(closestEnemy.y - hero.y, closestEnemy.x - hero.x); baseAngle += angleToEnemy; } for (var i = 0; i < splitCount; i++) { var splitAngle = WEAPON_CROSS_SPLIT_INCREMENT / 2 * (splitCount <= 1 ? 1 : Math.random() - 0.5); var direction = baseAngle + i * WEAPON_CROSS_SPLIT_INCREMENT + splitAngle; midFrontContainer.addChild(new ProjectileCross({ x: hero.x, y: hero.y, direction: direction, linger: linger + Math.floor(WEAPON_CROSS_LINGER_VARIANCE * Math.random()), range: range * (1 + WEAPON_CROSS_RANGE_VARIATION * (1 - 2 * Math.random())), growthRate: growthRate, damage: damage, scale: scale })); } self.cooldown = WEAPON_CROSS_COOLDOWN_BASE / attackSpeed; }; }); var UiCountdownTimer = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var countdown = config.countdown; var ticker = 60; var countdownTxt = self.addChild(new BorderedText('', { size: 80, anchorX: .5, anchorY: 0 })); self.update = function () { if (countdown > 0 && --ticker <= 0) { ticker = 60; if (--countdown === 0) { countdownTxt.setFill('#AA0000'); // TODO: Spawn boss } adjustLabel(); } difficultyScale = 1 - countdown / config.countdown; }; 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); } adjustLabel(); // Enable inheritance return self; }); var UiBoonUpgradeButton = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var hidden = false; var count = 0; self.attachAsset('shapeEllipse', { width: config.size - 5, height: config.size - 5, anchorX: 0.5, anchorY: 0.5, tint: 0xA0A0A0, alpha: 0.5 }); var button = self.attachAsset('uiBoonButton', { width: config.size, height: config.size, anchorX: 0.5, anchorY: 0.5, tint: 0x000000 }); var countTxt = self.addChild(new BorderedText('0', { y: config.size / 4, fill: config.fill, anchorX: .5, anchorY: .5 })); button.on('down', function (x, y, obj) { obj.event = obj; config.callback(obj); }); //self.visible = false; self.update = function () { var scaleFactor = 1 + Math.sin(LK.ticks / 10) * 0.1; countTxt.scale.x = scaleFactor; countTxt.scale.y = scaleFactor; }; self.setHidden = function (newHidden) { hidden = newHidden; self.checkHidden(); }; self.setCount = function (newCount) { count = newCount; countTxt.setText(newCount); self.checkHidden(); }; self.checkHidden = function () { // self.visible = !hidden && count > 0; }; return self; }); var UiBoonSelection = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var availableBoons = Object.keys(config.boons).filter(function (boon) { return config.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(config.type === 'Minor' ? 'Minor Heal' : 'Full Heal'); } self.attachAsset('uiBoonBackground', { y: 50, anchorX: 0.5, anchorY: 0.5 }); self.addChild(new BorderedText('Choose ' + config.count, { y: -220, size: 60, anchorX: .5, anchorY: 0 })); self.addChild(new BorderedText(config.type + ' Boon' + (config.count === 1 ? '' : 's'), { y: -150, anchorX: .5, anchorY: 0 })); for (var i = 0; i < selectedBoons.length; i++) { var boon = selectedBoons[i]; var boonButton = self.attachAsset('uiBoonButton', { y: i * 120, x: -120, anchorX: 0.5, anchorY: 0.4 }); boonButton.boon = boon; boonButton.on('down', function () { self.destroy(); config.callback(this.boon); }); var boonLevel = self.addChild(new BorderedText(config.boons[boon] !== undefined ? config.boons[boon] : '∞', { x: boonButton.x, y: boonButton.y, anchor: { x: .5, y: .5 } })); var boonName = self.addChild(new BorderedText(boon, { x: boonButton.x + 60, y: boonButton.y, anchorX: 0, anchorY: .5 })); } return self; }); var ProjectileEnemy = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var speedX = ENEMY_RANGED_SPEED_PROJECTILE * Math.cos(self.rotation); var speedY = ENEMY_RANGED_SPEED_PROJECTILE * Math.sin(self.rotation); var radiusSqr = ENEMY_RANGED_PROJECTILE_RADIUS * ENEMY_RANGED_PROJECTILE_RADIUS; var projectileAsset = self.attachAsset('projectileEnemy', { anchorX: 0.5, anchorY: 0.5, rotation: -MATH_QUARTER_PI }); self.update = function () { if (!isPaused) { self.x += speedX; self.y += speedY; var dx = hero.x - self.x; var dy = hero.y + heightDifference - self.y; var distanceSqr = dx * dx + dy * dy; if (LK.ticks % 15 === 0) { projectileAsset.scale.x *= -1; projectileAsset.scale.y *= -1; projectileAsset.rotation += Math.PI; } if (distanceSqr <= radiusSqr) { hero.takeDamage(damage); self.callDestroy(); } else if (!checkBounds(self.x, self.y, ENEMY_BORDER_SPAWN)) { self.callDestroy(); } } }; }); var ProgressBar = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var width = config.width || 120; var height = config.height || 15; var weight = config.weight || 6; self.attachAsset('shapeBox', { width: width + 2 * weight, height: height + 2 * weight, anchorX: 0.5, anchorY: 0.5, tint: 0x000000 }); var bar = self.attachAsset('shapeBox', { x: -width / 2, width: width, height: height, anchorY: 0.5, tint: config.tint || 0xFFFFFF }); self.updatePercentage = function (percentage) { bar.scale.x = Math.min(1.0, Math.max(0, percentage)); }; if (config.percentage !== undefined) { self.updatePercentage(config.percentage); } return self; }); var Pickup = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); self.tags[TAG_PICKUP] = true; self.activated = false; self.pickupRange = 0; self.update = function () { if (!isPaused && !self.activated) { var dx = hero.x - self.x; var dy = hero.y - self.y; var distanceSqr = dx * dx + dy * dy; if (distanceSqr <= self.pickupRange * self.pickupRange) { self.activated = true; self.onActivate(); } } }; self.onActivate = function () {}; return self; }); var PickupWeapon = Pickup.expand(function (config) { var self = Pickup.call(this, config); var updateBase = self.update; var scaleBase = self.scale; self.tags[TAG_WEAPON] = true; self.pickupRange = PICKUP_WEAPON_RANGE; var graphics = self.attachAsset(config.graphics, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { updateBase(); var scaleFactor = 1 + Math.sin(LK.ticks / 10) * 0.1; graphics.scale.x = scaleBase.x * scaleFactor; graphics.scale.y = scaleBase.y * scaleFactor; }; self.onActivate = function () { hero.addChild(new config.weaponClass()); for (var i = backgroundContainer.children.length - 1; i >= 0; i--) { var child = backgroundContainer.children[i]; if (child.tags[TAG_PICKUP] && child.tags[TAG_WEAPON]) { child.callDestroy(); } } self.callDestroy(); }; return self; }); var PickupHealing = Pickup.expand(function (config) { var self = Pickup.call(this, config); var updateBase = self.update; self.attachAsset('pickupHealing', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (hero.health < hero.healthMax) { updateBase(); } }; self.onActivate = function () { hero.healPercentage(PICKUP_HEAL_MINOR); }; self.onDestroy = function () { pickupHealthCount--; }; pickupHealthCount++; // Enable inheritance return self; }); var PickupCrucifix = Pickup.expand(function (config) { var self = Pickup.call(this, config); self.tags[TAG_CRUCIFIX] = true; self.pickupRange = PICKUP_CRUCIFIX_RANGE; self.attachAsset('pickupCrucifix', { anchorX: 0.5, anchorY: 0.5 }); self.onActivate = function () { for (var i = midgroundContainer.children.length - 1; i >= 0; i--) { var child = midgroundContainer.children[i]; if (child.tags[TAG_ENEMY]) { child.callDestroy(); } } for (var i = backgroundContainer.children.length - 1; i >= 0; i--) { var child = backgroundContainer.children[i]; if (child.tags[TAG_PICKUP] && child.tags[TAG_EXPERIENCE]) { child.onActivate(); } } self.callDestroy(); }; self.onDestroy = function () { pickupCrucifixCount--; }; pickupCrucifixCount++; return self; }); var JoystickKnob = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); self.attachAsset('shapeEllipse', { width: config.size, height: config.size, anchorX: 0.5, anchorY: 0.5, tint: 0x808080, alpha: 0.5 }); self.attachAsset('joystickKnob', { width: config.size * 0.65, height: config.size * 0.65, anchorX: 0.5, anchorY: 0.5, tint: 0x000000 }); self.attachAsset('outlineSmall', { width: config.size + 5, height: config.size + 5, anchorX: 0.5, anchorY: 0.5, tint: 0x000000 }); // Enable inheritance return self; }); var Joystick = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var size = config.size || 100; var maxDistance = size / 2; var base = self.attachAsset('shapeEllipse', { width: size, height: size, anchorX: 0.5, anchorY: 0.5, tint: 0xA0A0A0, alpha: 0.5 }); self.attachAsset('outlineLarge', { width: size + 5, height: size + 5, anchorX: 0.5, anchorY: 0.5, tint: 0x000000 }); var knob = self.addChild(new JoystickKnob({ size: size / 2 })); var pressed = false; self.magnitude = 0; self.direction = undefined; self.down = function (x, y, obj) { if (x === 0 && y === 0) { self.magnitude = 0; self.direction = undefined; } else { var distance = Math.sqrt(x * x + y * y); if (distance <= size / 2) { pressed = true; knob.x = x; knob.y = y; self.magnitude = distance / maxDistance; self.direction = Math.atan2(y, x); } } }; self.movement = function (x, y, obj) { if (pressed) { if (x === 0 && y === 0) { self.magnitude = 0; self.direction = undefined; } else { var distance = Math.sqrt(x * x + y * y); var direction = Math.atan2(y, x); if (distance > maxDistance) { x = Math.cos(direction) * maxDistance; y = Math.sin(direction) * maxDistance; distance = maxDistance; } knob.x = x; knob.y = y; self.magnitude = distance / maxDistance; self.direction = direction; } } }; self.release = function (x, y, obj) { pressed = false; self.magnitude = 0; self.direction = undefined; knob.x = 0; knob.y = 0; }; // Enable inheritance return self; }); var GameInstance = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); self.graphics = undefined; self.radius = config.radius || 0; self.elevation = config.elevation || 0; var shadowGraphics = self.attachAsset('shapeEllipse', { anchorX: 0.5, anchorY: 0.5, width: self.radius, height: self.radius * GAME_PERSPECTIVE, tint: 0x000000, alpha: 0.5 }); self.moveInDirection = function (direction, speed) { self.x += Math.cos(direction) * speed; self.y += Math.sin(direction) * speed * GAME_PERSPECTIVE; }; self.setRadius = function (newRadius) { self.radius = newRadius; shadowGraphics.width = newRadius; shadowGraphics.height = newRadius * GAME_PERSPECTIVE; self.onRadiusChanged(newRadius); }; self.setElevation = function (newElevation) { self.elevation = newElevation; if (self.graphics) { self.graphics.y = -newElevation; } self.onElevationChanged(newElevation); }; self.onRadiusChanged = function (newRadius) {}; self.onElevationChanged = function (newElevation) {}; return self; }); var Hero = GameInstance.expand(function (config) { var self = GameInstance.call(this, config); // Private variables var level = 1; var experience = 0; var levelRequirement = HERO_XP_REQUIRED; // Public variables self.speed = HERO_SPEED_BASE; self.healthMax = HERO_HEALTH_BASE; self.health = self.healthMax; // Graphics self.graphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 1.0 }); var experienceBar = self.addChild(new ProgressBar({ y: -self.graphics.height - 25, percentage: 0.01 })); var healthBar = self.addChild(new ProgressBar({ y: -self.graphics.height - 35, tint: HERO_COLOUR })); var levelTxt = self.addChild(new BorderedText('1', { y: -self.graphics.height - 30, anchorX: 0.5, anchorY: 0.5, size: 65 })); // Public functions self.update = function () { if (!isPaused && joystick.direction !== undefined) { self.moveInDirection(joystick.direction, joystick.magnitude * self.speed); self.graphics.scale.x = Math.cos(joystick.direction) < 0 ? -1 : 1; if (self.x < HERO_BORDER) { self.x = HERO_BORDER; } else if (self.x > GAME_WIDTH - HERO_BORDER) { self.x = GAME_WIDTH - HERO_BORDER; } if (self.y < HERO_BORDER) { self.y = HERO_BORDER; } else if (self.y > GAME_HEIGHT - HERO_BORDER) { self.y = GAME_HEIGHT - HERO_BORDER; } } }; self.addExperience = function (amount) { experience += amount; if (experience >= levelRequirement) { level++; experience -= levelRequirement; levelRequirement = Math.floor(levelRequirement * 1.2); // onLevelUp(level); } experienceBar.setPercentage(experience / levelRequirement); }; self.takeDamage = function (amount) { self.health = Math.max(0, self.health - amount); healthBar.updatePercentage(self.health / self.healthMax); LK.effects.flashObject(self.graphics, 0xAA0000, 1000); if (self.health <= 0) { LK.effects.flashScreen(0xAA0000, 1000); LK.showGameOver(); } }; self.healPercentage = function (percentage) { if (percentage > 0) { self.health = Math.min(self.healthMax, self.health + self.healthMax * percentage); LK.effects.flashObject(self.collision, HERO_COLOUR, 1000); } healthBar.updatePercentage(self.health / self.healthMax); }; // Enable inheritance return self; }); var Enemy = GameInstance.expand(function (config) { var self = GameInstance.call(this, config); // Private variables var damageTaken = 0; var cooldown = 0; // Public variables self.healthBar; self.health = 0; self.healthOffset = 0; self.speed = 0; self.fleeRange = 0; self.attackRange = 0; self.attackCooldown = 0; self.animationAlpha = 0; self.xpDropBase = 0; self.xpDropChance = 0; // Public functions self.update = function () { if (!isPaused) { self.animationAlpha++; var state = ENEMY_STATE_MOVE; var dx = hero.x - self.x; var dy = hero.y - self.y; var distanceSqr = dx * dx + dy * dy; if (checkBounds(self.x, self.y, ENEMY_BORDER)) { if (self.fleeRange > 0 && distanceSqr < self.fleeRange * self.fleeRange) { state = ENEMY_STATE_FLEE; } else if (self.attackRange > 0 && distanceSqr <= self.attackRange * self.attackRange) { state = ENEMY_STATE_ATTACK; } } var stateValues = self.adjustState(state, { cooldownAdjustment: 0, speedFactor: 0, canAttack: false }); // Perform the movement if (stateValues.speedFactor !== 0) { self.moveInDirection(Math.atan2(dy, dx), self.speed * stateValues.speedFactor); } // Perform the attack if it is ready cooldown += stateValues.cooldownAdjustment; if (stateValues.canAttack && cooldown <= 0) { cooldown = self.attackCooldown; self.onAttack(); } self.onUpdate(); } }; self.adjustState = function (state, stateValues) { switch (state) { case ENEMY_STATE_MOVE: stateValues.speedFactor = 1; break; case ENEMY_STATE_FLEE: stateValues.cooldownAdjustment = self.attackCooldown - cooldown; stateValues.speedFactor = -1; break; case ENEMY_STATE_ATTACK: stateValues.cooldownAdjustment = -1; stateValues.canAttack = true; break; } return stateValues; }; self.takeDamage = function (amount) { damageTaken += amount; if (damageTaken >= self.health) { self.callDestroy(); } if (!healthBar) { healthBar = self.addChild(new ProgressBar({ y: self.healthOffset, tint: ENEMY_COLOUR })); } healthBar.updatePercentage(Math.max(0, 1 - damageTaken / self.health)); LK.effects.flashObject(self.graphics, ENEMY_COLOUR, 1000); }; self.onDestroy = function () { dropExperience(); enemyCount--; foregroundContainer.addChild(new EffectEnemyDeath({ x: self.x, y: self.y })); }; self.onUpdate = function () {}; self.onAttack = function () {}; // Private functions function dropExperience() { var amount = self.xpDropBase; if (self.xpDropChance > 0) { for (var i = 0; i <= minorBoonLevels['Luck']; i++) { if (Math.random() < self.xpDropChance) { amount++; } } } if (amount > 0) { backgroundContainer.addChild(new PickupExperience({ x: self.x + ENEMY_XP_RANGE * (1 - 2 * Math.random()), y: self.y + ENEMY_XP_RANGE * (1 - 2 * Math.random()), experience: amount })); } } enemyCount++; // Enable inheritance return self; }); var EnemyRanged = Enemy.expand(function (config) { var self = Enemy.call(this, config); var adjustStateBase = self.adjustState; // Public variables self.speed = ENEMY_RANGED_SPEED; self.fleeRange = self.attackRange * ENEMY_RANGED_FLEE_DISTANCE_FACTOR; self.health = ENEMY_RANGED_HEALTH_BASE + ENEMY_RANGED_HEALTH_SCALE * difficultyScale; self.healthOffset = ENEMY_RANGED_HEALTH_OFFSET; self.attackRange = ENEMY_RANGED_RANGE_MIN * ENEMY_RANGED_RANGE_VAR * Math.random(); self.attackCooldown = ENEMY_RANGED_ATTACK_COOLDOWN; self.xpDropBase = ENEMY_RANGED_XP_DROP_BASE; self.xpDropChance = ENEMY_RANGED_XP_DROP_CHANCE; self.graphics = self.attachAsset('enemyRanged', { y: ENEMY_RANGED_GRAPHICS_OFFSET, anchorX: 0.6, anchorY: 0.5 }); // Public functions self.adjustState = function (state, stateValues) { var newStateValues = adjustStateBase(state, stateValues); switch (state) { case ENEMY_STATE_MOVE: newStateValues.cooldownAdjustment += ENEMY_RANGED_MOVE_COOLDOWN_ADJUSTMENT; break; case ENEMY_STATE_FLEE: stateValues.speedFactor *= ENEMY_RANGED_FLEE_SPEED_FACTOR; break; } return newStateValues; }; self.onAttack = function () { LK.effects.flashObject(self.graphics, 0x000000, 500); self.parent.addChild(new ProjectileEnemy({ x: graphics.x, y: graphics.y, rotation: Math.atan2(dy, dx), damage: ENEMY_RANGED_ATTACK_DAMAGE })); }; self.onUpdate = function () { // Scale the enemy up and down var newScale = 1 + Math.sin(self.animationAlpha / ENEMY_RANGED_SCALE_PERIOD) * ENEMY_RANGED_SCALE_MAGNITUDE; self.graphics.scale.x = newScale; self.graphics.scale.y = newScale; }; // Enable inheritance return self; }); var EnemyBasic = Enemy.expand(function (config) { var self = Enemy.call(this, config); var onDestroyBase = self.onDestroy; self.speed = ENEMY_BASIC_SPEED; self.health = ENEMY_BASIC_HEALTH_BASE + ENEMY_BASIC_HEALTH_SCALE * difficultyScale; self.attackRange = ENEMY_BASIC_ATTACK_RANGE; self.attackCooldown = ENEMY_BASIC_ATTACK_COOLDOWN; self.xpDropChance = ENEMY_BASIC_XP_DROP_CHANCE; self.graphics = self.attachAsset('enemyBasic', { y: ENEMY_BASIC_GRAPHICS_OFFSET, anchorX: 0.5, anchorY: 0.5 }); self.onUpdate = function () { self.setElevation(ENEMY_BASIC_GRAPHICS_OFFSET + ENEMY_BASIC_BOB_MAGNITUDE * Math.sin(self.animationAlpha / ENEMY_BASIC_BOB_PERIOD)); if (self.healthBar) { self.healthOffset = self.graphics.y + ENEMY_BASIC_HEALTH_OFFSET; self.healthBar.y = self.healthOffset; } }; self.onAttack = function () { hero.takeDamage(ENEMY_BASIC_ATTACK_DAMAGE); }; self.onDestroy = function () { onDestroyBase(); if (pickupCrucifixCount < PICKUP_CRUCIFIX_COUNT && Math.random() < Math.sqrt(minorBoonLevels['Luck']) / 100) { backgroundContainer.addChild(new PickupCrucifix({ x: self.x, y: self.y })); } else if (pickupHealthCount < PICKUP_HEALTH_COUNT) { for (var k = 0; k <= 1 + minorBoonLevels['Luck']; k++) { if (Math.random() < PICKUP_HEALTH_CHANCE) { backgroundContainer.addChild(new PickupHealing({ x: self.x, y: self.y })); break; } } } }; self.setElevation(ENEMY_BASIC_GRAPHICS_OFFSET); self.setRadius(80); return self; }); /** * config { * x : Number || 0, // See: ConfigContainer * y : Number || 0, // See: ConfigContainer * rotation : Number || 0, // See: ConfigContainer * anchorX : Number || 0, * anchorY : Number || 1, * size : Number || TEXT_DEFAULT_SIZE, * weight : Number || TEXT_DEFAULT_WEIGHT, * font : String || TEXT_DEFAULT_FONT, * fill : String || TEXT_DEFAULT_FILL, * border : String || TEXT_DEFAULT_BORDER, * } **/ var BorderedText = ConfigContainer.expand(function (text, config) { var self = ConfigContainer.call(this, config); config = config || {}; ; var anchorX = config.anchorX !== undefined ? config.anchorX : 0; var anchorY = config.anchorY !== undefined ? config.anchorY : 1; var size = config.size !== undefined ? config.size : TEXT_DEFAULT_SIZE; var weight = config.weight !== undefined ? config.weight : TEXT_DEFAULT_WEIGHT; var font = config.font !== undefined ? config.font : TEXT_DEFAULT_FONT; var textFill = config.fill !== undefined ? config.fill : TEXT_DEFAULT_FILL; var borderFill = config.border !== undefined ? config.border : TEXT_DEFAULT_BORDER; var textAssets = []; var mainAsset; ; self.setText = setText; self.setFill = setFill; ; function setText(newText) { for (var i = 0; i < textAssets.length; i++) { textAssets[i].setText(newText); } } function setFill(newFill) { textFill = newFill; mainAsset.fill = newFill; } function buildTextAssets(newText) { for (var i = 0; i < TEXT_OFFSETS.length; i++) { var main = i === TEXT_OFFSETS.length - 1; var fill = main ? textFill : borderFill; var textAsset = textAssets[i]; if (textAsset) { textAsset.destroy(); } textAsset = self.addChild(new Text2(newText, { fill: fill, font: font, size: size })); textAsset.anchor = { x: anchorX, y: anchorY }; // NOTE: Cannot be set in config textAsset.x = TEXT_OFFSETS[i][0] * weight; // NOTE: Cannot be set in config textAsset.y = TEXT_OFFSETS[i][1] * weight; // NOTE: Cannot be set in config textAssets[i] = textAsset; } mainAsset = textAssets[TEXT_OFFSETS.length - 1]; } ; buildTextAssets(text); // Enable inheritance return self; }); var EnemySpawner = Container.expand(function () { var self = Container.call(this); var borderedWidth = GAME_WIDTH - 2 * ENEMY_BORDER_SPAWN; var borderedHeight = GAME_HEIGHT - 2 * ENEMY_BORDER_SPAWN; var spawnTimer = ENEMY_SPAWN_DELAY; self.update = function () { if (enemyCount < ENEMY_LIMIT && --spawnTimer <= 0) { spawnTimer = Math.max(ENEMY_SPAWN_RATE_MIN, ENEMY_SPAWN_RATE_BASE - Math.floor(ENEMY_SPAWN_RATE_SCALE * difficultyScale)); var isRanged = difficultyScale >= ENEMY_RANGED_DIFFICULTY && Math.random() < Math.min(ENEMY_RANGED_SPAWN_CHANCE_MIN, ENEMY_RANGED_SPAWN_CHANCE_FACTOR * difficultyScale); var enemyClass = isRanged ? EnemyRanged : EnemyBasic; self.spawnClass(enemyClass); } }; self.spawnClass = function (enemyClass) { var spawnX, spawnY; var side = Math.floor(Math.random() * 4); var distance = Math.random(); switch (side) { case 0: spawnX = borderedWidth * distance; spawnY = ENEMY_BORDER_SPAWN; break; case 1: spawnX = GAME_WIDTH - ENEMY_BORDER_SPAWN; spawnY = borderedHeight * distance; break; case 2: spawnX = borderedWidth * distance; spawnY = GAME_HEIGHT - ENEMY_BORDER_SPAWN; break; case 3: spawnX = ENEMY_BORDER_SPAWN; spawnY = borderedHeight * distance; break; } midgroundContainer.addChild(new enemyClass({ x: spawnX, y: spawnY })); }; }); var SortingContainer = Container.expand(function () { var self = Container.call(this); self.update = function () { self.children.sort(function (a, b) { return a.y - b.y; }); }; // Enable inheritance return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ ; //============================================================================== // Global constants & settings //============================================================================== ; // Math constants / pre-calculations var MATH_2_PI = Math.PI * 2; var MATH_HALF_PI = Math.PI / 2; var MATH_QUARTER_PI = Math.PI / 4; var MATH_HALF_ROOT_3 = Math.sqrt(3) / 2; // Required by: TEXT_OFFSETS, BorderedText, BorderedSymbol, BorderedShape, SymbolText var MATH_APPROX_ZERO = 0.0000001; ; // Text settings var TEXT_OFFSETS = [[0, 1], [MATH_HALF_ROOT_3, 0.5], [MATH_HALF_ROOT_3, -0.5], [0, -1], [-MATH_HALF_ROOT_3, -0.5], [-MATH_HALF_ROOT_3, 0.5], [0, 0]]; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText var TEXT_DEFAULT_WEIGHT = 4; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText var TEXT_DEFAULT_BORDER = '#000000'; // Required by: BorderedText, BorderedSymbol, BorderedShape, SymbolText var TEXT_DEFAULT_FILL = '#FFFFFF'; // Required by: BorderedText, SymbolText var TEXT_DEFAULT_FONT = 'Consolas'; // Required by: BorderedText, SymbolText var TEXT_DEFAULT_SIZE = 50; // Required by: BorderedText, SymbolText ; // Game constants var GAME_TICKS = 60; var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var GAME_PERSPECTIVE = 0.5; ; // Tags var TAG_ENEMY = 'Enemy'; var TAG_PROJECTILE = 'Projectile'; var TAG_PICKUP = 'Pickup'; var TAG_EXPERIENCE = 'Experience'; var TAG_CRUCIFIX = 'Crucifix'; var TAG_WEAPON = 'Weapon'; ; // Hero settings var HERO_COLOUR = 0x0FA0FF; var HERO_BORDER = 250; var HERO_HEALTH_BASE = 100; var HERO_HEALTH_BONUS = 30; var HERO_SPEED_BASE = 8; var HERO_SPEED_BONUS = 2; var HERO_XP_REQUIRED = 20; var HERO_XP_SCALING = 1.2; ; // Boon settings var BOON_LUCK = 'Luck'; var BOON_SCALE = 'Scale'; var BOON_RANGE = 'Range'; var BOON_DAMAGE = 'Damage'; var BOON_REARM = 'Rearm'; var BOON_DURATION = 'Duration'; var BOON_HEALTH = 'Health'; var BOON_SPEED = 'Speed'; var BOON_GROWTH = 'Growth'; var BOON_SPLIT = 'Split'; ; // Weapon settings var WEAPON_CROSS_SPLIT_INCREMENT = 20 / 180 * Math.PI; var WEAPON_CROSS_RANGE_BASE = 200; var WEAPON_CROSS_RANGE_SCALING = 100; var WEAPON_CROSS_RANGE_VARIATION = 0.1; var WEAPON_CROSS_RADIUS_BASE = 80; var WEAPON_CROSS_SCALE_SCALING = 0.35; var WEAPON_CROSS_SCALE_DAMAGE_FACTOR = 0.1; var WEAPON_CROSS_COOLDOWN_HIT = GAME_TICKS / 6; var WEAPON_CROSS_COOLDOWN_BASE = 120; var WEAPON_CROSS_COOLDOWN_SCALING = 0.25; var WEAPON_CROSS_DAMAGE_BASE = 15; var WEAPON_CROSS_DAMAGE_SCALING = 10; var WEAPON_CROSS_LINGER_BASE = 0; var WEAPON_CROSS_LINGER_VARIANCE = GAME_TICKS / 6; var WEAPON_CROSS_LINGER_SCALING = 0.25 * GAME_TICKS; var WEAPON_CROSS_GROWTH_SCALING = 0.15 / GAME_TICKS; var WEAPON_CROSS_SPEED_BASE = 30; var WEAPON_CROSS_SPEED_DECREMENT = 1; var WEAPON_CROSS_HEIGHT = 50; var WEAPON_CROSS_ROTATION = 0.2; var WEAPON_CROSS_BORDER = -1000; ; // Enemy settings var ENEMY_COLOUR = 0xAA0000; var ENEMY_BORDER = 50; // Forced minimum move distance from the edge of the screen var ENEMY_BORDER_SPAWN = -100; var ENEMY_SPAWN_DELAY = 2 * GAME_TICKS; var ENEMY_SPAWN_RATE_BASE = 1 * GAME_TICKS; var ENEMY_SPAWN_RATE_SCALE = 0.75 * GAME_TICKS; var ENEMY_SPAWN_RATE_MIN = 0.25 * GAME_TICKS; var ENEMY_LIMIT = 40; var ENEMY_XP_RANGE = 50; var ENEMY_STATE_MOVE = 'Move'; var ENEMY_STATE_FLEE = 'Flee'; var ENEMY_STATE_ATTACK = 'Attack'; var ENEMY_BASIC_SPEED = 2.5; var ENEMY_BASIC_HEALTH_BASE = 10; var ENEMY_BASIC_HEALTH_SCALE = 50; var ENEMY_BASIC_HEALTH_OFFSET = 30; var ENEMY_BASIC_ATTACK_RANGE = 100; var ENEMY_BASIC_ATTACK_DAMAGE = 10; var ENEMY_BASIC_ATTACK_COOLDOWN = GAME_TICKS / 6; var ENEMY_BASIC_GRAPHICS_OFFSET = 100; var ENEMY_BASIC_BOB_MAGNITUDE = 20; var ENEMY_BASIC_BOB_PERIOD = 10; var ENEMY_BASIC_XP_DROP_CHANCE = 0.3; // Per level of Luck var ENEMY_RANGED_SPEED = 1.5; var ENEMY_RANGED_HEALTH_BASE = 20; var ENEMY_RANGED_HEALTH_SCALE = 60; var ENEMY_RANGED_HEALTH_OFFSET = 20; var ENEMY_RANGED_RANGE_MIN = 500; var ENEMY_RANGED_RANGE_VAR = 250; var ENEMY_RANGED_ATTACK_DAMAGE = 5; var ENEMY_RANGED_MOVE_COOLDOWN_ADJUSTMENT = -0.5; var ENEMY_RANGED_GRAPHICS_OFFSET = 100; var ENEMY_RANGED_FLEE_DISTANCE_FACTOR = 0.35; var ENEMY_RANGED_FLEE_SPEED_FACTOR = 1.5; var ENEMY_RANGED_SCALE_PERIOD = 20; var ENEMY_RANGED_SCALE_MAGNITUDE = 0.05; var ENEMY_RANGED_XP_DROP_BASE = 2; var ENEMY_RANGED_XP_DROP_CHANCE = 0.5; // Per level of Luck var ENEMY_RANGED_DIFFICULTY = 0.2; var ENEMY_RANGED_SPAWN_CHANCE_MIN = 0.4; var ENEMY_RANGED_SPAWN_CHANCE_FACTOR = 0.5; var ENEMY_RANGED_PROJECTILE_SPEED = 10; var ENEMY_RANGED_PROJECTILE_RADIUS = 100; ; // Pickup settings var PICKUP_HEAL_MINOR = 0.1; var PICKUP_HEAL_MAJOR = 1.0; var PICKUP_HEALTH_COUNT = 3; var PICKUP_HEALTH_CHANCE = 0.02; // Per level of luck var PICKUP_CRUCIFIX_COUNT = 1; var PICKUP_CRUCIFIX_RANGE = 200; var PICKUP_WEAPON_RANGE = 200; ; //============================================================================== // Instances & variables //============================================================================== ; // Variables var id = 0; var isPaused = false; var enemyCount = 0; var minorBoonCount = 0; var majorBoonCount = 0; var pickupHealthCount = 0; var pickupCrucifixCount = 0; var difficultyScale = 0; var startingWeapons = []; var minorBoonLevels = { 'Luck': 0, 'Scale': 0, 'Range': 0, 'Damage': 0, 'Rearm': 0, 'Duration': 0, 'Health': 0, 'Speed': 0 }; var majorBoonLevels = { 'Growth': 0, 'Split': 0 }; ; // Game instances game.attachAsset('grassTop', { y: HERO_BORDER - 100, x: GAME_WIDTH / 2, anchorX: 0.5 }); game.attachAsset('grassBot', { y: GAME_HEIGHT - HERO_BORDER + 100, x: GAME_WIDTH / 2, anchorX: 0.5, anchorY: 1.0 }); var enemySpawner = game.addChild(new EnemySpawner()); var backgroundContainer = game.addChild(new Container()); var midgroundContainer = game.addChild(new SortingContainer()); var foregroundContainer = game.addChild(new Container()); var interfaceContainer = game.addChild(new Container()); var hero = midgroundContainer.addChild(new Hero({ x: GAME_WIDTH / 2, y: GAME_HEIGHT / 2, radius: 150 })); /* backgroundContainer.addChild(new PickupWeapon({ x: GAME_WIDTH / 4 * 2, y: GAME_HEIGHT / 4, scale: 1.25, graphics: 'weaponFireball', weaponClass: WeaponFireball })); */ backgroundContainer.addChild(new PickupWeapon({ x: GAME_WIDTH / 4 * 2, y: GAME_HEIGHT / 4 * 3, scale: 1.25, rotation: -Math.PI / 8, graphics: 'weaponCross', weaponClass: WeaponCross })); ; // Interface instances var joystick = game.addChild(new Joystick({ size: 400, x: GAME_WIDTH - 400, y: GAME_HEIGHT - 400 })); var upgradeButton = interfaceContainer.addChild(new UiBoonUpgradeButton({ x: GAME_WIDTH - 200, y: GAME_HEIGHT - 750, size: 200, callback: function callback() { if (minorBoonCount + majorBoonCount > 0) { showBoonSelection(); } } })); var countdownTimer = interfaceContainer.addChild(new UiCountdownTimer({ x: GAME_WIDTH / 2, y: 20, countdown: 300 })); ; //============================================================================== // Global events //============================================================================== ; // Add event listeners for the joystick game.move = function (x, y, obj) { joystick.movement(x - joystick.x, y - joystick.y, obj); }; game.up = function (x, y, obj) { joystick.release(x, y, obj); }; ; //============================================================================== // Global helper functions //============================================================================== ; function checkBounds(x, y, border) { return !(x < border || x > GAME_WIDTH - border || y < border || y > GAME_HEIGHT - border); }
===================================================================
--- original.js
+++ change.js
@@ -34,9 +34,9 @@
var self = ConfigContainer.call(this, config);
self.cooldown = 0;
self.update = function () {
if (!isPaused) {
- if (--cooldown <= 0) {
+ if (--self.cooldown <= 0) {
self.launchProjectiles();
}
self.onUpdate();
}
@@ -74,9 +74,8 @@
if (closestEnemy) {
var angleToEnemy = Math.atan2(closestEnemy.y - hero.y, closestEnemy.x - hero.x);
baseAngle += angleToEnemy;
}
- LK.effects.flashObject(aimArrow, HERO_COLOUR, 1000);
for (var i = 0; i < splitCount; i++) {
var splitAngle = WEAPON_CROSS_SPLIT_INCREMENT / 2 * (splitCount <= 1 ? 1 : Math.random() - 0.5);
var direction = baseAngle + i * WEAPON_CROSS_SPLIT_INCREMENT + splitAngle;
midFrontContainer.addChild(new ProjectileCross({
@@ -168,11 +167,10 @@
countTxt.setText(newCount);
self.checkHidden();
};
self.checkHidden = function () {
- //self.visible = !hidden && count > 0;
+ // self.visible = !hidden && count > 0;
};
- // Enable inheritance
return self;
});
var UiBoonSelection = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
@@ -234,9 +232,8 @@
anchorX: 0,
anchorY: .5
}));
}
- // Enable inheritance
return self;
});
var ProjectileEnemy = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
@@ -293,9 +290,8 @@
};
if (config.percentage !== undefined) {
self.updatePercentage(config.percentage);
}
- // Enable inheritance
return self;
});
var Pickup = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
@@ -313,9 +309,8 @@
}
}
};
self.onActivate = function () {};
- // Enable inheritance
return self;
});
var PickupWeapon = Pickup.expand(function (config) {
var self = Pickup.call(this, config);
@@ -333,18 +328,17 @@
graphics.scale.x = scaleBase.x * scaleFactor;
graphics.scale.y = scaleBase.y * scaleFactor;
};
self.onActivate = function () {
- // hero.addChild(new config.weaponClass());
+ hero.addChild(new config.weaponClass());
for (var i = backgroundContainer.children.length - 1; i >= 0; i--) {
var child = backgroundContainer.children[i];
if (child.tags[TAG_PICKUP] && child.tags[TAG_WEAPON]) {
child.callDestroy();
}
}
self.callDestroy();
};
- // Enable inheritance
return self;
});
var PickupHealing = Pickup.expand(function (config) {
var self = Pickup.call(this, config);
@@ -493,10 +487,44 @@
};
// Enable inheritance
return self;
});
-var Hero = ConfigContainer.expand(function (config) {
+var GameInstance = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
+ self.graphics = undefined;
+ self.radius = config.radius || 0;
+ self.elevation = config.elevation || 0;
+ var shadowGraphics = self.attachAsset('shapeEllipse', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: self.radius,
+ height: self.radius * GAME_PERSPECTIVE,
+ tint: 0x000000,
+ alpha: 0.5
+ });
+ self.moveInDirection = function (direction, speed) {
+ self.x += Math.cos(direction) * speed;
+ self.y += Math.sin(direction) * speed * GAME_PERSPECTIVE;
+ };
+ self.setRadius = function (newRadius) {
+ self.radius = newRadius;
+ shadowGraphics.width = newRadius;
+ shadowGraphics.height = newRadius * GAME_PERSPECTIVE;
+ self.onRadiusChanged(newRadius);
+ };
+ self.setElevation = function (newElevation) {
+ self.elevation = newElevation;
+ if (self.graphics) {
+ self.graphics.y = -newElevation;
+ }
+ self.onElevationChanged(newElevation);
+ };
+ self.onRadiusChanged = function (newRadius) {};
+ self.onElevationChanged = function (newElevation) {};
+ return self;
+});
+var Hero = GameInstance.expand(function (config) {
+ var self = GameInstance.call(this, config);
// Private variables
var level = 1;
var experience = 0;
var levelRequirement = HERO_XP_REQUIRED;
@@ -504,41 +532,31 @@
self.speed = HERO_SPEED_BASE;
self.healthMax = HERO_HEALTH_BASE;
self.health = self.healthMax;
// Graphics
- self.attachAsset('shapeEllipse', {
- width: 150,
- height: 15,
+ self.graphics = self.attachAsset('hero', {
anchorX: 0.5,
- anchorY: 0.5,
- tint: 0x000000,
- alpha: 0.75
- });
- var heroGraphics = self.attachAsset('hero', {
- anchorX: 0.5,
anchorY: 1.0
});
var experienceBar = self.addChild(new ProgressBar({
- y: -heroGraphics.height - 25,
+ y: -self.graphics.height - 25,
percentage: 0.01
}));
var healthBar = self.addChild(new ProgressBar({
- y: -heroGraphics.height - 35,
+ y: -self.graphics.height - 35,
tint: HERO_COLOUR
}));
var levelTxt = self.addChild(new BorderedText('1', {
- y: -heroGraphics.height - 30,
+ y: -self.graphics.height - 30,
anchorX: 0.5,
anchorY: 0.5,
size: 65
}));
// Public functions
self.update = function () {
if (!isPaused && joystick.direction !== undefined) {
- var speedX = Math.cos(joystick.direction) * joystick.magnitude * self.speed;
- var speedY = Math.sin(joystick.direction) * joystick.magnitude * self.speed;
- self.x += speedX;
- self.y += speedY;
+ self.moveInDirection(joystick.direction, joystick.magnitude * self.speed);
+ self.graphics.scale.x = Math.cos(joystick.direction) < 0 ? -1 : 1;
if (self.x < HERO_BORDER) {
self.x = HERO_BORDER;
} else if (self.x > GAME_WIDTH - HERO_BORDER) {
self.x = GAME_WIDTH - HERO_BORDER;
@@ -547,9 +565,8 @@
self.y = HERO_BORDER;
} else if (self.y > GAME_HEIGHT - HERO_BORDER) {
self.y = GAME_HEIGHT - HERO_BORDER;
}
- heroGraphics.scale.x = speedX < 0 ? -1 : 1;
}
};
self.addExperience = function (amount) {
experience += amount;
@@ -563,9 +580,9 @@
};
self.takeDamage = function (amount) {
self.health = Math.max(0, self.health - amount);
healthBar.updatePercentage(self.health / self.healthMax);
- LK.effects.flashObject(heroGraphics, 0xAA0000, 1000);
+ LK.effects.flashObject(self.graphics, 0xAA0000, 1000);
if (self.health <= 0) {
LK.effects.flashScreen(0xAA0000, 1000);
LK.showGameOver();
}
@@ -579,10 +596,10 @@
};
// Enable inheritance
return self;
});
-var Enemy = ConfigContainer.expand(function (config) {
- var self = ConfigContainer.call(this, config);
+var Enemy = GameInstance.expand(function (config) {
+ var self = GameInstance.call(this, config);
// Private variables
var damageTaken = 0;
var cooldown = 0;
// Public variables
@@ -617,11 +634,9 @@
canAttack: false
});
// Perform the movement
if (stateValues.speedFactor !== 0) {
- var distance = Math.sqrt(distanceSqr);
- self.x += dx / distance * self.speed * stateValues.speedFactor;
- self.y += dy / distance * self.speed * stateValues.speedFactor;
+ self.moveInDirection(Math.atan2(dy, dx), self.speed * stateValues.speedFactor);
}
// Perform the attack if it is ready
cooldown += stateValues.cooldownAdjustment;
if (stateValues.canAttack && cooldown <= 0) {
@@ -743,31 +758,20 @@
});
var EnemyBasic = Enemy.expand(function (config) {
var self = Enemy.call(this, config);
var onDestroyBase = self.onDestroy;
- // Public variables
self.speed = ENEMY_BASIC_SPEED;
self.health = ENEMY_BASIC_HEALTH_BASE + ENEMY_BASIC_HEALTH_SCALE * difficultyScale;
self.attackRange = ENEMY_BASIC_ATTACK_RANGE;
self.attackCooldown = ENEMY_BASIC_ATTACK_COOLDOWN;
self.xpDropChance = ENEMY_BASIC_XP_DROP_CHANCE;
- self.attachAsset('shapeEllipse', {
- width: 100,
- height: 10,
- anchorX: 0.5,
- anchorY: 0.5,
- tint: 0x000000,
- alpha: 0.75
- });
self.graphics = self.attachAsset('enemyBasic', {
y: ENEMY_BASIC_GRAPHICS_OFFSET,
anchorX: 0.5,
anchorY: 0.5
});
- // Public functions
self.onUpdate = function () {
- // Bob the enemy up and down
- self.graphics.y = ENEMY_BASIC_GRAPHICS_OFFSET + ENEMY_BASIC_BOB_MAGNITUDE * Math.sin(self.animationAlpha / ENEMY_BASIC_BOB_PERIOD);
+ self.setElevation(ENEMY_BASIC_GRAPHICS_OFFSET + ENEMY_BASIC_BOB_MAGNITUDE * Math.sin(self.animationAlpha / ENEMY_BASIC_BOB_PERIOD));
if (self.healthBar) {
self.healthOffset = self.graphics.y + ENEMY_BASIC_HEALTH_OFFSET;
self.healthBar.y = self.healthOffset;
}
@@ -793,9 +797,10 @@
}
}
}
};
- // Enable inheritance
+ self.setElevation(ENEMY_BASIC_GRAPHICS_OFFSET);
+ self.setRadius(80);
return self;
});
/**
* config {
@@ -950,16 +955,18 @@
// Game constants
var GAME_TICKS = 60;
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
+var GAME_PERSPECTIVE = 0.5;
;
// Tags
var TAG_ENEMY = 'Enemy';
var TAG_PROJECTILE = 'Projectile';
var TAG_PICKUP = 'Pickup';
var TAG_EXPERIENCE = 'Experience';
var TAG_CRUCIFIX = 'Crucifix';
var TAG_WEAPON = 'Weapon';
+;
// Hero settings
var HERO_COLOUR = 0x0FA0FF;
var HERO_BORDER = 250;
var HERO_HEALTH_BASE = 100;
@@ -967,8 +974,44 @@
var HERO_SPEED_BASE = 8;
var HERO_SPEED_BONUS = 2;
var HERO_XP_REQUIRED = 20;
var HERO_XP_SCALING = 1.2;
+;
+// Boon settings
+var BOON_LUCK = 'Luck';
+var BOON_SCALE = 'Scale';
+var BOON_RANGE = 'Range';
+var BOON_DAMAGE = 'Damage';
+var BOON_REARM = 'Rearm';
+var BOON_DURATION = 'Duration';
+var BOON_HEALTH = 'Health';
+var BOON_SPEED = 'Speed';
+var BOON_GROWTH = 'Growth';
+var BOON_SPLIT = 'Split';
+;
+// Weapon settings
+var WEAPON_CROSS_SPLIT_INCREMENT = 20 / 180 * Math.PI;
+var WEAPON_CROSS_RANGE_BASE = 200;
+var WEAPON_CROSS_RANGE_SCALING = 100;
+var WEAPON_CROSS_RANGE_VARIATION = 0.1;
+var WEAPON_CROSS_RADIUS_BASE = 80;
+var WEAPON_CROSS_SCALE_SCALING = 0.35;
+var WEAPON_CROSS_SCALE_DAMAGE_FACTOR = 0.1;
+var WEAPON_CROSS_COOLDOWN_HIT = GAME_TICKS / 6;
+var WEAPON_CROSS_COOLDOWN_BASE = 120;
+var WEAPON_CROSS_COOLDOWN_SCALING = 0.25;
+var WEAPON_CROSS_DAMAGE_BASE = 15;
+var WEAPON_CROSS_DAMAGE_SCALING = 10;
+var WEAPON_CROSS_LINGER_BASE = 0;
+var WEAPON_CROSS_LINGER_VARIANCE = GAME_TICKS / 6;
+var WEAPON_CROSS_LINGER_SCALING = 0.25 * GAME_TICKS;
+var WEAPON_CROSS_GROWTH_SCALING = 0.15 / GAME_TICKS;
+var WEAPON_CROSS_SPEED_BASE = 30;
+var WEAPON_CROSS_SPEED_DECREMENT = 1;
+var WEAPON_CROSS_HEIGHT = 50;
+var WEAPON_CROSS_ROTATION = 0.2;
+var WEAPON_CROSS_BORDER = -1000;
+;
// Enemy settings
var ENEMY_COLOUR = 0xAA0000;
var ENEMY_BORDER = 50; // Forced minimum move distance from the edge of the screen
var ENEMY_BORDER_SPAWN = -100;
@@ -987,9 +1030,9 @@
var ENEMY_BASIC_HEALTH_OFFSET = 30;
var ENEMY_BASIC_ATTACK_RANGE = 100;
var ENEMY_BASIC_ATTACK_DAMAGE = 10;
var ENEMY_BASIC_ATTACK_COOLDOWN = GAME_TICKS / 6;
-var ENEMY_BASIC_GRAPHICS_OFFSET = -100;
+var ENEMY_BASIC_GRAPHICS_OFFSET = 100;
var ENEMY_BASIC_BOB_MAGNITUDE = 20;
var ENEMY_BASIC_BOB_PERIOD = 10;
var ENEMY_BASIC_XP_DROP_CHANCE = 0.3; // Per level of Luck
var ENEMY_RANGED_SPEED = 1.5;
@@ -999,9 +1042,9 @@
var ENEMY_RANGED_RANGE_MIN = 500;
var ENEMY_RANGED_RANGE_VAR = 250;
var ENEMY_RANGED_ATTACK_DAMAGE = 5;
var ENEMY_RANGED_MOVE_COOLDOWN_ADJUSTMENT = -0.5;
-var ENEMY_RANGED_GRAPHICS_OFFSET = -100;
+var ENEMY_RANGED_GRAPHICS_OFFSET = 100;
var ENEMY_RANGED_FLEE_DISTANCE_FACTOR = 0.35;
var ENEMY_RANGED_FLEE_SPEED_FACTOR = 1.5;
var ENEMY_RANGED_SCALE_PERIOD = 20;
var ENEMY_RANGED_SCALE_MAGNITUDE = 0.05;
@@ -1011,8 +1054,9 @@
var ENEMY_RANGED_SPAWN_CHANCE_MIN = 0.4;
var ENEMY_RANGED_SPAWN_CHANCE_FACTOR = 0.5;
var ENEMY_RANGED_PROJECTILE_SPEED = 10;
var ENEMY_RANGED_PROJECTILE_RADIUS = 100;
+;
// Pickup settings
var PICKUP_HEAL_MINOR = 0.1;
var PICKUP_HEAL_MAJOR = 1.0;
var PICKUP_HEALTH_COUNT = 3;
@@ -1068,9 +1112,10 @@
var foregroundContainer = game.addChild(new Container());
var interfaceContainer = game.addChild(new Container());
var hero = midgroundContainer.addChild(new Hero({
x: GAME_WIDTH / 2,
- y: GAME_HEIGHT / 2
+ y: GAME_HEIGHT / 2,
+ radius: 150
}));
/*
backgroundContainer.addChild(new PickupWeapon({
x: GAME_WIDTH / 4 * 2,
@@ -1095,11 +1140,11 @@
x: GAME_WIDTH - 400,
y: GAME_HEIGHT - 400
}));
var upgradeButton = interfaceContainer.addChild(new UiBoonUpgradeButton({
- x: GAME_WIDTH - 150,
- y: GAME_HEIGHT - 500,
- size: 125,
+ x: GAME_WIDTH - 200,
+ y: GAME_HEIGHT - 750,
+ size: 200,
callback: function callback() {
if (minorBoonCount + majorBoonCount > 0) {
showBoonSelection();
}
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