用pygame以多边形方式弹跳图像

0 投票
1 回答
968 浏览
提问于 2025-04-18 11:43

大家好,我是pygame的新手。我需要让一个球的图片ball.jpg以多边形的方式弹跳。我还有另一个球的图片,它是以方形的方式移动的。我想要添加另一个球的图片,并让它在pygame窗口中以多边形的方式弹跳。我的代码是

import pygame
from itertools import cycle
pygame.init() 
screen = pygame.display.set_mode((300, 300)) 
s_r = screen.get_rect()
ball = pygame.image.load('ball.jpg')
player = pygame.Rect((100, 100, 50, 50))
timer = pygame.time.Clock()
speed = 5
up, down, left, right = (0, -speed), (0, speed), (-speed, 0), (speed, 0)

dirs = cycle([up, right, down, left])
dir = next(dirs)

while True:

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

# move player
player.move_ip(dir)
# if it's outside the screen
if not s_r.contains(player):
    # put it back inside
    player.clamp_ip(s_r)
    # and switch to next direction
    dir = next(dirs)

screen.fill(pygame.color.Color('Black'))
screen.blit(ball,player)

pygame.display.flip()
timer.tick(25)

这段代码在一个图片上运行得很好……我需要的是添加另一个图片,并让它在pygame窗口中以多边形的形状移动。

希望大家能帮我一下……谢谢!

1 个回答

1

要做到这一点,你需要用到一些向量数学的知识。

首先,创建一个点的列表,这些点描述了物体应该移动的路径。接着,计算一个向量,这个向量表示从当前的位置到目标位置的方向。然后,利用这个向量来移动物体。一旦你到达了目标,就朝下一个点移动。

下面是一个例子:

import pygame
import math
from itertools import cycle

# some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637
def magnitude(v):
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))

def add(u, v):
    return [ u[i]+v[i] for i in range(len(u)) ]

def sub(u, v):
    return [ u[i]-v[i] for i in range(len(u)) ]    

def dot(u, v):
    return sum(u[i]*v[i] for i in range(len(u)))

def normalize(v):
    vmag = magnitude(v)
    return [ v[i]/vmag  for i in range(len(v)) ]

screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()    

class Ball(object):
    def __init__(self, path):
        self.x, self.y = (0, 0)
        self.speed = 2.5
        self.color = (200, 200, 200)
        self.path = cycle(path)
        self.set_target(next(self.path))

    @property
    def pos(self):
        return self.x, self.y

    # for drawing, we need the position as tuple of ints
    # so lets create a helper property
    @property
    def int_pos(self):
        return map(int, self.pos)

    @property
    def target(self):
        return self.t_x, self.t_y

    @property
    def int_target(self):
        return map(int, self.target)   

    def next_target(self):
        self.set_target(self.pos)
        self.set_target(next(self.path))

    def set_target(self, pos):
        self.t_x, self.t_y = pos

    def update(self):
        # if we won't move, don't calculate new vectors
        if self.int_pos == self.int_target:
            return self.next_target()

        target_vector = sub(self.target, self.pos) 

        # a threshold to stop moving if the distance is to small.
        # it prevents a 'flickering' between two points
        if magnitude(target_vector) < 2: 
            return self.next_target()

        # apply the balls's speed to the vector
        move_vector = [c * self.speed for c in normalize(target_vector)]

        # update position
        self.x, self.y = add(self.pos, move_vector)

    def draw(self):
        pygame.draw.circle(screen, self.color, self.int_pos, 4)

pygame.init()
quit = False

path = [(26, 43),
        (105, 110),
        (45, 225),
        (145, 295),
        (266, 211),
        (178, 134),
        (250, 56),
        (147, 12)]

path2 = [(26, 43),
         (105, 10),
         (45, 125),
         (150, 134),
         (150, 26),
         (107, 12)]

ball = Ball(path)
ball.speed = 1.9

ball2 = Ball(path2)
ball2.color = (200, 200, 0)

balls = [ball, ball2]

while not quit:
    quit = pygame.event.get(pygame.QUIT)
    pygame.event.poll()

    map(Ball.update, balls)

    screen.fill((0, 0, 0))

    map(Ball.draw, balls)

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

在这里输入图片描述


这是一个没有自定义类的例子:

import pygame
import math
from itertools import cycle

# some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637
def magnitude(v):
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))

def sub(u, v):
    return [ u[i]-v[i] for i in range(len(u)) ]    

def normalize(v):
    vmag = magnitude(v)
    return [ v[i]/vmag  for i in range(len(v)) ]

screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()    

pygame.init()
quit = False

path = [(26, 43),
        (105, 110),
        (45, 225),
        (145, 295),
        (266, 211),
        (178, 134),
        (250, 56),
        (147, 12)]
path = cycle(path)         
target = next(path)
ball = pygame.rect.Rect(target[0], target[1], 10, 10)
speed = 3.6

while not quit:
    quit = pygame.event.get(pygame.QUIT)
    pygame.event.poll()

    if ball.topleft == target:
        target = next(path)

    target_vector = sub(target, ball.topleft) 

    if magnitude(target_vector) < 2: 
        target = next(path)
    else:
        move_vector = [c * speed for c in normalize(target_vector)]
        ball.move_ip(move_vector)

    screen.fill((0, 0, 0))
    pygame.draw.rect(screen, pygame.color.Color('Grey'), ball)
    pygame.display.flip()
    clock.tick(60)

撰写回答