在预定的路径pygame上行走的球员

时间:2018-01-04 20:06:46

标签: python animation pygame sprite

我是pygame的新手,我正在尝试制作一个游戏,让玩家必须绕过一些敌人,以达到可以进入下一关的程度。我需要敌人在预定路径上前后行走,但我无法弄清楚如何去做。所以我想知道是否有一种简单的方法可以做到这一点?

这是我的代码。

import pygame
import random
import os
import time
from random import choices
from random import randint

pygame.init()
a = 0
b = 0
width = 1280
height = 720
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Game")
done = False
n = 0
x = 0
y = 0
x_wall = 0
y_wall = 0
clock = pygame.time.Clock()
WHITE = (255,255,255)
RED = (255,0,0)
change_x = 0
change_y = 0
HW = width / 2
HH = height / 2
background = pygame.image.load('mountains.png')

#player class
class Player(pygame.sprite.Sprite):
    def __init__(self):
      pygame.sprite.Sprite.__init__(self)
      self.image = pygame.image.load("character.png") 
      self.rect = self.image.get_rect()
      self.rect.x = width / 2
      self.rect.y = height / 2

#enemy class
class Enemy(pygame.sprite.Sprite):
  def __init__(self):
    pygame.sprite.Sprite.__init__(self)
    self.image = pygame.image.load("enemy.png")
    self.image = pygame.transform.scale(self.image, (int(50), int(50)))
    self.rect = self.image.get_rect()
    self.rect.x = width / 3
    self.rect.y = height / 3

#wall class
class Wall(pygame.sprite.Sprite):
  def __init__(self, x, y):
    pygame.sprite.Sprite.__init__(self)
    self.image = pygame.image.load("wall.png") 
    self.image = pygame.transform.scale(self.image, (int(50), int(50)))
    self.rect = self.image.get_rect()
    self.rect.x = x
    self.rect.y = y

#wall movement
  def update(self):
    self.vx = 0
    self.vy = 0
    key = pygame.key.get_pressed()
    if key[pygame.K_LEFT]:
      self.vx = 5
      self.vy = 0
    elif key[pygame.K_RIGHT]:
      self.vx = -5
      self.vy = 0
    if key[pygame.K_UP]:
      self.vy = 5
      self.vx = 0
    elif key[pygame.K_DOWN]:
      self.vy = -5
      self.vx = 0
    self.rect.x = self.rect.x + self.vx
    self.rect.y = self.rect.y + self.vy

#player sprite group
sprites = pygame.sprite.Group()
player = Player()
sprites.add(player)

#enemy sprite group
enemys = pygame.sprite.Group()
enemy = Enemy()
enemy2 = Enemy()
enemys.add(enemy, enemy2)

#all the wall sprites
wall_list = pygame.sprite.Group()
wall = Wall(x_wall, y_wall)
wall2 = Wall((x_wall + 50), y_wall)
wall3 = Wall((x_wall + 100), y_wall)
wall4 = Wall((x_wall + 150), y_wall)
wall5 = Wall((x_wall + 200), y_wall)
wall6 = Wall((x_wall + 250), y_wall)


#add all the walls to the list to draw them later
wall_list.add(wall, wall2, wall3, wall4, wall5, wall6)

#add all the walls here to fix the collision
all_walls = (wall, wall2, wall3, wall4, wall5, wall6)

while not done:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    sprites.update()
    wall_list.update()
    enemys.update()

    #collision between player and and walls
    if player.rect.collidelist(all_walls) >= 0:
      print("Collision !!")
      player.rect.x = player.rect.x - player.vx
      player.rect.y = player.rect.y - player.vx

    #fill the screen
    screen.fill((0, 0, 0))
    #screen.blit(background,(x,y))

    #draw the sprites
    sprites.draw(screen)
    wall_list.draw(screen)
    enemys.draw(screen)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

如果您想运行图片,请使用以下链接: https://geordyd.stackstorage.com/s/hZZ1RWcjal6ecZM

2 个答案:

答案 0 :(得分:4)

我给精灵一个点列表(self.waypoints)并将第一个分配给self.target属性。

update方法中,我从self.pos位置减去self.target以获得指向目标且长度等于目标的向量(heading)距离。将此向量缩放到所需的速度,并将其用作速度(每帧添加到self.pos向量),实体将朝目标移动。

当达到目标时,我只是增加航点索引并将列表中的下一个航点指定给self.target。当你靠近目标时放慢速度是一个好主意,否则如果精灵无法准确到达目标点,精灵可能会卡住并来回移动。因此,我还检查精灵是否比self.target_radius更近,并将速度降低到最大速度的一小部分。

import pygame as pg
from pygame.math import Vector2


class Entity(pg.sprite.Sprite):

    def __init__(self, pos, waypoints):
        super().__init__()
        self.image = pg.Surface((30, 50))
        self.image.fill(pg.Color('dodgerblue1'))
        self.rect = self.image.get_rect(center=pos)
        self.vel = Vector2(0, 0)
        self.max_speed = 3
        self.pos = Vector2(pos)
        self.waypoints = waypoints
        self.waypoint_index = 0
        self.target = self.waypoints[self.waypoint_index]
        self.target_radius = 50

    def update(self):
        # A vector pointing from self to the target.
        heading = self.target - self.pos
        distance = heading.length()  # Distance to the target.
        heading.normalize_ip()
        if distance <= 2:  # We're closer than 2 pixels.
            # Increment the waypoint index to swtich the target.
            # The modulo sets the index back to 0 if it's equal to the length.
            self.waypoint_index = (self.waypoint_index + 1) % len(self.waypoints)
            self.target = self.waypoints[self.waypoint_index]
        if distance <= self.target_radius:
            # If we're approaching the target, we slow down.
            self.vel = heading * (distance / self.target_radius * self.max_speed)
        else:  # Otherwise move with max_speed.
            self.vel = heading * self.max_speed

        self.pos += self.vel
        self.rect.center = self.pos


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    waypoints = [(200, 100), (500, 400), (100, 300)]
    all_sprites = pg.sprite.Group(Entity((100, 300), waypoints))

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        all_sprites.update()
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)
        for point in waypoints:
            pg.draw.rect(screen, (90, 200, 40), (point, (4, 4)))

        pg.display.flip()
        clock.tick(60)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

而不是航点列表和索引,我实际上更喜欢使用itertools.cycle,只需拨打next切换到下一个点:

# In the `__init__` method.
self.waypoints = itertools.cycle(waypoints)
self.target = next(self.waypoints)

# In the `update` method.
if distance <= 2:
    self.target = next(self.waypoints)

答案 1 :(得分:0)

使用清单让他来回走动。

class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("enemy.png")
        self.image = pygame.transform.scale(self.image, (int(50), int(50)))
        self.rect = self.image.get_rect()
        self.rect.x = width / 3
        self.rect.y = height / 3
        #x or y coordinates
        self.list=[1,2,3,4,5]
        self.index=0

    def update(self):
        # patrol up and down or left and right depending on x or y
        if self.index==4:
            #reverse order of list
            self.list.reverse()
            self.index=0
        #set the x position of the enemy according to the list
        self.rect.x=self.list[self.index] 
        self.index+=1