2013-09-08 3 views
0

У меня проблема с обнаружением конфликтов, которую я создавал для 3D-вещи, которую я делаю.3D обнаружение столкновений не работает должным образом

Способ обнаружения столкновения: сначала я храню старые координаты xyz в переменных, затем вызываю функцию перемещения, а затем функцию столкновения. Если после движения произошло столкновение, камера - как в проигрывателе (на данный момент) - вернется к старым координатам x y z.

Я хочу, чтобы персонаж мог «скользить» вдоль стороны куба, так что, если вы столкнетесь с осью x, вы все равно можете скользить вдоль оси z. Однако на углу персонаж полностью останавливается - потому что есть столкновение x и z. Я решил сделать отдельные переменные для столкновений z и x, чтобы это не произошло, но теперь я могу попасть внутрь куба, когда я нахожусь на углу, но только на оси X. Я понятия не имею, как это исправить, я пробовал разные вещи (например, последнюю переменную в коде), и я просто не могу это понять. Помощь была бы оценена. Вот соответствующая часть кода:

def otherCollision(self,x,y,z): 
     print(float(Camera.x)) 
     xcol = 0 
     zcol = 0 
     latest = 0 
     if (-Camera.x >= cubez[0][0] - 1) and \ 
      (-Camera.x <= cubez[0][0] + cubez[0][3] + 1) and \ 
      (-Camera.z >= cubez[0][2] - 1) and \ 
      (-Camera.z <= cubez[0][2] + cubez[0][5] + 1): 

      if (-Camera.x >= cubez[0][0] - 1) and \ 
       (-Camera.x <= cubez[0][0]) or \ 
       (-Camera.x <= cubez[0][0] - 1 + cubez[0][3] + 2) and \ 
       (-Camera.x >= cubez[0][0] - 1 + cubez[0][3] + 1): #> 
       #Camera.x = x 
       xcol = 1 
       latest = 1 

      if (-Camera.z >= cubez[0][2] - 1) and \ 
       (-Camera.z <= cubez[0][2]) or \ 
       (-Camera.z <= cubez[0][2] - 1 + cubez[0][5] + 2) and \ 
       (-Camera.z >= cubez[0][2] - 1 + cubez[0][5] + 1): #>= 
       #Camera.z = z 
       zcol = 1 
       latest = 2 

     if xcol == 1 and zcol == 0: 
      Camera.x = x 
     if zcol == 1 and xcol == 0: 
      Camera.z = z 
     if xcol == 1 and zcol == 1 and latest == 2: 
      Camera.x = x 
     if xcol == 1 and zcol == 1 and latest == 1: 
      Camera.z = z 

Следует отметить, что cubez имеет список внутри списка - первый индекс, номер объекта, а следующий индекс значение мы» ищу. Они, в порядке, x,y,z,width,height,depth.

Я использую pyglet 1.2alpha, но я не думаю, что это очень актуально для сообщения, так как ясно, что проблема в моей логике.

ответ

0

Я думаю, что лучшим решением является добавление атрибута скорости вашему актеру («символ» или «камера» в вашем примере?). Затем в зависимости от столкновения нулевой атрибут скорости.

Учитывая простой векторный класс, как это:

class Vector(object): 
    def __init__(self, x=0.0, y=0.0, z=0.0): 
     self.x = x 
     self.y = y 
     self.z = z 

... Ваш актер будет выглядеть следующим образом:

class Actor(object): 
    def __init__(self): 
     self.pos = Vector() 
     self.vel = Vector() 

Теперь при обновлении сцены, выполните следующие действия (абстрагировать к вашему примеру):

  1. Рассчитайте силы, действующие на вашего актора, и обновите vel attri Бьют.
  2. Определите столкновений и соответствующим образом измените атрибут vel.
  3. Обновить данные игрока pos с данными vel.

В приведенном ниже примере используется 2D мира для простоты (z всегда 0), а константа обновления временного шага (dt считается 1 секундой).

class Actor(object): 
    #(...) 
    def update(self, dt=1): 
     # Step 1 - assumes a constant movement to the top right 
     self.vel.x = 1 
     self.vel.y = 1 

     # Step 2 - cube is your collision tested object 
     cube = Cube() 
     new_pos = self.pos + (self.vel * dt) 
     if new_pos.x > cube.left and new_pos.x < cube.right: 
      self.vel.x = 0 
     if new_pos.y > cube.bottom and new_pos.y < cube.top: 
      self.vel.y = 0 

     # Step 3 
     self.pos += self.vel * dt 

Сначала вы должны получить что-то вроде этого. Действуя так, как нужно, добавьте ограничивающий прямоугольник вашему актеру, чтобы столкновение выполнялось по сторонам, а не по центру.

+0

Я буду отмечать его как правильный результат, если нет способа сделать это с тем, как я это делаю сейчас. Мне довольно интересно узнать, как это можно сделать, изменив координаты (система, которую я использую сейчас) - поскольку я читал, что многие игры обнаруживают столкновения, телепортируя игрока в предыдущие не сталкивающиеся координаты. – Arcticcu

+0

Это немного томатный помидор, я думаю. В моем примере вы «телепортируете» игрока на новую позицию, и если он сталкивается, адаптируйте направление движения так, чтобы оно не столкнулось. Таким образом, «телепортирование» происходит также, но по-другому, что я считаю более предпочтительным: расчеты, которые вы делаете, - это временный объект вычисления. Затем 'pos' _allways_ указывает фактическое положение вашего актера вместо того, чтобы возвращать его в зависимости от некоторых условий. – jro

+0

хорошо, спасибо. Я буду использовать это тогда – Arcticcu

Смежные вопросы