Приветствую Вас Гость | Зарегистрироваться | Вход | RSS

Поиск по сайту:
Поиск в интернете:
Главная » Статьи » Учебники по Blitz3d

Учебник для начинающих по Blitz3d (Часть 2_2)
Полный учебник по Blitz 3D. Часть 2.
Продолжение учебника по Blitz 3D. Теперь будет намного интереснее, конечно при условии, что Вы тщательно изучали первую часть учебника. В этой части мы займемся созданием простенькой 3D игры.

Внешний вид

Итак, движок разработан, что ещё делать программисту? Улучшать внешний вид! Всё таки игрок будет смотреть и оценивать игру «извне» - т.е. по тому, как она выглядит, и играется, а не по тому, каким образом там реализована проверка на столкновения. Поэтому нельзя недооценивать некоторые мелочи, которые могут приукрасить Вашу игру, что можно сделать сначала? Ну, во-первых, я предлагаю всё разукрасить! (а то чёрно-белое всё как-то примитивно смотрится) Делать-то для этого много не надо, а всё равно смотреться будет круче! Так, сначала разукрасим игрока зелёным (поставьте эту строчку после создания игрока):

EntityColor Player,0,255,0

Затем кубики красным (эту строчку нужно вставить в цикл создания кубиков):

EntityColor Walls(i),255,0,0

И, наконец, закрасим цилиндр жёлтым:

EntityColor Target,255,215,0

Во, теперь куда красочнее всё смотрится! Красный, жёлтый, зелёный! Если хотите, конечно, можете подставить свои цвета. Как выбрать себе цвет? Самый лёгкий способ – зайдите в PaintBrush, затем в меню Палитра > Изменить Палитру, и нажмите на кнопочку «Определить цвет», там такой спектр вылезет, и снизу цифры. Те что слева – как раз те, которые нужны!

Во-вторых. Есть такие мелочи, которые очень сильно улучшают внешний вид игры, это какой-нибудь вид, дополнительный выбор или ещё что-нибудь, что не очень сложно реализовать, но при этом сильно изменяет игру в лучшую сторону. Так вот, сейчас предлагаю внести два изменения, во-первых камеру при её создании поставить чуть пониже, строчку:

PositionEntity cam,0,60,0

Заменить на:

PositionEntity cam,0,40,0

И вставить такую ма-а-аленькую строчку кода в главный цикл игры, которая правда, покажет, что игра всё-таки трёхмерная:

PointEntity cam,Player


Догадались, что она будет делать? Она будет следить за нашим шариком, находясь в одной точке над серединой! Это немного ухудшит вид, зато смотреться сама игра будет в два раза круче вот так какая-то строчка может сильно повлиять на целую игру!

Вот, вроде как и оформили чуть-чуть.. ладно я тут ещё хотел кое-что добавить – стены, которые будут ограничивать область самой игры (а то раньше забыл добавить, а сейчас как бы и место как раз есть). Чтобы особо не париться, сделаем их того же типа, что и кубики, более того, предлагаю сделать их из того же массива, что и кубики. Но, для этого нам надо добавить ещё 4 элемента массива, поэтому:

Dim Walls(29)

Заменим на:

Dim Walls(33)


Дальше создадим 4 кубика, которые у нас скоро станут стенами

For i=30 To 33
Walls(i)=CreateCube()
EntityColor Walls(i),100,20,0
EntityType Walls(i),TypeWalls
Next


Здесь мы создаём ещё 4 кубика, меняем цвет и задаём тип столкновения, ну, понятно. Теперь расставим их по местам, где они будут стоять:

PositionEntity Walls(30),-50,0,0
PositionEntity Walls(31),50,0,0
PositionEntity Walls(32),0,0,-50
PositionEntity Walls(33),0,0,50


Но, кубики-то так кубиками и останутся, поэтому мы должны их расширить. Можно использовать команду ScaleEntity, но здесь я предлагаю использовать новую команду – FitMesh! Синтаксис: FitMesh объект, X, Y, Z, ширина, высота, длина – эта команда так трансформирует объект, и перемещает его вершины, что он занимает ровно отведённый куб, задаваемый этими параметрами - очень полезная команда! Позволяет Вам задать именно такой размер для модели, какой Вы хотите, независимо от того, какой размер модели был до этого! Так, вот для примера, возьмём Walls(30) – который находится слева от нашего игрока (в начале, во всяком случае), что нам надо с ним сделать? Пусть в ширине будет 2, в высоту он будет от –1 до 2 (т.е. выше всех остальных наших объектов), и в длину – на всё поле + ещё немножко (т.к. кубики у нас расставляются от –40 до 40 – т.е. на дистанции 80, сделаем размер поля равным 100…) – т.е. от –50 до 50. Значит мы пишем: FitMesh –1,-1,-50,2,3,100 – не забудьте, что последние три цифры – не координаты, а размеры! А для Walls(33) – который находится спереди, нам надо сделать ширину от –50 до 50, высоту от –1 до 2, а длину от –1 до 1. И для неё мы пишем: FitMesh –50,-1,-1,100,3,2. Так по аналогии все команды:

