[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Форум Panda3D - по русски » Panda3D » Для начинающих » ДеЦЦкий сад "ПандЁнок"
ДеЦЦкий сад "ПандЁнок"
pupДата: Вторник, 22.01.2013, 19:05 | Сообщение # 271
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
хочу сделать линейное движение гнома с текущего местоположения в указанное. чтоб в апдейде расчитывался прирост координат х,у

сделал так    
Код
def control(self,action,param):    
         if action is 'add_wp':    
             self.waypoints.append(Vec3(param[0],param[1],0))    
         elif action is 'replace_wp':    
             self.currentTime = 0       
             self.a = Vec3(self.root.getPos())    
             self.waypoints=[]    
             self.waypoints.append(Vec3(param[0],param[1],0))    
             self.v=self.waypoints[0]    
             self.v.setZ(self.root.getZ())        
             if self.v.length()<0.3:    
                 del self.waypoints[0]    
             else:    
                 self.durationx = self.v[0]/2  
                 self.durationy = self.v[1]/2    
         
     def update(self,task):
         if len(self.waypoints)>0:    
             v=self.waypoints[0]    
             v.setZ(self.root.getZ())    
             v=Vec3(v-self.a)
             if v.length()<0.3:    
                 del self.waypoints[0]    
             else:
                 self.currentTime += globalClock.getDt()
                 x = self.a[0]+self.v[0]*(self.currentTime/self.durationx)
                 y = self.a[1]+self.v[1]*(self.currentTime/self.durationy)
                 self.root.setPos(x,y,self.root.getX())
             if self.state is not 'walk':
                 self.animInterval=LerpAnimInterval(self.model, 0.2, 'stand', 'walk')
                 self.animInterval.start()
                 self.state='walk'
         elif self.state is not 'stand':
             self.animInterval=LerpAnimInterval(self.model, 0.3, 'walk', 'stand')
             self.animInterval.start()
             self.state='stand'
              
         if self.collsys.GroundHandler.getNumEntries()>0:
             self.collsys.GroundHandler.sortEntries()
             self.root.setZ(self.collsys.GroundHandler.getEntry(0).getSurfacePoint(render).getZ())
         return task.cont

гном плавно шагает кудто в одном направлении причем очень уверенно скозь куб)
 
ninthДата: Вторник, 22.01.2013, 21:32 | Сообщение # 272
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Ну в общем всё правильно гном делает - линейное движение на то и линейное, что не подразумевает поворотов. Поэтому для такого типа движения тебе придётся либо каким-то образом вычислять несколько точек, которые будут огибать препятствие, либо просто останавливать гнома, если он будет в препятствие упираться.
А не останавливается он потому что ты забываешь обнулить self.currentTime когда удаляешь вэйпойнт. И проверка окончания пути будет иной в твоём случае - незачем делать так if v.length()<0.3: del self.waypoints[0] потому что v у тебя это расстояние от начальной точки, а не от игрока до конечной . Тебе достаточно сравнить когда твой currentTime станет больше или равен duration - тогда и обнулить его и удалить вэйпойнт. Сейчас попробую поправить.

Но я всё равно не пойму чем не устроил изначальный вариант?
 
