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

 

Но это ещё не всё… Дальше мы возьмём готовые куски кода, и создадим из них функции… (вот где всё самое клёвое-то начинается J!!!)

 

Для начала предлагаю сделать функцию, создающую кубики. Назовём её, например, CreateWalls(tn), в скобки которой будем указывать, сколько кубиков нам надо создать! (Вот для чего нам нужны были списки J)…

 

Функции (как вы помните) нужно вставлять в конце кода, после команды End. Как мы её сделаем? Да просто вырежем весь кусок кода, в котором мы создаём кубики и стены, и засунем в функцию (поменяв заодно цифру 29 на tn – переменную, в которой будет содержаться число, введённое в функцию):

 

Function CreateWalls(tn)

 

 For i=0 To tn

  w.Walls = New Walls

  w\model=CreateCube()

  Repeat 

   PositionEntity w\model,Rnd(-40,40),0,Rnd(-40,40)

  Until Abs(EntityX(w\model))>10 Or Abs(EntityZ(w\model))>10

  EntityType w\model, TypeWalls

  EntityColor w\model,255,0,0

 Next

 

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,-50,0,0

  FitMesh w\model,-1,-1,-50,2,3,100

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,50,0,0

  FitMesh w\model,-1,-1,-50,2,3,100

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,0,0,-50

  FitMesh w\model,-50,-1,-1,100,3,2

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,0,0,50

  FitMesh w\model,-50,-1,-1,100,3,2

 

End Function

 

… а вместо него напишем:

 

CreateWalls(29)

 

Дальше предлагаю создать функцию для того, чтобы ставить цилиндр в случайное место и заодно проверять его – вырежем то, что у нас в главном цикле, где цилиндр устанавливается в случайное место, и проверяется его пересечение с кубиками:

 

Function PositionTarget()

 

 Repeat

  inter=False

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

  For w.Walls = Each Walls

   If MeshesIntersect(Target, w\model) inter=True

  Next

 Until inter=False

 

End Function

 

Ну а вместо этого куска кода вставим вызов этой функции – т.е. так:

 

If EntityCollided (Player,TypeTarget)

 PositionTarget()

 UpdateWorld

 Score=Score+1

 Speed=Speed+.01

EndIf

 

Заодно, заменим строчку в самом начале, когда мы создаём цилиндр:

 

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

 

…на:

 

PositionTarget()

 

(а то я забыл в самом начале указать проверку на пересечение с кубиками, и получалось так, что в самом начале цилиндр мог находиться наполовину в кубе J)

 

Так продолжим нашу вырезательную деятельность…

Теперь засунем в функцию команды создания игрока

 

Function CreatePlayer()

 

 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

 

End Function

 

А наверху у нас останется:

 

Global Player

CreatePlayer()

 

Также сделаем функцию для создания цилиндра

 

Function CreateTarget()

 

 Target=CreateCylinder()

 PositionTarget()

 EntityColor Target,255,215,0

 

 EntityType Target,TypeTarget

 

End Function

 

Ну, а наверху, мы напишем…

 

Global Target

CreateTarget()

 

Не забудьте обозначить переменную Target как Global – иначе функция не «увидит» её…

И функцию для создания камеры и света

 

Function CreateEnv()

 

 cam=CreateCamera()

 PositionEntity cam,0,40,0

 TurnEntity cam,90,0,0

 

 lit=CreateLight()

 TurnEntity lit,70,70,0

 

End Function

 

Ну, и наверху, не забыв обозначить переменные cam и lit как Global, напишем

 

Global cam

Global lit

CreateEnv()

 

Теперь, возьмём все команды в главном цикле (кроме команды Flip), и сделаем из них… правильно Функцию! А как вы догадались? J

 

Function UpdateGame()

 

 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)

  PositionTarget()

  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

 

End Function

 

И весь главный цикл у нас будет представлять:

 

Repeat

 

 UpdateGame()

 

 Flip

 

Until KeyHit(1)

 

А команды инициализации после некоторой оптимизации и расставления по местам будут выглядеть так:

 

