Но это ещё не всё… Дальше мы возьмём готовые куски blitzbasicа, и создадим из них функции…

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

Функции (как вы помните) нужно вставлять в конце blitzbasicа, после команды End. Как мы её сделаем? Да просто вырежем весь кусок blitzbasicа, в котором мы создаём кубики и стены, и засунем в функцию (поменяв заодно цифру 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 

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

If EntityCollided (Player,TypeTarget)

	PositionTarget()
	
	UpdateWorld
	
	Score=Score+1 
	
	Speed=Speed+.01

EndIf

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

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

…на:

 
PositionTarget()

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

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

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

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), и сделаем из них… правильно Функцию! А как вы догадались?

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

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

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

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

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