Pygame Sprite движется с постоянной скоростью

Я работаю над базовой игрой, но я не уверен, где я хочу ее взять. Так что пока я работаю только над базовой механикой.

Проблема, с которой я столкнулся, заключается в том, что мне нужно, чтобы вражеские спрайты двигались к спрайту игрока. Я уже разобрался с базовой векторизацией, но поскольку спрайты движутся по вектору, они также замедляются по мере приближения к своей цели.

Вот отрывок моего кода.

#Enemy Mechanics
for enemy in enemy_list:
    pygame.draw.rect(screen, green, (enemy.rect.x, enemy.rect.y-5, enemy.Health/4, 3), 0)
    pygame.draw.rect(screen, green, (enemy.rect.x, enemy.rect.y-5, 25, 3), 1)

    ppos = pPlayer.rect.x, pPlayer.rect.y
    epos = enemy.rect.x, enemy.rect.y
    etarget = epos[1] - ppos[1], epos[0] - ppos[0]

    enemy.rect.x -= etarget[1]/20 #This is the problem
    enemy.rect.y -= etarget[0]/20


#Bullet Mechanics
for bullet in bullet_list:
    mpos = pygame.mouse.get_pos()
    bpos = bullet.rect.x, bullet.rect.y
    target = bpos[1] - mpos[1], bpos[0] - mpos[0]
    dist = math.sqrt(((bpos[0] - mpos[0])**2) + ((bpos[1] - mpos[1])**2))

    bullet.rect.x -= target[1]/20
    bullet.rect.y -= target[0]/20

    if dist < 30:
        bExplode(bullet.rect.x, bullet.rect.y)
        blist.remove(bullet)
        bullet.kill()

    enemy_hit_list = (pygame.sprite.spritecollide(bullet, enemy_list, False))
    for enemy in enemy_hit_list:
        enemy.Health -= 25
        print(enemy.Health)
        if enemy.Health <= 0:
            enemy_list.remove(enemy)
            all_sprites_list.remove(enemy)

        bullet_list.remove(bullet)
        all_sprites_list.remove(bullet)
        blist.remove(bullet)

Как видите, я разделил векторы на 20, потому что это замедляет их до разумной скорости, но они также останавливаются, не достигнув своей цели. Мне нужна помощь, чтобы спрайты двигались к игроку с постоянной заданной скоростью.


person Isaacashtox    schedule 11.06.2013    source источник
comment
Почему эта помеченная производительность? Ваша текущая реализация может быть неправильной, но ... это тоже занимает слишком много процессорного времени? Это маловероятно.   -  person abarnert    schedule 11.06.2013
comment
Извините, когда я ввел скорость, по умолчанию была установлена ​​производительность.   -  person Isaacashtox    schedule 12.06.2013
comment
Ах, вы имели в виду скорость как скалярную скорость пуль. Да, иногда SO немного переусердствует с угадыванием псевдонимов. Вероятно, вы не хотите оптимизировать работу пуль. Если да, то попробуйте нарезать многоугольные нарезы на дульной части петли for. :)   -  person abarnert    schedule 12.06.2013


Ответы (1)


Ваш код означает, что враги всегда перемещаются на 1/20 пути к своей цели. Вы хотите, чтобы они переместились на 1 шаг фиксированного размера в том же направлении.

Ответ здесь - нормализовать вектор, то есть использовать единичный вектор в том же направлении, что и вектор расстояния вместо прямого использования вектора расстояния.

Самый простой способ сделать это - просто разделив вектор на его длину. . И чтобы получить длину вектора, это просто теорема Пифагора.

So:

def vector_length(x, y):
    return math.sqrt(x*x + y*y)

def normalize_vector(x, y):
    norm = vector_length(x, y)
    return x/norm, y/norm

target = normalize_vector(bpos[1] - mpos[1], bpos[0] - mpos[0])

Это заставляет пули перемещаться на 1 единицу пространства за единицу времени (например, пиксель на кадр). Если вы хотите, чтобы они летели быстрее или медленнее, просто определите скорость пули в тех же единицах и умножьте на нее:

bullet.rect.x -= target[1] * BULLET_SPEED 
bullet.rect.y -= target[0] * BULLET_SPEED 

Фактически, вы уже делаете большую часть этого, просто вы этим не пользуетесь:

dist = math.sqrt(((bpos[0] - mpos[0])**2) + ((bpos[1] - mpos[1])**2))

Итак, если вы сочтете это более ясным, просто измените следующие две строки на:

bullet.rect.x -= target[1] / dist * BULLET_SPEED
bullet.rect.y -= target[0] / dist * BULLET_SPEED
person abarnert    schedule 11.06.2013