Меню Сайта
Главная
Чат
__________________
Naruto TV-1
Naruto TV-2 Shipudenn
Naruto MOVIE-3
Naruto MOVIE-4
Naruto Приколы-Online
____________________
Windows XP
Linux
Vista
_______________
Games
3D_Модели
Програмы нужные Для Создания ИГР
ГАЛЕРЕЯ СКРИНШОТОВ из УРОКОВ
_______________________
--Blitz3D для начинающих---
Первая комната Blitz3d---
--Основы Cоздания Cетевых Игр---
Создание чата---
--Спрайты и Tекстуры---
Моделирование---
--Создание Серьезных Уровней---
Создание Kосмической Aркады---
--Звук, музыка и Интерфейс---
Создание основ Pолевой Игры---
--Простейший First-Person Шутер---
--Пиктограмма exe-файла---
___________________
Обои для Рабочего Стола
_________________
Раздел Банеров
Друзья-Сайта
Аниация и кправление камерой---
Redact
 

ToP Sites http://mo3del.ru/ http://mir3d.3dn.ru/ http://sw-in.narod.ru/

--Создание Серьезных Уровней---

 Создание серьезных уровней

9.1.  Ознакомление  с редактором Cartography Shop
    Для создания внутренних лабиринтов существует десяток редакторов, которые в той или ной степени позволяют проектировать карты в формате совместимом с
Blitz3D. Но так как  Blitz3D понимает форматы .X, .3DS, .MD2 и собственный .B3D и уровень при создании в сторонних редакторах проектируется как неделимое целое, то это не очень удобное решение. Поясним на примере: допустим мы создали лабиринт из нескольких комнат в редакторе MilkShape и экспортировали его в формат .3DS или .X. Загрузив уровень в нашу игру, сделанную на Blitz3D мы сможем двигаться в этом лабиринте, но это будет целостный лабиринт, а потому разные объекты интерьера нам придется грузить отдельно. Если же мы создадим объекты интерьера в этом редакторе, то будучи экспортированными в .3DS или .X формате они будут частью уровня и мы никак не осуществим с ними взаимодействия. А если в нашей игре стоит задача, допустим, щелкнуть мышкой на шкаф и достать оттуда конверт, затем щелкнуть на стул и сдвинуть его с места? Увы, мы будем не в состоянии это осуществить!  У Blitz3D правда еще есть возможность грузить уровни от игры Quake3 в формате .BSP, но в этом случае, понадобится сама игра Quake3, чтоб брать нужные текстуры, и кроме того понадобится нахождение конвертеров для созданных уровней, потому что Blitz3D не всегда может понять .BSP файл, созданный в разных редакторах.
   Разрешение этого конфликта нашлось и имя ему - Cartography Shop! Нельзя сказать, что это идеальное средство, этот редактор еще в стадии разработки (на сегодняшний момент стабильной является версия 4.0 доступна также 4.1). Но сама идея редактора, его удивительная простота и гибкость, заставляет его уважать с самого начала ознакомления с этой программой.
Скачать этот редактор можно, зайдя на сайт разработчика:    
http://www.leadwerks.com/
иля прямо на страничку редактора:
http://www.leadwerks.com/index.php?page=mapeditor.htm

Редактор имеет возможность экспорта в формат .Х для версии 4.0 и в форматы
.B3D и Half-Life .MAP в версии 4.1. Но самое интересное для нас то, что автор редактора, привел фрагмент кода, благодаря которому в программы, написанные на Blitz3D можно загружать родной формат редактора .CSM. Надо заметить, что это открывает большие перспективы для программиста, ведь несколько модифицировав код автора, можно получить доступ не только к отдельным объектам созданной карты, но и создавать описания своих объектов непосредственно в редакторе, а потом уже читать их параметры в программе. Теперь уже карты не представляется в виде одного многополигонального целого, а разбита на объекты. Например, если в редакторе мы назначим кубу имя, Дверь, то в программе, щелкнув на нем мышью, мы прочитаем его имя и будем работать с ним как с дверью!
Если вы уже успели загрузить редактор и запустили его, то увидите перед собой 4 экрана, три из которых проекции, а четвертая 3-х мерный вид нашей карты.



На рисунке выше
- один из примеров, которые поставляются вместе с редактором. Некоторые объекты антуража уже есть в редакторе, такие как кровать, кресло, столик, шкаф и тумбочка, и т.д. так что вам не нужно будет ломать голову обставляя комнату.
Для создания новой карты, выберите пункт меню:
File->New или нажмите комбинацию клавиш Ctrl+N.  Присмотритесь к меню Objects редактора. В нем есть различные разделы, такие как: Primitives, Splines, Bedroom, Living Room, Space и Lights. Сразу оговоримся, заметив, что в это меню можно добавлять свои объекты. Например, если вы в редакторе создадите свой объект, вы можете сохранить его в одну из папок в каталоге Prefabs редактора и этот объект будет уже доступен для ваших дальнейших карт. Например вы очень потрудились и создали красивую башню для крепости, теперь остается только сохранить ее в каталог Prefabsв папку, например "Fortress" и ваша башня будет всегда под рукой в любом из дальнейших проектов.
Давайте создадим простейший объект в редакторе - например куб. Для этого выберите их меню
Objects->Primitives->Box и далее на одной из проекций прижмите левую кнопку мыши и растягивайте пунктирный прямоугольник до необходимого размера:



