簡體   English   中英

在 pygame 中移動彗星

[英]Moving a comet in pygame

添加了圖片

我想要一個 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.commets列表中添加了 20 個 commets。

  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中所指的self.commets上方一個索引位置處的self.commetsx值的self.commets 。我希望這些彗星沿着一般的 x = 相互跟隨y **2 二次曲線。 它們確實遵循曲線,但都以相同的速率(我預計它們會以不同的速率跟隨,因為所有彗星都有不同的 x 值),這給我帶來了類似尾巴的效果。 我怎樣才能產生這種尾巴狀的效果?

我的問題的第二部分是我希望第一個之后的彗星變得越來越小。 我嘗試減小radius值,該值用於縮放我導入的圖像。 代碼看起來像這樣

    # Decrease radius
    for i in range(n):
        self.commets[i].radius = i + 1

當我在控制台上打印出彗星半徑的值時,它們的范圍從 1 到 20,正如我所期望的那樣,但是屏幕上顯示的圖像大小對於列表中的所有彗星都是相同的。以下代碼是我如何對彗星進行 blit

  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

假設您希望彗星在全高清屏幕上從左到右飛行。

彗星應從左側 y 坐標 900 處開始,然后在 x=1400 和 y = 100 處達到其最高點,然后在屏幕右側下降至 600。

彗星飛行

拋物線通常是 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)

那么彗星就很簡單了。 它只需要知道它的拋物線函數,然后就可以從 x 計算 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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM