Первая статья из цикла "делаем игру вместе". Делать мы будем ни что иное как мега РПГ всех времён и народов Ведь именно этого желают почти все начинающие геймдевелоперы, за исключением тех, конечно, кто делает GTA Для начала создадим структуру папок для нашей мегаРПГ megarpg (корневая папка) +modules (папка для созданных нами программных модулей) +res (папка с ресурсами игры) ++textures (текстуры) ++actors (анимированные персонажи) ++geometry (обычная геометрия) ++sound (звуки) Теперь создадим (пока пустые) файлы скриптов: в корневой папке: main.py в папке modules: __init__.py - этот файл информирует питон о том, что папка, в которой он находится является модулем, из которого можно экспортировать нужные нам классы и функции location.py - здесь у нас будут скрипты для работы с локацией control.py - здесь - скрипты управления - камера, мышь Пока хватит, приступим к коду. (Если ещё не запаслись подходящим редактором для питона, то сначала изучаем статью Быстрый старт) Открываем файл location.py и пишем Code # -*- coding: utf_8 -*- Это сообщит интерпретатору, что кодировка у нас будет utf-8. Она необходима для нормальной работы с кириллическими символами. Для земли в нашей локации мы будем использовать карту высот и класс GeoMipTerrain. Для этого импортируем нужный нам класс Code from pandac.PandaModules import GeoMipTerrain Теперь создадим класс gameLocation и процедуру его инициализации Code class gameLocation(): def __init__(self): self.terrain=GeoMipTerrain("Terrain") процедура __init__ всегда выплняется при создании нового экземпляра класса - это стандарт языка python, впрочем, об этом лучше почитать в любом учебнике по python-у. Так же как и о базовом синтаксисе. Поэтому будем считать, что хотя бы основы питона вы уже знаете (учебников и статей по питону в сети хватает). В процедуре у нас пока одна строчка, которая создаёт новый экземпляр GeoMipTerrain с именем "Terrain" Добавим к нашему классу новую процедуру loadTerrain для построения нашей земли на основе карты высот. В качестве второго (первым идёт обязательный self) параметра будем передавать имя файла, содержащего карту высот. Для тех, кто не в курсе - карта высот - обычно, файл, содержащий чёрно-белое изображение - чем темнее цвет, тем ниже уровень земли и наоборот. У меня карта высот - это файлик, созданный с помощью Different Clouds (Разностные облака) в гимпе. Аналогичный фильтр есть и в фотошопе, если кому-то удобнее он. Code def loadTerrain(self,hfFile): self.terrain.setHeightfield(Filename(hfFile)) self.terrain.setBlockSize(32) self.terrain.setFactor(64) self.terrain.setMinLevel(2) self.terrain.getRoot().reparentTo(render) self.terrain.getRoot( ).setSz (30) self.terrain.generate() self.terrain.setFocalPoint(base.camera) Первая строка - объявление нашей процедуры в дальнейшем я этого пояснять не буду и первой строкой буду считать уже непосредственно код, поэтому первая строка - self.terrain.setHeightfield(Filename(hfFile)) Этой строкой мы назначаем карту высот, которая будет передана в параметре hfFile созданному нами при инициализации террайну. Обратите внимание - мы используем Filename для чего, как и зачем - читать здесь. Ну и конечно нужно его импортировать - строка импотра теперь выглядит так Code from pandac.PandaModules import GeoMipTerrain, Filename Вторая строка - размер блока на основе которого будет строиться сетка - в нашем случае - 32 пикселя - т.е. изображение будет разбито на блоки 32х32 пикселя и на основе этого будет построена сетка. Третья строка - качество создаваемой сетки вблизи камеры. Забыл сказать сразу - GeoMipTerrain умеет динамически генерировать сетку в зависимости от расстояния до камеры - чем ближе камера, тем больше полигонов в сетке. Вот, качество этой сетки мы и устанавливаем третьей строкой Четвёртая строка - уровень минимальной детализации. По дефолту он 0 - максимальное качество, однако, мы его несколько снизим. Вообще говоря, эти параметры подбираются экспериментальным путём в зависимости от расстояния камеры до нашего террайна, разрешения карты высот, желаемого качества. Пятая строка - присоединяем нашу землю к корневому узлу сцены чтоб она была видна. почитать1 почитать2 Шестая - устанавливаем масштабирование по оси Z - вертикальной для придания видимости рельефу, т.к. изначально рельеф минимален. Седьмая - генерируем террайн на основе уcтановленных нами параметров Восьмая - назначаем узел, который будет считаться камерой для нашей земли и на основе положения которого будет рассчитываться уровень детализации. С генерацией пока закончили. Теперь нужно добавить задачу обновления нашего террайна при изменении положения камеры. Пишем процедуру для нашей задачи - всё в том же классе Code def update(self,task): self.terrain.update() #self.terrain.getRoot().setRenderModeWireframe() return task.cont тут всё просто - первая строчка обновляет террайн, вторая закомментирована - если её раскомментировать, то мы будем видеть сетку (Wireframe) террайна - это если интересно посмотреть как наш террайн генерируется. По поводу формы записи процедур для пандовского менеджера задач читать здесь Ну и добавим написанную процедуру в менеджер задач - для этого вернёмся к процедуре __init__ и допишем строку Code taskMgr.add(self.update,'location_update') taskMgr является глобальной переменной менеджера задач, которая создаётся при использовании DirectStart, так же как и некоторые другие базовые объекты, например, корневые узлы или камера. Мы конечно можем это всё создавать сами, но проще использовать готовый DirectStart. Переходим к главному файлу main.py Пишем следующее: Code # -*- coding: utf_8 -*- import direct.directbase.DirectStart from modules.location import gameLocation
loc=gameLocation() loc.loadTerrain('res/textures/heightfield.png')
run() Певая строка - понятно, уже пояснял. Вторая - Импортируем DirectStart о котором я только что говорил. Третья - Импортируем созданный нами модуль локации Четыре - создаём экземпляр нашей локации и присваиваем её переменной loc Пять - генерируем террайн - процедурой, которую мы только что с вами написали в модуле location.py. Естественно, карту высот нужно предварительно кинуть в res/textures Шесть - "Мотор!" Можно запускать, в итоге мы узреем серый экран с непонятной белой фигнёй Если покрутить её при помощи зажатой средней клавиши мыши, то станет ясно, что это всё же какая-то поверхность. Попробуйте повторить. Вот мой heightfield. P.S. Вопросы и обсуждение лучше вести в соответствующей ветке форума.
|