serg-kkz | Дата: Среда, 25.01.2012, 15:58 | Сообщение # 1 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Мой пример реализации дверей и зон, которые являются тригерами. В данном примере реализованно: возможность визуально настроить зону, ось открытия двери и скорость.
В архиве все нужные ресурсы для демонстрации.
Главные файлы.
primer.py Code # -*- coding: utf-8 -*- import direct.directbase.DirectStart from pandac.PandaModules import * from direct.showbase import DirectObject from direct.interval.IntervalGlobal import *
class Game(object, DirectObject.DirectObject): def __init__(self): # Импорт класса двери from class_door import door_vert base.cTrav = CollisionTraverser() base.pusher = CollisionHandlerPusher() self.level = loader.loadModel('level.egg') self.level.reparentTo(render) self.level.setTwoSided(True) self.igrok = Player()
# Вызываем класс двери и передаем ссылку на объект который будет открывать дверь если окажется в зоне. door_vert(self.igrok)
class Player(object):
STOP = Vec3(0) walk = STOP strafe = STOP def __init__(self): self.node = NodePath('player') self.node.reparentTo(render) self.node.setPos(0,0,0) self.node.setScale(.05)
colnode = CollisionNode('player') colnode.addSolid(CollisionSphere(0,0,0,3)) solid1 = self.node.attachNewNode(colnode) solid1.show() base.cTrav.addCollider(solid1, base.pusher) base.pusher.addCollider(solid1, self.node) base.accept( "w" , self.__setattr__,["walk",Vec3(0,1,0)]) base.accept( "w-up" , self.__setattr__,["walk",Vec3(0)] ) base.accept( "s" , self.__setattr__,["walk",Vec3(0,-1,0)] ) base.accept( "s-up" , self.__setattr__,["walk",Vec3(0)] ) base.accept( "a" , self.__setattr__,["strafe",Vec3(-1,0,0)]) base.accept( "a-up" , self.__setattr__,["strafe",Vec3(0)] ) base.accept( "d" , self.__setattr__,["strafe",Vec3(1,0,0)] ) base.accept( "d-up" , self.__setattr__,["strafe",Vec3(0)] ) base.accept( "z" , self.__setattr__,["strafe",Vec3(0,0,1)] ) base.accept( "z-up" , self.__setattr__,["strafe",Vec3(0)] ) base.accept( "x" , self.__setattr__,["strafe",Vec3(0,0,-1)] ) base.accept( "x-up" , self.__setattr__,["strafe",Vec3(0)] ) taskMgr.add(self.moveUpdate, 'move-task')
def moveUpdate(self,task): self.node.setPos(self.node,self.walk*globalClock.getDt()*17) self.node.setPos(self.node,self.strafe*globalClock.getDt()*17) return task.cont
Game() run()
И модуль который реализует дверь.
class_door.py Code # -*- coding: utf-8 -*- from direct.directtools.DirectGeometry import LineNodePath from pandac.PandaModules import * from direct.interval.IntervalGlobal import *
class door_vert(): def __init__(self, obekt): self.igrok = obekt # Передаем ссылку на объект который будет открывать дверь если окажется в зоне. linescreate = 1 # Включаем отображение зоны, чтоб выключить установите 0 self.statys_door = 0 # Статус двери, 0 - закрыта, 1-открыта.
self.door = loader.loadModel('door.egg') # Загрузка модели двери. self.door.reparentTo(render) # Добавляем в рендер. # Позиция двери self.posdoor = (0, 1.5, 0) # Задаем координаты двери self.door.setPos(self.posdoor) # Устанавливаем эту позицию для модели двери. # Настройка зоны двери, считается от центра двери.
xlevo = 0.5 # Прибавление зоны в левую сторону. xpravo = 0.5 # Прибавление зоны в правую сторону. yvpered = 0.8 # Прибавление зоны в перед. ynazad = 0.8 # Прибавление зоны на зад. zverx = 0.4 # Прибавление зоны вверх. zniz = 0.4 # Прибавление зоны вниз. # Выбираем по какой оси открыть дверь и насколько. self.x = 0 self.y = 0 self.z = 1 # Открываем вверх, а если с минусом, то наоборот. self.timemove = 0.6 # Время открытия и закрытия двери. # Блок кода для расчета точек, по которым строятся линии зоны и собственно сама зона. self.t1, self.t2, self.t3 = self.door.getX()-xlevo, self.door.getY()+yvpered, self.door.getZ()-zniz self.t4, self.t5, self.t6 = self.door.getX()+xpravo, self.door.getY()+yvpered, self.door.getZ()-zniz self.t7, self.t8, self.t9 = self.door.getX()-xlevo, self.door.getY()-ynazad, self.door.getZ()-zniz self.t10, self.t11, self.t12 = self.door.getX()+xpravo, self.door.getY()-ynazad, self.door.getZ()-zniz self.t13, self.t14, self.t15 = self.door.getX()-xlevo, self.door.getY()+yvpered, self.door.getZ()+zverx self.t16, self.t17, self.t18 = self.door.getX()+xpravo, self.door.getY()+yvpered, self.door.getZ()+zverx self.t19, self.t20, self.t21 = self.door.getX()-xlevo, self.door.getY()-ynazad, self.door.getZ()+zverx self.t22, self.t23, self.t24 = self.door.getX()+xpravo, self.door.getY()-ynazad, self.door.getZ()+zverx
# Проверяем включено ли отображение зоны. if (linescreate == 1): # Строим зону из линий. lines = LineNodePath(render, colorVec = Vec4(1, 0, 0, 1)) lines.drawLines([((self.t1, self.t2, self.t3),(self.t4, self.t5, self.t6)), ((self.t7, self.t8, self.t9),(self.t10, self.t11, self.t12)), ((self.t4, self.t5, self.t6), (self.t10, self.t11, self.t12)), ((self.t1, self.t2, self.t3), (self.t7, self.t8, self.t9)), ((self.t13, self.t14, self.t15), (self.t16, self.t17, self.t18)), ((self.t19, self.t20, self.t21), (self.t22, self.t23, self.t24)), ((self.t16, self.t17, self.t18), (self.t22, self.t23, self.t24)), ((self.t13, self.t14, self.t15), (self.t19, self.t20, self.t21)), ((self.t1, self.t2, self.t3), (self.t13, self.t14, self.t15)), ((self.t4, self.t5, self.t6), (self.t16, self.t17, self.t18)), ((self.t7, self.t8, self.t9), (self.t19, self.t20, self.t21)), ((self.t10, self.t11, self.t12), (self.t22, self.t23, self.t24))]) lines.create()
taskMgr.add(self.posget, 'move')
# Проверка находится ли игрок или нужный объект в зоне двери. def posget(self,task): if (self.igrok.node.getX() > self.t1) and (self.igrok.node.getX() < self.t4): if (self.igrok.node.getY() < self.t5) and (self.igrok.node.getY() > self.t8): if (self.igrok.node.getZ() > self.t9) and (self.igrok.node.getZ() < self.t15): self.opendoor() # Если да, то запускаем функцию открытия двери. else: self.closedoor() # Если нет, то закрытия. else: self.closedoor() # Если нет, то закрытия. else: self.closedoor() # Если нет, то закрытия.
return task.cont
# Функция открытия двери. def opendoor(self): # Проверям статус двери, если закрыта, то открываем. if (self.statys_door == 0): if (self.door.getPos() == Point3(self.posdoor)):# Проверка закрылась ли дверь. open = self.door.posInterval(self.timemove,Point3(self.door.getPos())+(self.x, self.y, self.z), startPos=Point3(self.posdoor)) move = Sequence(open) move.start() self.statys_door = 1 # Меняем статус. def closedoor(self): # Проверям статус двери, если открыта, то закрываем. if (self.statys_door == 1): if (self.door.getPos() == Point3(self.posdoor)+(self.x, self.y, self.z)):# Проверка открылась ли дверь. close = self.door.posInterval(self.timemove,Point3(self.posdoor), startPos=Point3(self.door.getPos())) move = Sequence(close) move.start() self.statys_door = 0 # Меняем статус.
Управление W, S, A, D и Z, X
ООП -
Сообщение отредактировал serg-kkz - Среда, 25.01.2012, 17:30 |
|
| |
serg-kkz | Дата: Воскресенье, 29.01.2012, 21:56 | Сообщение # 7 |
Генерал-полковник
Группа: Модераторы
Сообщений: 803
Награды: 3
Репутация: 18
Статус: Offline
| Написал другую версию двери, как мне кажется более правильную. Здесь дверь открывается от расстояния. И главное её можно поворачивать на нужный угол.
Все нужное в архиве.
Сам код класса, который в модуле door.py
Code # -*- coding: utf-8 -*- from direct.directtools.DirectGeometry import LineNodePath from pandac.PandaModules import * from direct.interval.IntervalGlobal import Sequence import math
class Door(): def __init__(self, obekt, pos, rot): self.dist=0.5 # Задаем дистанцию до двери, при которой она открывается. self.timemove = 0.4 # Время движения двери self.igrok = obekt # Передаем ссылку на объект который будет открывать дверь если окажется в зоне. self.posdoor = pos # Задаем координаты зоны двери. self.statys_door = 0 # Статус двери, 0 - закрыта, 1-открыта. zonaview = 1 # Включаем отображение зоны, чтоб выключить установите 0 self.door = loader.loadModel('Objects/door.egg') # Загрузка модели двери. self.door.setPos(self.posdoor) # Устанавливаем позицию для модели двери. self.door.setHpr(rot) # Задаем поворот двери self.door.reparentTo(render) # Добавляем в рендер. # Создаем пустышку, для расчета конечной точки двери. self.emty = NodePath('pointend') # Собственно создаем. self.emty.setPos(self.door, 0,0,1) # Устанавливаем конечную позицию и ось, а также расстояние. # Проверяем включено ли отображение зоны. Данный код можно удалить с 25 стр по 41 и "zonaview = 1" на 14 стр. if (zonaview == 1): # Если да(т.е. 1), то строим зону. seg = LineSegs() seg.setColor(1, 0, 0, 1) seg.moveTo(self.dist,0,0) for angle in range(0,360,10): x = self.dist*math.cos(math.radians(angle)) y = self.dist*math.sin(math.radians(angle)) seg.drawTo(x,y,0) seg.drawTo(self.dist,0,0) axis1 = render.attachNewNode(seg.create()) axis1.setPos(pos) axis2 = axis1.copyTo(render) axis2.setR(90) axis2.setH(self.door.getH()) axis3 = axis2.copyTo(render) axis3.setH(self.door.getH()+90) taskMgr.add(self.movedoor, 'move')
def movedoor(self, task): if ((self.igrok.node.getPos(render) - self.posdoor).length() < self.dist): # Проверка на каком растоянии находится игрок. if (self.statys_door == 0): if (self.door.getPos() == Point3(self.posdoor)):# Проверка закрылась ли дверь полностью. open = self.door.posInterval(self.timemove, self.emty.getPos(), startPos=self.posdoor) move = Sequence(open) move.start() self.statys_door = 1 # Меняем статус. else: if (self.statys_door == 1):# Проверяем статус двери, если открыта, то закрываем. if (self.door.getPos() == self.emty.getPos()):# Проверка открылась ли дверь полностью. close = self.door.posInterval(self.timemove,self.posdoor, startPos=self.door.getPos()) move = Sequence(close) move.start() self.statys_door = 0 # Меняем статус. return task.cont
ООП -
|
|
| |