…Надоело играть… слишком сырая получилась… хотелось бы её переделать. Вот и давайте её доработаем…

Первым, что бросается в глаза – во-первых, (во всяком случае на более медленных машинах это заметно) это то, что когда мы прикасаемся к цилиндру, он меняет своё положение, причём 2 раза, во-вторых очки тоже прибавляются на 2, хотя мы белым по синему написали “Score=Score+1” то бишь на 1, а не на 2, ну, и кроме того в общем скорость тоже увеличивается в 2 раза быстрее чем надо… Когда я это заметил (а заметил я это сразу), моё подсознание сразу так выдала мне способ решения этой баги (интуиция, блин, хорошая вещь), затем через некоторое время сознание дало подробное объяснение, почему это происходит, ну, а память, блин, посчитала эту информацию ненужной и не запомнила … короче не помню я почему, но решается это всего одной единственной строкой:

UpdateWorld

Что вы уже эту команду знаете? И она уже у нас стоит? Правильно, а вы добавьте ещё одну! Да не рядом с предыдущей! Добавьте её в условие соприкосновения шара и Типа Цилиндра после установки цилиндра на новое место… кому здесь не понятно? Объясняю подробнее, кто не хочет осмысливать мою предыдущую фразу: поставьте эту команду после строчки PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40) … Как где она? В программе! !

Почему так происходит? Вспоминать не охота, попробуйте догадаться сами, помню только, что это связано с коллизион детекшном и, кажется после первого UpdateWorld как бы коллизия остаётся, хотя цилиндр перемещается, поэтому надо ставить ещё один… муть какая-то… не помню, в общем и всё тут … (программист называется

Вторая бага:

Вы наверное уже заметили, что иногда, когда вы запускаете игру, она сразу выходит? Вот здесь всё наоборот: объяснение простое, а попариться придётся дольше! Так вот, если вы ещё не поняли, в таких случаях получается так, что кубик создаётся слишком близко к шарику, так что шарик уже «влезает» в него при своём создании, дольше срабатывает условие… и игра выходит… так что нам нужно будет сделать так, что бы кубики не создавались слишком близко к центру…

Сделать это можно в начале… Алгоритм таков: когда кубики случайным образом расставляются по местам, нужно проверять их положение, и, если они будут находиться на расстоянии меньше чем 3 от центра, задавать их положение заново… т.е. циклом с условием.

Так нам просто строчку в цикле создания кубиков:

PositionEntity Walls(i),Rnd(-40,40),0,Rnd(-40,40)

Нужно заменить на:

Repeat  

	PositionEntity Walls(i),Rnd(-40,40),0,Rnd(-40,40)

Until Abs(EntityX(Walls(i)))>4 Or Abs(EntityZ(Walls(i)))>4

Так, новые слова: Abs(число) – это не команда, а функция. Она возвращает нам модуль числа в скобках (т.е. если в скобках было –4, то она возвращает 4, если 5 – то число так и остаётся положительным: 5).

Эти строчки расшифровываются так: Сначала в случайное место ставится кубик, затем идёт проверка, если X координата или Z координата меньше 4 по модулю (т.е. в диапазоне от –4 до 4), то цикл повторяется (так пока кубик не встанет в нужное место)… короче, получается такой квадрат размером 4*4 вокруг центра, в который кубики уже никогда не попадут… (можно кстати сделать ограничение не квадратом, а кругом – заменив на Until Sqr(Abs(EntityX(Walls(i)))^2 + Abs(EntityZ(Walls(i)))^2)>10 , по обычной теории Пифагора, но это ни к чему…)

Третья бага:

Особенно некрасиво смотрится, когда цилиндр оказывается внутри какого-либо кубика, и его невозможно достать… сейчас мы с ней справимся.

Опять же исправлять это надо в тот момент, когда цилиндр куда-то ставится случайным образом… Алгоритм будет примерно такой же как в прошлый раз – т.е. в цикле с условием, только на этот раз предметом проверки будет пересечение цилиндра с кубиками…

Так, строчку в главном цикле:

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

…нам нужно заменить, вот только каким образом это лучше сделать? В прошлый раз у нас было 29 квадратов, и на каждый была одна проверка… здесь у нас один цилиндр, только кубиков – 30… поэтому и цилиндр будет проверяться на пересечение 30 раз – таким образом:

  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

Объясняю как это происходит:

Для начала новая команда – MeshesIntersect(объект1,объект2) возвращает True, если объект1 пересекается с объектом2… так как здесь применяется метод проверки полигон к полигону, она довольно медленная, (зато точная ) но для нашей игры как раз…

Дальше – как идёт цикл…

Сначала мы задаём переменной inter значение False, затем ставим в случайное место цилиндр, и затем идёт цикл из 29 проверок, и если цилиндр пересекается хотя бы с одним из кубиков, значение переменной inter становится равным True. Ну и дальше проверяем – если inter так и осталась False идём дальше, если нет – возвращаемся и проводим все операции заново…

Ну, вот вроде все самые бросающиеся в глаза баги убрали – теперь это довольно играбельный движок …

А вот всё что у нас есть на данный момент:

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

FreeEntity Plac

Dim Walls(29)

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

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)
	
		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