Как заставить врага следовать за игроком? Pygame - PullRequest
1 голос
/ 20 января 2020

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

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

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

# player class
class player:
    def __init__(self, x, y, w, h, xChange, yChange, vel):
        self.x = x # plater x value
        self.y = y # player y value
        self.w = w # player w (width)
        self.h = h # player h (height)
        self.xChange = xChange # player xChange (to add to x value to move player horizontally)
        self.yChange = yChange # player yChange (to aad to y value to move player vertically)
        self.vel = vel # velocity of player (needed for collision)

# enemy class
class enemy:
    def __init__(self, x, y, w, h):
        self.x = x # enemy x value
        self.y = y # enemy y value 
        self.w = w # enemy w (width) value
        self.h = h # enemy h (height) value

# ----------------------------------------------------------------

"""enemy's x value (random value) (we pick 750 because the enemy width is 50 and
the screen width is 800. If we set the random value to 800, then the enemy has a
chance of spawning outside of the screen.)"""
enemyX = random.randint(0, 700)

"""enemy's y value (random value) (we pick 540 because the enemy height is 60
and the screen height is 600. If we set the random value to 600, the enemy has a
chance of spawning outside of the screen.)"""
enemyY = random.randint(0, 540) # enemy's y value

score = 0 # score set to 0. Will update in while loop.

rec = player(50, 50, 24, 32, 0, 0, 5) # the player's values (x, y, w, h, xChange, yChange, vel)
redRec = enemy(enemyX, enemyY, 24, 32) # the enemy's values (x, y, w, h)

# mainloop #
def mainloop():
    global running, score, intro, sprite, next_zombie_time

    while running:
        """keeps filling window with the background image"""
        window.blit(background, (0, 0))
        pygame.time.delay(25) # delay
        for event in pygame.event.get(): # for every event in game
            if event.type == pygame.QUIT: # if I exit the game
                quitGame()

            if event.type == pygame.KEYUP: # if any keys are let go
                if event.key == pygame.K_a: # if key a
                        rec.xChange = 0 # set xChange to 0 (stop moving rec)

                if event.key == pygame.K_d: # if key d
                    rec.xChange = 0 # set xChange to 0 (stop moving rec)

                if event.key == pygame.K_w: # if key w
                    rec.yChange = 0 # set xChange to 0 (stop moving rec)

                if event.key == pygame.K_s: # if key s
                    rec.yChange = 0 # set xChange to 0 (stop moving rec)

            if event.type == pygame.KEYDOWN: # if any keys are pressed
                if event.key == pygame.K_F4: # if key F4
                    pygame.quit() # set running to false

                if event.key == pygame.K_a: # if key a
                    rec.xChange += -5 # add -5 to xChange (move rec left)
                    sprite = spriteLeft

                if event.key == pygame.K_d: # if key a
                    rec.xChange += 5 # adds 5 to xChange (move rec right)
                    sprite = spriteRight

                if event.key == pygame.K_w: # if key a
                    #adds -5 to yChange (moves rec up). Yes, this is supposed to say up.
                    rec.yChange += -5
                    sprite = spriteUp

                if event.key == pygame.K_s: # if key a
                    # adds 5 to yChange (moves rec down). Yes, this is supposed to say down.
                    rec.yChange += 5
                    sprite = spriteDown

                # pause key to pause game 
                if event.key == pygame.K_o: # if key o
                    running = False # set running to false
                    intro = False # intro set to False
                    pauseMenu() # pauseMenu is called




        rec.x += rec.xChange # add rec's xChange to x (to do the moving)
        rec.y += rec.yChange # adds rec's yChange to y (to do the moving)


        # ----------------BOUNDARIES------------------------------
        if rec.x <= 0: # if rec's x is less than or equal to 0 (if tries to escape screen)
            rec.x  = 0 # rec's x is set to 0 so it won't go off screen.

        """(we pick 750 because the player width is 50 and the screen width is 800.
        If we set it to 800, then the player can go outside of screen."""   
        if rec.x  >= 750: # if rec's x is greater than or equal to 750 (if tries to escape screen)
            rec.x  = 750  # set rec's x to 750 so it won't go off screen

        if rec.y <= 0: # if rec's y is less than or equal to 0 (if tries to escape screen)
            rec.y = 0 # set rec's y to 0 so it won't go off screen
        """we pick 540 because the player height is 60 and the screen height is 600.
            If we set it to 600, then the player can go outside of screen"""
        if rec.y >= 540: # if rec'y is greater than or equal to 540 (if tries to escape screen) 
            rec.y = 540 # set rec's y to 540 so it won't go off screen  

        #enemy.update(delta_time, player)
        collisions = detCollision(rec.x, rec.y, rec.w, rec.h, redRec.x, redRec.y, redRec.w, redRec.h)
        # activate the redrawWin function
        redrawWin(collisions)



1 Ответ

1 голос
/ 20 января 2020

Вам нужно немного информации для этого. Во-первых, вам понадобится расстояние между игроком и противником. Вы можете рассчитать расстояние, используя функцию math.hypot, подобную этой distance = (math.hypot(enemy.x - player.x, enemy.y - player.y) ). Тогда вы захотите определить угол между ними в радианах, используя math.atan2 funciton. Обратите внимание, что эта функция сначала принимает y позиционный аргумент. Вы можете использовать это следующим образом

angle_radians = (math.atan2(enemy.y - player.y , enemy.x - player.x))

Теперь, чтобы заставить противника двигаться в направлении игрока, вы можете сделать это

     enemy.y += math.sin(angle_radians) 
     enemy.x += math.cos(angle_radians)

Узнайте, почему это работает http://setosa.io/ev/sine-and-cosine/. Вы даже можете добавить диапазон того, насколько близко вы хотите, чтобы игрок был противником, когда он начинает следовать, установив условие на расстояние между ними, как это.

if distance < range:

Вы также можете управлять скоростью, умножая и грех и косинус на одно и то же число, и это работает, потому что они крысы ios. Это может выглядеть примерно так

 enemy.y += math.sin(angle_radians) * speed # Note both speeds must be the same nnumber
 enemy.x += math.cos(angle_radians) * speed

В последней части вашего вопроса, если вы хотите, чтобы это работало для всем врагам, я бы порекомендовал добавить свои игровые объекты в список. Например, вы можете добавить врагов в список и заставить их следовать за игроком. Допустим, вы делаете список всех врагов, делая это

all_enemies = []
for i in range(number of enemies you want):
    all_enemies.append(enemy())

У вас может быть конечный результат, который выглядит примерно так:

 def Follow_player(self):
        for  e in all_enemies:
              distance = (math.hypot(e.x  - player.x, e.y - player.y) )
              angle_radians = (math.atan2(e.y - player.y , e.x - player.x))

              e.y += math.sin(angle_radians) 
              e.x += math.cos(angle_radians)  

              if distance < 1:
                  # they have collided 

РЕДАКТИРОВАТЬ Вот ссылка на очень хорошее видео на YouTube, которое описывает все это https://www.youtube.com/watch?v=DVYDkHdsTIM

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...