10. Первая 3Д игра. Часть 0 – основы движка

 

Итак, мы уже достаточно вооружены, чтобы сделать простенькую игру, так что хватит абстрактных примеров, а начнём уже делать игры, а то, что мы ещё не изучили, узнаем в самом процессе, по мере надобности…

 

Что это будет за игра? Сделаем такой вариант игры, которую делали в основах по BlitzBasic`у, только трёхмерный. Там у нас будет шарик, который будет ездить по плоскости, собирать, допустим, жёлтые кубики, и умирать от столкновения с красными… короче, сюжет стандартный…

 

Начнём с того, что создадим шарик игрока и его управление… (ну и камеру со светом):

 

SeedRnd MilliSecs()

 

Graphics3D 640,480,16,1

SetBuffer BackBuffer()

 

Global Player=CreateSphere()

 

cam=CreateCamera()

PositionEntity cam,0,60,0

TurnEntity cam,90,0,0

 

lit=CreateLight()

TurnEntity lit,70,70,0

 

 

Repeat

 

 If KeyDown(200) MoveEntity Player,0,0,.2

 If KeyDown(208) MoveEntity Player,0,0,-.2

 If KeyDown(203) TurnEntity Player,0,3,0

 If KeyDown(205) TurnEntity Player,0,-3,0

 

 UpdateWorld

 RenderWorld

 

 Flip

 

Until KeyHit(1)

 

End

 

Итак, всё просто – есть шарик, который ездит где-то внизу и поворачивается… вот только одно меня здесь смущает – не понятно, куда этот шарик повёрнут – он везде круглый, не видно, где перед, где … гм… это… зад… J. У меня вот такое решение этого вопроса – что если сделать у него такой мини хвост – как у капли или метеора? Т.е. здесь просто бы подошёл конус. Можно, конечно, сделать ещё один объект – как раз конус и просто сделать привязку к шару, но привязки полезны, когда нам нужно обязательно 2 различных объекта, а не один, или, например, если привязка через некоторое время должна пропасть… здесь же нам желателен объект, представляющий из себя цельный меш. Можно сделать модельку в 3ДМаксе, конечно, а потом её сюда загрузить, вот только зачем забивать лишнее дисковое пространство на модельки… которые мы сами можем сделать в самом Блитце! Как? Очень просто – присоединив к мешу шара меш конуса!

Вот как мы поступим (после создания шара):

 

Plac=CreateCone(8)

RotateMesh Plac,-90,0,0

ScaleMesh Plac,1,1,1.2

PositionMesh Plac,0,0,-1.5

 

Здесь мы создаём конус по имени Plac, вертим его там и по всякому подгоняем. Так как после создания шар будет стоять в точке 0,0,0 – конус будет ровно подогнан к нему – можете запустить и посмотреть… Вот только если вы будете этот шар двигать, конус останется на месте (естественно J). Итак, как я уже говорил, можно этот конус привязать (особой разницы не будет), но всё таки основываясь на программерскую этику, сделаем из них один объект (у нас есть возможность, да и зачем нам 2 объекта вместо одного).

 

Короче, добавляем:

 

AddMesh Plac,Player

 

Эта команда добавляет один меш к другому… то есть в данном случае мы добавляем меш конуса к мешу шара. НО! При этом сам объект конуса не исчезает (то есть мы этот конус как бы добавляем копированием). Короче, теперь у нас 2 меша – шар присоединённый к конусу, и сам конус, который нам сейчас не нужен. Поэтому (опять новая команда J) мы его уберём:

 

FreeEntity Plac

 

Эта команда убирает заданный объект (в данном случае конус) и (самое главное) очищает от него память. Когда будете делать большие игры, где будет много уровней, при выходе из одного из них, не забывайте очищать ненужные объекты, иначе они будут копиться и занимать память, которая (L) не резиновая, в результате всё будет тормозить после определённого времени «играния»…

 

Дальше… не будет же этот шарик просто так ездить по полю! Надо создать ему определенные препятствия. Создадим-ка мы кубики, и разбросаем их по нашему будущему полю:

 

Dim Walls(29)

 

For i=0 To 29

 Walls(i)=CreateCube()

 PositionEntity Walls(i),Rnd(-50,50),0,Rnd(-50,50)

Next

 

Здесь мы, как вы видите, создаём массив на 30 элементов, и затем расставляем в них кубики. А сами кубики раскидываем в случайном порядке по полю.

 

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

 

Поехали:

 

Сначала мы должны определить 2 константы для наших объектов – для шарика и для кубиков:

 

Const TypePlayer=1,TypeWalls=2

 

Вставьте эту строчку после инициализации графики – т.е. в начало… так типы есть, осталось только указать что шар и кубики к ним принадлежат:

 

EntityType Player, TypePlayer

 

Эту строчку поставьте после создания самого объекта шарика- т.е. после присоединения к нему конуса…

 

EntityType Walls(i), TypeWalls

 

А эту вставьте в конец цикла создания кубиков (После команды PositionEntity Walls(i)…)

Так, типы задали, конечно, но сталкиваться они всё равно не будут – пока мы прямо не укажем, что они, мол, сталкиваться должны J.

 

Collisions TypePlayer,TypeWalls,2,2

 

Здесь мы задали, что TypePlayer – который у нас является шаром должен сталкиваться с TypeWalls – т.е. с кубиками, соприкасаясь методом сфера к полигону, полностью скользя по нему. Можно последнюю цифру заменить на 1 – тогда шарик будет как бы «прилипать» к кубикам. Эту строчку поставьте после создания всех кубиков…

 

Хочу сразу заметить: (из своего опыта) команды Collisions нужно ставить одной из последних – т.е. сначала нужно инициализировать все предметы, затем их все расставить по местам, и только ПОТОМ обозначать коллизии между ними… можно, конечно сразу задать константы, и все столкновения между этими константами, но потом, когда вы будете создавать объекты, помните, что создаются-то они все в одной точке – 0,0,0 и получается, что находятся друг в друге, и затем, когда мы будем их расставлять, могут появиться баги – т.е. мы скажем объекту, типа, «Поставься в точку 0,10,100», а он окажется в точке 0,8,70 (или типа того), и можно долго ругаться, вспоминая его материнские отношения (J)… либо в таком случае нужно делать так: создавать объекты, и тут же их переставлять в новые места… но, по-моему то как я предложил – лучше!!! (Scaven никогда не обманывает! J)

 

Так, теперь можно со спокойной душой всё это дело запустить… да нет, не в производство J - рановато пока…

Но уже что-то вырисовывается!

 

По традиции – полный код всего этого безобразия J:

 

SeedRnd MilliSecs()

 

Graphics3D 640,480,16,1

SetBuffer BackBuffer()

 

Const TypePlayer=1,TypeWalls=2

 

Global Player=CreateSphere()

 

Plac=CreateCone(8)

RotateMesh Plac,-90,0,0

ScaleMesh Plac,1,1,1.2

PositionMesh Plac,0,0,-1.5

AddMesh Plac,Player

EntityType Player, TypePlayer

 

FreeEntity Plac

 

Dim Walls(29)

 

For i=0 To 29

 Walls(i)=CreateCube()

 PositionEntity Walls(i),Rnd(-40,40),0,Rnd(-40,40)

 EntityType Walls(i), TypeWalls

Next

 

cam=CreateCamera()

PositionEntity cam,0,60,0

TurnEntity cam,90,0,0

 

lit=CreateLight()

TurnEntity lit,70,70,0

 

Collisions TypePlayer,TypeWalls,2,2

 

Repeat

 

 If KeyDown(200) MoveEntity Player,0,0,.2

 If KeyDown(208) MoveEntity Player,0,0,-.2

 If KeyDown(203) TurnEntity Player,0,3,0

 If KeyDown(205) TurnEntity Player,0,-3,0

 

 UpdateWorld

 RenderWorld

 

 Flip

 

Until KeyHit(1)

 

End

 

 

 Оглавление:

 

0.  Введение

1.  В начале была Тьма

2.  Есть ли жизнь в DirectX

3.  Свобода и Власть 3Д (0)

4.  Свобода и Власть 3Д (1)

5.  2Д в 3Д

6.  Трёхмерный курсор

7.  Родительская зависимость или Привязки

8.  Фишки с привязками

9.  Коллизион Детекшн или как устроен мир…

10.     Первая 3Д игра. Часть 0 – основы движка

11.     Первая 3Д игра. Часть 1 – разработка движка

12.     Первая 3Д игра. Часть 2 – устранение багов

13.     Первая 3Д игра. Часть 3 – внешний вид

14.     Первая 3Д игра. Часть 4 – от массива к спискам

15.     Первая 3Д игра. Часть 5 – оптимизация кода

16.     Первая 3Д игра. Часть 6 – завершение

17.     Выведение

 

 

 

 

Используются технологии uCoz