首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何让对象永久停留在窗口中,而不在Pygame中刷新?

如何让对象永久停留在窗口中,而不在Pygame中刷新?
EN

Stack Overflow用户
提问于 2020-01-22 23:07:37
回答 1查看 140关注 0票数 2

我正在尝试使用Pygame重新创建Atari Breakout。我遇到了一个问题,我把所有三行的瓷砖放在三个列表中,我想把它们打印出来,让它们在球击中它们之前留在原来的位置。

代码如下:

代码语言:javascript
运行
复制
import pygame
import random

pygame.init()

screenWidth = 1200
screenHeight = 700

window = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption('Atari Breakout')

pygame.mouse.set_pos(-500,650)


class Plate():

    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5

    def draw_plate(self):
        pygame.mouse.set_visible(True)
        pos = pygame.mouse.get_pos()
        self.x = pos[0]-100

        pygame.draw.rect(window, (00,00,255), (self.x, self.y ,self.width, self.height))


class Circle():

    def __init__(self, x, y, radius):
        self.x = x
        self.y = y
        self.radius = radius
        self.vel_x = 5
        self.vel_y = 5


class Tiles():

    def __init__(self, x, y, width, height, color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color

    def draw(self):
        if self.color == 'red':
            pygame.draw.rect(window, (255,0,0), (self.x, self.y, self.width, self.height))
        elif self.color == 'green':
            pygame.draw.rect(window, (44,176,55), (self.x, self.y, self.width, self.height))
        elif self.color == 'blue':
            pygame.draw.rect(window, (0,191,255), (self.x, self.y, self.width, self.height))
        pygame.display.update()


def draw_titles():
    first_row = []
    second_row = []
    third_row = []
    preset_width1 = [70, 120, 200, 30, 240, 140, 130, 120, 80]                       # nine elements
    preset_width2 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
    preset_width3 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
    random.shuffle(preset_width1)
    random.shuffle(preset_width2)
    random.shuffle(preset_width3)
    #print(f'preset_width1 is: {preset_width1}')
    put_width1 = []
    put_width2 = []
    put_width3 = []

    for t in range(1,10):

        if t==1:
            width = preset_width1.pop(0)
            put_width1.append(width)
            #print(f'put_width1 is: {put_width1}')


        if t==1:
            x = 0 + 5
        else:
            add = sum(put_width1)
            #print(f'add is: {add}')
            x = t*5 + add
            #print(f'x is: {x}')

        if t>1:
            width = preset_width1.pop(0)
            put_width1.append(width)
            #print(f'put_width1 is: {put_width1}')

        y = 125

        height = 35


        first_row.append(Tiles(x,y,width,height,'red'))

        if t == 9:
            break

    for t in range(1,10):

        if t==1:
            width = preset_width2.pop(0)
            put_width2.append(width)

        if t==1:
            x = 0 + 5
        else:
            add = sum(put_width2)
            x = t*5 + add

        if t>1:
            width = preset_width2.pop(0)
            put_width2.append(width)

        y = 170

        height = 35

        second_row.append(Tiles(x,y,width,height,'green'))

        if t == 9:
            break

    for t in range(1,10):

        if t==1:
            width = preset_width3.pop(0)
            put_width3.append(width)

        if t==1:
            x = 0 + 5
        else:
            add = sum(put_width3)
            x = t*5 + add

        if t>1:
            width = preset_width3.pop(0)
            put_width3.append(width)

        y = 215

        height = 35

        third_row.append(Tiles(x,y,width,height,'blue'))

        if t == 9:
            break


    for num in range(0,9):
        first_row[num].draw()

    for num in range(0,9):
        second_row[num].draw()

    for num in range(0,9):
        third_row[num].draw()

    keys = pygame.key.get_pressed()
    if keys[pygame.K_BACKSPACE]:
        run = False







# main loop
plate = Plate(10,650,200,40)
ball = Circle(600,300,10)
run = True
start = False
bounds = pygame.Rect(0, 0, 1200, 700)


while run:
    pygame.time.Clock().tick(120)

    for event in pygame.event.get():
        if event == pygame.QUIT:
            run = False


    plate.draw_plate()



    keys = pygame.key.get_pressed()


    # bounce algorithem 
    if keys[pygame.K_SPACE]:
        start = True

    if start:
        ball.y -= ball.vel_y        
        ball.x += ball.vel_x

        if ball.x - ball.radius < bounds.left or ball.x + ball.radius > bounds.right:
            ball.vel_x *= -1 
        if ball.y - ball.radius < bounds.top or ball.y + ball.radius > bounds.bottom:
            ball.vel_y *= -1 

    pygame.draw.rect(window, (0, 0, 0), bounds, 1)
    pygame.draw.circle(window, (44,176,55), (ball.x, ball.y), ball.radius)
    #pygame.display.update()


    draw_titles()



    # close call
    if keys[pygame.K_BACKSPACE]:
        run = False
        break





    window.fill((0,0,0))
    pygame.display.update()




pygame.quit()

这是理想的情况:

但相反,它会像疯了一样刷新。我知道问题是我把draw_titles()函数放在了主While循环中。但我相信这是我编写draw_tiles()函数的方式,导致它无法工作。如果我把draw_titles()放在循环之前,瓷砖就会出现并立即消失,球和盘子都不会显示。

我在网上做了一些研究,我看到了文本和图像的教程。对于图像,他们使用.blit(),但我相信它只适用于图像。

我尝试了许多变体来解决这个问题,但都无济于事。请帮帮忙。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-22 23:23:45

这里有一个快速解决方案:

代码语言:javascript
运行
复制
import pygame
import random

pygame.init()

screenWidth = 1200
screenHeight = 700

window = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption('Atari Breakout')

pygame.mouse.set_pos(-500,650)


class Plate():

    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5

    def draw_plate(self):
        pygame.mouse.set_visible(True)
        pos = pygame.mouse.get_pos()
        self.x = pos[0]-100

        pygame.draw.rect(window, (00,00,255), (self.x, self.y ,self.width, self.height))


class Circle():

    def __init__(self, x, y, radius):
        self.x = x
        self.y = y
        self.radius = radius
        self.vel_x = 5
        self.vel_y = 5


class Tiles():

    def __init__(self, x, y, width, height, color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color

    def draw(self):
        if self.color == 'red':
            pygame.draw.rect(window, (255,0,0), (self.x, self.y, self.width, self.height))
        elif self.color == 'green':
            pygame.draw.rect(window, (44,176,55), (self.x, self.y, self.width, self.height))
        elif self.color == 'blue':
            pygame.draw.rect(window, (0,191,255), (self.x, self.y, self.width, self.height))

first_row = []
second_row = []
third_row = []

def create_titles():
    preset_width1 = [70, 120, 200, 30, 240, 140, 130, 120, 80]                       # nine elements
    preset_width2 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
    preset_width3 = [70, 120, 200, 30, 240, 140, 130, 120, 80]
    random.shuffle(preset_width1)
    random.shuffle(preset_width2)
    random.shuffle(preset_width3)
    #print(f'preset_width1 is: {preset_width1}')
    put_width1 = []
    put_width2 = []
    put_width3 = []

    for t in range(1,10):

        if t==1:
            width = preset_width1.pop(0)
            put_width1.append(width)
            #print(f'put_width1 is: {put_width1}')


        if t==1:
            x = 0 + 5
        else:
            add = sum(put_width1)
            #print(f'add is: {add}')
            x = t*5 + add
            #print(f'x is: {x}')

        if t>1:
            width = preset_width1.pop(0)
            put_width1.append(width)
            #print(f'put_width1 is: {put_width1}')

        y = 125

        height = 35


        first_row.append(Tiles(x,y,width,height,'red'))

        if t == 9:
            break

    for t in range(1,10):

        if t==1:
            width = preset_width2.pop(0)
            put_width2.append(width)

        if t==1:
            x = 0 + 5
        else:
            add = sum(put_width2)
            x = t*5 + add

        if t>1:
            width = preset_width2.pop(0)
            put_width2.append(width)

        y = 170

        height = 35

        second_row.append(Tiles(x,y,width,height,'green'))

        if t == 9:
            break

    for t in range(1,10):

        if t==1:
            width = preset_width3.pop(0)
            put_width3.append(width)

        if t==1:
            x = 0 + 5
        else:
            add = sum(put_width3)
            x = t*5 + add

        if t>1:
            width = preset_width3.pop(0)
            put_width3.append(width)

        y = 215

        height = 35

        third_row.append(Tiles(x,y,width,height,'blue'))

        if t == 9:
            break

# main loop
plate = Plate(10,650,200,40)
ball = Circle(600,300,10)
run = True
start = False
bounds = pygame.Rect(0, 0, 1200, 700)

create_titles()

while run:
    pygame.time.Clock().tick(120)

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

    keys = pygame.key.get_pressed()
    # bounce algorithem 
    if keys[pygame.K_SPACE]:
        start = True
    # close call
    if keys[pygame.K_BACKSPACE]:
        run = False
        break

    if start:
        ball.y -= ball.vel_y        
        ball.x += ball.vel_x

        if ball.x - ball.radius < bounds.left or ball.x + ball.radius > bounds.right:
            ball.vel_x *= -1 
        if ball.y - ball.radius < bounds.top or ball.y + ball.radius > bounds.bottom:
            ball.vel_y *= -1 

    window.fill((0,0,0))
    plate.draw_plate()
    pygame.draw.rect(window, (0, 0, 0), bounds, 1)
    pygame.draw.circle(window, (44,176,55), (ball.x, ball.y), ball.radius)
    for tile in first_row:
        tile.draw()
    for tile in second_row:
        tile.draw()
    for tile in third_row:
        tile.draw()

    pygame.display.update()

pygame.quit()

当绘制到屏幕时,首先清除屏幕表面,然后绘制所有对象,如下所示:

代码语言:javascript
运行
复制
    ...
    window.fill((0,0,0))
    plate.draw_plate()
    pygame.draw.rect(window, (0, 0, 0), bounds, 1)
    pygame.draw.circle(window, (44,176,55), (ball.x, ball.y), ball.radius)
    for tile in first_row:
        tile.draw()
    for tile in second_row:
        tile.draw()
    for tile in third_row:
        tile.draw() 
    ...

请注意,所有与绘图相关的东西都在一个地方。这样,它就更清晰、更少混淆了。

您应该确保每帧只调用一次pygame.display.flip() (或.update()) (正如Rabbid76在注释中所说的那样)。

我还将列表移到了draw_titles函数之外,并将其重命名为create_titles。该函数创建平铺,因此它应该只做一次,而不是每一帧。

您可能还应该研究一下pygame的SpriteGroup类。下面是我使用pygame的一些特性的一个例子:

代码语言:javascript
运行
复制
import pygame
import random

class Paddle(pygame.sprite.Sprite):

    def __init__(self, x, y, width, height, bounds, *grps):
        super().__init__(*grps)
        self.image = pygame.Surface((width, height))
        self.image.fill((0,0,255))
        self.rect = self.image.get_rect(topleft=(x, y))
        self.bounds = bounds

    def update(self, dt):
        pos = pygame.mouse.get_pos()
        self.rect.centerx = pos[0]
        self.rect.clamp_ip(self.bounds)

class Circle(pygame.sprite.Sprite):

    def __init__(self, x, y, radius, bounds, *grps):
        super().__init__(*grps)
        self.image = pygame.Surface((radius, radius))
        self.image.set_colorkey((1, 2, 3))
        self.image.fill((1, 2, 3))
        self.rect = self.image.get_rect(topleft=(x, y))
        pygame.draw.circle(self.image, (44,176,55), (radius//2, radius//2), 5)
        self.vel = pygame.Vector2((5, 5))
        self.pos = self.rect.center
        self.bounds = bounds

    def update(self, dt):
        self.pos += self.vel * min(dt/15, 10)
        self.rect.center = self.pos

        if self.rect.left < self.bounds.left or self.rect.right > self.bounds.right:
            self.vel.x *= -1
        if self.rect.top < self.bounds.top or self.rect.bottom > self.bounds.bottom:
            self.vel.y *= -1

        self.rect.clamp_ip(self.bounds)

    def bounce(self, sprite):
        if self.rect.top <= sprite.rect.top or sprite.rect.bottom >= sprite.rect.bottom:
            self.vel.y *= -1
        elif self.rect.left <= sprite.rect.left or sprite.rect.right >= sprite.rect.right:
            self.vel.x *= -1


class Tiles(pygame.sprite.Sprite):

    def __init__(self, x, y, width, height, color,  *grps):
        super().__init__(*grps)
        self.image = pygame.Surface((width, height))
        self.image.fill(color)
        self.rect = self.image.get_rect(topleft=(x, y))

    def hit(self):
        self.kill()

def main():
    pygame.init()
    screen = pygame.display.set_mode((1200, 700))
    screen_rect = screen.get_rect()
    pygame.display.set_caption('Atari Breakout')

    sprites = pygame.sprite.Group()
    tiles = pygame.sprite.Group()
    paddle = Paddle(10,650,200,40, screen_rect, sprites)
    ball = Circle(600,300,10, screen_rect, sprites)

    preset = [70, 120, 200, 30, 240, 140, 130, 120, 80]
    y = 215
    for color in ['blue', 'green', 'red']:
        x = 5
        line = preset[:]
        random.shuffle(line)
        for width in line:
            Tiles(x, y, width, 35, pygame.Color(color), sprites, tiles)
            x += width + 5
        y -= 45

    dt = 0
    clock = pygame.time.Clock()
    while True:
        pygame.time.Clock().tick(120)

        # events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_BACKSPACE:
                    return

        # game logic
        tile = pygame.sprite.spritecollideany(ball, tiles)
        if tile:
            tile.hit()
            ball.bounce(tile)

        if pygame.sprite.collide_rect(paddle, ball):
            ball.bounce(paddle)

        sprites.update(dt)

        # drawing
        screen.fill((0,0,0))
        sprites.draw(screen)
        pygame.draw.rect(screen, (0, 0, 0), screen_rect, 1)

        pygame.display.update()
        dt = clock.tick(120)

    pygame.quit()

if __name__ == '__main__':
    main()
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59862666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档