воскресенье, 27 декабря 2015 г.

Всех с наступающим! И немного про агрегатирование.

    Агрегатирование - удобная вещь. Заключается оно в том, что экземпляр класса А со всеми своими данными и методами, используется как свойство класса Б. Собственно, ничего удивительного - каждый раз, когда мы прописываем в определении какого-то класса свойство, например типа int, то происходит именно агрегатирование, поскольку тип int - это и есть определение объекта класса, а свойство этого типа - экземпляр его. Для чего удобно агрегатирование? Во-первых, пользовательские типы данных - это удобно, где бы мы их не использовали. Во-вторых, мы таким образом получаем дополнительное подпространство, если можно так выразится, имен. В-третьих, часть методов класса вполне можно перенести в определение агрегатируемого класса, а там уже и дополиморфизма и прочих ништяков недалеко...
    Вот, приспичило мне на днях сделать нормальную реализацию состояний клавиатуры для pygame. Что бы можно было в игровом цикле проверить, нажата ли клавиша "М" и как давно. Почему я занялся этой библиотекой - другой вопрос, но дело в том, что либо я не нашел в описании API соответствующей функции, хотя вроде искал, либо её там отродясь не было. Точнее оно там есть, но зело неудобно пользоваться- доступ только по числовому индексу клавиши, и из всех состояний - только нажата клавиша, или отпущена, причем при зажатой клавише событие не генерируется. То есть если вам нужно смещение персонажа при нажатой стрелочке "вправо", то на эту кнопку придется нажимать со скоростью пулемета "Максим"Зажатой и удерживаемой стрелочки для него не существует. Не суть важно, главное, что в любой момент можно запросить состояние всех клавишь, и получить кортеж с кучей 0 и парой единиц, индексы которых соответствуют числовому коду клавишь. А имя клавиши можно узнать также с помощью функции библиотеки pygame, просто скормив ей индекс.


class keyboard(object):
    def __init__(self):
        keys = pygame.key.get_pressed() # получаем кортеж текущих состояний клавишь
        self.buttons = buttonList(keys)  # создаем список кнопок клавиатуры
        self.status = keyStatus() # дописываем в объект переменные

class buttonList(object):
    """ объект хранит в своих переменных объекты - кнопки клавиатуры"""
    def __init__(self, keys):
        for index in range(len(keys)):
            currName = pygame.key.name(index)
            self.__dict__[currName] = button(index, currName, keys[index])

class button(object):
    """объект реализует клавиши клавиатуры"""
    def__init__(self, index, name, state):
        self.index = index
        self.name = name
        self.currentState = state

class keyStatus(object):
    """ объект просто хранит переменные в удобном для использования виде"""
    def __init__(self):
       self.FREE = 0
       self.DOWN = 1
       self.HOLD = 3
       self.UP = 4


За работоспособность кода ручаться не буду, писал прямо с мозга, но суть понятна - объект одного типа записывается в свойство объекта другого типа, а уже тот в свойство третьего. Там еще кучи функций не хватает для полноценной работы, типа обновления состояния клавишь и прочего. Полная версия умеет вроде как так:
X = 1000
key = keyboard()
key.update()
if key.buttons.escape.status == key.status.DOWN:
    # QUIT на самом деле здесь конкретный код выхода из игрового цикла
if key.buttons.right.status == key.status.HOLD:
    X = X - 1
Определение статуса кнопки я здесь не прописал, как и таковое свойство, но оно в оригинале есть, как и еще куча методов.
На что похоже? Правильно, pygame.key.name() реализованно аналогичным образом.

Комментариев нет:

Отправить комментарий