Показать сообщение отдельно
Старый 12.06.2010, 20:29   #7
Hurrit
Мастер
 
Аватар для Hurrit
 
Регистрация: 27.01.2008
Адрес: Россия, СКФО, ЧР, Грозный
Сообщений: 1,144
Написано 578 полезных сообщений
(для 2,207 пользователей)
Ответ: Делаем квест на Xors3D

Продолжим. У нас появился инвентарь, давайте же научимся брать предметы. Как мы помним, предметы которые можно брать имеют тип номер 2, и чтобы научить игру отличать эти предметы от других, нам надо модифицировать функцию SortMapObjects(), InventoryAddItem() и UpdatePlayer(), также, нам надо будет изменить массив img(100):

Dim img(100)
	img(3)=xLoadImage("key.png")
	img(7)=xLoadImage("batareyka.png")
	img(11)=xLoadImage("key.png")

Function SortMapObjects(entity)
	name$=xEntityName(entity)
	xEntityPickMode entity,2 ; Устанавливаем PickMode равным 2, чтобы мы могли "ловить" его камерой
	
	If Instr(name,"player") Then
		xPositionEntity player,xEntityX#(entity),xEntityY#(entity),xEntityZ#(entity)
		xResetEntity player
		xHideEntity entity
	EndIf
	
	If Instr(name,"map") Then
		xEntityType entity,TypeMap
	EndIf
	
	If Instr(name,"obj") Then
		object_type=Int(Mid(name,4,1))
		object_id=Int(Mid(name,5,3))
				obj(object_id)=New properties
				obj(object_id)\entity=entity
				obj(object_id)\obj_type=object_type ; Здесь, мы записываем тип объекта в поле obj_type
					xExtractAnimSeq(obj(object_id)\entity,0,30) ; Получаем анимацию открывания
					xExtractAnimSeq(obj(object_id)\entity,30,60) ; Получаем анимацию закрывания
					xEntityType obj(object_id)\entity,TypeMap ; Устанавливаем тип для коллизий
					xNameEntity obj(object_id)\entity,name ; Даем имя объекту, для дальнейшей идентификации
		Select object_type ; Здесь, мы получаем тип объекта
			Case 2
				obj(object_id)\id_parent=Int(Mid(name,8,3))
			Case 3
				obj(object_id)\id_object=Int(Mid(name,8,3))	
			Case 4
				obj(object_id)\id_object=Int(Mid(name,8,3))	
				obj(object_id)\id_child1=Int(Mid(name,11,3))	
				obj(object_id)\id_child2=Int(Mid(name,14,3))	
		End Select
	EndIf
	
	For i=0 To xCountChildren(entity)-1
		SortMapObjects(xGetChild(entity,i))
	Next
End Function

Function InventoryAddItem(image)
	For i=1 To 100
		If inv(i)\id=0 Then 
			inv(i)\image=img(image) ; Здесь, мы добавляем в инвентарь рисунок с номером равному image
				inv(i)\id=image ; И присваиваем ему ID равное значению image
			Exit
		EndIf
	Next
End Function

