Рефакторинг "ударить" значения для игры - PullRequest
1 голос
/ 26 октября 2008

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

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

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

Вот что у меня сейчас есть:

    def calcBaseHitNumbers(self, dict):
        """Calculate character's base hit numbers depending on skill level."""

        self.skill_dict = dict

        self.rifle = self.skill_dict.get('CRM', 0)
        self.pistol = self.skill_dict.get('PST', 0)
        self.big_gun = self.skill_dict.get('LCG', 0)
        self.heavy_weapon = self.skill_dict.get('HW', 0)
        self.bow = self.skill_dict.get('LB', 0)
        #self.skill_tuple = (self.rifle, self.pistol, self.big_gun, self.heavy_weapon,
        #    self.bow)

#---Short range
##        for skill in self.skill_tuple:
##            self.base_hit_short = skill * 0.6
        self.charAttribs.bhCRM_short = self.rifle * 0.6
        self.charAttribs.bhPST_short = self.pistol * 0.6
        self.charAttribs.bhHW_short = self.heavy_weapon * 0.6
        self.charAttribs.bhLCG_short = self.big_gun * 0.6
        self.charAttribs.bhLB_short = self.bow * 0.6
#---Med range
        self.charAttribs.bhCRM_med = self.rifle * 0.3
        self.charAttribs.bhPST_med = self.pistol * 0.3
        self.charAttribs.bhHW_med = self.heavy_weapon * 0.3
        self.charAttribs.bhLCG_med = self.big_gun * 0.3
        self.charAttribs.bhLB_med = self.bow * 0.3
#---Long range
        self.charAttribs.bhCRM_long = self.rifle * 0.1
        self.charAttribs.bhPST_long = self.pistol * 0.1
        self.charAttribs.bhHW_long = self.heavy_weapon * 0.1
        self.charAttribs.bhLCG_long = self.big_gun * 0.1
        self.charAttribs.bhLB_long = self.bow * 0.1

Как бы вы изменили рефакторинг, чтобы он был более динамичным?


Редактировать: Я думаю, что я хочу сделать что-то вроде этого: Создайте кортеж (подобный тому, который я закомментировал) и повторите его 3 раза, каждый раз создавая новое значение (для каждого навыка) на основе модификатора для каждого конкретного диапазона. Затем полученное значение автоматически присваивается соответствующей переменной.

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

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

Ответы [ 5 ]

6 голосов
/ 26 октября 2008

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

SHORT_RANGE = 'S'
MEDIUM_RANGE = 'M'
LONG_RANGE = 'L'
SHORT_RANGE_MODIFIER = 0.6
MEDIUM_RANGE_MODIFIER = 0.3
LONG_RANGE_MODIFIER = 0.1

class Weapon(object):
    def __init__(self, code_name, full_name, base_hit_value,
                 short_range_modifier=None, medium_range_modifier=None,
                 long_range_modifier=None):
        self.code_name, self.full_name = code_name, full_name
        self.base_hit_value = base_hit_value
        self.range_modifiers = {
            SHORT_RANGE: short_range_modifier or SHORT_RANGE_MODIFIER,
            MEDIUM_RANGE: medium_range_modifier or MEDIUM_RANGE_MODIFIER,
            LONG_RANGE: long_range_modifier or LONG_RANGE_MODIFIER,
        }

    def hit_value(self, range, modifier=1):
        return self.base_hit_value * self.range_modifiers[range] * modifier

Оттуда вы можете создавать экземпляры оружия внутри вашего объекта персонажа следующим образом:

    self.rifle = Weapon('CRM', 'rifle', 5)
    self.pistol = Weapon('PST', 'pistol', 10)

И затем, если, скажем, персонаж стреляет из пистолета с близкого расстояния:

    hit_value = self.pistol.hit_value(SHORT_RANGE)

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

Конечно, следующим шагом после этого будет непосредственное моделирование оружия как подкласса оружия (возможно, с разбивкой на конкретные типы оружия, такие как пушки, луки, гранаты и т. Д., Каждое из которых имеет свои базовые значения) и добавьте класс Inventory для представления оружия, которое носит персонаж.

Все это довольно стандартная, скучная объектно-ориентированная процедура проектирования, но во многих ситуациях этот тип мышления быстро поднимет вас с ног и обеспечит хотя бы небольшую базовую гибкость.

1 голос
/ 26 октября 2008

Давайте посмотрим, понимаю ли я вас сценарий: у каждого оружия есть своя собственная точка попадания, поэтому у винтовки может быть 1, у тяжелого оружия может быть 2 и т. Д. Затем у каждого персонажа есть короткое, среднее и длинное значение, которое нужно умножить точка попадания оружия.

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

Тогда у персонажа есть одно или несколько видов оружия в зависимости от вашего игрового процесса. Вычислить точку попадания для конкретного оружия так же просто, как

current_weapon * self.medium

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

In Pseudo Python

class Weapon
    hit = 1
    #other properties of weapon

class Rifle(Weapon)
    #other properties of Rifle

class Pistol(Weapon)
    #other properties of Pistol

class Character
   weapon = Rifle()
   long=0.6
   def calcHit()
      return self.long*weapon.hit

john = Character()
john.weapon= Rifle()
john.calcHit
0 голосов
/ 27 октября 2008

У меня был бы класс для атрибутов персонажа (чтобы у вас не было кучи вещей в классе персонажа) и класс для атрибутов оружия:

class WeaponAttribute(object):

    short_mod = 0.6
    med_mod = 0.3
    long_mod = 0.1

    def __init__(self, base):
        self.base = base

    @property
    def short(self):
        return self.base * self.short_mod

    @property
    def med(self):
        return self.base * self.med_mod

    @property
    def long(self):
        return self.base * self.long_mod


class CharacterAttributes(object):

    def __init__(self, attributes):
        for weapon, base in attributes.items():
            setattr(self, weapon, WeaponAttribute(base))

Имейте объект CharacterAttributes в классе персонажа и используйте его следующим образом:

# Initialise
self.charAttribs = CharacterAttributes(self.skill_dict)
# Get some values
print self.charAttribs.CRM.short
print self.charAttribs.PST.med
print self.charAttribs.LCG.long
0 голосов
/ 26 октября 2008

Какое чувство динамики вы имеете в виду? Что может варьироваться - количество навыков или весовые коэффициенты, количество диапазонов (короткий, средний, длинный) или все эти?

Что происходит с (например) значениями bhPST_ * после этого - объединяются ли они в одно число?

Одна вещь, которая бросается в глаза, заключается в том, что список навыков запрограммирован в коде - я был бы склонен заменить переменные bh методом

Итак (пожалуйста, примите во внимание, что я не знаю о Python первым делом :))

def bh_short(self, key)
  skill = self.skill_dict.get(key, 0)
  return skill * 0.6

Теперь вы можете хранить список навыков, которые способствуют достижению очков жизни, и повторять их, вызывая bh_short и т. Д.

Возможно также передать диапазон (long med short) функции или вернуть все три значения - все это зависит от того, что вы собираетесь делать дальше с вычисленными хитпоинтами.

В основном нам нужна дополнительная информация о контексте, который будет использоваться в

0 голосов
/ 26 октября 2008

@ Vinko: возможно, создайте calcBaseHitNumbers, выполните внутреннюю проверку «если не self.calculatedBase:» и просто не выполняйте никаких операций, если это было сделано ранее. Тем не менее, я не вижу насущной необходимости в предварительном расчете этой информации. Но я не эксперт по производительности Python.

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