И вот теперь только мы готовы к тому, чтобы создать остальные части игры – это Стартовый экран и экран Гейм Овера (можно было бы и больше, конечно, но нам хватит).

Для начала введём переменную, в которой будет находится информация о том, какой экран мы сейчас показываем. Ну, назовём её GameScr, а значения она будет принимать: 0 - стартовый экран, 6 - Экран Гейм Овера, и, например 9 – экран самой игры.
Global GameScr=0
Т.е. начинаться у нас будет со стартового экрана.

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

Repeat
	Select GameScr
		Case 0
			UpdateStartScreen() 
		Case 9
			UpdateGame()
	End Select
	
	Flip
 
Until KeyHit(1)

Вы хотите узнать, что это за команды - Select и Case? Ну, это просто команды условия. Например, нам нужно что-то делать, в зависимости от того, какое значение принимает переменная variable. Можно написать так:

If variable=0 then
            …
EndIf

If variable=1 then 
            …
EndIf

If variable=2 then 
            …
EndIf

If variable=3 then 
            …
EndIf

If variable=4 then 
            …
EndIf
 
А можно – так:
 
Select variable
	Case 0
	            …
	Case 1
	            …
	Case 2
	            …
	Case 3
	            …
	Case 4
            …
End Select

Достоинства последнего метода перечислять не буду

Дальше, в зависимости от того, какое значение у переменной GameScr, выполняются определённые действия… т.е. если GameScr=9 (идёт сама игра), то мы вызываем функции UpdateGame(), в которую мы поместили все наши команды игры. А если GameScr=0, мы должны показывать стартовый экран. Мы вызываем функцию UpdateStartScreen(), которую сейчас напишем.

Так, стартовый экран у нас будет выглядеть таким образом: сверху большими буквами название – “First Game”, например, а снизу две опции – Start и Quit. Всё это будем делать текстом. Для этого нам нужно загрузить шрифт (два шрифта точнее):

Global fontB=LoadFont("Verdana",72)
Global FontM=LoadFont("Verdana",32)

Эти строчки поставьте после команд инициализации графики.

Синтакс: LoadFont (название,размер) – загружает шрифт. По-моему, всё ясно…

Теперь создадим саму функцию UpdateStartScreen()

Function UpdateStartScreen()
 
 
	Cls
	SetFont FontB
	Color 255,100,40
	Text 320,150,"First Game",True,True
	SetFont FontM
	Text 320,240, "Start",True,True
	Text 320,280, "Quit",True,True

 
End Function

Так, экран сделали, теперь нам нужен курсор. Как сделать курсор? Так как наша игра никаких внешних ресурсов до сих пор не использовала, здесь тоже обойдёмся без картинок… Более того, я вообще предлагаю вместо курсора текст использовать, точнее символ «*»…

Вот как это сделать (вставить в функцию):

Color 250,200,0
Text MouseX(),MouseY(),"*",True,True

Получился жёлтый курсор. Однако кликание на текст ничего не даёт... Нам нужна проверка – не находится ли курсор над надписью Start или Quit.

Function UpdateStartScreen()
 
 
	Cls
	SetFont FontB
	Color 255,100,40
	Text 320,150,"First Game",True,True
	SetFont FontM
	Text 320,240, "Start",True,True
	Text 320,280, "Quit",True,True

 
End Function

