Главная › Форумы › Blender Game Engine (BGE) › Курс по BGE от drdotmom › Ответ в теме: Курс по BGE от drdotmom
Глава 3.
Физика в Rally Cross. Или «учимся читать» + продолжение к теме логики.
Загнул я про построчное чтение физики машинки — не нужно это. Чуть позже поймёте почему.
Физика Rally Cross базируется на небольшом примере.
Собственно — к первичному варианту мало чего добавилось — лишь корректировки переменных да всякие мелочи вроде нормальной работы сцепления с дорогой, адекватной управляемости через лёгкий занос и более-менее приятной динамики ускорения (а с недавних пор ещё и зависимость мощности от «оборотов» (тык по RallyCross в этой главе — на ЯД исходник(ну, или тут)). Сразу скажу, что это только тестовая версия обновления и она не содержит трассы и интерфейса!
Ну, не суть. Сейчас-то речь идёт о физике.
Вам потребуется записать новое слово:
Констреинт, Constraint. Это физическая связь объектов. Лучший пример такой связи — две сосиски в одной оболочке. Та сосиска, которая будет дочерней — вращается свободно, но только относительно «главной» сосиски. Констреинт же не только создаёт эту связь, но и ограничивает её. Констреинт автомобиля, о котором идёт речь ниже — значительно сложнее и включает в себя несколько связей + подвеску.
Итак, вся логика машинки находится в трёх скриптах:
1. CarSetup. Этот скрипт определяет положение колёс, их размеры, направение и т.д.
2. Suspension. Этот скрипт, как понятно из названия — по подвеске. В нём находятся параметры, отвечающие за жёсткость подвески на сжатие, усилие отбоя и поперечную стабилизацию.
3. Powertrain. Содержит в себе кучу регулировок — там и мощность двигателя, и сцепление колёс, и клавиши управления — всё-всё-всё, чего нет в двух прошлых скриптах.
Все переменные упаковываются в аккуратные функции, превращаясь в аргументы для одной единственной функции — bge.constraints.getVehicleConstraint
Да, вот так просто. Фактически эта функция — это здоровенная такая кнопка «сделать красиво».
Всё, что перечисленно в этих трёх скриптах — является упаковкой аргументов для красивого вида кода и удобного редактирования.
Все «упаковки» можно определить по заголовку «def имя_функци()»
На примере Tire_Objects():
def Tire_Objects(): //создаём функцию
frontDriver = "FLWheel" //Переднее левое колесо
frontPassenger = "FRWheel"//
rearDriver = "RLWheel"//
rearPassenger = "RRWheel"//
scene = bge.logic.getCurrentScene()// Сокращение функции "текущая сцена"
objList = scene.objects// Сокращение функции "получить объекты из текущей сцены
tire_0 = objList[frontDriver]//присвоение объекта-колеса из сцены переменной tire_0
tire_1 = objList[frontPassenger]//
tire_2 = objList[rearDriver]//
tire_3 = objList[rearPassenger]//
return (tire_0, tire_1, tire_2, tire_3)//Перечисление. Эти переменные (в полном виде типа bge.logic.getCurrentScene().objects['имя колеса1'] ) функция отправит тогда, когда её вызовут.
На самом деле можно было бы и сократить до:
def Tire_Objects(): Создаём функцию
scene = bge.logic.getCurrentScene() Текущая сцена
objList = scene.objects Объекты в текущей сцене
tire_0 = objList["FLWheel" ] Присвоить переменной tire_0 объект из текущей сцены с именем FLWheel
tire_1 = objList"FRWheel"]
tire_2 = objList"RLWheel"]
tire_3 = objList"RRWheel"]
return (tire_0, tire_1, tire_2, tire_3) Перечисляем то, что функция вернёт при вызове.
Но, мысль кодера сложна и он почему-то решил, что будет круто создать 4 лишних переменных.
Иначе говоря — мы можем получить все 4 колеса всего одной функцией — Tire_Objects()
Например:
objects=Tire_Objects()
objects.localScale=[2,2,2]
Таким образом одновременно увеличив размер всех колёс. (правда в самом скрипте это не работает ищ-ща определённых особенностей констреинта)
Далее — что такое vehicle ID?
vehicleID указывает на тип констреинта и объект, на который этот констреинт накладывается.
Иначе говоря vehicleID это сокращение bge.constraints.getVehicleConstraint(bge.constraints.createConstraint(bge.logic.getCurrentController().owner.getPhysicsId(), 0, 11).getConstraintId())
Что переводится как «Констреинт автомобиля (создать констреинт для(текущего контроллера).получив его физический идентификатор и применив аргументы 0 и 11, которые являются то ли типом констреинта, то ли ограничениями, то ли осями (фиг его разберёт короче. Я так и не смог найти на это ответа )»
Фактически чувак просто взял и грамотно, чисто и красиво подготовил переменные для установки оных как аргументов к констреинту. Местами, правда, перестарался и получилась фигня, как с Tire_Objects(). Бонусом лишняя регулировка поворачивающих колёс в CarSetup, которая не работает.
Почему во многих функциях присутствует точка? Что это и зачем?
Я до знакомства с bge python пописывал на gml и общий принцип работы кода знал, но эти точки сожгли мой стул. Без хорошего примера тут определённо не обойтись:
Мы, допустим, имеем большой дом. В доме есть коридор, который ведёт к разным дверям. Разные двери открывают разные комнаты, в каждой из которых свои элементы. Чайник, ванная, кровать, окно и т.д.
Таким образом, что бы использовать определённый элемент нам нужно пройти к нему.
коридор.комната.кухня.чайник
Как-то так.
Для того, что бы сослаться на определённый актуатор — нам нужно пройти довольно большой путь:
bge.logic.getCurrentController().actuators ["Актуатор1"]
bge.logic.getCurrentController().actuators ["Актуатор2"]
Мы можем это дело исравить
#1
qwerty=bge.logic
qwerty.getCurrentController().actuators ["Актуатор1"]
qwerty.getCurrentController().actuators ["Актуатор2"]
#2
cont=bge.logic.getCurrentController()
cont.actuators ["Актуатор1"]
cont.actuators ["Актуатор2"]
#3
act = bge.logic.getCurrentController().actuators
act["Актуатор1"]
act["Актуатор1"]
#
Все 3 варианта равнозначны. Другое дело — целесообразность и удобство использования\чтения.
т.к. писать много мне лень, да и не получилось с физикой машинки ибо всё слишком просто — опишу как пользоваться API документацией.
Использование документации.
В Game Engine Modules вы найдёте все функции, работающие чисто с bge.
Game Types (bge.types) — тут имеются все актуаторы, сенсоры и контроллеры. Чисто технически они сами по себе вам не нужны, однако в них можно найти функции актуаторов, что уже значительно полезнее.
Так, например, для актуатора Action (BL_ActionActuator(SCA_IActuator)) вы можете увидеть список всех регулировок вроде начального кадра, конечного, текущего и т.д.
Для актуатора Sound( KX_SoundActuator(SCA_IActuator)) — pitch, громкость, пауза и т.д.
Использовать эти функции просто:
envSound = cont.actuators ["Sound_wind"]
envSpeed = (speed*0.02)+.3
envSound.pitch = abs(envSpeed)
if impulse.positive:
cont.activate(envSound)
Эта функция активирует актуатор Sound с именем ‘Sound_Wind’, присваивая в процессе значение pitch, в зависимости от скорости автомобиля (abs превращает любое значение скорости в положительное)
Аналогично можно и с любым другим актуатором:
action = bge.logic.getCurrentController().actuators ["FGHY"]
action.frame=35
action.activate
Установит Action актуатору с именем FGHY 35 кадр.
Иначе говоря — если вы видете регулироку у актуатора и хотите её поменять кодом или вовсе поставить зависимость и менять в процессе игры — вы можете найти её в интересующем вас Актуаторе в разделе Game Types.Более того — там можно найти даже то, чего нет в настройках кирпичиков.
Game Logic (bge.logic)
В первую очередь в логике нас интересуют:
bge.logic.getCurrentController()
bge.logic.getCurrentScene()
первая функция управляет текущим контроллером (объектом, на котором был запущен скрипт). Предоставляет доступ ко всему — от сенсоров-актуаторов до переменных и настроек физики объекта.
Вторая функция предостовляет нам доступ к объектам и настройкам всей сцены. Через неё мы можем как связаться с любой информацией от другого контроллера, так и изменить активную камеру, настройки освещения и, даже, создавать копии объектов.
В остальном функция огромная и может менять количество проходов физики\логики за шаг, записывать анимацию, закрывать игру или открывать из других файлов. Ех, славные были времена, когда я с GML возился, где каждая функция означала одно единственное действие =\
Rasterizer (bge.render). Как понятно (или не очень) из названия — содержит в себе все функции, касающиеся растеризации (см Часть1). Это и тип рендера (GLSL или Multitexture), и разрешения\V-Sunc\AA\mipmapping — вся вот эта вот лабуда. Может также создавать скриншоты в файл, показывать фпс и дэбаг переменных\физики, что просто незаменимая вещь, если вы хотите сделать менюшку с настройками перед игрой.
Video Texture (bge.texture) содержит в себе функции, касающиеся чисто анимированных текстур. Если вам хочется добавить в игру видеоролик, написать свой шейдер, использующий текстуру или изменить текстуру объекта в процессе игры — вам сюда.
Game Keys (bge.events) отвечает за обработку событий клавамыши.
Пример:
Wkey=bge.events.WKEY
if Wkey.positive:
действие
Действие произойдёт по нажатию на клавишу. вроде всё просто)
Physics Constraints (bge.constraints) — это констреинты. Функции, содержащиеся в этом разделе помогут вам правильно настроить физические связи между объектами (например открывающиеся двери авто после аварии или дверь, которая будет открываться брошеным в неё камнем)
Application Data (bge.app) поможет вам, если вы хотите проверить версию блендера соседа, открывшего вашу игрушку(если я правильно понял), определить, подключен ли джойстик.
Ну, на этом пока всё. Меня пугает эта тишина. Вы хоть отпишите, что эту фигню хоть кто-то читает) А то вдруг я пишу просто так) Да и интересно — может есть какие пожелания к следующим главам, способе подачи или ещё чего.