123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- function Hero() {
- var game = null;
- var position = {x : 10, y: 10};
- var angle = 90;
- var destination = null;
- var maxSpeed = 3;
- var triggerPlusOne = 0;
- var coinAddAmount = 0;
- var triggerHeartPickup = 0;
- var triggerHeartDecrement = 0;
- var triggerXpGain = 0;
- var xpGainAmount = 0;
- var level = 1;
- var knockbackStrength = 10;
- var triggerSale = 0;
- var saleAmount = 0;
- var shopMemory = [];
- var purchaseHistory = [];
- var triggerWeaponUpgrade = 0;
- var triggerLevelUp = 0;
- var inventory = {coins: 0, hearts: 1, xp: 0};
- var viewRange = 150;
- var attentionSpan = 50;
- var attention = 50;
- var delay = 0;
- var aggressiveness = 1.5;
- var name = "";
- var heroColor = "";
- this.init = function(canvas, gameReference, index) {
- game = gameReference;
- position.x = Math.floor(canvas.width * Math.random());
- position.y = Math.floor(canvas.height * Math.random());
- inventory.maxSpeed = precisionRound(2.5 * Math.random() + 0.5, 1);
- inventory.coins = 0;
- inventory.maxHearts = Math.floor(1 * (6 * Math.random() + 1) + 8);
- inventory.hearts = inventory.maxHearts;
- inventory.xp = 0;
- inventory.weaponStrength = 1;
- level = 1;
- viewRange = Math.floor(150 * Math.random() + 50);
- attentionSpan = Math.floor(viewRange * Math.random() + 100);
- attention = attentionSpan;
- aggressiveness = 3 * Math.random();
- name = game.nameGenerator.generate();
- heroColor = getRandomColor();
- if(index + 1 <= 5) {
- heroColor = colorPicker(index);
- }
- };
- var colorPicker = function(colorIndex) {
- switch(colorIndex) {
- case 0:
- return "#000000";
- case 1:
- return "#DD3333";
- case 2:
- return "#33DD33";
- case 3:
- return "#3333DD";
- case 4:
- return "#DD33DD";
- case 5:
- return "#33DDDD";
- }
- };
- var getRandomColor = function() {
- var colorIndex = Math.floor(5 * Math.random());
- return colorPicker(colorIndex);
- }
- this.update = function(canvas) {
- if(delay > 0) {
- delay -= maxSpeed;
- return;
- }
- attention--;
- if(attention <= 0) {
- destination = null;
- attention = attentionSpan;
- }
- if(destination != null && !destination.isConsumed) {
- var destPos = destination.getPosition();
- angle = Math.atan2(destPos.y - position.y, destPos.x - position.x) * 180 / Math.PI;
- var deltaX = maxSpeed * Math.cos(angle * Math.PI / 180);
- var deltaY = maxSpeed * Math.sin(angle * Math.PI / 180);
- angle %= 360;
- position.x += deltaX;
- position.y += deltaY;
- if(Math.abs(Math.floor(destPos.x - position.x)) <= maxSpeed + 0.5 && Math.abs(Math.floor(destPos.y - position.y)) <= maxSpeed + 0.5) {
- attention = attentionSpan;
- if(doneWithDestination(destination.visit(this))) {
- destination = null;
- }
- }
- } else {
- var visibleDestinations = game.getVisibleDestinations(position.x, position.y, viewRange);
- this.setFocus(this.decideDestination(visibleDestinations, game.getAllDestinations()));
- }
- };
- this.actionDelay = function(delayAmount) {
- delay += delayAmount;
- }
- var doneWithDestination = function(dest) {
- if(dest.getType() == "monster") {
- if (inventory.hearts > 1 && !dest.isConsumed) {
- return false;
- }
- }
- return true;
- }
- this.decideDestination = function(visibleDestinations, allDestinations) {
- //remove self
- for(var i = visibleDestinations.length - 1; i >= 0; i--) {
- var hero = visibleDestinations[i];
- if(hero.getType() == "hero") {
- if(hero == this) {
- visibleDestinations.splice(i, 1);
- }
- }
- }
- //if low on hearts, prioritize looking for a heart
- if(inventory.hearts < inventory.maxHearts) {
- for(var i = 0, newDest = visibleDestinations[0]; newDest = visibleDestinations[i]; i++) {
- if(newDest.getType() == "heart") {
- return newDest;
- }
- }
- }
- for(var i = 0, newDest = visibleDestinations[0]; newDest = visibleDestinations[i]; i++) {
- if (newDest.getType() == "coin") {
- return newDest;
- }
- }
- for(var i = 0, newDest = visibleDestinations[0]; newDest = visibleDestinations[i]; i++) {
- if (newDest.getType() == "monster" && assessThreat(newDest)) {
- return newDest;
- }
- if(newDest.getType() == "shop" && shopMemory.length <= 0) {
- return newDest;
- }
- if(newDest.getType() == "shop" && inventory.coins >= 5) {
- for(var j = 0; j < shopMemory.length; j++) {
- if(inventory.coins >= shopMemory[j].cost && hasNeedToBuy(shopMemory[j])) {
- return newDest;
- }
- }
- }
- if(newDest.getType() == "hero" && newDest.getLevel() > 5 && assessThreat(newDest)) {
- return newDest;
- }
- }
- for(var i = 0, newDest = allDestinations[0]; newDest = allDestinations[i]; i++) {
- if(newDest.getType() == "shop" && shopMemory.length <= 0) {
- return newDest;
- }
- if(newDest.getType() == "shop" && inventory.coins >= 5) {
- for(var j = 0; j < shopMemory.length; j++) {
- if(inventory.coins >= shopMemory[j].cost && hasNeedToBuy(shopMemory[j])) {
- return newDest;
- }
- }
- }
- if (newDest.getType() == "monster" && assessThreat(newDest)) {
- return newDest;
- }
- }
- //when in doubt, go back to town
- for(var i = 0, newDest = allDestinations[0]; newDest = allDestinations[i]; i++) {
- if(newDest.getType() == "shop") {
- console.log(name + " has nothing to do");
- return newDest;
- }
- }
- //pick randomly
- //return visibleDestinations[Math.floor(visibleDestinations.length * Math.random())];
- }
- var assessThreat = function(monster) {
- var isNotSuicide = inventory.hearts + 1 > monster.getLevel();
- var itCanKillMe = level < monster.getLevel();
- var iCanKillIt = inventory.weaponStrength + aggressiveness > monster.getLevel() + 1;
- return isNotSuicide && !itCanKillMe || iCanKillIt;
- }
- var precisionRound = function(number, precision) {
- var factor = Math.pow(10, precision);
- return Math.round(number * factor) / factor;
- };
-
- this.getHeroColor = function() {
- return heroColor;
- }
- this.draw = function(context, offset) {
- context.save();
- context.translate(position.x, position.y);
-
- context.beginPath();
- context.rotate(angle * Math.PI / 180);
- context.strokeStyle = this.getHeroColor();
- context.fillStyle = this.getHeroColor();
- context.moveTo(10, 0);
- context.lineTo(-10, -8);
- context.lineTo(-10, 8);
- context.lineTo(10, 0);
- context.fill();
- context.stroke();
- //DEBUG
- /*context.beginPath();
- context.fillStyle = "#DD3333";
- context.rect(12, -2, 4, 4);
- context.fill();
- context.beginPath();
- context.strokeStyle = "#000000";
- context.arc(0, 0, 15, 0, 2 * Math.PI);
- context.stroke();*/
-
- context.restore();
- context.save();
- context.translate(position.x, position.y);
- if(triggerPlusOne > 0) {
- context.fillStyle = "#FFFF00";
- context.font = "16px Roboto";
- context.fillText("+" + coinAddAmount, -10, -30 + triggerPlusOne);
- triggerPlusOne--;
- }
- if(triggerSale > 0) {
- context.fillStyle = "#FFFF00";
- context.font = "16px Roboto";
- context.fillText("-"+saleAmount, -10, 30 - triggerSale);
- triggerSale--;
- }
- if(triggerHeartPickup > 0) {
- context.fillStyle = "#FF0000";
- context.font = "16px Roboto";
- context.fillText("\u2665", -10, -30 + triggerHeartPickup);
- triggerHeartPickup--;
- }
- if(triggerWeaponUpgrade > 0) {
- context.fillStyle = "#FF00FF";
- context.font = "16px Roboto";
- context.fillText("+1 ATK", -20, -30 + triggerWeaponUpgrade);
- triggerWeaponUpgrade--;
- }
- if(triggerHeartDecrement > 0) {
- context.fillStyle = "#FF0000";
- context.font = "16px Roboto";
- context.fillText("-\u2665", -10, 30 - triggerHeartDecrement);
- triggerHeartDecrement--;
- }
- if(triggerXpGain > 0) {
- context.fillStyle = "#FF00FF";
- context.font = "16px Roboto";
- context.fillText("+" + xpGainAmount + " XP", -20, -30 + triggerXpGain);
- triggerXpGain--;
- }
- if(triggerLevelUp > 0) {
- context.fillStyle = "#FFFF00";
- context.font = "16px Roboto";
- context.fillText("**LEVEL UP**", -30, -30 + Math.floor(triggerLevelUp / 2));
- triggerLevelUp--;
- }
- //debug view range
- /*
- context.beginPath();
- context.strokeStyle = "#000000";
- //context.rect(-viewRange, -viewRange, viewRange * 2, viewRange * 2);
- context.arc(0, 0, viewRange, 0, 2 * Math.PI);
- context.stroke();
- */
- context.restore();
- // context.save();
- // context.beginPath();
- // context.fillStyle = "#000000";
- // context.rect(position.x - viewRange, position.y - viewRange, viewRange * 2, viewRange * 2);
- // context.fill();
- // context.beginPath();
- // context.arc(position.x, position.y, viewRange, 0, Math.PI * 2);
- // context.clip();
- // draw the image
- // context.restore();
- };
- this.mouseMove = function(canvas, x, y) {
- };
- this.getInfo = function() {
- return {
- level: level,
- name: name,
- inventory: inventory,
- heroColor: heroColor
- };
- }
- this.addToLeaderboard = function(element) {
- var topInfo = "level " + level + " " + name + " " + inventory.hearts + "/" + inventory.maxHearts;
- var info = "coins:" + inventory.coins + " xp:" + inventory.xp + " dmg:" + inventory.weaponStrength;
- var topNode = document.createTextNode(topInfo);
- var infoNode = document.createTextNode(info);
- var topLine = document.createElement('p');
- topLine.style.color = heroColor;
- var infoLine = document.createElement('p');
- infoLine.style.color = heroColor;
- topLine.appendChild(topNode);
- infoLine.appendChild(infoNode);
- element.appendChild(topLine);
- element.appendChild(infoLine);
- }
- this.addCoin = function(amount) {
- inventory.coins += amount;
- triggerPlusOne = 30;
- coinAddAmount = amount;
- }
- this.addHeart = function(amount) {
- if(inventory.hearts != inventory.maxHearts) {
- triggerHeartPickup = 30;
- var healedBy = Math.min(inventory.maxHearts - inventory.hearts, amount);
- console.log(name + " healed by " + healedBy + " points");
- inventory.hearts += healedBy;
- return true;
- }
- return false;
- };
- this.deductHeart = function(amount) {
- inventory.hearts -= Math.min(amount, inventory.hearts);
- triggerHeartDecrement = 30;
- if(inventory.hearts <= 0) {
- game.spawnCoins(position, inventory.coins);
- for(var i = 0; i < inventory.hearts + level; i++) {
- game.spawnHeart(position.x, position.y);
- }
- game.heroDies(this);
- return true;
- }
- return false;
- }
- this.dealDamage = function(monster) {
- console.log(""+ monster.getName() +"("+monster.getLevel()+") takes " + inventory.weaponStrength + " damage from " + this.getName() + "("+this.getLevel()+")");
- if(monster.deductHeart(inventory.weaponStrength)) {
- console.log("%c"+ monster.getName() +"("+monster.getLevel()+") is killed by " + this.getName() + "("+this.getLevel()+")", 'color: #FF0000');
- this.gainXp(monster.getXpValue());
- } else {
- monster.knockBack(this);
- monster.setFocus(this);
- }
- };
- this.knockBack = function(monster) {
- //var destPos = monster.getPosition();
- var deltaX = monster.getKnockback() * Math.cos(angle * Math.PI / 180);
- var deltaY = monster.getKnockback() * Math.sin(angle * Math.PI / 180);
- position.x -= deltaX;
- position.y -= deltaY;
- };
- var calculateLevel = function(xp) {
- return Math.floor(0.5 + Math.sqrt(1 + 8*(xp)/(100)) / 2);
- }
- this.gainXp = function(amount) {
- var prevXP = inventory.xp;
- inventory.xp += amount;
- triggerXpGain = 30;
- xpGainAmount = amount;
- if(calculateLevel(inventory.xp) > level) {
- level++;
- console.log("%c" + name + " is now level " + level, "color: #FF00FF");
- triggerLevelUp = 60;
- //inventory.maxHearts++;
- inventory.maxHearts += Math.floor(level * (6 * Math.random() + 1));
- //inventory.hearts = inventory.maxHearts;
- }
- }
- this.markMemory = function(item) {
- if(item == "potion") {
- return;
- }
- purchaseHistory.push(item);
- }
- var hasNeedToBuy = function(shopItem) {
- if (shopItem.type == "potion" && inventory.hearts < inventory.maxHearts) {
- return true;
- }
- if(shopItem.type == "weapon1" && purchaseHistory.indexOf("weapon1") == -1) {
- return true;
- }
- if(shopItem.type == "weapon2" && purchaseHistory.indexOf("weapon2") == -1) {
- return true;
- }
- if(shopItem.type == "weapon3" && purchaseHistory.indexOf("weapon3") == -1) {
- return true;
- }
- if(shopItem.type == "weapon4" && purchaseHistory.indexOf("weapon4") == -1) {
- return true;
- }
- if(shopItem.type == "weapon5" && purchaseHistory.indexOf("weapon5") == -1) {
- return true;
- }
- if(shopItem.type == "weapon6" && purchaseHistory.indexOf("weapon6") == -1) {
- return true;
- }
- }
- this.shop = function(shopInventory) {
- shopMemory = shopInventory;
- for(var i = 0; i < shopInventory.length; i++) {
- if(inventory.coins >= shopInventory[i].cost && hasNeedToBuy(shopInventory[i])) {
- return shopInventory[i];
- }
- }
- //console.log(name + " bought nothing", inventory, shopMemory, purchaseHistory);
- return;
- }
- this.upgradeWeapon = function() {
- inventory.weaponStrength++;
- triggerWeaponUpgrade = 30;
- }
- this.deductCoins = function(amount) {
- inventory.coins -= amount;
- triggerSale = 30;
- saleAmount = amount;
- }
- this.getPosition = function() {
- return position;
- }
- this.getType = function() {
- return "hero";
- }
- this.visit = function(attacker) {
- attacker.dealDamage(this);
- return this;
- }
- this.getLevel = function() {
- return level;
- }
- this.getKnockback = function() {
- return knockbackStrength * inventory.weaponStrength;
- }
- this.getName = function() {
- return name;
- }
- this.getXpValue = function() {
- return 25 * level;
- }
- this.setFocus = function(newFocus) {
- //console.log(this.getName() + " is targeting " + newFocus.getName() + "("+ newFocus.getLevel()+ ")", level, aggressiveness);
- destination = newFocus;
- }
- }
|