SeedRnd MilliSecs()

 

Type Walls

 Field model

End Type

 

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

 

Global Speed#=.1,Score=0

 

Global Player

Global Target

Global cam

Global lit

 

Graphics3D 640,480,16,1

SetBuffer BackBuffer()

 

CreatePlayer()

CreateWalls(29)

CreateTarget()

CreateEnv()

 

Collisions TypePlayer,TypeWalls,2,2

Collisions TypePlayer,TypeTarget,2,2

 

И последнюю функцию мы создадим сами. Она будет очистит из памяти все объекты которые мы тут создавали…

 

Function FreeGame()

 

ClearCollisions

 

 FreeEntity cam

 FreeEntity lit

 FreeEntity Player

 FreeEntity Target

 

 For w.Walls=Each Walls

  FreeEntity w\model

  Delete w

 Next

 

 Speed#=.1

 Score=0

 

End Function

 

Обратите внимание на то, как удаляются списки. Сначала удаляются все объекты, занимающие память, а потом указатель на элемент списка… ну, понятно, короче J

 

И заодно вызовем эту функцию как раз перед командой End. (ну это надеюсь сами сделаете)

 

Вот так выглядит наш код после оптимизации, (или офункциации J):

 

SeedRnd MilliSecs()

 

Type Walls

 Field model

End Type

 

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

 

Global Speed#=.1,Score=0

 

Global Player

Global Target

Global cam

Global lit

 

Graphics3D 640,480,16,1

SetBuffer BackBuffer()

 

CreatePlayer()

CreateWalls(29)

CreateTarget()

CreateEnv()

 

Collisions TypePlayer,TypeWalls,2,2

Collisions TypePlayer,TypeTarget,2,2

 

;*******************

;Main Cycle

;*******************

 

Repeat

 

 UpdateGame()

 

 Flip

 

Until KeyHit(1)

 

FreeGame()

End

 

;*******************

;Functions

;*******************

 

Function CreateWalls(tn)

 

 For i=0 To tn

  w.Walls = New Walls

  w\model=CreateCube()

  Repeat 

   PositionEntity w\model,Rnd(-40,40),0,Rnd(-40,40)

  Until Abs(EntityX(w\model))>10 Or Abs(EntityZ(w\model))>10

  EntityType w\model, TypeWalls

  EntityColor w\model,255,0,0

 Next

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,-50,0,0

  FitMesh w\model,-1,-1,-50,2,3,100

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,50,0,0

  FitMesh w\model,-1,-1,-50,2,3,100

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,0,0,-50

  FitMesh w\model,-50,-1,-1,100,3,2

 

 w.Walls = New Walls

  w\model=CreateCube()

  EntityColor w\model,100,20,0

  EntityType w\model,TypeWalls

 PositionEntity w\model,0,0,50

  FitMesh w\model,-50,-1,-1,100,3,2

 

End Function

 

Function PositionTarget()

 

 Repeat

  inter=False

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

  For w.Walls = Each Walls

   If MeshesIntersect(Target, w\model) inter=True

  Next

 Until inter=False

 

End Function

 

Function CreatePlayer()

 

 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

 

End Function

 

Function CreateTarget()

 

 Target=CreateCylinder()

 PositionTarget()

 EntityColor Target,255,215,0

 

 EntityType Target,TypeTarget

 

End Function

 

Function CreateEnv()

 

 cam=CreateCamera()

 PositionEntity cam,0,40,0

 TurnEntity cam,90,0,0

 

 lit=CreateLight()

 TurnEntity lit,70,70,0

 

End Function

 

Function UpdateGame()

 

 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)

  PositionTarget()

  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

 

End Function

 

Function FreeGame()

 

ClearCollisions

 

 FreeEntity cam

 FreeEntity lit

 FreeEntity Player

 FreeEntity Target

 

 For w.Walls=Each Walls

  FreeEntity w\model

  Delete w

 Next

 

 Speed#=.1

 Score=0

 

End Function

 

 

 Оглавление:

 

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