ninthДата: Вторник, 22.01.2013, 21:48 | Сообщение # 273
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Код
class character():
      def __init__(self,modelstr,anims,trav,id):
          self.id=id
          self.root=render.attachNewNode('character')
          self.model=Actor.Actor(modelstr,anims)
          self.model.reparentTo(self.root)
          self.model.setBlend(frameBlend=1,blendType=1)
          self.model.enableBlend()
          self.model.loop('walk')
          self.model.loop('stand')
          self.animInterval=LerpAnimInterval(self.model, 1, 'walk', 'stand')
          self.state=''
          self.collsys=characterCollSystem(self.root,trav,id)
          self.waypoints=[]
          self.start_pos = Vec3()
          self.current_time = 0.0
          self.move_duration = 0.0
          self.direction = Vec3()
            
      def control(self,action,param):
          if action is'add_wp':
              self.waypoints.append(param)
          elif action is 'replace_wp':
              self.waypoints=[]
              self.waypoints.append(param)
              self.start_pos = self.root.getPos()
              self.current_time = 0.0
              self.direction = param - self.start_pos
              self.move_duration = self.direction.length() * 0.5
                
        
      def update(self,task):
          if len(self.waypoints)>0:
              self.current_time += globalClock.getDt()
              if self.current_time >= self.move_duration:
                  del self.waypoints[0]
                  if len(self.waypoints)>0:
                      self.start_pos = self.root.getPos()
                      self.current_time = 0.0
                      self.direction = self.waypoints[0] - self.start_pos
                      self.move_duration = self.direction.length() * 0.5
              else:
                  self.root.setPos(self.start_pos + self.direction * self.current_time / self.move_duration)
              if self.state is not 'walk':
                  self.animInterval=LerpAnimInterval(self.model, 0.2, 'stand', 'walk')
                  self.animInterval.start()
                  self.state='walk'
          elif self.state is not 'stand':
              self.animInterval=LerpAnimInterval(self.model, 0.3, 'walk', 'stand')
              self.animInterval.start()
              self.state='stand'
                
          if self.collsys.GroundHandler.getNumEntries()>0:
              self.collsys.GroundHandler.sortEntries()
              self.root.setZ(self.collsys.GroundHandler.getEntry(0).getSurfacePoint(render).getZ())
          return task.cont
 
pupДата: Вторник, 22.01.2013, 23:24 | Сообщение # 274
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
то что надо. спасибо огромное

Добавлено (22.01.2013, 23:24)
---------------------------------------------
Изначальный вариант конечно лучше. просто я планирую на сервере считать координаты гнома. там так не получиться..

 
ninthДата: Вторник, 22.01.2013, 23:35 | Сообщение # 275
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Тогда тебе всё же придется придумывать какой-то алгоритм для обхода препятствий. Стандартно для этого используют A* (A-star, А-звёздочка) но в этом случае требуется разбивка поля на сектора/квадраты с отметкой какой квадрат проходимый, а какой - нет
 
pupДата: Вторник, 22.01.2013, 23:40 | Сообщение # 276
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
это попозже. пока хочу бонально сеть прикрутить. Еще вопрос. в данном случае гном проходит любое расстояние за опред. время. Так? а как сделать чтоб у него скорость была и он любое расстояние проходил со своей скоростью. а не за определенное время
 
ninthДата: Среда, 23.01.2013, 00:30 | Сообщение # 277
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Скорость, грубо говоря, вот она self.move_duration = self.direction.length() * 0.5 попробуй поиграть с числом на которое умножается

т.е. время перемещения = расстояние умноженное на числовой коэффициент, который можно принять за "скорость". Единственное, что в даннном случае зависимость обратная получается - время (коэффициент) меньше - > скорость больше
 
pupДата: Среда, 23.01.2013, 01:03 | Сообщение # 278
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
просто чем меньше расстояние до вейпоинта тем меньше скорость. есои клацнуть в конец карты то гном быстро побежит. а если близко то ползёт
 
ninthДата: Среда, 23.01.2013, 01:29 | Сообщение # 279
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
А ты ничего не менял? У меня с одинаковой скоростью на любое расстояние ходит. Можешь взять чистый исходник 6 урока и заменить класс персонажа тем, что я привёл - должно работать.
 
pupДата: Среда, 23.01.2013, 05:19 | Сообщение # 280
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
теперь надо тоже самое сделать на сервере средствами питона.
есть вот такой класс. все работает но координаты считаються не зависимо от времени.

Код
class Move():
        def __init__(self,c):

               self.c = c
               self.trueX = self.c.x
               self.trueY = self.c.y
               self.pos = (self.trueX, self.trueY)
               self.speed = 0.5
               self.speedX = 0
               self.speedY = 0
               self.target = self.c.target

        def get_direction(self, target):
               if target:
                      position = Vector(self.pos[0], self.pos[1])
                      target = Vector(target[0], target[1])
                      self.dist = target - position
                      direction = self.dist.normalize()
                      return direction

        def distance_check(self, dist):

               dist_x = dist[0] ** 2
               dist_y = dist[1] ** 2
               t_dist = dist_x + dist_y
               speed = self.speed ** 2

               if t_dist < (speed):
                      return True

        def update(self):
               self.dir = self.get_direction(self.target)
               if self.dir:
                      if self.distance_check(self.dist):
                             self.pos = self.target
                      else:
                             self.trueX += (self.dir[0] * self.speed)
                             self.trueY += (self.dir[1] * self.speed)
                             self.pos = float(round(self.trueX)),float(round(self.trueY))
                      self.c.x, self.c.y = self.pos
               else: self._stop()

        def _stop(self):
               self.c.action = None
               self.c.target = None
               self.target = None

        def run(self):
              while self.target:
              clock.tick(100)
              self.update()

