在pygame中移动彗星

4

添加一张图片

我想让pygame中的一个注释横跨屏幕。这是我的注释类:

class Commet:
    def __init__(self):
        self.x  = -10
        self.y = 10
        self.radius = 20
        self.commet = pygame.image.load(r"C:\Users\me\OneDrive\Documents\A level python codes\final game\commet.png")
        self.commet = pygame.transform.scale(self.commet, (self.radius, self.radius))
        self.drop = 0.0000009
        self.speed = 2
        self.pos = 0
        self.commets = []

然后我向self.comments列表中添加了20条评论。

  def tail(self, n): # n is a variable used to denote the length of the self.commets
        for i in range(n):
            if len(self.commets) <= n - 1:
                self.commets.append(Commet())

我有两个问题。第一个问题是移动评论。为了移动它,我做了这个:

def move_tail(self):
    for c in  self.commets:
        c.x += self.speed
    for i in range(len(self.commets) - 1):
         self.commets[i].y += ((self.commets[i + 1].x) ** 2) * self.drop

对于x坐标,我每帧只需将其值加2即可。然而,对于彗星的y值,我想让它产生一种拖尾效果。我尝试将彗星的y值分配给在列表self.commets中引用我们正在参考的彗星上方一个位置的彗星的x值的平方。我期望彗星沿着一个通用的x = y ** 2二次曲线相互跟随。虽然它们确实沿着曲线移动,但速度却是一样的(我期望它们以不同的速率跟随,因为所有彗星的x值不同),这并没有给我拖尾效果。我该如何产生这种拖尾效果?
我的第二个问题是,我希望跟随第一个彗星的彗星越来越小。我尝试减小用于缩放我导入的图像的半径值。代码看起来像这样。
    # Decrease radius
    for i in range(n):
        self.commets[i].radius = i + 1

当我在控制台打印出彗星的半径值时,它们的范围从1到20,正如我所预期的那样,但是在屏幕上出现的图像大小对于列表中所有的彗星都是相同的。以下代码是我如何粘贴彗星的方式:
  for i in range(n):
        self.commets[i].pos = i * 10 #  This line maintains a certain x- distance between commets

    for c in self.tails:
        D.blit(c.commet, (c.x - c.pos, c.y))

        if self.pos >= n:
            self.pos = n

2
随着彗星的移动,它需要创建一个新的自身图像并更新任何以前的副本——就像 Python 一样。;¬) 为了做到这一点,您需要将当前活动的图像存储在一个容器中,比如一个 list(最多可以有一些)。 - martineau
@Thomas Weller,我添加了一张图片。我基本上只想让一些小圆圈跟随大圆圈。 - user12291970
1个回答

2
假设您希望在FullHD屏幕上让您的彗星从左向右飞行。
彗星应该从y坐标为900的左侧开始,然后在x = 1400和y = 100达到最高点,然后掉落到屏幕右侧的600。

Comet flight

一条抛物线通常表示为y = ax² + bx + c。
为了不受屏幕分辨率的影响,您当然可以从某个百分比计算这些值,例如900〜屏幕高度* 83%,600〜屏幕高度* 55%,1400〜屏幕宽度* 73%,100〜屏幕高度* 9%。
有了三个给定点,您可以计算出一条抛物线。
class ParabolaFrom3Points:
    def __init__(self, points: list):
        self.a = (points[0][0] * (points[1][1] - points[2][1]) + points[1][0] * (
                points[2][1] - points[0][1]) + points[2][0] * (points[0][1] - points[1][1])) / (
                         (points[0][0] - points[1][0]) * (points[0][0] - points[2][0]) * (
                         points[2][0] - points[1][0]))
        self.b = (points[0][0] ** 2 * (points[1][1] - points[2][1]) + points[1][0] ** 2 * (
                points[2][1] - points[0][1]) + points[2][0] ** 2 * (points[0][1] - points[1][1])) / (
                         (points[0][0] - points[1][0]) * (points[0][0] - points[2][0]) * (
                         points[1][0] - points[2][0]))
        self.c = (points[0][0] ** 2 * (points[1][0] * points[2][1] - points[2][0] * points[1][1]) +
                  points[0][0] * (points[2][0] ** 2 * points[1][1] - points[1][0] ** 2 * points[2][1]) +
                  points[1][0] * points[2][0] * points[0][1] * (points[1][0] - points[2][0])) / (
                         (points[0][0] - points[1][0]) * (points[0][0] - points[2][0]) * (
                         points[1][0] - points[2][0]))

    def y(self, x: int) -> int:
        return int(self.a * x ** 2 + self.b * x + self.c)

彗星很简单。它只需要知道它的抛物线函数,就可以计算出 y 值。
class Comet:
    def __init__(self, radius: int, para: ParabolaFrom3Points):
        self.x = -radius  # Be invisible at the beginning
        self.radius = radius
        self.para = para

    def move(self, x):
        self.x = x

    def paint(self, screen):
        x = self.x
        radius = self.radius
        for tail in range(20):
            pygame.draw.circle(screen, [255, 255, 255], (int(x), self.para.y(x)), radius)
            x = x - radius / 2
            radius -= 1

测试代码:
import pygame

pygame.init()
pygame.fastevent.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode((1920, 1080))

pygame.display.set_caption('Comet example')
comet = Comet(20, ParabolaFrom3Points([(0, 1080 * 0.83), (1920 * 0.73, 1080 * 0.12), (1920, 1080 * 0.55)]))
for x in range(-20, 1920 + 200, 3):
    comet.move(x)
    comet.paint(window)
    clock.tick(90)
    pygame.display.flip()
    window.fill([0, 0, 0])

pygame.quit()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接