Хороший способ справиться с использованием способностей в многопользовательской игре? - PullRequest
0 голосов
/ 17 сентября 2009

Я написал многопользовательскую игру на основе клиента <> и закончил основы (это flash-клиент, написанный на ActionScript 3). Следующим шагом будет внедрение системы, которая позволит мне легко добавлять способности в игру.

Проблема здесь в том, что способность может делать так много вещей. Например. игрок A использует способность «чинить» игрока B, должно произойти следующее:

  • Игрок А отправляет на сервер сообщение с сообщением о действии
  • Игрок A теперь показывает анимацию "каст с ремонтом" на своем корабле.
  • Сервер должен сообщить всем игрокам, находящимся рядом с этим кораблем. A теперь имеет анимацию "Cast Cast"
  • Сервер должен увеличить «здоровье» игрока B, потому что он был восстановлен игроком A
  • Сервер должен сообщить всем находящимся поблизости игрокам, что у игрока B теперь другое значение здоровья
  • Сервер должен сообщить всем ближайшим игрокам, что игрок B должен показать анимацию «ремонтируется»

Это всего лишь пример, много вещей должно произойти для одной простой способности. Я мог бы войти в каждый объект и добавить строки кода только для этого заклинания. Однако это может привести к путанице, когда мне нужно будет добавить много (~ 50) способностей. Также обратите внимание, что некоторые способности делают другие вещи, а не другие, некоторые должны показывать анимацию, некоторые нет. Некоторым придется наносить урон, другим - увеличивать статистику и т. Д.

Итак, как такая «система способностей» обычно обрабатывается как на стороне клиента, так и на стороне сервера?

Ответы [ 2 ]

4 голосов
/ 17 сентября 2009

На стороне клиента никогда ничего не делать без согласия сервера. Таким образом, клиент должен только отправить запрос способности и необязательной цели или некоторого значения. Также клиент должен прослушивать сервер для любых команд. С другой стороны, сервер должен реализовывать функцию или классы (как вам удобно) для управления действиями способностей. Всякий раз, когда клиент запрашивает способность разыграть способность, должна быть вызвана функция. В качестве первой задачи, функция должна проверить предварительные условия. Если они терпят неудачу, клиент должен быть уведомлен. В противном случае сигнал о возможности восстановления использования должен быть передан клиенту. Затем функция находит и отправляет необходимые команды на любые близлежащие корабли при обновлении их статусов. Этот метод гарантирует, что способности не могут быть использованы клиентами.

Чтобы понять это, проверьте следующее, это для иллюстрации метода, поэтому не говорите мне, что не рекомендуется использовать так много ifs.

Клиент

function massRepair() {
    server.send("USE mass_repair;"); //no decisions in here
}

function recive(command, target) {
    if(command=="USE mass_repair OK")
        massRepairAnim.gotoAndPlay(0);

    if(command=="ANIM mass_repair") {
        massRepairAnim.setTarget(target);
        massRepairAnim.gotoAndPlay(0);
    }

    if(command==/SET ENERGY [0-9]/) {
         value=getValue(command);
         setEnergy(value);
    }

    if(command==/SET HEALTH [0-9]/) {
         value=getValue(command);
         setHealth(value);
    }

    if(command=="ANIM self_repair") {
        selfRepairAnim.gotoAndPlay(0);
    }

    if(command=="USE mass_repair FAIL NOENERGY") {
        display("Not enough energy to use the skill");
    }
}

somebutton.click=function() { massRepair(); }

Сервер

function userMassRepair(Ship owner) {
    if(owner.energy<30) {
        send(owner, "USE mass_repair FAIL NOENERGY");
        return false;
    }

    owner.energy-=30;
    send(owner, "SET ENERGY "+owner.energy); //every data sent is absolute
    send(owner, "USE mass_repair OK");

   foreach(ship in owner.shipsInRange(100)) {
        if(owner.ally(ship)) {
             ship.health+=10;
             ship.send("SET HEALTH " + ship.health);
             ship.send("ANIM mass_repair "+owner.position);
             ship.send("ANIM self_repair");
        }
   }
}
2 голосов
/ 17 сентября 2009

Похоже, что многое, но на самом деле это просто перестановка нескольких стандартных компонентов. Большинство действий будет состоять из изменений внутренних свойств и некоторых косметических средств, которые будут отображаться на клиенте, и существует всего несколько различных способов сделать это.

Вам нужно что-то вроде следующего:

  • стандартный способ отправки действий на сервер, который позволяет удобно извлекать произвольные параметры (поскольку каждое действие может иметь несколько очень специфических аргументов)
  • тип сообщения от сервера к клиентам, чтобы начать воспроизведение указанной анимации на указанном корабле
  • тип сообщения от сервера к клиентам, увеличивающий значение здоровья на корабле

Тогда ваш серверный код для упомянутого вами действия выглядит следующим образом:

if (message.type == REPAIR)
{
    repairer = message.actor;
    repaired = message.target;

    // Insert verification code here to check that the 2 ships are close enough,
    // that the repairer is entitled to perform this action, etc

    // Verification has passed: do the work
    broadcastToAllClients(new Message(type=PLAY_ANIM, target=repairer, value=REPAIR_CASTED));
    broadcastToAllClients(new Message(type=CHANGE_PROPERTY, target=repaired, proerty=HEALTH, value=5)); // 5 is the amount 
    broadcastToAllClients(new Message(type=PLAY_ANIM, target=repaired, value=BEING_REPAIRED));
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...