Если вас удовлетворяют размеры будущей фигуры, отпустите клавишу мыши и цвет пунктирного прямоугольника поменяется. Кроме того добавятся еще квадратики для последующего изменения размеров. Если вы не намерены больше модифицировать размеры, то смело нажимайте клавишу
Enter и фигура будет создана.



Этот принцип справедлив для добавления любого объекта в окно редактора, начиная с куба и заканчивая каким-нибудь сложным объектом из существующих или созданных вами.

Теперь когда объект реально создан, его можно изменять следующим образом. Щелкните на значке х, который обозначает цент нашего объекта. Должны появиться белые квадратики по всему периметру объекта:


В этом режиме доступно изменение размеров объекта. Если вы щелкните на значке х второй раз, то квадратики сменятся на кружки:


В этом режиме доступно вращение объекта. Третье нажатие на значке х приведет к смене режима на следующий:


Это режим сдвига или перекоса.
Перемещение самого объекта целиком с места на место, можно осуществить если прижать его в районе все того же значка х и тащить в нужном направлении. При этом объект должен быть выделенным.

На панели быстрых кнопок редактора есть целая их группа, дающая быстрый доступ к элементам меню редактора. Так например кнопки: 
Wireframe, Solid, Textured меняют режимы отображения карты в окне 3-х мерной проекции. Кнопки Select object, Select surface, Select vertex дают возможность выделять целый объект, одну из его поверхностей или группу его вертексов соответственно.
Очень полезными являются кнопки сгруппировать объекты или разгруппировать объект (
Group, Ungroup). Так например, кровать Bed в группе Bedroom после разгруппировки состоит из двух объектов для каждого из которых можно задать свои параметры.
В версии 4.1 редактора появились кнопки
Carve и Hollow и если функциональность первой так и не удалось проверить, то вторая исправно делала дырки в объектах, главное было задать толщину стенок.
Также можно найти довольно интересными кнопки
Flip и Mirror. Первая позволяет инвертировать поверхности объекта. Иногда это помогает для объектов которые созданы в других редакторах и импортированы в Cartography Shop и при переносе могли потерять информацию о правильной ориентации поверхностей. Вторая кнопка дает возможность инвертирования всего объекта относительно одной из выбранных координат.
А теперь изюминка редактора: кнопка
Calculate Lights. Эта функция просчитывает карты освещения (естественно после добавления нами в карту источников освещения) и мы можем их использовать в игре. В окне трехмерной проекции после расчета освещения тут же появляются правильные тени от расставленных объектов. Карта освещения (lightmap) сохраняется в формате .CSM и мы ее считываем в нашу игру.
Теперь немного о текстурах. Текстуры хранятся в каталоге Textures в подкаталогах Brick, Fabric, Floor и т.д. но вам никто не запретил добавлять свои папки и файлы в эту директорию. Все ваши текстуры тут же будут доступны из меню Textures редактора или в обозревателе текстур (Texture Browser) активируемого клавишей "T".
Применить текстуру к выбранному объекту или поверхности можно используя правую панель
Cartography Shop
:


Кроме простого наложения текстуры, вы можете точно подобрать масштаб текстуры, ее расположение на поверхности и даже угол поворота текстуры! Все это доступно из меню на правой поверхности, когда вы войдете в режим
Select surface:


На рисунке ниже, мы применили к одной из поверхностей куба другую текстуру, отмасштабировали ее, уменьшив в два раза и развернули на 45 градусов:


Заметим, что после загрузки в игру все будет выглядеть аналогично.
Давайте для примера сделаем пол, установим на него кровать из доступного набора объектов и создадим источник освещения, а потом просчитаем карту освещения.
Итак полом у нас будет служить куб (
Objects->Primitives->Box) мы лишь слегка растянем его в плоскости XZ. Затем добавим кровать (Objects->Bedroom->Bed). Выровняйте ее хорошенько относительно пола для достоверности и теперь добавьте источник освещения (Objects->Lights
->Light
) Позиционируйте его в нужном вам месте и нажмите Enter как вы делали и для других объектов. Допустим у вас получилась следующая картина:


Теперь выберите кнопку
Calculate Lights в панели быстрого доступа или нажмите Ctrl+L. После просчета и наложения карты освещения (lightmap) получаем следующую картинку:



Теперь попробуйте поупражняться в освоении редактора, создавая различные архитектурные композиции и интерьеры из доступных элементов. Думаю даже новичку будет легко и удобно пользоваться этим гибким инструментом.

9.2.  Создаем лестницы и арки, используем конвертер

      Без всякого сомнения, чтоб подниматься с этажа на этаж нашему персонажу кроме лифта может понадобится лестница. А так как этого объекта нет в редакторе, то построим ее из кубов - самого простого подручного материала, который можно найти в
 Cartography Shop.
Поставим в ряд 9 кубов один выше другого, как это показано на рисунке ниже:


Если у вас талант дизайнера, то можете добавить резные перила и витые решетки . Мы же просто попросим вас выделить все поверхности кубов лестницы, которые составляют ступени и лежат в плоскости
ZY. и затем поменять для них текстуру. После этого можете сгруппировать все составляющие объекта (после выделения их всех, естественно)и сохранить наш труд в папку "Misc" (создайте ее предварительно) каталога "Prefabs" редактора Cartography Shop под именем Stair.csm.



