Мастер
Регистрация: 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.: Приношу глубочайшие извинения за то, что продолжение не выходило так долго!
Последний раз редактировалось Hurrit, 12.06.2010 в 20:09.
|