пятница, 9 октября 2015 г.

Немного о классах, точнее о их использовании.

    Все игровые объекты в BGE являются экземплярами классов, предоставляя пользователю широкий выбор возможностей для управления. Есть конечно нюансы, например новый экземпляр класса, наследующего базовый, невозможно создать "с нуля", обязательно нужно "мутировать" старый экземпляр, в офф. документации есть пример кода, его обязательно нужно прочитать. И есть один затык - " а как же собственно, созданным экземпляром управлять?" То есть как вызывать дописанные нами функции? Попробуем разобраться.
   



    Пишем определение тестового класса, он будет простейшим:

class a(bge.types.KX_GameObject):
    
    def __init__(self, old_owner):
        self.prop = 0
    
    def update(self):
        self.prop +=
        self.worldPosition[1] += 0.1

Как видно, расширенное определение класса при создании экземпляра всего-навсего добавляет базовому классу дополнительное (неигровое!!!) свойство и функцию .update(), которая прибавляет к значению этого свойства 1 и смещает экземпляр по глобальной оси Y на 0.1 будем считать что метра. Где-то  делаем отдельную функцию или вообще отдельный скрипт, который будет добавлять с неактивного слоя выбранный нами объект и дополнять его, как в примере кода.  Что-то вроде:

         # должно еще быть оформление функции или if sensor.positive:
    old = scene.addObject('Sphere')
    obj = a(old)

Всё, экземпляр создан, все функции по идее доступны, мы в любой момент можем вызвать obj.update() вручную, но сей пост затевался с целью прояснить вопрос, а как бы экземпляр сам себе вызывал функции, автоматом. Самый простой способ - создать в глобальном словаре, или еще где, список ссылок на экземпляры класса, нуждающиеся в обновлении. И потом просто пробегать его каждый тик циклом:

    for obj in bge.logic.globalDict['updateObjects']:
        obj.update()

Вполне подходит для всяких эмиттеров частиц, или для других объектов, нуждающихся в постоянном запуске одной и той же функции, причем скопом. Есть еще вариант всунуть функцию update в список pre_draw или post_draw объекта текущей сцены, но там есть еще подводные камни, типа невозможности нормального удаления объекта с помощью endObject(). Я этот способ рекомендовать не могу, поскольку сам не разбираюсь толком. Чисто посмотреть на код:

    def __init__(self, old_owner):
        self.prop = 0
        scene.pre_draw.append(self.update)

Функция .update будет исполнятся каждый раз при подготовке рендера, или после него. Оба предыдущих варианта вполне подходят, что бы организовать в .update чтение событий клавиатуры, или состояния сенсоров, к примеру. Но раз уж зашла речь о сенсорах, то зная, какой объект мы будем добавлять в сцену для последующего тюнинга, вполне возможно организовать на нём цепочку сенсор -> контроллер, типа "модуль", и указать для исполнения функцию типа такой:

def update(cont):
    own = cont.owner
    own.update()

Как-то так:

В таком варианте используется BGE-шный способ управления событиями, основанный на связке кирпичей и скриптов, получается более привычно, что для новичка немаловажно.  Каким способом воспользоваться, решайте сами. Если придумаете еще какой-нибудь, обязательно отпишитесь, интересно же.

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

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