Function UpdatePlayer()
	mxspd#=xMouseXSpeed()*0.05 ; Получаем координаты передвижения мышки по Х
	myspd#=xMouseYSpeed()*0.05 ; Получаем координаты передвижения мышки по Y
	
	If inv_draw=0 xMoveMouse xGraphicsWidth()/2,xGraphicsHeight()/2 ; Передвигаем мышку в центр окна
	If xEntityPitch(camera)+myspd<-89 xRotateEntity camera,-89,0,0 ; Проверяем угол поворота камеры по X
	If xEntityPitch(camera)+myspd>89 xRotateEntity camera,89,0,0 ; Проверяем угол поворота камеры по X
	xRotateEntity camera,xEntityPitch(camera)+myspd,0,0 ; Поворачиваем камеру по X
	xRotateEntity player,0,xEntityYaw(player)-mxspd,0 ; Поворачиваем камеру по Y
	
	If xKeyDown(KEY_W) xMoveEntity player,0,0,0.5
	If xKeyDown(KEY_S) xMoveEntity player,0,0,-0.5
	If xKeyDown(KEY_A) xMoveEntity player,-0.5,0,0
	If xKeyDown(KEY_D) xMoveEntity player,0.5,0,0
	If xMouseHit(2) inv_draw=1-inv_draw ; Если нажата правая кнопка мыши, то меняем значение inv_draw на обратное
	
	If inv_draw=1 Then ; Если inv_draw=1, то отрисовываем и обновляем наш инвентарь
		InventoryDraw()
		InventoryUpdate()
	EndIf
	
	Select xKeyDown(KEY_LCONTROL)
		Case True
			xPositionEntity camera,0,5,0
			
		Case False
			xPositionEntity camera,0,15,0
	End Select
	
	If xKeyHit(KEY_E) Then
		xCameraPick(camera,xMouseX(),xMouseY()) ; Делаем пик камерой
		picked=xPickedEntity() ; Даем picked'у значение "пойманного" нами объекта
		picked_name$=xEntityName(picked) ; Получаем имя picked'a
	EndIf
	
	If picked<>0 Then ; Проверяем, равен ли picked 0
		If Instr(picked_name,"obj") Then ; Проверяем, есть ли в имени picked'a "obj"
			id=Mid(picked_name,5,3) ; Получаем ID объекта
				Select obj(id)\obj_type ; Узнаем, какой тип объекта мы пикнули
				
					Case 1 ; Если тип 1, то
						If xAnimating(obj(id)\entity)=0 Then ; Проверяем, играет ли сейчас какая-нибудь анимация
							Select obj(id)\time ; Узнаем, какая была последняя анимация
								Case 0 ; Если закрытия, то проигрываем открывание
									xAnimate obj(id)\entity,3,1,1
									obj(id)\time=1 ; Меняем состояние
								Case 1
									xAnimate obj(id)\entity,3,1,2 ; Если открытия, то проигрываем закрывание
									obj(id)\time=0 ; Меняем состояние
							End Select					
						EndIf
						
					Case 2
						InventoryAddItem(id) ; Добавляем в инвентарь картинку с ID объекта
						xHideEntity obj(id)\entity ; Скрываем объект
						
				End Select
		EndIf
	EndIf
	
End Function
Жмем F5, открываем полочку, и берем ключик, затем жмем правую кнопку мыши, и видим ключ в инвентаре. Также, Вы можете заметить что дверь, к которой нужен ключ не открывается, без него не открывается. Однако, есть две проблемы: 1 - ключ не выкатывается вместе с полочкой, 2 - дверь не откроется и с ключом. Давайте, для начала исправим первую ошибку:

Function InitScene()
	light=xCreateLight()
	
	map=xLoadAnimMesh("map.b3d")
		SortMapObjects(map)
	
	For i=1 To 999
		If obj(i)<>Null Then ; Если наш объект существует, то
			Select obj(i)\obj_type ; Получаем его тип
				Case 2 ; И если он равен двум, то 
					If obj(i)\id_parent<>0 Then ; Проверяем, существует ли у него родитель
						xEntityParent obj(i)\entity, obj(obj(i)\id_parent)\entity; Если да, то присваиваем его ему
					EndIf
			End Select
		EndIf
	Next
	
	For i=1 To 100
		inv(i)=New inventory ; Создаем новую ячейку
	Next
		
	xCollisions TypePlayer,TypeMap,2,2
End Function
Теперь, ключ выкатывается вместе с полкой. Давайте, решать проблему номер два:

