15 февраля 2010 в 19:55
Blitz3d уроки - 10. Первая 3Д игра – основы движка
Итак, мы уже достаточно вооружены, чтобы сделать простенькую игру, так что хватит абстрактных примеров, а начнём уже делать игры, а то, что мы ещё не изучили, узнаем в самом процессе, по мере надобности…
Что это будет за игра? Сделаем такой вариант игры, которую делали в основах по 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
Итак, всё просто – есть шарик, который ездит где-то внизу и поворачивается… вот только одно меня здесь смущает – не понятно, куда этот шарик повёрнут – он везде круглый, не видно, где перед, где … гм… это… зад. У меня вот такое решение этого вопроса – что если сделать у него такой мини хвост – как у капли или метеора? Т.е. здесь просто бы подошёл конус. Можно, конечно, сделать ещё один объект – как раз конус и просто сделать привязку к шару, но привязки полезны, когда нам нужно обязательно 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 – конус будет ровно подогнан к нему – можете запустить и посмотреть… Вот только если вы будете этот шар двигать, конус останется на месте (естественно ). Итак, как я уже говорил, можно этот конус привязать (особой разницы не будет), но всё таки основываясь на программерскую этику, сделаем из них один объект (у нас есть возможность, да и зачем нам 2 объекта вместо одного).
добавляем:
AddMesh Plac,Player
Эта команда добавляет один меш к другому… то есть в данном случае мы добавляем меш конуса к мешу шара. НО! При этом сам объект конуса не исчезает (то есть мы этот конус как бы добавляем копированием). Короче, теперь у нас 2 меша – шар присоединённый к конусу, и сам конус, который нам сейчас не нужен. Поэтому (опять новая команда) мы его уберём:
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 (или типа того), и можно долго ругаться, вспоминая его материнские отношения … либо в таком случае нужно делать так: создавать объекты, и тут же их переставлять в новые места… но, по-моему то как я предложил – лучше!!! (Scaven никогда не обманывает!)
Так, теперь можно со спокойной душой всё это дело запустить… да нет, не в производство - рановато пока…
Но уже что-то вырисовывается!
По традиции – полный код всего этого безобразия:
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
комментарии отсутствуют
авторизуйтесь