пятница, 23 февраля 2018 г.

Прячься, кто может! Инкапсуляция в классах. Кажется, выхожу на оперативный простор...

На довольно долгое время я застрял. Хорошо так застрял, давно со мной такого не было. Причиной этому стала "размазанная" по нескольким скриптам ошибка в иде недостающих аргументов для функций. А учитывая то, что функции вызывались через try-except  с перхватом исключения, и внешне все выглядело благообразно... Едиснтвенно, что выглядело безобразно- так это целераспределение для ботов. Боты считали противниками своих собратьев и не стреляли по своим только потому, что в условие пуска был заложен запрет на стрельбу по объекту с одинаковыми для бота "цветами". Это выглядело смешно, если бы не отняло у меня три недели. Правда, насчет "отняли", я погорячился. По-всякому измываясь над собственным кодом, я научился с подсказки dron-a проводить инкапсуляцию внутри кода. Кода класса, я имею в виду. Теперь, значит, кроме наследования, еще и инкапсуляция... Собственно говоря, ошибка лежала в несколько другой плоскости, но это именно тот случай, когда не было бы счасться, да несчастья помогло. Ее устранение свелось всего-начсего к тщательной проверке "шапок" модулей и наборам переменных в скобках после названий функций...
Инкапсуляция - это другое дело. Она позвоялет исключить "накладок"  в поеведении объектов, "пряча" данные внутри класса от внешнего мира. Вообще-то до них все равно добраться можно, но сделать это гораздо сложнее. Основательной переделке подверглись все классы боевых самолетов, причем делалось это неоднократно, по мере выяснения свойств инкапсуляции и осознания области ее применения. Ниже приводится класс для МиГ-23БН. Мне влом его резать, проще клавишами копировать-вставить. Да и образцом в случае чего послужит.

import bge
#import UnitAir_engine

from ClassUnitAir  import UnitAir