Function InventoryUpdate()
	If (xMouseX()>=30) And (xMouseX()=<330) And (xMouseY()>=30) And (xMouseY()=<330) Then ; Проверяем, находится ли наш курсор наш курсор над ячейками
		If xMouseHit(1) Then
			num=((xMouseY()/30)*10)-(10-(xMouseX()/30)) ; Этой функцией, мы вычисляем кликнутую ячейку
				selected_obj=inv(num)\image ; Присваиваем картинку выбранного объекта
				selected_id=inv(num)\id ; И также ID
				selected_num=num
		EndIf
	EndIf
End Function

Function UpdatePlayer()
	mxspd#=xMouseXSpeed()*0.05 ; Получаем координаты передвижения мышки по Х
	myspd#=xMouseYSpeed()*0.05 ; Получаем координаты передвижения мышки по Y
	
	If inv_draw=0 xMoveMouse xGraphicsWidth()/2,xGraphicsHeight()/2 ; Передвигаем мышку в центр окна
	If xEntityPitch(camera)+myspd<-89 xRotateEntity camera,-89,0,0 ; Проверяем угол поворота камеры по X
	If xEntityPitch(camera)+myspd>89 xRotateEntity camera,89,0,0 ; Проверяем угол поворота камеры по X
	xRotateEntity camera,xEntityPitch(camera)+myspd,0,0 ; Поворачиваем камеру по X
	xRotateEntity player,0,xEntityYaw(player)-mxspd,0 ; Поворачиваем камеру по Y
	
	If xKeyDown(KEY_W) xMoveEntity player,0,0,0.5
	If xKeyDown(KEY_S) xMoveEntity player,0,0,-0.5
	If xKeyDown(KEY_A) xMoveEntity player,-0.5,0,0
	If xKeyDown(KEY_D) xMoveEntity player,0.5,0,0
	If xMouseHit(2) inv_draw=1-inv_draw ; Если нажата правая кнопка мыши, то меняем значение inv_draw на обратное
	
	If inv_draw=1 Then ; Если inv_draw=1, то отрисовываем и обновляем наш инвентарь
		InventoryDraw()
		InventoryUpdate()
	EndIf
	
	If selected_obj<>0 xDrawImage selected_obj,600,100 ; Если у нас имеется выбранный предмет, то отрисовываем его
	
	Select xKeyDown(KEY_LCONTROL)
		Case True
			xPositionEntity camera,0,5,0
			
		Case False
			xPositionEntity camera,0,15,0
	End Select
	
	If xKeyHit(KEY_E) Then
		xCameraPick(camera,xMouseX(),xMouseY()) ; Делаем пик камерой
		picked=xPickedEntity() ; Даем picked'у значение "пойманного" нами объекта
		picked_name$=xEntityName(picked) ; Получаем имя picked'a
	EndIf
	
	If picked<>0 Then ; Проверяем, равен ли picked 0
		If Instr(picked_name,"obj") Then ; Проверяем, есть ли в имени picked'a "obj"
			id=Mid(picked_name,5,3) ; Получаем ID объекта
				Select obj(id)\obj_type ; Узнаем, какой тип объекта мы пикнули
				
					Case 1 ; Если тип 1, то
						If xAnimating(obj(id)\entity)=0 Then ; Проверяем, играет ли сейчас какая-нибудь анимация
							Select obj(id)\time ; Узнаем, какая была последняя анимация
								Case 0 ; Если закрытия, то проигрываем открывание
									xAnimate obj(id)\entity,3,1,1
									obj(id)\time=1 ; Меняем состояние
								Case 1
									xAnimate obj(id)\entity,3,1,2 ; Если открытия, то проигрываем закрывание
									obj(id)\time=0 ; Меняем состояние
							End Select					
						EndIf
						
					Case 2
						InventoryAddItem(id) ; Добавляем в инвентарь картинку с ID объекта
						xHideEntity obj(id)\entity ; Скрываем объект
						
					Case 3
						If selected_id=obj(id)\id_object Then ; Проверяем, сходится ли ID объекта выбранного из инвентаря, с ID объектом, который надо применять для данного предмета
							xAnimate obj(id)\entity,3,1,1 ; Если да, то проигрываем анимацию
							xFreeImage inv(selected_num)\image ; Удаляем предмет из инвентаря
							selected_id=0 ; Обнуляем ID выбранного предмета
							inv(selected_num)\id=0
							selected_num=0
						EndIf
						
				End Select
		EndIf
	EndIf
	