можно ли его както исправить чтоб он вычислял координаты не зависимо от ФПС.?


Сообщение отредактировал pup - Среда, 23.01.2013, 05:28
 
ninthДата: Среда, 23.01.2013, 08:15 | Сообщение # 281
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Учитывается не FPS, а время. getDt() возвращает время в секундах, прошедшее между двумя последними кадрами. т.е. при умножении dt на fps мы должны всегда получать одну секунду. В формуле мы вообще просто задаём время за которое должен быть пройден отрезок пути. self.move_duration = self.direction.length() * 0.5 мы получаем, что одна единица пути будет проходиться за 2 секунды. если умножить, например на 0.25 - то за 4 с, а если на 2.0, то за 0.5 с
В общем  dt и существует для того чтобы независимо от фпс получать одинаковую скорость
 
pupДата: Четверг, 24.01.2013, 08:07 | Сообщение # 282
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
а зачем в апдейте после


Код
del self.waypoints[0]   if len(self.waypoints)>0:      self.start_pos = self.root.getPos()      self.current_time = 0.0      self.direction = self.waypoints[0] - self.start_pos      self.move_duration = self.direction.length() * 0.5
   

это условие никогда не выполниться же. это лишнее?
 
ninthДата: Четверг, 24.01.2013, 08:33 | Сообщение # 283
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Оно пригодится если будешь делать несколько контрольных точек, например при обходе препятствия. Я вроде где-то делал по контрол+клик добавление а не замену вэйпойнта, но не помню - это отдельно или в рамках деццкого сада.
 
pupДата: Пятница, 25.01.2013, 05:59 | Сообщение # 284
Рядовой
Группа: Пользователи
Сообщений: 15
Награды: 0
Репутация: 0
Статус: Offline
Как правильно сюда сеть прикрутить? Я сделал так: создал в модулях файл нетворк.ру, который коннектиться к серверу средствами панды. в менеджере читает/отправляет данные. кода приходит пакет о том что игрок подключился (допустим я) он все в этом же нетворк.ру создаёт экземпляр класса character учитывая всю инфу которую о нём сервер дал, кидает его в словарь, и добавляет  его апдейт в менеджер. Этот нетворк.ру я импортнул в глобалс.ру.в глобалсе создаю екземпляр классе нетворк. а глобалс.ру в контрол.ру дабы можно было в контрол.ру пользоваться эти экземпляром и отправлять данные по клику на сервер. и в маин.ру импортнул глобалс. для инициализации нетворк.ру (к какому ИП коннектиться и тд)

Насколько это все правильно? просто я боюсь что потом гденибудь не смогу подобраться к какому нибудь классу который нужен будет и тд
 
ninthДата: Пятница, 25.01.2013, 08:25 | Сообщение # 285
Admin
Группа: Администраторы
Сообщений: 1582
Награды: 5
Репутация: 46
Статус: Offline
Питон очень гибкая штука. Ты можешь просто передать ссылку на экземпляр класса в любую процедуру и работать с ним даже не импортируя нужные модули. Так что проблем с тем чтобы добраться к классу быть не должно.
Вообще в деццком саду на самом деле не самая удачная "архитектура" с globals.py, если можно так сказать. Делалось это чтобы не пугать первыми уроками ), а вообще я например использую такой подход: создаю класс, наследуемый от ShowBase (в этом случае этот класс используется вместо direct) и передаю ссылки на него во все остальные нужные модули/классы, так что при желании имею доступ к любому элементу. Примерно так:
Код
class App(ShowBase):
            
        def __init__(self):
            ShowBase.__init__(self)
            self.world = World(self)
            self.player = Player(self)
            self.ai = AI(self)

Конечно тоже может быть не самый удачный подход. Хотя от ShowBase наследоваться не обязательно, можно просто создать класс-контейнер, который будет содержать все элементы игры.
 
Форум Panda3D - по русски » Panda3D » Для начинающих » ДеЦЦкий сад "ПандЁнок"
Поиск: