python - 无法让我的 Sprite 沿着路径点移动

标签 python pygame

我在移动汽车时遇到问题。对于一项作业,我必须制作一个模拟器。我需要让汽车产生,让它们检查交通信号灯是红色、橙色还是绿色,并在绿灯出现时移动。我怎样才能使我生成的汽车沿着我使用我制作的路径点创建类指定的路径点移动? 我有以下 python 文件,它列出了路径点列表。

waypoints.py:

class WayPoint:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def getX(self):
        return self.x
    def getY(self):
        return self.y

class WayPointsList:
    def __init__(self):
        self.wayPoints = []
    def add_wayPoint(self, x, y):
        self.wayPoints.append(WayPoint(x, y))
    def __len__(self):
        return len(self.wayPoints)
    def get_wayPoint(self, i):
        return [self.wayPoints[i].getX(), self.wayPoints[i].getY()]

当我调用这个类时,我的使用方式是这样的:

l = WayPointsList
l.add_wayPoint(55,67)

这是我的ma​​in.py:

import math
import random, assets
from bus import Bus
from car import Car
from lights import Lights
from waypoints import WayPointsList
import pygame as pg


class Mainstuff(object):
    def __init__(self):
        pg.init()
        self.clock = pg.time.Clock()
        self.screen = pg.display.set_mode((assets.screen_width, assets.screen_height))
        self.background = pg.image.load(assets.background)
        self.running = True
        self.car_group = pg.sprite.Group()
        self.light_group = pg.sprite.Group()

    def event_loop(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_1:
                    car110 = Car()
                    car110.set_image(assets.furore)
                    car110.rotate(180)
                    car110.set_position(0, 273)
                    self.car_group.add(car110)
                elif event.key == pg.K_2:
                    car109 = Car()
                    car109.set_image(assets.hachura)
                    car109.rotate(180)
                    car109.set_position(0, 306)
                    self.car_group.add(car109)
                elif event.key == pg.K_3:
                    car108 = Car()
                    car108.set_image(assets.jefferson)
                    car108.rotate(180)
                    car108.set_position(0, 343)
                    self.car_group.add(car108)
                elif event.key == pg.K_4:
                    car107 = Car()
                    car107.set_image(assets.michelli)
                    car107.rotate(270)
                    car107.set_position(410, 550)
                    self.car_group.add(car107)
                elif event.key == pg.K_5:
                    car106 = Car()
                    car106.set_image(assets.traceAM)
                    car106.rotate(270)
                    car106.set_position(460, 550)
                    self.car_group.add(car106)
                elif event.key == pg.K_6:
                    car105 = Car()
                    car105.set_image(assets.traceAM)
                    car105.set_position(750, 300)
                    self.car_group.add(car105)
                elif event.key == pg.K_7:
                    car104 = Car()
                    car104.set_image(assets.rumbler)
                    car104.set_position(750, 265)
                    self.car_group.add(car104)
                elif event.key == pg.K_8:
                    car103 = Car()
                    car103.set_image(assets.rumbler)
                    car103.rotate(90)
                    car103.set_position(294, 0)
                    self.car_group.add(car103)
                elif event.key == pg.K_9:
                    car102 = Car()
                    car102.set_image(assets.rumbler)
                    car102.rotate(90)
                    car102.set_position(337, 0)
                    self.car_group.add(car102)
                elif event.key == pg.K_0:
                    car101 = Car()
                    car101.set_image(assets.rumbler)
                    car101.rotate(90)
                    car101.set_position(380, 0)
                    self.car_group.add(car101)
                elif event.key == pg.K_b:
                    car201 = Bus()
                    car201.set_image(assets.bus)
                    car201.set_position(700, 229)
                    self.car_group.add(car201)
                elif event.key == pg.K_x:
                    self.car_group.empty()
    def update(self):
        self.screen.fill(assets.white)
        self.car_group.update()
        #self.light_group.update()
    def draw(self):
        self.screen.blit(self.background,(0,0))
        self.car_group.draw(self.screen)
        self.light_group.draw(self.screen)
    def run(self):
        while self.running:
            self.event_loop()
            self.update()
            self.draw()
            pg.display.update()
            self.clock.tick(assets.FPS)

if __name__ == '__main__':
    test = Mainstuff()
    test.run()
    pg.quit()

这是我的car.py:

import pygame, assets, math
class Car(pygame.sprite.Sprite):
    def __init__(self):
        super(Car, self).__init__()
        self.image = pygame.Surface((assets.car_width, assets.car_height))
        self.image.fill(assets.red)
        self.rect = self.image.get_rect()
        self.speed = 1
        self.angle = 0
    def set_position(self, x, y):
        self.rect.x = x
        self.rect.y = y
    def get_x_position(self):
        return self.rect.x
    def get_y_position(self):
        return self.rect.y
    def set_image(self, filename=None):
        if filename != None:
            self.image = pygame.image.load(filename).convert()
            #self.image.fill(assets.green)
            self.rect = self.image.get_rect()
    def rotate(self, angle):
        self.angle = angle
        self.image = pygame.transform.rotate(self.image, angle)
        self.rect = self.image.get_rect()
    #not sure what to do here
    def move_position(self, x, y):

        # use angle to calculate direction
        radius_angle = math.radians(self.angle)
        self.rect.x -= self.speed * math.cos(radius_angle)
        self.rect.y -= self.speed * math.sin(radius_angle)
        print('move', self.angle, self.rect.x, self.rect.y)
    def update(self):
        self.move_position(0, 0)

最佳答案

我举了例子。

它将列表中的第一个点作为起始位置,第二个点作为目标。

它使用 pygame.math.Vector2()计算一步

current = current + (target - current).normalize() * speed

当玩家位于目标中时,它会从列表中获取下一个点作为目标。

enter image description here

#!/usr/bin/env python3

import pygame

# === CONSTANS === (UPPER_CASE names)

BLACK = (  0,   0,   0)
WHITE = (255, 255, 255)

RED   = (255,   0,   0)
GREEN = (  0, 255,   0)
BLUE  = (  0,   0, 255)

SCREEN_WIDTH  = 600
SCREEN_HEIGHT = 400

# === CLASSES === (CamelCase names)

class Player():

    def __init__(self, waypoints, loop=False):

        # create green circe 
        r = 10

        self.image = pygame.Surface((2*r, 2*r)).convert_alpha()
        self.rect = self.image.get_rect()

        self.image.fill((0,0,0,0))
        pygame.draw.circle(self.image, (0,255,0), (r, r), r)

        # ---

        self.loop = loop

        self.speed = 5

        self.waypoints = waypoints
        self.next_point = 0

        # set current position
        # I use Vector2 because it keeps position as float numbers 
        # and it makes calcuations easier and more precise
        self.current = pygame.math.Vector2(self.waypoints[0])

        # set position in rect to draw it
        self.rect.center = self.current

        # set end point if exists on list
        self.target_index = 1
        if self.target_index < len(self.waypoints) - 1:
            self.target = pygame.math.Vector2(self.waypoints[self.target_index])
            self.moving = True
        else:
            self.target = self.current
            self.moving = False

    def move(self):

        if self.moving:

            # get distance to taget
            distance = self.current.distance_to(self.target)

            # 
            if distance > self.speed:
                self.current = self.current + (self.target - self.current).normalize() * self.speed
                self.rect.center = self.current
            else:
                # put player in tagert place, 
                # and find new target on list with waypoints 

                self.current = self.target
                self.rect.center = self.current

                # set next end point if exists on list
                self.target_index += 1
                if self.target_index < len(self.waypoints):
                    self.target = pygame.math.Vector2(self.waypoints[self.target_index])
                else:
                    if self.loop:
                        self.target_index = 0
                    else:
                        self.moving = False


    def draw(self, surface):
        surface.blit(self.image, self.rect)

# === MAIN === (lower_case names)

# --- init ---

pygame.init()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
screen_rect = screen.get_rect()

# --- objects ---

start = pygame.math.Vector2(screen_rect.centerx, screen_rect.bottom)
end = start
length = 150

waypoints = [(50, 50), (400, 150), (500, 50), (450, 350), (200, 200), (100, 350), (50, 50)]

player = Player(waypoints, True)

# --- mainloop ---

clock = pygame.time.Clock()
is_running = True


while is_running:

    # --- events ---

    for event in pygame.event.get():

        # --- global events ---

        if event.type == pygame.QUIT:
            is_running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                is_running = False

        # --- objects events ---

            # empty

    # --- updates ---

        # empty

    player.move()

    # --- draws ---

    screen.fill(BLACK)

    for start, end in zip(waypoints, waypoints[1:]):
        pygame.draw.line(screen, RED, start, end)

    player.draw(screen)

    pygame.display.update()

    # --- FPS ---

    clock.tick(25)

# --- the end ---

pygame.quit()

顺便说一句:因为玩家从一个点移动到另一个点时不会改变方向(并且目标不会改变位置),因此它只能计算该值一次

(target - current).normalize() * speed

当到达下一个点作为目标时重新计算。

<小时/>

顺便说一句:示例如何使用math模块进行计算来回答

finding change in x and y given two points and length of vector

关于python - 无法让我的 Sprite 沿着路径点移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47894415/

相关文章:

python - 如何使用 pygame 通过单击鼠标来暂停循环?

python - 用户的字符串(例如段落)可以导入/输入到 PyGame 中吗?

Python 从同一包中的文件导入 __init__.py 中的类

python - 如果等于 groups[*][0],其中 groups 是元组数组?

Python Pygame 不会退出

pygame - 在 buildozer 上使用 pygame 构建 apk 不起作用

python - Pygame screen.fill() 没有正确填充颜色

python - 使用 python sdk 从 facebook ads api 过滤统计信息

python - 使用 psutil.Process.memory_info 内存使用情况与 Pandas.memory_usage 不同

python - 如果 csv 文件包含空白字段,如何替换虚拟名称?