@kikosko

Как корректно реализовать метод «battle» в моей мини игре?

Помогите корректно реализовать метод "battle" в классе "Game". Когда я запускаю данный метод, у меня получается беспрерывный бой между командами, а нужно, что бы при достижении "currentHealth" нулю, выводило сообщение о победе соответствующей команды и бой заканчивался.
function Weapon(name, damage) {
    this.name = name;
    this.damage = damage;
}
Weapon.prototype.getDamage = function () {
    return this.damage;
};
Weapon.prototype.toString = function () {
    return this.name + 'damage: ' + this.getDamage() + " points";
};
var bow = new Weapon('Golden bow, ', 20);
var sword = new Weapon('Magic sword, ', 30);
var staff = new  Weapon('Whale-Stick Harpoon ', 10);

var spear = new Weapon('Selizas Spear, ', 15);
var axe = new Weapon('Nifflevar Bearded Axe, ', 40);
var stick = new  Weapon('Wanderers Stick of Deserts', 5);

//constructor for creating a unit
function Unit(maxHealth, basicDamage, evasion, type) {
    this.maxHealth = maxHealth;
    this.currentHealth = maxHealth;
    this.basicDamage = basicDamage;
    this.evasion = evasion;
    this.type = type;
}
/*method for showing the status of life, true if the "health" is greater
 than 0 and false if equal to or lower */
Unit.prototype.isAlive = function () {
    return this.currentHealth > 0;
};
/* a method that
 shows the level of health*/
Unit.prototype.getFormattedHealth = function () {
    return this.currentHealth + "/" + this.maxHealth + " HP";
};
/*method which fills an array with 10 digit of 0s and 1s according
 to evasion and return a random 1 or 0:*/
Unit.prototype.probability = function () {
    var notRandomNumbers = [],
        maxEvasion = 0;
    if (
        (this.evasion + "").split(".")[0] == 1 &&
        (this.evasion + "").split(".")[1] == 0
    ) {
        maxEvasion = 10;
    } else {
        maxEvasion = (this.evasion + "").split(".")[1];
    }
    for (var i = 0; i < maxEvasion; i++) {
        notRandomNumbers.push(1);
    }
    for (var i = 0; i < 10 - maxEvasion; i++) {
        notRandomNumbers.push(0);
    }
    var idx = Math.floor(Math.random() * notRandomNumbers.length);
    if (idx == notRandomNumbers[idx] ) {
        console.log(this.type + ' miss ' + this.type);
    }else {
        if (this.type.currentHealth <= 0) {
            console.log(this.type + ' die');
        }else {
            console.log(this.type + ' hit ' + this.type);
        }
    }
    return notRandomNumbers[idx];
};
/* The method that defines the weapon created in the constructor "Weapon"*/
Unit.prototype.setWeapon = function (weapon) {
    var me = this;
    me.weapon = weapon;
    return me;
};
/*a method that returns the base damage of the hero and damage to the
 weapon (if it is set)*/
Unit.prototype.getDamage = function () {
    return (this.weapon ? this.weapon.getDamage() : 0) + this.basicDamage;
};
/* The method of hitting
 the hero for the chosen purpose*/
Unit.prototype.kick = function (target) {
    if (this.isAlive()) {
        target.currentHealth = Math.max(0, target.currentHealth - this.probability() * this.getDamage());
    }
    return this;
};
/*method for showing all the characteristics of the hero and changes
 with them*/
Unit.prototype.toString = function () {
    return "Type - " + this.type + ", is alive - " + this.isAlive() + ", Have weapon - " + this.weapon +
        ", " + this.getFormattedHealth() + ', hero current damage - ' + this.getDamage() + ' points' +
        ", hero evasion - " + this.evasion;
};
/*the constructors of the main types of units  which we will use*/
function Archer(maxHealth, basicDamage, evasion) {
    Unit.apply(this, arguments);
    this.type = "archer";
}
function Swordsman(maxHealth, basicDamage, evasion) {
    Unit.apply(this, arguments);
    this.type = "swordsman";
}
function Mage(maxHealth, basicDamage, evasion) {
    Unit.apply(this, arguments);
    this.type = "mage";
}
Archer.prototype = Object.create(Unit.prototype);
Swordsman.prototype = Object.create(Unit.prototype);
Mage.prototype = Object.create(Unit.prototype);

/*a method of treatment that works when the
 archer's health falls below his maximum health*/
