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

 

Я не спорю, ездить шариком по плоскости, лавируя между кубиков, в созданной вами программе конечно очень захватывающе… но боюсь другие люди (не вы… – да, да существуют ещё и другие! J) скажут что это, конечно, круто, но Quake им нравится больше… правильно, они ничего не понимают в искусстве! Вот только таких людей подавляющее большинство, да и сами игры обычно создаются для других людей (за редким исключением J), а этим варварам нужно что? Стимул, блин – ну не нравится им просто спокойно ездить по полю!!! Хорошо, мы им такое сейчас устроим!!! Хе-хе J!!!

 

Начнём со стимула! Помните, в змейке кажется для этого использовали такой квадратик, который надо было собирать… используем этот примитивный метод.

 

Для начала добавим для него отдельную константу – вот так:

 

Const TypePlayer=1,TypeWalls=2,TypeTarget=3

 

Дальше создадим сам объект… на этот раз у нас будет цилиндр, и укажем его тип:

 

Target=CreateCylinder()

 

EntityType Target,TypeTarget

 

Ну, и добавим коллизион детекшн для кучи:

 

Collisions TypePlayer,TypeTarget,2,2

 

Ок, вроде основу инициализировали…

 

Дальше сделаем так, чтобы цилиндр перемещался в другое место при столкновении с шаром. Как это сделать? Естественно – условием внутри главного цикла (вы хоть помните такой? J):

 

If EntityCollided (Player,TypeTarget) PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)

 

Новая команда? Точно! Вы наверное уже поняли что это? Да – это и есть проверка на соприкосновение: Пишется так EntityCollided (Объект, тип с которым он соприкасается) – итак, эта команда возвращает нам True, если заданный в скобках объект соприкасается с заданным типом. Т.е. в данном случае – шар соприкасается с типом цилиндра (TypeTarget). Перед использованием этой команды нужно обязательно указать этот тип коллизии командой Collisions, а иначе она работать не будет!

 

Так, теперь уже ездить можно не бесцельно, а гоняясь за цилиндром.

 

Но, опять же – слишком миролюбиво… нам нужен Гейм Овер!!! Как его реализовать? Очень просто – когда шар будет сталкиваться с кубиками – тогда и будет конец игры!

 

Следующее условие:

 

If EntityCollided (Player,TypeWalls) End

 

Здесь мы пишем, что когда шар сталкивается с типом кубиков, игра заканчивается… она просто выходит… грубо, конечно, но мы всё это потом исправим, я вам обещаю! …правда исправим!!! Да я вас вообще когда-нибудь обманывал?.. …Когда??! (J)

 

Пойдём дальше… игрок начинает подумывать о том, что ему хочется выйти тогда, когда игра даёт ему шанс расслабиться – то есть проиграв или просто затормозив где-нибудь, у игрока начинает происходить процесс анализа происходящего. К чему это я? А, да – внимание игрока должно быть сосредоточено на игре – т.е. шарик должен всё время быть в движении, что бы у центрального процессора человека под названием «мозг» даже не появлялось мысли о кнопке Esc, НО и двигаться быстро он тоже не должен – если человек будет проигрывать сразу после нажатия кнопки Старт – тоже будет не очень хорошо…

 

Теперь нам нужна постоянная скорость, и, естественно, стрелки управления – вперёд-назад теперь нам будут не нужны (если игрок будет передвигаться с постоянной скоростью), поэтому строчки:

 

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

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

 

…можно заменить на:

 

MoveEntity Player,0,0,.2

 

Так… уже что-то, во что можно ПОИГРАТЬ, во всяком случае уже интереснее… но поиграв какое-то время (минут 10) можно натренироваться так, что пальцы уже сами будут нажимать на стрелки, и обходить препятствия используя уже один спинной мозг J, и опять же центральный процессор головного мозга будет посылать сигналы о том, что, типа, не пора бы выйти?.. поэтому требуется усложнять игру. Как это сделать? О, в голову приходят всякие извращённые мысли о том, что можно сделать с игроком, но, думаю, лучше всего просто так увеличивать скорость после каждого собранного цилиндра… заодно ещё и будем записывать очки игрока!

 

Для этого нам потребуется указать новые переменные (эту строчку нужно вставить где-нить в начале, допустим, после констант…):

 

Global Speed#=.1,Score=0

 

Здесь у нас Speed# (не забудьте, что когда вы собираетесь использовать дробные числа, вы должны использовать # после названия переменных, а то у вас ничего не получится) – скорость, и Score – очки

 

Теперь, скорость должна увеличиваться после столкновения с цилиндром, поэтому простое условие:

 

If EntityCollided (Player,TypeTarget) PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)

 

заменим на:

 

If EntityCollided (Player,TypeTarget)

  PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)

  Score=Score+1

  Speed=Speed+.01

 EndIf

 

Т.е. здесь мы при условии, что шар сталкивается с Типом цилиндра, выполняются три действия – цилиндр перемещается в новое место, переменная Score увеличивается на 1, и переменная Speed увеличивается на 0.1… вот только скорость-то от этого не меняется, поэтому строчку перемещения самого игрока в цикле:

 

MoveEntity Player,0,0,.2

 

заменим на:

 

MoveEntity Player,0,0,Speed#

 

Что-то изменилось? Видите – теперь игрок передвигается не просто со скоростью 0.2, а со значением переменной Speed#, которое изменяется…

 

Ну, вот так намного интереснее – теперь это уже может, хоть и с натягом, но называться игрой…! В это даже самому можно поиграть, чем я сейчас и займусь… после того, как покажу, как писать на экране количество очков игрока…

 

Итак новая команда:

 

Text 320,10,"Score : "+Score,True,True

 

Синтакс: Text x, y, текст, центрирование по х, центрирование по у – эта команда схожа с командой Print, только предназначена для графического режима…

 

Эта команда 2-х мерная, т.е. рисуется поверх экрана… запомните, 2-х мерные команды типа рисования линий, картинок, текста нужно ставить между командами RenderWorld и Flip, иначе вы их не увидите!!!

 

Ну всё кажется самая глючная из ваших игр готова… да… глючная, а всё же игра!!! Но все глюки мы постараемся убрать в следующей части.

 

Весь код:

 

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

 

Target=CreateCylinder()

PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)

 

EntityType Target,TypeTarget

 

cam=CreateCamera()

PositionEntity cam,0,60,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

 

 If EntityCollided (Player,TypeTarget)

  PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)

  Score=Score+1

  Speed=Speed+.01

 EndIf

 

 If EntityCollided (Player,TypeWalls) End

 

 UpdateWorld

 RenderWorld

 

 Text 320,10,"Score : "+Score,True,True

 

 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