class MiG23BN_Libya_(UnitAir):
    import UnitAir_engine as __UnitAir_engine
 
    def __init__(self, old_owner):
        UnitAir.__init__(self, old_owner)
   
    __air = True
    __airtype = "JET"
    __dron = False
    __multiengine = False
    __airbrake = True
    __slats = True
    __flaps = True
    __swingwing = True
    __canopy = True
    __chassy = True
    __yaw = True
   
    #Летательный аппарат
    def is_AIR(self):
        return self.__air
    #Подтип ЛA - вертолет, самолет (реактивный или внитовой)
    def is_AIRTYPE(self):
        return self.__airtype
    #Пилотируемый или БПЛА
    def is_DRON(self):
        return self.__dron
    def is_FLAPS(self):
        return self.__flaps
    def is_SLATS(self):
        return self.__slats
    def is_SWINGWING(self):
        return self.__swingwing
    def is_AIRBRAKE(self):
        return self.__airbrake
    #Одно- или многодвигательный
    def is_MULTIENGINE(self):
        return self.__multiengine
    def is_CHASSY(self):
        return self.__chassy
    def is_CANOPY(self):
        return self.__canopy
    def is_YAW(self):
        return self.__yaw
   
   
    #######################################
    def is_CANOPY_Device(self):
        CANOPY_Device = [
                        ["Cnp_",[0.0087,0.0,0.0],"rotat"]
                        ]
        return CANOPY_Device
    def is_POINT_CANOPY(self):
        reper = [0, 114]
        return reper
    ########################################
    def is_FLAPS_Device(self):
        FLAPS_Device = [
                        ["FlpR_",[-0.0087,0.0,0.0],"rotat"],
                        ["FlpL_",[-0.0087,0.0,0.0],"rotat"]
                        ]
        return FLAPS_Device
    def is_POINT_FLAPS(self):
        reper = [-50, 0, 100]
        return reper
   
   
    ######################################
    #Наличие-отсутствие предкрылков
    def is_SLATS_Device(self):
        SLATS_Device = [
                        ["SltR_",[-0.0087,0.0,0.0],"rotat"],
                        ["SltL_",[-0.0087,0.0,0.0],"rotat"]
                        ]
        return SLATS_Device
    def is_POINT_SLATS(self):
        reper = [0, 40]
        return reper
   
    #####################################
    #Наличие-отсутствие крыла изменяемой стреловидности
    def is_POINT_WINGS(self):
        reper = [0, 300, 550]
        return reper
   
    def is_WINGS_Device(self):
        WINGS_Device = [
                        ["WngR_",[0.0,0.0,-0.00174],"rotat"],
                        ["WngL_",[0.0,0.0,0.00174],"rotat"]
                        ]
        return WINGS_Device
   
    ####################################
    #Наличие-отсутствие воздушных тормозов
    def is_AIRBRAKE_Device(self):
        AIRBRAKE_Device = [
                           ["ArbUR_",[-0.00783,0.0,0.0],"rotat"],
                           ["ArbUL_",[-0.00783,0.0,0.0],"rotat"],
                           ["ArbDR_",[0.00696,0.0,0.0],"rotat"],
                           ["ArbDL_",[0.00696,0.0,0.0],"rotat"]
                          ]
        return AIRBRAKE_Device
   
    def is_POINT_AIRBRAKE(self):
        reper = [0, 100]
        return reper
   
    ####################################
    #Наличие-отсутствие рулей направления
    def is_YAW_Device(self):
        YAW_Device = [
                      ["Rdd_",[-0.0018,0.0036,-0.0174],"rotat",-1],
                      ["Rdd_",[-0.0018,0.0036,-0.0174],"rotat",1]
                     ]
        return YAW_Device
    def is_POINT_YAW(self):
        reper = [-25, 25]
        return reper
   
    ####################################
    #Наличие-отсутствие стабилизатора
    def is_ROLL(self):
        return True
    def is_ROLL_Device(self):
        ROLL_Device = [
                      ["ElvL_",[-0.0087,0.0,0.0],"rotat",-1],
                      ["ElvR_",[0.0087,0.0,0.0],"rotat",-1],
                      ["ElvL_",[-0.0087,0.0,0.0],"rotat",1],
                      ["ElvR_",[0.0087,0.0,0.0],"rotat",1]
                     ]
        return ROLL_Device
    def is_POINT_ROLL(self):
        reper = [-20, 20]
        if self.WINGS > 300:
            reper = [-13, 13]
        #print(reper)
        return reper
    #Наличие-отсутствие стабилизатора
    def is_ROLLwings(self):
        return True
    def is_ROLLwings_Device(self):
        ROLLwings_Device = [
                            ["InpR_",[0.0,0.0,0.0],"rotat",0],
                            ["InpL_",[0.0,0.0,0.0],"rotat",0]
                           ]
                   
        if self.ROLLwings < 0 and self.rollSelf == -1:
            ROLLwings_Device = [["InpL_",[0.0174,0.0,0.0],"rotat",-1]]
        elif self.ROLLwings > 0 and self.rollSelf == 1:
            ROLLwings_Device = [["InpR_",[-0.0174,0.0,0.0],"rotat",1]]
        elif self.ROLLwings < 0 and self.rollSelf == 0:
            ROLLwings_Device = [["InpL_",[0.0174,0.0,0.0],"rotat",1]]
        elif self.ROLLwings > 0 and self.rollSelf == 0:
            ROLLwings_Device = [["InpR_",[-0.0174,0.0,0.0],"rotat",-1]]
        elif self.ROLLwings < 0 and self.rollSelf == 1:
            ROLLwings_Device = [["InpL_",[0.0174,0.0,0.0],"rotat",1]]
        elif self.ROLLwings > 0 and self.rollSelf == -1:
            ROLLwings_Device = [["InpR_",[-0.0174,0.0,0.0],"rotat",-1]]
       
        #print(self.ROLLwings,self.rotatY)
        return ROLLwings_Device
    def is_POINT_ROLLwings(self):
        reper = [-45, 45]
        if 299 < self.WINGS < 549:
            reper = [-30, 30]
        elif self.WINGS > 549:
            reper = [0, 0]
        #print(reper)
        return reper
   
    ####################################
    #Наличие-отсутствие стабилизатора
    def is_PITCH(self):
        return True
    def is_PITCH_Device(self):
        PITCH_Device = [
                      ["ElvL_",[-0.0087,0.0,0.0],"rotat",-1],
                      ["ElvR_",[-0.0087,0.0,0.0],"rotat",-1],
                      ["ElvL_",[-0.0087,0.0,0.0],"rotat",1],
                      ["ElvR_",[-0.0087,0.0,0.0],"rotat",1]
                     ]
        return PITCH_Device
    def is_POINT_PITCH(self):
        reper = [-17, 49]
        return reper 
           
    #################################################
    #Методы движения, работы ЛОД и прочего
    def engine(self):
        self.__UnitAir_engine.engine(self)
 
