Pygame:如何为旋转的正方形设置边界?

时间:2020-04-08 02:46:23

标签: python pygame

我有一个围绕屏幕移动的旋转方块,任务是(1)设置边界使其保持在屏幕内,以及(2)使用类似的旋转方块进行碰撞检测。我需要第一个问题的帮助。

P.S。对于我的老师(如果您正在阅读),我已经针对这个特定问题进行了6个多小时的讨论,因此必须寻求他人的帮助。某些问题可以承受持续思考的冲击,失败不是成功的延误-仅仅是失败,技能不是99%的努力+ 1%的才能-相反,等等。

注意:很抱歉格式不正确。这是我第一次使用Stack Overflow。以前使用过Y!A,但是那里的编程部分人不多

import pygame 
import random

pygame.init()  # Initialize py-game
screen = pygame.display.set_mode((800, 500))  # Create screen
color = (255, 240, 245)

# Initial Coordinates
objectX, objectY = random.randint(100, 700), random.randint(100, 400)

fps = pygame.time.Clock()
velocity = [8, 6]  # speed
velocity2 = [6, 8]
size = 0  # size
drag = False

# Rotating the object
sat_orig = pygame.Surface((70, 70))
sat_orig.set_colorkey((0, 0, 0))
sat_orig.fill(color)
sat = sat_orig.copy()
sat.set_colorkey((0, 0, 0))
rect = sat.get_rect()
rect.center = (800 // 2, 500 // 2)
rotation = 0
rotation_speed = 2


# --------------------------------------------------------------------------


running = True
while running:  # Game Loop

    screen.fill((0, 0, 0))
    pygame.display.set_caption('Collision Interactions ' + str(pygame.mouse.get_pos()))  # caption

    # exit button
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                drag = False
                rotation_speed = 2

        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                drag = True
                rotation_speed = 0

    size = 70

    old_center = rect.center
    rotation = (rotation + rotation_speed) % 360
    new_image = pygame.transform.rotate(sat_orig, rotation)
    rect = new_image.get_rect()
    rect.center = old_center
    screen.blit(new_image, (objectX, objectY))
    objectArea = rect

    ############
    # Movement #
    ############
    if drag:  # Manual
        if objectArea.collidepoint(event.pos):
            objectX, objectY = pygame.mouse.get_pos()
            objectX -= size // 2
            objectY -= size // 2
    else:  # Automatic
        objectX += velocity[0]
        objectY += velocity[1]

        ##############
        # Boundaries #
        ##############
        if objectX + size > 800 or objectX + size < 0:
            velocity[0] = -velocity[0]
        if objectY + size > 500 or objectY + size < 0:
            velocity[1] = -velocity[1]

    fps.tick(80)

    pygame.display.update()  # Displays updates

1 个答案:

答案 0 :(得分:0)

轴对齐的宽度和高度大于旋转矩形的原始高度。 旋转后的矩形的边界存储在objectArea中。使用旋转的矩形进行碰撞测试:

while running:  # Game Loop
    # [...]

    if drag:  # Manual
        # [...]

    else:  # Automatic

        objectX += velocity[0]
        objectY += velocity[1]

        # set new location of rotated rectangle
        objectArea.topleft = (objectX, objectY)

        # bounce on bounds
        if objectArea.right > 800 or objectArea.left < 0:
            velocity[0] = -velocity[0]
        if objectArea.bottom > 500 or objectArea.top < 0:
            velocity[1] = -velocity[1]#

请注意,由于矩形的移动大于1,因此可能会稍微超出边界。为了防止矩形可以调整到边界:

while running:  # Game Loop
    # [...]

    if drag:  # Manual
        # [...]

        objectX += velocity[0]
        objectY += velocity[1]
        objectArea.topleft = (objectX, objectY)

        if objectArea.left < 0:
            velocity[0] *= -1
            objectX = 0
        elif objectArea.right > screen.get_width():
            velocity[0] *= -1
            objectX = screen.get_width() - objectArea.width 

        if objectArea.top < 0:
            velocity[1] *= -1
            objectY = 0
        elif objectArea.bottom > screen.get_height():
            velocity[1] *= -1
            objectY = screen.get_height() - objectArea.height

我建议在主应用程序循环的末尾绘制矩形(和整个)场景。因此,可以看到矩形的当前位置,而不是移动之前的位置:

while running:

    # handle the events
    for event in pygame.event.get():
        # [...]


    # do all the computations
    # [...]

    # draw the scene
    screen.fill((0, 0, 0))
    screen.blit(new_image, (objectX, objectY))
    pygame.display.update()  # Displays updates
    fps.tick(80)

完整示例:

import pygame 
import random

pygame.init()  # Initialize py-game
screen = pygame.display.set_mode((800, 500))  # Create screen
color = (255, 240, 245)

# Initial Coordinates
objectX, objectY = random.randint(100, screen.get_width()-100), random.randint(100, screen.get_height()-100)

fps = pygame.time.Clock()
velocity = [8, 6]  # speed
velocity2 = [6, 8]
size = 0  # size
drag = False

# Rotating the object
sat_orig = pygame.Surface((70, 70))
sat_orig.set_colorkey((0, 0, 0))
sat_orig.fill(color)
sat = sat_orig.copy()
sat.set_colorkey((0, 0, 0))
rect = sat.get_rect()
rect.center = (screen.get_width() // 2, screen.get_height() // 2)
rotation = 0
rotation_speed = 2


# --------------------------------------------------------------------------

pygame.display.set_caption('Collision Interactions ' + str(pygame.mouse.get_pos()))  # caption

running = True
while running:  # Game Loop

    # exit button
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                drag = False
                rotation_speed = 2

        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                drag = True
                rotation_speed = 0

    size = 70
    old_center = rect.center
    rotation = (rotation + rotation_speed) % 360
    new_image = pygame.transform.rotate(sat_orig, rotation)
    rect = new_image.get_rect()
    rect.center = old_center
    objectArea = rect

    ############
    # Movement #
    ############
    if drag:  # Manual
        if objectArea.collidepoint(event.pos):
            objectX, objectY = pygame.mouse.get_pos()
            objectX -= size // 2
            objectY -= size // 2
    else:  # Automatic

        objectX += velocity[0]
        objectY += velocity[1]
        objectArea.topleft = (objectX, objectY)

        if objectArea.left < 0:
            velocity[0] *= -1
            objectX = 0
        elif objectArea.right > screen.get_width():
            velocity[0] *= -1
            objectX = screen.get_width() - objectArea.width 

        if objectArea.top < 0:
            velocity[1] *= -1
            objectY = 0
        elif objectArea.bottom > screen.get_height():
            velocity[1] *= -1
            objectY = screen.get_height() - objectArea.height 

    screen.fill((0, 0, 0))
    screen.blit(new_image, (objectX, objectY))
    pygame.display.update()  # Displays updates
    fps.tick(80)

对于2个旋转矩形的碰撞,我建议使用pygame.mask.Mask对象和pygame.mask.Mask.overlap()pygame.sprite.Spritepygame.sprite.collide_mask()

进一步了解:
Collision between masks in pygame
How can I made a collision mask?
Pygame mask collision