Всё очень просто (хотя это и 2Д … Здесь мы используем команды RectsOverlap – она проверяет, не пересекаются ли заданные прямоугольники.

Синтакс: RectsOverlap (X коорд. прямоугольника 1, Y коорд. прямоугольника 1, Ширина прямоугольника 1, Высота прямоугольника 1, X коорд. прямоугольника 2, Y коорд. прямоугольника 2, Ширина прямоугольника 2, Высота прямоугольника 2)

X и Y координаты – левого верхнего угла прямоугольника.

tShift=0
If RectsOverlap(MouseX(),MouseY(),1,1,320-50,240-12,100,32) tShift=1
If RectsOverlap(MouseX(),MouseY(),1,1,320-50,280-12,100,32) tShift=2

Эти команды нужно вставить в начало функции.

Теперь мы у нас есть курсор и мы знаем, когда он находится над “Start” и ”Quit”. Теперь надо сделать так, чтобы цвет текста менялся, когда курсор будет наведён на него, так что немного перепишем строки:

If tShift=1 Color 0,255,0 Else Color 255,0,0
Text 320,240, "Start",True,True
If tShift=2 Color 0,255,0 Else Color 255,0,0
Text 320,280, "Quit",True,True

Так, интерактивность (хоть и примитивная, но хотя бы что-то присутствует, осталось только заставить это работать. Для этого нужно поставить в конец функции вот эти строчки:

If MouseHit(1)
	Select tShift
		Case 1
			CreatePlayer()
			CreateWalls(29)
			CreateTarget()
			CreateEnv()
			
			Collisions TypePlayer,TypeWalls,2,2
			Collisions TypePlayer,TypeTarget,2,2
			
			GameScr=9
			Case 2
		End
	End Select 
EndIf

Здесь у нас идёт проверка на нажатие левой кнопки. Затем, если курсор находится над Start`ом, происходит инициализация (мы её из начала кода вырезали), и меняется переменная GameScr, так, что со следующим кадром покажется уже не стартовый экран, а сама игра. Ну, а если курсор над кнопкой Quit, то программа просто выходит…

Дальше, теперь нам надо сделать так, чтобы при проигрыше или нажатии кнопки Esc, игра выходила на стартовый экран. Но перед этим, показывала экран ГеймОвера. Для этого внесём некоторые изменения в функцию UpdateGame():
Во первых сменим строчку, где игра заканчивается при столкновении с кубиком

If EntityCollided (Player,TypeWalls) End
 
  на эту:
 
If EntityCollided (Player,TypeWalls) Or KeyDown(1)
	GameScr= 6
	FreeGame()
EndIf

Теперь игра будет очищаться и выходить на экран геймовера. И теперь у нас будет только один способ (без нажатия Ctrl+Alt+Del выйти из игры – нажать Quit или Esc на стартовом экране. Поэтому немного поменяем условие в главном цикле:

 
Until KeyHit(1)
 
…на :
 
Until Quit

Quit – будет нашей переменной, которая будет показывать, что на этом шаге игра выходит…
Сначала создадим её (в самом начале программы есь-сно, где мы задаём остальные глобальные переменные):

 
Global Quit=False

False будет обозначать, что, типа, игра не выходит ещё…

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

Case 2
 End
 
поменяем на:
 
Case 2
 Quit=True
 
И добавим ещё условие:
 
If KeyDown(1) Quit=True

Так, вот уже почти всё, осталось только сделать сам экран Геймовера, о котором мы тут столько говорим
В главный цикл вставляем строчки Select`овского условия:

Case 6
 
	Cls
	Flip
	Cls
	SetFont fontB
	Color 255,0,0
	Text 320,240,"Game Over",True,True
	Flip
	Delay 1000
	FlushKeys
	GameScr = 0 

Здесь у нас описан экран Геймовера: Что здесь и как – объясняю по порядку:

Сначала очищаем первую поверхность, флипим, очищаем вторую, устанавливаем шрифт, цвет и пишем Гейм Овер, опять флипим, ждём одну секунду (1000 миллисекунд) командой FlushKeys очищаем список всех нажатых клавиш (если была нажата Esc игра выйдет, дойдя до условия в функции UpdateStartScreen()), и меняем переменную GameScr на 0… вот экран Гейм Овера и готов….

На этом можно и закончить – мы сделали хоть и примитивную, но всё-таки полноценную игру!!! Практически можно поздравить вас, что вы всё-таки заставили себя дочитать это до конца, ну и себя самого, за то что этот кошмар под названием «писать туториал» позади. Я постарался показать (хотя бы мельком) все аспекты программирования игры. Кстати, они не очень сильно отличаются от более «серьёзных» проектов, в которых просто больше элементов. Так что вы теперь готовы к писанию своих игрушек!!!

Вот весь код нашей получившейся в итоге игры:

SeedRnd MilliSecs()
 
Global GameScr=0
Global Quit=False
 
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()
 
Global fontB=LoadFont("Verdana",72)
Global FontM=LoadFont("Verdana",32)
 
;*******************
;Main Cycle
;*******************
 
Repeat
 
	Select GameScr
		Case 0
		
			UpdateStartScreen()
		
		Case 6
		
			Cls
			Flip
			Cls
			SetFont fontB
			Color 255,0,0
			Text 320,240,"Game Over",True,True
			Flip
			Delay 1000
			FlushKeys
			GameScr = 0 
		
		Case 9
	
		UpdateGame()
	
	End Select
	
	Flip
 
Until Quit
 
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) Or KeyDown(1)
		GameScr=6
		FreeGame()
	EndIf
  
 
	UpdateWorld
	RenderWorld
	
	Color 255,215,0
	Text 320,10,"Score : "+Score,True,True

End Function
 
Function UpdateStartScreen()
 
	tShift=0
	If RectsOverlap(MouseX(),MouseY(),2,2,320-50,240-12,100,32) tShift=1
	If RectsOverlap(MouseX(),MouseY(),2,2,320-50,280-12,100,32) tShift=2
	
	Cls
	SetFont FontB
	Color 255,0,0
	Text 320,150,"First Game",True,True
	SetFont FontM
	If tShift=1 Color 0,255,0 Else Color 255,0,0
	Text 320,240, "Start",True,True
	If tShift=2 Color 0,255,0 Else Color 255,0,0
	Text 320,280, "Quit",True,True
	
	Color 250,200,0
	Text MouseX(),MouseY(),"*",True,True

	If MouseHit(1)
		Select tShift
			Case 1
				CreatePlayer()
				CreateWalls(29)
				CreateTarget()
				CreateEnv()
				
				Collisions TypePlayer,TypeWalls,2,2
				Collisions TypePlayer,TypeTarget,2,2
				
				GameScr=9
			Case 2
				Quit=True
		End Select 
	EndIf
	
	If KeyHit(1) Quit=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