Каков наилучший способ хранения глобальных / статических переменных в продвинутой Java-игре? - PullRequest
4 голосов
/ 23 марта 2011

Я - программист-самоучка, поэтому не знаю, как правильно делать много вещей.

Я написал несколько простых игр (таких как Астероиды, Снейк и т. Д.)..) Так что я знаю, как сделать основы.Сейчас я работаю над более сложной игрой, ролевой игрой с зомби.Я начал писать, не задумываясь о том, как я это структурирую.Сначала я создал класс 'item', чтобы хранить данные для простого элемента (стоимость, вес, урон).Затем я создал класс для хранения переменных для игрока (здоровье, броня, предметы).В конце концов я создал меню, в котором были переменные, необходимые для хранения того, какой пункт меню в данный момент выбирается.

Вскоре я понял, что у меня много глобальных переменных, которые мне нужно как-то хранить.Мне нужно было бы использовать переменные в отдельных классах (например, класс, который печатает на экране, должен знать расположение всего).

Итак, как лучше всего написать большое количество глобальных переменных?Как я уже сказал, я не знаю, как правильно делать вещи, и я не могу найти хороший сайт, который объясняет объявление переменных в больших масштабах.Могу ли я создать класс, содержащий все переменные, и сделать так, чтобы класс 'Main' имел статическое объявление этого класса 'VariableStorage'?

Заранее спасибо!

PS Пожалуйста, предоставьте ссылки, есливы можете!: D

Ответы [ 3 ]

8 голосов
/ 23 марта 2011

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

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

Как обычно это делается, примерно так:

class Player {
    String name;
    Location loc;
    List<Item> inventory;

    void pickup() {
        if (itemsOnGround.isEmpty()) {
            throw new InvalidActionException("There appears to be nothing to pick up here");
        }
        inventory.add(loc.itemsOnGround.get(0));
        loc.itemsOnGround.remove(0);
    }
}

class Location {
    List<Items> itemsOnGround;

    /** null if there isn't a monster here */
    Monster monster;
}

class Game {
    Player player;
}

class Ui {
    Game game;

    void keypressed(char key) {
        try {
            if (key == 'p') {
                game.player.pickup();
            } else {
                showKeyboardHelp();
            }
        } catch (InvalidActionException e) {
            showErrorMessage(e.getMessage());
        }
    }
}

Как вы можетевидите, не должно быть статического поля.Это позволяет вам переключать игры без перезапуска приложения (просто перезапись всех статических полей может привести к ошибкам - что если вы забудете одно? Должен ли игрок, получивший амулет yendor в предыдущей игре, действительно перенести?), Позволяя при этом создаватьдополнительные предметы, игрок (или персонажи, похожие на игрока, обычно называемые NPC в RPG lingo) на ваше усмотрение, и все же позволяет логически группировать связанные поля в классы, так что вы можете найти их снова, когда вы снова посмотрите на свой код через несколько месяцев.

Если ваша игра становится нетривиальной, вам также следует обратить внимание на инкапсуляцию.Политика, которую я обычно использую в небольших проектах, заключается в том, что поля могут быть записаны только кодом из класса, который их объявляет, но могут считываться по всей программе.В более крупном проекте, особенно если в нем участвуют несколько человек, вы, вероятно, захотите, чтобы компилятор принудительно применил это, сделав поля приватными и получив доступ к их состоянию через открытые методы (часто называемые «получателями»), написанные для этой цели.

1 голос
/ 23 марта 2011

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

//A possible heirarchy
PlayableCharacter
|-Stats
| |-int totalHealth
| |-int currentHealth
| |-int speed
| \-int strength
|
|-List<Equipment> inventory
|-Helmet head //Helmet would be a subclass of Equipment
|-HandEquipment leftHand
|-HandEquipment rightHand
|-ChestEquipment torso
\-LegEquipment legs

Со структурой организации, которая соответствует вашим потребностям и является хорошей абстракцией игрового мира, доступ к вашим переменным будет простым и значимым.

public int getAttackLevel() {
  return leftHand.getAttackPoints() + 
      rightHand.getAttackPoints() + 
      stats.getStrength();
}

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

GameVariables
|-LocationVariables
| |-int worldX
| |-int worldY
| \-int worldZ
|
|-QuestVariables
| |-String questName
| \-double questProgress
|
|-GameSettings
| |-int resolutionX
| |-int resolutionY
| \-Difficulty difficultyLevel
|
| //And so on....
1 голос
/ 23 марта 2011

Нет одного ответа, который можно дать.В общем, «множество глобальных переменных» - это анти-паттерн - тот, кто не должен знать, где находится все, не должен уметь - таким образом, эта часть вашего кода не может его испортить.Так что принимайте это к сведению.

Вам нужен способ узнать местоположение всех объектов?Например, создайте класс ObjectMap и поместите туда все местоположения.

Опять же, вы всегда можете иметь что-то вроде

public class Everything {
  public static HashMap<Object, Object> everythingHolder = new HashMap<Object, Object>();
}

, но если вы продолжите в том же духе, ваш кодочень скоро станет непригодным.

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