def mutate(cont):
    MiG23BN_Libya_(cont.owner)

Самая вкусная строчка почти в самом низу:
self.__UnitAir_engine.engine(self)
Символ __ означает как раз эту самую инкапсуляцию. Вызов идет изнутри самого класса и других объектов не касается. Если посмотреть на класс с методами, то там тоже можно встретить переменные вида __air. Это специфические переменные, сообщающие, например, что у МиГ-23БН один двигатель, крыло с изменяемой стреловидностью, есть тормоза, закрылки и прочее. Это чисто его внутреннее дело.
Теперь же движение объекта из логического кирпича в пусковом файле выглядит так:
ge
import json
import sys
import random

cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()
import sys
pathFolder = own.unitName + own.unitNation + "/folderPy"
sys.path.append(bge.logic.expandPath("//Aircraft/" + pathFolder))

unitmodule = own.unitNode + own.unitNation + "NodeScript"
unit_module = __import__(unitmodule)

UNITCLASS = own.unitNode + own.unitNation
UNIT_CLASS = __import__(UNITCLASS)


#Импорт из папки для юнитов ЛА модклей
import UnitAir_engine
import UnitAir_LODes
import UnitAir_shoot
import CONTROL_Operations
import mathutils

import UnitGround_Sensores
import UnitGround_Artillery
import UnitGround_LODes

import Weapon
ArbitrGame = scene.objects["ArbitrGame"]

#############################################
#############################################
def UnitAir():
    cont = bge.logic.getCurrentController()
    own = cont.owner
   
    #if len(own.idTarget) > 0:
     #   print(own.unitName, scene.objects.from_id(int(own.idTarget[0])).unitName)     
         
   
    if own.controlUnit != "Statist":
        own.globalTargetList = ArbitrGame.UNITS[0][own.targetType][own.target]
        #UnitAir_engine.engine(own, scene)
       
        own.engine()
       
        unit_module.correctData(own)
   
       
    #Работа уровня детализации идет ВСЕГДА
    UnitAir_LODes.LODes(own)
       
   
Думаю, извивы моей мысли понятны - импорттируем класс по названию - MiG-23BN_Libya_.py, а из него тащим метод движения, который, в свою очередь, дергает скрипт движения. Если посмотреть класс, то в начале можно найти строку import UnitAir_engine.  Это он и есть...
Теперь подобные вещи придется делать для оружия, от греха подальше. А то вдруг нацелятся все ракеты типа Р-23Р на один "Фантом" (который еще делать надо).
Простор для инкапсуляции еще есть, но не будем пока о грустном. После отлова ошибки и доводки сриптов, наконец, боты стали вести себя правильно. А именно - разворачиваться в сторону противника, сканировать местность, сбрасывать баки, разгоняться и маневрировать, и даже стрелять... Вновь ожила СПО, заработали звуковые маркеры. Короче, жизнь стала налаживаться.
             
             
     

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

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