Mage.prototype.heal = function (target) {
    if (target.currentHealth < target.maxHealth) {
        target.currentHealth = Math.min(target.maxHealth,
            target.currentHealth + 20);
    }
    return this;
};
/*We create units of which we will then write to the teams.
 Three units per team*/
var archer = new Archer(60, 5, 0.6);
archer.setWeapon(bow);
var swordsman = new Swordsman(100, 10, 0.3);
swordsman.setWeapon(sword);
var mage = new Mage(40, 15, 0.5);
mage.setWeapon(staff);

var troll = new Archer(70, 5, 0.2);
troll.setWeapon(spear);
var orc = new Swordsman(150, 10, 0.1);
orc.setWeapon(axe);
var druid = new Mage(50, 15, 0.3);
druid.setWeapon(stick);


/*method for creating teams*/
function Team(name) {
    this.name = name;
    this.members = [];
}
/*method for adding a new unit with an arbitrary number of units*/
Team.prototype.addMember = function (...members) {
    for (var i=0; i< members.length;i++) {
        this.members.push(members[i]);
    }
}
/*method of life of the team, if all participants have "currentHealth" <0 then this method = "false"*/
Team.prototype.isAlive = function () {
    return !this.members.every(function (memb) {
        return memb.currentHealth === 0;
    });
};
/*method to output information about the team*/
Team.prototype.toString = function () {
    var res = "Name of team - " + this.name +  '\n' + "life of a team : " + this.isAlive() + '\n' +"members :\n";
    for (var i=0; i<this.members.length; i++)
        res += this.members[i]+"\n";
    return  res;
};
/*create team 1 and add units to it*/
var team1 =  new Team('Alliance');
team1.addMember(archer,swordsman,mage);
console.log(team1 instanceof  Team);
/*create team 2 and add units to it*/
var team2 = new Team('Orcs');
team2.addMember(troll,orc,druid);
console.log(team2 instanceof  Team);
//show created teams


/*class that organizes a battle between two teams until
 "currentHealth" of all units in the team will not be zero*/

function Game(team1, team2) {
    this.team1 = team1;
    this.team2 = team2;
}
Game.prototype.battle = function() {
    if (!this.team1.isAlive() && !this.team2.isAlive()) {
        if (this.team1.isAlive()) {
            alert("Team 1 is win");
        }
        else if (this.team2.isAlive() && !this.team1.isAlive() ) {
            alert("Team 2 is win");
        }
        console.log(`END,
      ${this.team1.name} - ${this.team1.members.length}
      ${this.team2.name} - ${this.team2.members.length}
    `);
        return;
    }
    archer.kick(troll);
    troll.kick(archer);
    mage.kick(druid);
    druid.kick(mage);
    swordsman.kick(orc);
    orc.kick(swordsman);
    requestAnimationFrame(this.battle.bind(this));
};
var game = new Game(team1, team2);
game.battle();

console.log(team1.toString());
console.log(team2.toString());
  • Вопрос задан
  • 125 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Во-первых - у вас неправильное условие окончания боя. Ошибка тривиальная, так что тут ничего более не скажу, думайте сами.

Во-вторых - фантастически козлиная реализация самого метода battle в целом. Почему этот метод должен знать о конкретных экземплярах Unit? Не должен. Что, при изменении состава команд полезете его исправлять? Это абсурд.

Отсюда, кстати и происходит упомянутый вами "беспрерывный бой" - поскольку вы каждому члену обеих команд назначили в противники кого-то конкретного из другой команды раз и навсегда, то... как вы думаете, какова вероятность, что сразу всем членам одной команды удастся одолеть своих противников? - часто получается так, что в одной из команд жив один её участник, а в другой два - и они никак не взаимодействуют.

Надо сделать так, чтобы участники команд не были привязаны к конкретному противнику раз и навсегда. Можно добавить в Team метод kick (аналогично таковому в Unit), где будет осуществляться выбор - кто кого атакует (например, участники команды по очереди атакуют случайного участника другой команды). Ну и соответственно, использовать этот метод в battle, типа так.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
SummerWeb Ярославль
от 120 000 до 180 000 ₽
КРАФТТЕК Санкт-Петербург
от 60 000 до 80 000 ₽
Brightdata Тель-Авив
от 5 500 до 6 500 $
16 июн. 2024, в 22:40
5000 руб./за проект
16 июн. 2024, в 22:17
30000 руб./за проект