End Function
Так, теперь всё должно работать просто великолепно. Продолжим. Давайте "учиться" вставлять батарейки, для этого, нам надо изменить функцию UpdatePlayer():

Function UpdatePlayer()
	mxspd#=xMouseXSpeed()*0.05 ; Получаем координаты передвижения мышки по Х
	myspd#=xMouseYSpeed()*0.05 ; Получаем координаты передвижения мышки по Y
	
	If inv_draw=0 xMoveMouse xGraphicsWidth()/2,xGraphicsHeight()/2 ; Передвигаем мышку в центр окна
	If xEntityPitch(camera)+myspd<-89 xRotateEntity camera,-89,0,0 ; Проверяем угол поворота камеры по X
	If xEntityPitch(camera)+myspd>89 xRotateEntity camera,89,0,0 ; Проверяем угол поворота камеры по X
	xRotateEntity camera,xEntityPitch(camera)+myspd,0,0 ; Поворачиваем камеру по X
	xRotateEntity player,0,xEntityYaw(player)-mxspd,0 ; Поворачиваем камеру по Y
	
	If xKeyDown(KEY_W) xMoveEntity player,0,0,0.5
	If xKeyDown(KEY_S) xMoveEntity player,0,0,-0.5
	If xKeyDown(KEY_A) xMoveEntity player,-0.5,0,0
	If xKeyDown(KEY_D) xMoveEntity player,0.5,0,0
	If xMouseHit(2) inv_draw=1-inv_draw ; Если нажата правая кнопка мыши, то меняем значение inv_draw на обратное
	
	If inv_draw=1 Then ; Если inv_draw=1, то отрисовываем и обновляем наш инвентарь
		InventoryDraw()
		InventoryUpdate()
	EndIf
	
	If selected_obj<>0 xDrawImage selected_obj,600,100 ; Если у нас имеется выбранный предмет, то отрисовываем его
	
	Select xKeyDown(KEY_LCONTROL)
		Case True
			xPositionEntity camera,0,5,0
			
		Case False
			xPositionEntity camera,0,15,0
	End Select
	
	If xKeyHit(KEY_E) Then
		xCameraPick(camera,xMouseX(),xMouseY()) ; Делаем пик камерой
		picked=xPickedEntity() ; Даем picked'у значение "пойманного" нами объекта
		picked_name$=xEntityName(picked) ; Получаем имя picked'a
	EndIf
	
	If picked<>0 Then ; Проверяем, равен ли picked 0
		If Instr(picked_name,"obj") Then ; Проверяем, есть ли в имени picked'a "obj"
			id=Mid(picked_name,5,3) ; Получаем ID объекта
				Select obj(id)\obj_type ; Узнаем, какой тип объекта мы пикнули
				
					Case 1 ; Если тип 1, то
						If xAnimating(obj(id)\entity)=0 Then ; Проверяем, играет ли сейчас какая-нибудь анимация
							Select obj(id)\time ; Узнаем, какая была последняя анимация
								Case 0 ; Если закрытия, то проигрываем открывание
									xAnimate obj(id)\entity,3,1,1
									obj(id)\time=1 ; Меняем состояние
								Case 1
									xAnimate obj(id)\entity,3,1,2 ; Если открытия, то проигрываем закрывание
									obj(id)\time=0 ; Меняем состояние
							End Select					
						EndIf
						
					Case 2
						InventoryAddItem(id) ; Добавляем в инвентарь картинку с ID объекта
						xHideEntity obj(id)\entity ; Скрываем объект
						
					Case 3
						If selected_id=obj(id)\id_object Then ; Проверяем, сходится ли ID объекта выбранного из инвентаря, с ID объектом, который надо применять для данного предмета
							xAnimate obj(id)\entity,3,1,1 ; Если да, то проигрываем анимацию
							xFreeImage inv(selected_num)\image ; Удаляем предмет из инвентаря
							selected_id=0 ; Обнуляем ID выбранного предмета
							inv(selected_num)\id=0
							selected_num=0
						EndIf
						
					Case 4
						If selected_id=obj(id)\id_object Then ; Проверяем, сходится ли ID объекта выбранного из инвентаря, с ID объектом, который надо применять для данного предмета
							xAnimate obj(obj(id)\id_child1)\entity,3,1,1  ; Если да, то проигрываем анимацию объекта номер 1
							xShowEntity obj(obj(id)\id_child2)\entity ; И показываем объект номер 2
							xFreeImage inv(selected_num)\image ; Удаляем предмет из инвентаря
							selected_id=0 ; Обнуляем ID выбранного предмета
							inv(selected_num)\id=0
							selected_num=0
						EndIf
						
				End Select
		EndIf
	EndIf
	