Теперь эта лестница содержится в списке готовых объектах и доступна в любой момент и для любой карты из меню редактора:
Objects->Misc->Stair

Теперь давайте создадим простейшую арку:
Воспользуемся нашим известным строительным материалом - кубом (
box) . Создайте 6 кубов, установленных друг на друге в проекции XY:



Теперь выделите все кубы при помощи левой кнопки мыши щелкая на значок х и удерживая клавишу
Ctrl пока все они не выделятся красным цветом. Теперь перейдите в режим "Select vertex" (кнопка на панели быстрого доступа редактора). После чего у нас появляется возможность изменять наши объекты, растягивая их форму при перемещении точек (вертексов).
Однако для более точного позиционирования можно уменьшить шаг сетки. Нажмите клавишу "
["
(левая скобка). Теперь поменяйте координаты вертексов при помощи мыши пока не получите следующее:


Теперь вернитесь к режиму выделения объектов
"Select object" (кнопка на панели быстрого доступа редактора) и скопируйте объект (Ctrl+C). Вставьте объект (Ctrl+V) - он вставится на тоже место, что и копируемый.  Оттащите его чуть правее и поверните вокруг оси Х, при помощи кнопки "Mirror" . Состыкуйте объекты до получения целостной арки.


Сгруппируйте и можете сохранить как
Prefab для использования в последующих проектах. Трехмерная проекция должна выглядеть примерно так:


Если вы уже достаточно освоились в редакторе
Cartography Shop, то наверняка заметили, что в числе предопределенных объектов типа куб, конус, цилиндр  отсутствует весьма необходимый - сфера. Чтоб не особенно напрягаться создавая его в Cartography Shop можно легко и просто создать его в MilkShape3D и потом экспортировать в .3DS для конвертирования в .CSM при помощи конвертера PrefabMaker, который вы также можете найти на сайте разработчика Cartography Shop - http://www.leadwerks.com/  из раздела Tools. Или по прямой ссылке:
Download
Если вы, к примеру создали шар в редакторе
MilkShape3D  и экспортировали его в файл sphere.3ds,


то после запуска конвертера (файл convert.exe) и выбора вышеуказанного файла, получаем конвертированный файл sphere.csm, который можно сохранить в Prefabs для дальнейшего использования. Как видите у нас уже накопилось 3 объекта, которые мы создали самостоятельно:


9.3.  Загрузка уровней в Blitz3D

    Как мы уже сообщали, разработчик редактора Cartography Shop  во встроенной помощи к своему продукту привел код для загрузки уровня в Blitz3D непосредственно из .CSM файла.
Данный код, который вы должны добавить к дальнейшим нашим проектам содержится ниже:
 
;=================================================
;=================================================
Function LoadCSM(file$,texturepath$=".")

f=
ReadFile(file)
If Not f Return

ChangeDir FileDir(file)

lightmapbank=
CreateBank()
texturebank=
CreateBank()

;Version - this will load CShop 4.0 and CShop 4.1 maps
version=ReadInt(f)
If version<>4 And version<>5
 
CloseFile f
  Return
EndIf

map=
CreatePivot()

;Groups
DebugLog groupcount+" groups"
groupcount=ReadInt(f)
For n=1 To groupcount
   flags=
ReadInt(f)
   group=
ReadInt(f)
   Properties$=readstringn(f)
   r=
ReadInt(f)
   g=
ReadInt(f)
   b=
ReadInt(f)
Next

;Visgroups (new in 4.1)
If version=5
   visgroupcount=
ReadInt(f)
   For n=1 To visgroupcount
      name$=readstringn(f)
      flags=
ReadInt(f)
      r=
ReadInt(f)
      g=
ReadInt(f)
      b=
ReadInt(f)
  Next
EndIf

;Lightmaps
lightmapcount=
ReadInt(f)
DebugLog lightmapcount+" lightmaps"
For n=1 To lightmapcount
   w=
ReadInt(f)
   h=
ReadInt(f)
   texture=
CreateTexture(w,h)
   TextureCoords texture,1
   ResizeBank lightmapbank,BankSize(lightmapbank)+4
   PokeInt lightmapbank,BankSize(lightmapbank)-4,texture
   LockBuffer TextureBuffer(texture)
   For ty=0 To h-1
      For tx=0 To w-1
          hue=
ReadInt(f)
          WritePixelFast tx,ty,hue,TextureBuffer(texture)
     Next
   Next
  
UnlockBuffer TextureBuffer(texture)
Next

;Meshes
meshcount=
ReadInt(f)
DebugLog meshcount+" meshes"
For n=1 To meshcount
flags=
ReadInt(f)
group=
ReadInt(f)
properties$=readstringn(f)
r=
ReadInt(f)
g=
ReadInt(f)
b=
ReadInt(f)
x#=
ReadFloat(f)
y#=
ReadFloat(f)
z#=
ReadFloat(f)

If version=5 visgroup=ReadInt(f)

facecount=
ReadInt(f)
DebugLog facecount+" surfaces."

mesh=
CreateMesh(map)
NameEntity mesh,properties
PositionEntity mesh,x,y,z

;Surfaces
For s=1 To facecount
flags=
ReadInt(f)
texturefile$=readstringn(f)
lightmapindex=
ReadInt(f)
offsetu#=
ReadFloat(f)
offsetv#=
ReadFloat(f)
scaleu#=
ReadFloat(f)
scalev#=
ReadFloat(f)
rotation#=
ReadFloat(f)
vertexcount=
ReadInt(f)
DebugLog vertexcount+" vertices"
trianglecount=
ReadInt(f)
DebugLog trianglecount+" triangles"
linecount=
ReadInt(f)

surf=
CreateSurface(mesh)
brush=
CreateBrush()
texturefile=
Lower(texturefile)
texture=retrievetexture(texturepath+texturefile,texturebank)
If texture BrushTexture brush,texture
If lightmapindex>0 And lightmapindex*4<=BankSize(lightmapbank)
lightmap=
PeekInt(lightmapbank,(lightmapindex-1)*4)
If lightmap
BrushTexture brush,lightmap,0,1
BrushFX brush,1
EndIf
EndIf
PaintSurface surf,brush
FreeBrush brush

;Vertices
For v=0 To vertexcount-1
x#=
ReadFloat(f)
y#=
ReadFloat(f)
z#=
ReadFloat(f)
nx#=
ReadFloat(f)
ny#=
ReadFloat(f)
nz#=
ReadFloat(f)
r=
ReadInt(f)
g=
ReadInt(f)
b=
ReadInt(f)
u0#=
ReadFloat(f)
v0#=
ReadFloat(f)
w0#=
ReadFloat(f)
u1#=
ReadFloat(f)
v1#=
ReadFloat(f)
w1#=
ReadFloat(f)

TFormPoint x,y,z,0,mesh
AddVertex surf,TFormedX(),TFormedY(),TFormedZ(),u0,-v0
VertexColor surf,v,r,g,b
VertexTexCoords surf,v,u1,-v1,0,1
VertexNormal surf,v,nx,ny,nz

Next

;Triangles
For t=0 To trianglecount-1
   a=
ReadInt(f)
   b=
ReadInt(f)
   c=
ReadInt(f)
AddTriangle surf,a,c,b
Next

For l=0 To linecount-1
a=
ReadInt(f)
b=
ReadInt(f)
Next

Next
Next

;Point Entities
entitycount=ReadInt(f)
DebugLog entitycount+" entities"
For n=1 To entitycount
   visgroup=
ReadInt(f)  ; used to be flags, but wasn't really used
   group=ReadInt(f)
   properties$=readstringn(f)
   x#=
ReadFloat(f)
   y#=
ReadFloat(f)
   z#=
ReadFloat(f)
   entity=
CreatePivot(map)
   NameEntity entity,properties
   PositionEntity entity,x,y,z
Next

;Free textures
For n=0 To BankSize(lightmapbank)-1 Step 4
  
FreeTexture PeekInt(lightmapbank,n)
Next
FreeBank lightmapbank
For n=0 To BankSize(texturebank)-1 Step 8
  
FreeBank PeekInt(texturebank,n)
   FreeTexture PeekInt(texturebank,n+4)
   Next
FreeBank texturebank

CloseFile f
Return map
End Function

;Read a null-terminated string
Function ReadStringN$(f,maxlength=0)
Repeat
   ch=
ReadByte(f)
   If ch=0 Return t$
   If maxlength
   If Len(t$)=maxlength Return t$+Chr(ch)
   EndIf
   t$=t$+Chr$(ch)
Forever
End Function


;Return a loaded texture
Function RetrieveTexture(file$,bank)
For n=0 To BankSize(bank)-1 Step 8
  namebank=
PeekInt(bank,n)
  s$=""
  For b=0 To BankSize(namebank)-1
    s=s+
Chr(PeekByte(namebank,b))
  Next
  If s=file Return PeekInt(bank,n+4)
Next
ResizeBank bank,BankSize(bank)+8
namebank=
CreateBank(Len(file))
For b=0 To BankSize(namebank)-1
   PokeByte namebank,b,Asc(Mid(file,b+1))
Next
DebugLog "Loading texture "+file
PokeInt bank,BankSize(bank)-8,namebank
texture=
LoadTexture(file)
If Not texture DebugLog "Failed to load texture "+Chr(34)+CurrentDir()+file+Chr(34)
PokeInt bank,BankSize(bank)-4,texture
Return texture
End Function


;Get the file part of a file path
Function FileName$(file$,ext=1)
file=
Replace(file,"/","")
Repeat
p=
Instr(file,"")
If p
file=Right(file,Len(file)-p)
Else
Exit
EndIf
Forever
If Not ext
p=
Instr(file,".")
If p file=Left(file,p-1)
EndIf
Return file
End Function

;Get the directory of a file path
Function FileDir$(file$)
file=
Replace(file,"/","")
oldp=1
Repeat
p=
Instr(file,"",oldp)
If p
oldp=p+1
Else
file=
Left(file,oldp-1)
Exit
EndIf
Forever
Return file
End Function

;Parsing function
Function Piece$(s$,entry,char$=" ")
While Instr(s,char+char)
s=
Replace(s,char+char,char)
Wend
For n=1 To entry-1
p=
Instr(s,char)
s=
Right(s,Len(s)-p)
Next
p=
Instr(s,char)
If p<1
a$=s
Else
a=
Left(s,p-1)
EndIf
Return a
End Function

;Function for retrieving entity properties
;[ "light"=KeyValue(entity,"classname") ]

Function KeyValue$(entity,key$)
properties$=
EntityName(entity)
key$=
Lower(key)
Repeat
p=
Instr(properties,Chr(10))
If p test$=(Left(properties,p-1)) Else test=properties
testkey$=
Piece(test,1,"=")
testkey=
Trim(testkey)
testkey=
Replace(testkey,Chr(34),"")
testkey=
Lower(testkey)
If testkey=key
value$=
Piece(test,2,"=")
value$=
Trim(value$)
value$=
Replace(value$,Chr(34),"")
Return value
EndIf
If Not p Return
properties=Right(properties,
Len(properties)-p)
Forever
End Function

Сохраните данный фрагмент кода в виде шаблона (например под именем load_csm.bb), он Вам понадобится не один раз. Сразу можно смело сказать, что его придется модифицировать, так как простая загрузка уровня нас никак не может устроить. Нам понадобится контролировать столкновения с объектами, добавлять свои объекты и получать информацию о них в программе и многое другое.
Давайте создадим простейший уровень в редакторе
Cartography Shop и загрузим его в программу на Blitz3D. Начните новый проект и добавьте в него какие-либо объекты по Вашему усмотрению, например так:


Сохраните ваш уровень под именем
mymap.csm в папку с проектами для урока №9 и туда же поместите каталог TEXTURES из папки, куда вы поставили Cartography Shop, так как текстуры понадобятся для загрузки в программу. Файл mymap.csm можно скачать тут.
Совет: Все текстуры в
Cartography Shop содержатся в формате *.bmp что не очень экономично. Вы можете конвертировать их всех в формат  *.JPG и далее уже создавать карты с этими текстурами. Экономия места будет очень существенной.

Теперь напишем небольшой стандартный фрагмент кода для перемещения камеры и загрузки созданного Вами уровня:

Graphics3D 640,480
SetBuffer BackBuffer()

Global player=
CreateSphere()
PositionEntity player,0,0,0
TurnEntity player,0,0,0
EntityRadius player, 100

cam=
CreateCamera(player)

map=
LoadCSM("mymap.csm","textures")

While Not KeyHit(1)

If KeyDown(200) MoveEntity player, 0, 0, 5
If KeyDown(208) MoveEntity player, 0, 0, -5
If KeyDown(203) TurnEntity player, 0, 2, 0
If KeyDown(205) TurnEntity player, 0, -2, 0

RenderWorld
UpdateWorld
Flip
Wend
End

Как видите, загрузка уровня сводится лишь к вызову функции LoadCSM и передаче ей двух параметров - имени файла карты и имени каталога с загружаемыми текстурами.
Добавьте этот код к коду чтения карты и выполните программу. Безусловно сразу бросается в глаза, то что мы проходим сквозь все объекты. Для устранения этого недоразумения, введите две константы, определяющие тип объектов, как мы уже делали ранее:

Const TypePlayer = 1, TypeWall = 2

Первая определяет тип игрока, вторая любую поверхность с которой мы будем сталкиваться. Теперь опишем коллизии и назначим тип объекта нашему игроку:

EntityType player, TypePlayer
Collisions TypePlayer, TypeWall, 2, 1

Теперь найдите раздел Meshes в коде загрузки уровня и после строчек, затененных у нас в следующем фрагменте серым цветом вставьте следующую строку.

;Meshes
.......
.......

mesh=CreateMesh(map)
NameEntity mesh,properties
PositionEntity mesh,x,y,z

EntityType mesh, TypeWall               ; Added

Этой строкой мы указываем программе, что любой объект загруженной карты принимает тип содержащийся в константе TypeWall.
Запустите программу и убедитесь, что теперь объекты карты перестали быть проходимыми для игрока.

9.4.  Свободное вращение камеры

     Следующим нашим заданием будет реализация управления камеры при помощи мыши. Как вы знаете, во всех современных
3D-шутерах от первого лица управление камеры осуществляется мышью. Все это вполне по силам реализовать в Blitz3D. Давайте воспользуемся редактором Cartography Shop и создадим более продвинутую карту. Наша цель создать по крайней мере два этажа соединенных между собой лестницей. Как вы помните, лестница уже нами создана и остается ее лишь вставить в нужную позицию. Этажи конструируются из объектов Box. Кое-где расставим мебель из стандартной поставки редактора. Даже для новичка в картостроении это не должно занять более получаса времени.
Тем не менее для экономии ваших 30 минут на создание уровня можно скачать его по этой ссылке. Распакуйте его в каталог, где ранее находился ваш тестовый уровень
mymap.csm. Распакованный файл носит имя -  house.csm. Напоминаем, что в том же каталоге должна находиться папка с текстурами редактора Cartography Shop.
   Воспользуйтесь шаблоном load_csm.bb и добавьте к нему (естественно выше) следующий код:

Const TypePlayer = 1, TypeWall = 2

Graphics3D 640,480
SetBuffer BackBuffer()

Global camera,campitch#,camyaw#,mvx#,mvy#,mvz#

player=
CreateSphere()
PositionEntity player,420, 70, 170
TurnEntity player,0,0,50
EntityRadius player, 60
EntityType player, TypePlayer

camera=
CreateCamera(player)
CameraFogMode camera,1
CameraFogColor camera,100,200,255

map=LoadCSM(
"house.csm","textures")
ScaleEntity map, 0.5,0.5,0.5

Collisions TypePlayer, TypeWall, 2, 3

While Not KeyHit(1)

   mxspd#=
MouseXSpeed()*0.2
   myspd#=
MouseYSpeed()*0.2

   MoveMouse GraphicsWidth()/2,GraphicsHeight()/2

   campitch=campitch+myspd
   If campitch<-89 Then campitch=-89
   If campitch>89 Then campitch=89
   RotateEntity player,campitch,EntityYaw(player)-mxspd,0

   If KeyDown( 203 )=True Then mvx=mvx-1.5
   If KeyDown( 205 )=True Then mvx=mvx+1.5
   If KeyDown( 200 )=True Then mvz=mvz+1.5
   If KeyDown( 208 )=True Then mvz=mvz-1.5

   mvy=mvy-0.1
   If EntityCollided(player,TypeWall)
     mvy=mvy+0.1
   EndIf

   mvx=mvx/1.2
   mvy=mvy/1.2
   mvz=mvz/1.2
   MoveEntity player,mvx,0,mvz
   TranslateEntity player,0,mvy,0

   RenderWorld
   UpdateWorld
   Flip
Wend
End
 

После стандартного уже создания игрока, камеры и загрузки уровня, в главном цикле представляет интерес функции Blitz3D работы с мышью. Вначале вызываются функции MouseXSpeed и MouseYSpeed которые определяют разницу между тем где был указатель мыши и где он находится теперь. MoveMouse  позиционирует указатель мыши в центре экрана. Далее осуществляются проверки на не превышение угла подъема камеры более 89 градусов, чтоб наш игрок не сломал себе шею, рассматривая пол и потолок После чего осуществляется поворот нашего игрока в зависимости от рассчитанных параметров скорости движения указателя мыши.
Простейшая проверка на коллизии по координате У, заставляет нашего игрока прижиматься к полу, а не свободно висеть в воздухе, при спуске и подъеме по лестницам и объектам расставленным в комнатах.

mvy=mvy-0.1
If EntityCollided(player,TypeWall)
   mvy=mvy+0.1
EndIf

Функция TranslateEntity используется для учета текущей координаты У независимо от ориентации объекта player.

Полный текст программы на всякий случай приведен здесь.

Теперь поставим перед собой задачу отображения информации об объектах нашей карты при наведении на них курсора мыши. Откройте карту
house.csm в редакторе Cartography Shop. Выделите понравившийся объект, например пол и нажмите клавишу "P" на клавиатуре.



В открывшемся окне, нажмите кнопку
"Entity properties..."
В диалоговом окне:


Введите  ключ (
поле Key) - name, и значение (поле Value) - "это пол". Вы можете добавить еще несколько значений, какие вам понадобятся. Все они, в дальнейшем могут быть считаны в процессе игры! 
Внимание: Некоторые объекты (например кровать, дверь и т.д.) на самом деле являются группами объектов и потому для того чтоб ввести считываемые параметры в игре, их нужно разгруппировать. (Пометьте объект и нажмите Ctrl+U или выберите пункт меню Tools->Ungroup) После разгруппировки можно задать ключевые параметры для каждого из объектов слагающих основной.

Задайте значения еще нескольким объектам и сохраните карту.
Теперь найдите раздел
Meshes в коде загрузки уровня и после строчек, затененных у нас в следующем фрагменте серым цветом вставьте следующую строку.

;Meshes
.......
.......

mesh=CreateMesh(map)
NameEntity mesh,properties
PositionEntity mesh,x,y,z

EntityType mesh, TypeWall               ; было добавлено ранее
EntityPickMode mesh, 2

Эта строка указывает программе, что объект может быть выбран мышью по полигональной поверхности. Теперь прямо после ключевого слова while главного цикла нашей программы вставим следующий код:

ent = CameraPick(camera,MouseX(),MouseY())
If ent
   CName$ = KeyValue(ent,"name")
Else
   CName$ = ""
EndIf

а между UpdateWorld и Flip поместим следующую строку:

Text 10, 10, "Info: "+CName

Теперь при наведении курсора мыши на объект, строковую информацию о котором мы задали в редакторе, в углу экрана отобразится эта строка. Как вы понимаете, это открывает огромные перспективы перед программистом, так как мы теперь может задавать стартовые значения любых объектов карты и по идентификаторам объектов манипулировать ими в программе.
Текст программы можно увидеть тут.

9.5.  Создание кубических отражений

   
Предположим, что перед нами стоит задача касательно создания эффекта отражения окружающих предметов от поверхности воды. В Blitz3D для этих целей предусмотрена функция SetCubeFace, которая может принимать следующие параметры:

texture - идентификатор текстуры
face - поверхность куба. Аргумент может содержать одно из следующих значений:
0: левая поверхность (отрицательная X)
1: передняя поверхность (положительная Z) - по умолчанию.
2: правая поверхность (положительная X)
3: задняя поверхность (отрицательная Z)
4: верхняя поверхность (положительная Y)
5: нижняя поверхность (отрицательная Y)

Для примера воспользуемся нашим предыдущим проектом с двухэтажным домом и для создания эффекта кубических отражений, зальем первый этаж водой по щиколотку. Если вы помните, для создания эффекта воды мы применяли объект
mesh в формате .3DS. В данном примере мы поступим таким же образом, только текстура воды должна, по замыслу, отражать антураж комнаты первого этажа.
Сохраните предыдущий проект под другим именем в ту же папку. Загрузите
mesh водной поверхности или возьмите из урока № 8.
Теперь немного теории:  Для того чтоб отражать в воде объекты комнаты, а также е стены и потолок, необходимо создать вторую камеру и периодически переключать управление на нее. Камера создается в точке, где находится игрок и имеет все координаты игрока, кроме координаты
Y, которую можно опустить до уровня воды (нашего объекта mesh) Созданную камеру мы направляем вправо, влево, вперед, назад и вверх от этой базовой точки ее расположения и делаем моментальные снимки дублирующего буфера экрана (BackBuffer()), которые потом можно копировать в заранее созданную текстуру воды при помощи функции CopyRect() . Функция SetCubeFace() рассмотренная выше применяется все пять раз, получая в качестве аргументов текстуру воды и номер поверхности.

Добавьте глобальные переменные в программу, загрузите
mesh  воды и опишите функции добавления объекта воды следующим кодом:

Global WaterCamera,water,WaterMapSize,WaterMapTexture

WaterMapSize = 256

water=
LoadMesh("water.3ds")
MoveEntity water,100,6,1100
WaterMapTexture=
CreateTexture(WaterMapSize,WaterMapSize,128+256+48)
EntityTexture water,WaterMapTexture
EntityColor water,100,200,255
EntityColor water,512,512,512
EntityAlpha water,0.7
ScaleEntity water, 5,5,5

AddEntity(water)

Type Vertices
 
Field x#
 
Field y#
 
Field z#
End Type
surf=
GetSurface(water,1)
Dim Vertex.Vertices(CountVertices(surf))
For i=0 To CountVertices(surf)-1
  Vertex(i) =
New Vertices
  Vertex(i)x#=
VertexX#(surf,i)
  Vertex(i)y#=
VertexY#(surf,i)
  Vertex(i)z#=
VertexZ#(surf,i)
Next

Type entity
Field ent
End Type

;----------------------------------------------------------------------------------
Function AddEntity(ent)
  e.entity=
New entity
  eent=ent
End Function
 

Как видите текстура создается внутри программы и имеет размеры 256 х 256 пикселей. Загрузку mesh воды и заполнение массива его вертексов мы уже проходили. Теперь остается написать функцию рендеринга водной поверхности на основе теории приведенной выше:

Function RenderWater()

CameraProjMode camera,0
CameraProjMode WaterCamera,1

PositionEntity WaterCamera,EntityX(player),EntityY(water),EntityZ(player)

;Left view
SetCubeFace WaterMapTexture,0
RotateEntity WaterCamera,0,90,0
RenderWorld
CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
;forward view
SetCubeFace WaterMapTexture,1
RotateEntity WaterCamera,0,0,0
RenderWorld
CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
;right view
SetCubeFace WaterMapTexture,2
RotateEntity WaterCamera,0,-90,0
RenderWorld
CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
;backward view
SetCubeFace WaterMapTexture,3
RotateEntity WaterCamera,0,180,0
RenderWorld
CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
;up view
SetCubeFace WaterMapTexture,4
RotateEntity WaterCamera,-90,0,0
RenderWorld
CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)

