ДеЦЦкий сад "ПандЁнок"
|
|
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 наследоваться не обязательно, можно просто создать класс-контейнер, который будет содержать все элементы игры.
|
|
| |