簡體   English   中英

如何在Pygame中畫一個小角度低速閃爍的運動圓?

[英]How to draw a moving circle in Pygame with a small angle at a low speed and blinking?

下面的代碼在屏幕上移動兩個球。 第一個以低速移動10度角,繪圖質量好。 第二個球以 1 度的角度移動,為了尊重該角度,速度必須高得多,並且繪圖不令人滿意,閃爍很多。 有沒有辦法減慢第二個球的繪制速度並避免過度眨眼?

import pygame, sys, math
from pygame.locals import *

pygame.init()
DISPLAYSURF = pygame.display.set_mode((1000, 600))
pygame.display.set_caption('Bouncing Ball with position and angle')

# Set our color constants
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)

# Create the ball class
class Ball():
    def __init__(self,
                 screen,
                 color,
                 radius,
                 startX,
                 startY,
                 speed,
                 angle=45):
        super().__init__()
        self.screen = screen
        self.color = color
        rectSize = radius * 2
        self.rect = pygame.Rect(startX, startY, rectSize, rectSize)
        self.speed = speed
        self.angle = math.radians(angle)

    def update(self):
        delta_x = self.speed * math.cos(self.angle)
        delta_y = self.speed * math.sin(self.angle)
        self.rect = self.rect.move(delta_x, delta_y)

        if self.rect.right >= self.screen.get_width() or self.rect.left <= 0:
            self.angle = math.pi - self.angle

        if self.rect.top <= 0 or self.rect.bottom >= self.screen.get_height():
            self.angle = -self.angle

    def draw(self):
        '''
        Draw our ball to the screen with position information.
        '''
        pygame.draw.circle(self.screen, self.color, self.rect.center, int(self.rect.width / 2))

# Create a new Ball instance named 'myball'
myball = Ball(screen=DISPLAYSURF, color=YELLOW, startX=100, startY=100, radius=150, speed=8, angle=10)
mySmaLlAngleball = Ball(screen=DISPLAYSURF, color=YELLOW, startX=100, startY=500, radius=150, speed=58, angle=-1)

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

# Display loop
while run:
    # Handle events
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    # Update ball position
    myball.update()
    mySmaLlAngleball.update()

    # Draw screen
    DISPLAYSURF.fill(BLACK)
    myball.draw()
    mySmaLlAngleball.draw()
    pygame.display.update()
    clock.tick(30)

問題是因為pygame.Rect存儲積分坐標:

Rect 對象的坐標都是整數。 [...]

delta_xdelta_y的小數部分在self.rect.move(delta_x, delta_y)處丟失。

您必須使用浮點數進行計算。 添加一個屬性self.pos ,它是一個包含 2 個組件的元組,用於存儲球的中心點:

self.pos = self.rect.center

以最大浮點精度計算 position:

delta_x = self.speed * math.cos(self.angle)
delta_y = self.speed * math.sin(self.angle)
self.pos = (self.pos[0] + delta_x, self.pos[1] + delta_y)   

通過round() ed position 更新self.rect.center

self.rect.center = round(self.pos[0]), round(self.pos[1])

self.pos是“內部”position 並負責 position 的精確計算。 self.rect.center是積分 position 負責抽球。 self.pos在每一幀中略有變化。 self.rect.center只有在坐標的 a 分量改變 1 時才會改變。

Class Ball

class Ball():
    def __init__(self,
                 screen,
                 color,
                 radius,
                 startX,
                 startY,
                 speed,
                 angle=45):
        super().__init__()
        self.screen = screen
        self.color = color
        rectSize = radius * 2
        self.rect = pygame.Rect(startX, startY, rectSize, rectSize)
        self.speed = speed
        self.angle = math.radians(angle)
        self.pos = self.rect.center

    def update(self):
        delta_x = self.speed * math.cos(self.angle)
        delta_y = self.speed * math.sin(self.angle)
        self.pos = (self.pos[0] + delta_x, self.pos[1] + delta_y)

        self.rect.center = round(self.pos[0]), round(self.pos[1])

        if self.rect.right >= self.screen.get_width() or self.rect.left <= 0:
            self.angle = math.pi - self.angle

        if self.rect.top <= 0 or self.rect.bottom >= self.screen.get_height():
            self.angle = -self.angle

    def draw(self):
        '''
        Draw our ball to the screen with position information.
        '''
        pygame.draw.circle(self.screen, self.color, self.rect.center, int(self.rect.width / 2))

使用此解決方案,您可以擴大每秒的觸發器 ( clock.tick() ) 並將速度縮小相同的比例。 這會導致平穩的運動而不會眨眼。

暫無
暫無

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

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