End Function
Если Вы, нажмете F5 и немного поиграете, то поймете, что всё работает отлично, однако, есть одно "но": батарейка, заранее вставленная в механизм не была изначально спрятана, но это можно изменить, изменив функцию InitScene():

Function InitScene()
	light=xCreateLight()
	
	map=xLoadAnimMesh("map.b3d")
		SortMapObjects(map)
	
	For i=1 To 999
		If obj(i)<>Null Then ; Если наш объект существует, то
			Select obj(i)\obj_type ; Получаем его тип
			
				Case 2 ; И если он равен двум, то 
					If obj(i)\id_parent<>0 Then ; Проверяем, существует ли у него родитель
						xEntityParent obj(i)\entity, obj(obj(i)\id_parent)\entity; Если да, то присваиваем его ему
					EndIf
				
				Case 4
					xHideEntity obj(obj(i)\id_child2)\entity	 ; Прячем объект с ID объекта номер 2
			End Select
		EndIf
	Next
	
	For i=1 To 100
		inv(i)=New inventory ; Создаем новую ячейку
	Next
		
	xCollisions TypePlayer,TypeMap,2,2
End Function
Ну и последнее что осталось сделать, это показать надпись "Game Over", для этого мы изменим функцию UpdatePlayer():

Function UpdatePlayer()
	mxspd#=xMouseXSpeed()*0.05 ; Получаем координаты передвижения мышки по Х
	myspd#=xMouseYSpeed()*0.05 ; Получаем координаты передвижения мышки по Y
	
	If inv_draw=0 xMoveMouse xGraphicsWidth()/2,xGraphicsHeight()/2 ; Передвигаем мышку в центр окна
	If xEntityPitch(camera)+myspd<-89 xRotateEntity camera,-89,0,0 ; Проверяем угол поворота камеры по X
	If xEntityPitch(camera)+myspd>89 xRotateEntity camera,89,0,0 ; Проверяем угол поворота камеры по X
	xRotateEntity camera,xEntityPitch(camera)+myspd,0,0 ; Поворачиваем камеру по X
	xRotateEntity player,0,xEntityYaw(player)-mxspd,0 ; Поворачиваем камеру по Y
	
	If xKeyDown(KEY_W) xMoveEntity player,0,0,0.5
	If xKeyDown(KEY_S) xMoveEntity player,0,0,-0.5
	If xKeyDown(KEY_A) xMoveEntity player,-0.5,0,0
	If xKeyDown(KEY_D) xMoveEntity player,0.5,0,0
	If xMouseHit(2) inv_draw=1-inv_draw ; Если нажата правая кнопка мыши, то меняем значение inv_draw на обратное
	
	If inv_draw=1 Then ; Если inv_draw=1, то отрисовываем и обновляем наш инвентарь
		InventoryDraw()
		InventoryUpdate()
	EndIf
	
	If selected_obj<>0 xDrawImage selected_obj,600,100 ; Если у нас имеется выбранный предмет, то отрисовываем его
	If win=1 Then ; Если win равен 1, то 
		xText 400,300,"Game Over",True ; Показывать надпись "Game Over"
	EndIf
	
	Select xKeyDown(KEY_LCONTROL)
		Case True
			xPositionEntity camera,0,5,0
			
		Case False
			xPositionEntity camera,0,15,0
	End Select
	
	If xKeyHit(KEY_E) Then
		xCameraPick(camera,xMouseX(),xMouseY()) ; Делаем пик камерой
		picked=xPickedEntity() ; Даем picked'у значение "пойманного" нами объекта
		picked_name$=xEntityName(picked) ; Получаем имя picked'a
	EndIf
	
	If picked<>0 Then ; Проверяем, равен ли picked 0
		If Instr(picked_name,"obj") Then ; Проверяем, есть ли в имени picked'a "obj"
			id=Mid(picked_name,5,3) ; Получаем ID объекта
				Select obj(id)\obj_type ; Узнаем, какой тип объекта мы пикнули
				
					Case 1 ; Если тип 1, то
						If xAnimating(obj(id)\entity)=0 Then ; Проверяем, играет ли сейчас какая-нибудь анимация
							Select obj(id)\time ; Узнаем, какая была последняя анимация
								Case 0 ; Если закрытия, то проигрываем открывание
									xAnimate obj(id)\entity,3,1,1
									obj(id)\time=1 ; Меняем состояние
								Case 1
									xAnimate obj(id)\entity,3,1,2 ; Если открытия, то проигрываем закрывание
									obj(id)\time=0 ; Меняем состояние
							End Select					
						EndIf
						
					Case 2
						InventoryAddItem(id) ; Добавляем в инвентарь картинку с ID объекта
						xHideEntity obj(id)\entity ; Скрываем объект
						
					Case 3
						If selected_id=obj(id)\id_object Then ; Проверяем, сходится ли ID объекта выбранного из инвентаря, с ID объектом, который надо применять для данного предмета
							xAnimate obj(id)\entity,3,1,1 ; Если да, то проигрываем анимацию
							xFreeImage inv(selected_num)\image ; Удаляем предмет из инвентаря
							
							If id=12 Then ; Если ID равен ID последней двери, то
								win=1 ; Присвоить переменной win значение 1
							EndIf
							
							selected_id=0 ; Обнуляем ID выбранного предмета
							inv(selected_num)\id=0
							selected_num=0
						EndIf
						
						
					Case 4
						If selected_id=obj(id)\id_object Then ; Проверяем, сходится ли ID объекта выбранного из инвентаря, с ID объектом, который надо применять для данного предмета
							xAnimate obj(obj(id)\id_child1)\entity,3,1,1  ; Если да, то проигрываем анимацию объекта номер 1
							xShowEntity obj(obj(id)\id_child2)\entity ; И показываем объект номер 2
							xFreeImage inv(selected_num)\image ; Удаляем предмет из инвентаря
							selected_id=0 ; Обнуляем ID выбранного предмета
							inv(selected_num)\id=0
							selected_num=0
						EndIf
						
				End Select
		EndIf
	EndIf
	
End Function
Примечание: Добавьте переменную win в Globals.
Вложения
Тип файла: rar Quest.rar (162.8 Кб, 906 просмотров)

Последний раз редактировалось Hurrit, 13.06.2010 в 22:23.
(Offline)
 
Ответить с цитированием
Эти 7 пользователя(ей) сказали Спасибо Hurrit за это полезное сообщение:
baton4ik (13.06.2010), Harter (11.07.2010), Nex (14.06.2010), pax (28.07.2010), Randomize (11.10.2011), strayhnd (10.07.2010), viper86 (21.07.2010)