0

In my code I have a zombie that looks to a player and follows it, it is ok for the player to move up/down left/right or in diagonals because the person controlling is using the arrows on the keyboard, but for the zombie it feels very weird not to have a large range of directions it can go, the discrepancy got very weird when I added the fact that the zombie had a free range of motion to look at the player but not to walk directly in its direction. What changes can I make to make his movement more smooth?

this is how I move the player:

playerSprite.vel = 3

playerSprite.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * playerSprite.vel 
playerSprite.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * playerSprite.vel

this is how I move the zombie:

zombieSprite.vel = 1

    if zombieSprite.x > playerSprite.x: 
      zombieSprite.x -= zombieSprite.vel 

    if zombieSprite.x < playerSprite.x: 
      zombieSprite.x += zombieSprite.vel

    if zombieSprite.y > playerSprite.y: 
      zombieSprite.y -= zombieSprite.vel

    if zombieSprite.y < playerSprite.y: 
      zombieSprite.y += zombieSprite.vel
DeMauro
  • 27
  • 5
  • Could you elaborate what the problem is? the logic here looks ok for the most part. One thing i can definitely suggest is using the minimum between `zombieSprite.vel` and the distance between the player and the zombie on that axis, otherwise when the zombie is less than `vel` away he will starting being very jerky instead of stopping right on the player – Nullman Jan 31 '22 at 15:49

3 Answers3

1

@Rabbid76 solution is good, but in case you don't want such "complicated" solution you can do the following: convert the difference in position to polar coordinates, and then split your zombie velocity into x and y vectors based on the angle from polar coordinates.

import numpy as np
from math import sin, cos

def cart2pol(x, y):
    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)
    return(rho, phi)

class Pos:
    def __init__(self, x, y):
        self.x = x
        self.y = y

player = Pos(5, 1)

zombie = Pos(3, 2)

diff = Pos(player.x - zombie.x, player.y - zombie.y)

dist, angle = cart2pol(diff.x, diff.y)

zombieVelocity = 0.5

newZombiePos = (zombie.x + zombieVelocity * cos(angle), zombie.y + zombieVelocity * sin(angle))

print(newZombiePos)
matszwecja
  • 6,357
  • 2
  • 10
  • 17
0

How to make smooth movement in pygame. You can use the following function to make an enemy follow a player smoothly:

LERP_FACTOR      = 0.05
minimum_distance = 25
maximum_distance = 100

def follow_me(target_pos, follower_pos):
    target_vector       = pygame.math.Vector2(*target_pos)
    follower_vector     = pygame.math.Vector2(*follower_pos)
    new_follower_vector = pygame.math.Vector2(*follower_pos)

    distance = follower_vector.distance_to(target_vector)
    if distance > minimum_distance:
        direction_vector    = (target_vector - follower_vector) / distance
        min_step            = max(0, distance - maximum_distance)
        max_step            = distance - minimum_distance
        step_distance       = min_step + (max_step - min_step) * LERP_FACTOR
        new_follower_vector = follower_vector + direction_vector * step_distance

    return (new_follower_vector.x, new_follower_vector.y) 

Call the function and assign the return value back to the zombies position:

zombieSprite.x, zombieSprite.y = follow_me(
    (playerSprite.x, playerSprite.y), (zombieSprite.x, zombieSprite.y))
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
-1

This is a solution I think is good using the module pygame.

Example usage:

import pygame

win = pygame display.set_mode((size, size))
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
stampe
  • 13
  • 4
  • Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Jan 31 '22 at 19:59