由于在 pygame 中调整了大小,我无法让物体正常从墙上弹开

问题描述 投票:0回答:1

这是我的代码:

import pygame
import random

WIDTH = 800
HEIGHT = 650
FPS = 30

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)


class Ball(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((50, 50))
        self.image.fill(YELLOW)
        self.width = self.image.get_rect().width
        self.height = self.image.get_rect().height
        self.rect = self.image.get_rect()
        self.rect.center = (400, 600)
        self.changex = 10
        self.changey = -10
    def update(self):
        if self.rect.right >= 800:
            self.changex = -10
            self.image = pygame.transform.scale(self.image, (int(self.width*1.2),          int(self.height*1.2)))
            self.width = self.image.get_rect().width
            self.height = self.image.get_rect().height
        if self.rect.left <= 0:
            self.changex = 10
            self.image = pygame.transform.scale(self.image, (int(self.width*1.2), int(self.height*1.2)))
            self.width = self.image.get_rect().width
            self.height = self.image.get_rect().height
        self.rect.x += self.changex
        if self.rect.top <= 0:
            self.changey = 10
            self.image = pygame.transform.scale(self.image, (int(self.width*1.2), int(self.height*1.2)))
            self.width = self.image.get_rect().width
            self.height = self.image.get_rect().height
        if self.rect.bottom >= 650:
            self.changey = -10
            self.image = pygame.transform.scale(self.image, (int(self.width*1.2), int(self.height*1.2)))
            self.width = self.image.get_rect().width
            self.height = self.image.get_rect().height
        self.rect.y += self.changey

pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Snake")
clock = pygame.time.Clock()
all_sprites = pygame.sprite.Group()
ball = Ball()
all_sprites.add(ball)



running = True
while running:
    clock.tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    all_sprites.update()

    screen.fill(BLACK)
    all_sprites.draw(screen)
    pygame.display.flip()

pygame.quit()

问题出在这个地方:

if self.rect.right >= 800:
            self.changex = -10
            self.image = pygame.transform.scale(self.image, (int(self.width*1.2), int(self.height*1.2)))
            self.width = self.image.get_rect().width
            self.height = self.image.get_rect().height

Python 认为 self.rect.right 是对象原始大小的右侧,即使对象已经增大,它也会继续从其原始大小的边界反弹。

在这张图中,立方体已经远远超出了边界,只有当它到达原来的小右侧时才被推开(https://i.stack.imgur.com/RM0ia.jpg)

这种情况仅发生在物体的右侧和底部。我不明白如何使已经放大的立方体正确地从边界反弹。

python pygame
1个回答
0
投票

您的代码的问题不是调整大小而是弹跳。如果您的球反射在墙上,您需要调整由

rect
对象定义的球的大小和位置。添加一个方法。添加当球与墙壁碰撞时改变球的运动方向和大小的方法

def reflect(self, NV):
    self.dir = self.dir.reflect(pygame.math.Vector2(NV))
    self.radius = min(50, self.radius + 1)
    self.image = pygame.transform.scale(self.original_image, (self.radius * 2, self.radius * 2))
    self.pos += NV
    self.rect = self.image.get_rect(center = (round(self.pos.x), round(self.pos.y)))

当小球碰撞边界时调用

update
中的方法:

def update(self, border):
    self.pos += self.dir * self.velocity
    self.rect.center = round(self.pos.x), round(self.pos.y)
    if self.rect.left <= border.left:
        self.reflect((1, 0))
    if self.rect.right >= border.right:
        self.reflect((-1, 0))
    if self.rect.top <= border.top:
        self.reflect((0, 1))
    if self.rect.bottom >= border.bottom:
        self.reflect((0, -1))

完整示例:

import pygame
import random

class Ball(pygame.sprite.Sprite):

    def __init__(self, startpos, velocity, startdir):
        super().__init__()
        self.pos = pygame.math.Vector2(startpos)
        self.velocity = velocity
        self.dir = pygame.math.Vector2(startdir).normalize()
        self.original_image = pygame.Surface((100, 100), pygame.SRCALPHA)
        pygame.draw.circle(self.original_image, (0, 255, 0), (50, 50), 50)
        self.radius = 5
        self.image = pygame.transform.scale(self.original_image, (self.radius * 2, self.radius * 2))
        self.rect = self.image.get_rect(center = (round(self.pos.x), round(self.pos.y)))

    def reflect(self, NV):
        self.dir = self.dir.reflect(pygame.math.Vector2(NV))
        self.radius = min(50, self.radius + 1)
        self.image = pygame.transform.scale(self.original_image, (self.radius * 2, self.radius * 2))
        self.pos += NV
        self.rect = self.image.get_rect(center = (round(self.pos.x), round(self.pos.y)))

    def update(self, border):
        self.pos += self.dir * self.velocity
        self.rect.center = round(self.pos.x), round(self.pos.y)
        if self.rect.left <= border.left:
            self.reflect((1, 0))
        if self.rect.right >= border.right:
            self.reflect((-1, 0))
        if self.rect.top <= border.top:
            self.reflect((0, 1))
        if self.rect.bottom >= border.bottom:
            self.reflect((0, -1))
   
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

all_groups = pygame.sprite.Group()
start, velocity, direction = (250, 250), 5, (random.random(), random.random())
ball = Ball(start, velocity, direction)
all_groups.add(ball)

border_rect = pygame.Rect(100, 100, 300, 300)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    all_groups.update(border_rect)

    window.fill(0)
    pygame.draw.rect(window, (255, 0, 0), border_rect, 1)
    all_groups.draw(window)
    pygame.display.flip()
© www.soinside.com 2019 - 2024. All rights reserved.