|
Первая
3D игра
Итак, мы уже достаточно вооружены, чтобы сделать простенькую
игру, так что хватит абстрактных примеров, а начнём уже делать игры,
а то, что мы ещё не изучили, узнаем в самом процессе, по мере надобности…
Что это будет за игра? Сделаем такой вариант игры, которую делали в
основах по 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)…) Так, типы задали, конечно, но сталкиваться они всё равно
не будут – пока мы прямо не укажем, что они, мол, сталкиваться должны.
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
|