Мастер
Регистрация: 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.
Последний раз редактировалось Hurrit, 13.06.2010 в 22:23.
|