FitMesh Walls(30),-1,-1,-50,2,3,100
FitMesh Walls(31),-1,-1,-50,2,3,100
FitMesh Walls(32),-50,-1,-1,100,3,2
FitMesh Walls(33),-50,-1,-1,100,3,2


Вот, вроде внешний вид и приведён в норму, на выставку она может не попрёт, но для первой игры очень даже неплохо! Зато я знаю, что Ваша вторая (ну не вторая, так третья!) – точно будет намного красочнее и интереснее! (Главное не забудьте прислать мне демку или полную версию Вашей игры! И через некоторое время Ваше чудо будет красоваться в разделе "Игры"! Буду ждать!). Весь код:

SeedRnd MilliSecs()
Graphics3D 640,480,16,1
SetBuffer BackBuffer()
Const TypePlayer=1,TypeWalls=2,TypeTarget=3
Global Speed#=.1,Score=0
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
EntityColor Player,0,255,0
FreeEntity Plac
Dim Walls(33)
For i=0 To 29
Walls(i)=CreateCube()
Repeat
PositionEntity Walls(i),Rnd(-40,40),0,Rnd(-40,40)
Until Abs(EntityX(Walls(i)))>10 Or Abs(EntityZ(Walls(i)))>10
EntityType Walls(i), TypeWalls
EntityColor Walls(i),255,0,0
Next
For i=30 To 33
Walls(i)=CreateCube()
EntityColor Walls(i),100,20,0
EntityType Walls(i),TypeWalls
Next
PositionEntity Walls(30),-50,0,0
FitMesh Walls(30),-1,-1,-50,2,3,100
PositionEntity Walls(31),50,0,0
FitMesh Walls(31),-1,-1,-50,2,3,100
PositionEntity Walls(32),0,0,-50
FitMesh Walls(32),-50,-1,-1,100,3,2
PositionEntity Walls(33),0,0,50
FitMesh Walls(33),-50,-1,-1,100,3,2
Target=CreateCylinder()
PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)
EntityColor Target,255,215,0
EntityType Target,TypeTarget
cam=CreateCamera()
PositionEntity cam,0,40,0
TurnEntity cam,90,0,0
lit=CreateLight()
TurnEntity lit,70,70,0
Collisions TypePlayer,TypeWalls,2,2
Collisions TypePlayer,TypeTarget,2,2
Repeat
MoveEntity Player,0,0,Speed#
If KeyDown(203) TurnEntity Player,0,3,0
If KeyDown(205) TurnEntity Player,0,-3,0
PointEntity cam,Player
If EntityCollided (Player,TypeTarget)
Repeat
inter=False
PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)
For i=0 To 29
If MeshesIntersect(Target, Walls(i)) inter=True
Next
Until inter=False
UpdateWorld
Score=Score+1
Speed=Speed+.01
EndIf
If EntityCollided (Player,TypeWalls) End
UpdateWorld
RenderWorld
Color 255,215,0
Text 320,10,"Score : "+Score,True,True
Flip
Until KeyHit(1)
End


От массива к спискам

В этой части не произойдёт никаких изменений во внешнем виде игры, не изменится геймплей и даже не увеличится частота кадров, но без этой части нам не подойти к следущей. Сейчас мы будем оптимизировать движок, делать его более понятным и унифицированным! Для начала, мы переведём наши кубики из массива в список. Итак, грядут большие изменения в программе. Для начала создадим новый тип - Walls:

Type Walls
Field model
End Type


Эту строчку поместите до констант. Здесь мы создаём новый тип с одним полем – model. В этом поле у нас будет содержаться модели кубика. Далее, можно стереть строчку Dim Walls(33). Так как нам теперь не надо будет задавать, какое именно количество элементов мы будем использовать. Дальше, весь процесс создания кубиков нам нужно переделать:

For i=0 To 29
w.Walls = New Walls
wmodel=CreateCube()
Repeat
PositionEntity wmodel,Rnd(-40,40),0,Rnd(-40,40)
Until Abs(EntityX(wmodel))>10 Or Abs(EntityZ(wmodel))>10
EntityType wmodel, TypeWalls
EntityColor wmodel,255,0,0
Next


