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

А вот и продолжение. Игра уже умеет "читать" объекты на карте, пора бы научить её взаимодействовать с ними. Для начала, надо проанимировать все необходимые объекты (двери, полочки). Я это уже сделал, Вы же, как обычно, можете взять готовую карту в аттаче. Так, ну раз анимация готова, то давайте, для начала изменим функцию SortMapObjects():

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
					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
Теперь, мы можем приступать к добавлению взаимодействия с объектом, для этого мы изменим функцию UpdatePlayer():

Function UpdatePlayer()
	mxspd#=xMouseXSpeed()*0.05 ; Получаем координаты передвижения мышки по Х
	myspd#=xMouseYSpeed()*0.05 ; Получаем координаты передвижения мышки по Y
	
	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
	
	
	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 объекта
				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
		EndIf
	EndIf

	
End Function
Примечание: Добавьте поле time в тип properties.

Жмыкаем F5, подходим к двери, нажимаем Е, и вуаля, она открывается. Если нажать ещё раз, то она закрывается. Так, теперь нам понадобится инвентарь, чтобы брать объекты, и использовать их.

У нас в коде будет 3 функции для работы с инвентарем: InventDraw(), InventUpdate(), InventAddItem(). Нам понадобится тип inventory и массивы inv.inventory(100), img(100), и картинки "key.png", "batareyka.png", "back.png":

Global back=xLoadImage("back.png")

Dim inv.inventory(100)
Dim img(100)
    
img(1)=xLoadImage("key.png")
    
img(2)=xLoadImage("batareyka.png")

Type inventory
    Field image
id%
End Type 
А вот и функции для работы с инвентарем:

Function InventoryDraw()
	For i=1 To 10
		For j=1 To 10
			xDrawBlock back,j*30,i*30 ; Рисуем бэкграунд
		Next
	Next

	k=1
	For i=1 To 10
		For j=1 To 10
			If inv(k)\image<>0 xDrawBlock inv(k)\image,j*30,i*30 ; Если ячейка не пуста, то отрисовываем её		
			k=k+1
		Next
	Next
End Function

Function InventoryAddItem(image,id)
	For i=1 To 100
		If inv(i)\image=0 Then 
			inv(i)\image=img(image) ; Здесь, мы добавляем в инвентарь рисунок с номером равному image
				inv(i)\id=id ; И присваиваем ему ID равное значению ID
			Exit
		EndIf
	Next
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
		EndIf
	EndIf
End Function
Примечание: Добавьте в глобалы три переменные: selected_obj, selected_id, inv_draw. Также, картинки вы можете взять в аттаче.

Так, теперь нам надо модифицировать функцию InitScene():

Function InitScene()
    
light=xCreateLight()
    
    
map=xLoadAnimMesh("map.b3d")
        
SortMapObjects(map)
        
    For 
i=1 To 100
        inv
(i)=New inventory Создаем новую ячейку
    Next
        
    xCollisions TypePlayer
,TypeMap,2,2
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
	
	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 объекта
				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
		EndIf
	EndIf
	
End Function
Примечание: Перенесите вызов функции UpdatePlayer() между xUpdateWorld и xFlip, чтобы наш инвентарь мог отрисовываться.

P.S.: Приношу глубочайшие извинения за то, что продолжение не выходило так долго!
Вложения
Тип файла: rar Quest.rar (162.1 Кб, 921 просмотров)

Последний раз редактировалось Hurrit, 12.06.2010 в 20:09.
(Offline)
 
Ответить с цитированием
Эти 8 пользователя(ей) сказали Спасибо Hurrit за это полезное сообщение:
Android (12.06.2010), baton4ik (12.06.2010), Harter (11.07.2010), IGR (10.06.2010), Nex (14.06.2010), pax (28.07.2010), St_AnGer (10.06.2010), viper86 (21.07.2010)