CameraProjMode WaterCamera,0
CameraProjMode camera,1

;Animate Water Mesh
s=GetSurface(water,1)
Freq#=
MilliSecs()/4
For i=0 To CountVertices(s)-1
Vertex(i)y#=
Sin(freq+Vertex(i)x#*500+Vertex(i)z#*300)*1.2
VertexCoords s,i,Vertex(i)x#,-Vertex(i)y#,Vertex(i)z#
Next

End Function
 

Нужно сразу оговориться, что данный код съедает изрядно процессорного времени и на слабых компьютерах может изрядно тормозить. Для оптимизации алгоритма и убыстрения рендеринга сцены можно разнести текстурирование отдельных видов. То есть - за один цикл визуализации сцены - текстурировать один вид. Перепишем функцию RenderWater() чуть по другому:

Function RenderWater()

CameraProjMode camera,0
CameraProjMode WaterCamera,1

PositionEntity WaterCamera,EntityX(player),EntityY(water),EntityZ(player)

;Left view
If water_side = 0
   SetCubeFace WaterMapTexture,0
  
RotateEntity WaterCamera,0,90,0
   RenderWorld
   CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
Endif
;forward view
If water_side = 1
  
SetCubeFace WaterMapTexture,1
   RotateEntity WaterCamera,0,0,0
   RenderWorld
   CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
Endif
;right view
If water_side = 2
  
SetCubeFace WaterMapTexture,2
   RotateEntity WaterCamera,0,-90,0
   RenderWorld
   CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
Endif
;backward view
If water_side = 3
   SetCubeFace
WaterMapTexture,3
   RotateEntity WaterCamera,0,180,0
   RenderWorld
   CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
Endif
;up view
If water_side = 0
  
SetCubeFace WaterMapTexture,4
   RotateEntity WaterCamera,-90,0,0
   RenderWorld
   CopyRect 0,0,WaterMapSize,WaterMapSize,0,0,BackBuffer(),TextureBuffer(WaterMapTexture)
Endif

water_side = water_side + 1
If water_side > 4
   water_side = 0
EndIf
+
CameraProjMode WaterCamera,0
CameraProjMode camera,1

;Animate Water Mesh
s=GetSurface(water,1)
Freq#=
MilliSecs()/4
For i=0 To CountVertices(s)-1
Vertex(i)y#=
Sin(freq+Vertex(i)x#*500+Vertex(i)z#*300)*1.2
VertexCoords s,i,Vertex(i)x#,-Vertex(i)y#,Vertex(i)z#
Next

End Function

Определите глобальную переменную water_side где-то до главного цикла программы и подправьте код, как показано выше. Разнос рендеринга отдельных отражений по разным циклам визуализации сцены не приводит к значительному ухудшению получаемой картинки, но очень существенно повышает скорость игры.
Полный текст программы приведен здесь.


9.6.  Расстановка пользовательских объектов

     Очень полезным свойством редактора
Cartography Shop является возможность расстановки пользовательских объектов не связанных с геометрией уровня. Нельзя сказать, что эта функция является документированной в помощи редактора, но тем не менее она существует и мы можем ее использовать. Предположим, что мы создали уровень и теперь желаем разместить монстров в нужных позициях. Весьма неудобно будет размещать их на глаз, грузить уровень и потом подгонять их позиции, раз за разом меняя координаты монстров и снова просматривая правильность их позиционирования в игре.
     Однако если мы создадим контрольные токи размещения этих монстров в редакторе  
Cartography Shop, то нам останется лишь считать их в игре и ни о чем больше не заботиться как о создании модели монстра в этих координатах.
     Более того, кроме координат, задающихся в редакторе автоматически при визуальном размещении этого объекта, мы можем добавлять ему некоторые параметры, как мы делали это уже с другими геометрическими объектами в редакторе.
     Итак для добавления объекта найдите папку
Entities в каталоге, где вы установили Cartography Shop и создайте в нем файл с расширением .def , например user_obj.def.
Отредактируйте файл добавив в него такие строки:

Pointclass Monster : [50,255,50] : [32,32]
{
"name"="Toad"
"color"="255 255 255" : color()
"style"="1" : choices("active","passive")
"flags"="1" : flags("live","dead")
}

PointClass - стандартное ключевое слово редактора Cartography Shop и мы лишь указываем имя класса  - Monster
[50,255,50] -
это цвета создаваемого объекта в формате RGB (в нашем случае - зеленый)
[32,32] -
размеры объекта (в нашем случае это кубик 32х32)
name -
имя монстра (или его тип), которое мы можем анализировать в игре.
остальные параметры символизирует его статус и живой он или нет. Безусловно это слишком мало характеристик, которыми можно описать монстра в современной игре, поэтому Вы можете добавить другие, создающие полную картину для начальной инициализации монстра.
Если вы находитесь в редакторе, то выйдите из него и снова войдите для вступления изменений в силу. Теперь в меню Objects появилось подменю user_obj, где находится созданный вам класс Monster. Если поместите его на карту, то он будет отображаться у вас в виде зеленого квадратика на проекциях и в виде зеленого куба на трехмерном виде:


    
Свойств объекта будут доступны при нажатии в редакторе клавиши
"P" при выделенном объекте:


Само собой разумеется, что мы можем добавить другие свойства, какие нам необходимы.
Теперь давайте посмотрим, как это работает в при загрузки карты в
программу на Blitz3D.
Добавьте пол к нашему уровню, чтоб кроме пользовательского объекта
Monster на уровне было хоть что-то еще. Сохраните карту под именем addobj.csm. Воспользуйтесь шаблоном  load_csm.bb и добавьте в него функции загрузки уровня, управления камерой (вобщем, все то что мы уже не раз проделывали для демонстрации загрузки и навигации по уровню .CSM) Теперь модифицируем секцию Point Entities в коде загрузки карты, следующим образом:

;Point Entities
entitycount=ReadInt(f)
DebugLog entitycount+" entities"
For n=1 To entitycount
visgroup=ReadInt(f); used to be flags, but wasn't really used
group=ReadInt(f)
properties$=readstringn(f)
x#=ReadFloat(f)
y#=ReadFloat(f)
z#=ReadFloat(f)
entity=CreatePivot(map)
NameEntity entity,properties
PositionEntity entity,x,y,z


; Added Code!!!
MonsterName$ = KeyValue$(entity,
"name")
If MonsterName = "Toad"
  
Monster = CreateSphere()
  
ScaleEntity Monster, 5,5,5
   PositionEntity Monster,x,y,z
EndIf

Next
 

    Как вы уже догадались, все добавленные пользователем объекты попадают в раздел Point Entities где их можно анализировать и предпринимать определенные действия. В данном случае мы проанализировали свойство name объекта и когда программа нашла соответствие на заданное в редакторе имя (в нашем случае Toad) создаем обычный объект сфера, для индикации местоположения монстра. Безусловно в игре у вас будет гораздо большее количество объектов. Поэтому изначально нужно хорошо продумать их типизацию, все начальные свойства и параметры. Однако загрузка их и анализ в программу будет универсален. На месте сферы, безусловно мог быть добавлен любой объект и модель монстра в том числе. Карта и программа для загрузки этого примера - (карта, программа).

Что будет далее:

           Наш следующий урок будет посвящен сетевому взаимодействию и как его можно реализовать в Blitz3D

 

 
 
 

уже 16011 посетителей!
 
Часы
 
Этот сайт был создан бесплатно с помощью homepage-konstruktor.ru. Хотите тоже свой сайт?
Зарегистрироваться бесплатно