Здесь мы создаём новый элемент типа Walls, и создаём новый куб в его поле model, ну остальное всё осталось также. Теперь мы свободно можем поставить любую другую конечную цифру вместо 29 (раньше нам бы понадобилось менять конечное количество элементов когда мы описывали массив). Дальше также меняем создание стен:

w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,-50,0,0
FitMesh wmodel,-1,-1,-50,2,3,100
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,50,0,0
FitMesh wmodel,-1,-1,-50,2,3,100
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,0,0,-50
FitMesh wmodel,-50,-1,-1,100,3,2
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,0,0,50
FitMesh wmodel,-50,-1,-1,100,3,2


К сожалению у нас не получится так же как раньше сначала создать сразу 4 модельки, а потом их расставлять и трансформировать (вернее вряд ли получится это сделать написав меньшее количество строк и не усложняя), поэтому создадим четыре стены и расставим их по отдельности (чего нам места жалко, что ли?). И дальше поменяем цикл проверки пересечения модельки цилиндра и кубиков в главном цикле (это когда мы ставим цилиндр в новое место – помните?) – поменяем строчки:

For i=1 To 29
If MeshesIntersect(Target, Walls(i)) inter=True
Next


На:

For w.Walls = Each Walls
If MeshesIntersect(Target, wmodel) inter=True
Next


Здесь даже проще получается – т.е. независимо от того, насколько большой у нас список, мы просто «пролистываем» его от начала до конца.

Всё – переход на списки прошёл успешно! Можете запустить игру – видите, никаких изменений! Возможно кому-то покажется, что это лишь усложнение, но это только видимость. Списки намного удобнее чем массивы, если научиться с ними работать. Не нужно указывать, какое именно количество элементов Вы собираетесь использовать, а значит, игра стала более гибкой – т.е. сейчас мы можем задать любое число во время создания кубиков. Допустим, если бы мы захотели изменить цифру, если бы мы использовали массив, то нам надо было бы поменять цифру:

1) Когда мы указываем какое кол-во элементов у нас будет в массиве

2) Когда мы создаём стены (потому что стены мы создавали последними элементами)

3) В главном цикле – когда мы делали проверку на пересечение цилиндра и кубиков – опять же кол-во кубиков изменилось, значит и количество проверок должно измениться.

Три замены. Конечно, это немного, но ведь и игрушка у нас маленькая. Представьте, что было бы в большом проекте!

SeedRnd MilliSecs()
Graphics3D 640,480,16,1
SetBuffer BackBuffer()
Type Walls
Field model
End Type
Const TypePlayer=1,TypeWalls=2,TypeTarget=3
Global Speed#=.1,Score=0
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
EntityColor Player,0,255,0
FreeEntity Plac
For i=0 To 29
w.Walls = New Walls
wmodel=CreateCube()
Repeat
PositionEntity wmodel,Rnd(-40,40),0,Rnd(-40,40)
Until Abs(EntityX(wmodel))>10 Or Abs(EntityZ(wmodel))>10
EntityType wmodel, TypeWalls
EntityColor wmodel,255,0,0
Next
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,-50,0,0
FitMesh wmodel,-1,-1,-50,2,3,100
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,50,0,0
FitMesh wmodel,-1,-1,-50,2,3,100
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,0,0,-50
FitMesh wmodel,-50,-1,-1,100,3,2
w.Walls = New Walls
wmodel=CreateCube()
EntityColor wmodel,100,20,0
EntityType wmodel,TypeWalls
PositionEntity wmodel,0,0,50
FitMesh wmodel,-50,-1,-1,100,3,2
Target=CreateCylinder()
PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)
EntityColor Target,255,215,0
EntityType Target,TypeTarget
cam=CreateCamera()
PositionEntity cam,0,40,0
TurnEntity cam,90,0,0
lit=CreateLight()
TurnEntity lit,70,70,0
Collisions TypePlayer,TypeWalls,2,2
Collisions TypePlayer,TypeTarget,2,2
Repeat
MoveEntity Player,0,0,Speed#
If KeyDown(203) TurnEntity Player,0,3,0
If KeyDown(205) TurnEntity Player,0,-3,0
PointEntity cam,Player
If EntityCollided (Player,TypeTarget)
Repeat
inter=False
PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)
For w.Walls = Each Walls
If MeshesIntersect(Target, wmodel) inter=True
Next
Until inter=False
UpdateWorld
Score=Score+1
Speed=Speed+.01
EndIf
If EntityCollided (Player,TypeWalls) End
UpdateWorld
RenderWorld
Color 255,215,0
Text 320,10,"Score : "+Score,True,True
Flip
Until KeyHit(1)
End
Категория: Учебники по Blitz3d | Добавил: blitz3d-portal (08.Декабрь.04) E W
Просмотров: 2212 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]