Pygame基础8-碰撞

简介: Pygame基础8-碰撞

Collisions

Pygame中,我们使用矩形来移动物体,并且用矩形检测碰撞。

colliderect检测两个矩形是否碰撞,但是没法确定碰撞的方向。

Rect1.colliderect(Rect2)
# collision -> return Ture 
# else -> return False

collidepoint可以确定一个矩形是否和另一个矩形的某个碰撞(并确定碰撞方向),但是会很麻烦,并且很容易遗漏某些碰撞。

Rect1.collidepoint(x, y)
# x,y is the point on a Rect

综合考虑之后,

我们通常使用colliderect来检测碰撞,然后根据两个矩形的相对位置确定碰撞方向。

案例

一个矩形(和边框的碰撞)

# rect1
rect1 = pygame.Rect(100, 100, 50, 50)
color1 = (255, 255, 255)
speed_1_x = 5
speed_1_y = 5

def update_rect():
    global speed_1_x, speed_1_y
    rect1.x += speed_1_x
    rect1.y += speed_1_y

    # rect 和边界的碰撞:
    if rect1.left <= 0 and speed_1_x <0:
        speed_1_x *= -1
    elif rect1.right >= witdth and speed_1_x > 0:
        speed_1_x *= -1

    if rect1.top <= 0 and speed_1_y < 0 :
        speed_1_y *= -1
    elif rect1.bottom >= height and speed_1_y > 0:
        speed_1_y *= -1

    pygame.draw.rect(screen, color1, rect1)

# 在主循环中调用 update_rect()
while True:
    ...
    screen.fill((30, 30, 30))
    update_rect()
    ...

添加第二个矩形

注意:除了判断碰撞方向之外,还要判断矩形的速度方向,以防止矩形在碰撞后反复移动。

# rect2
rect2 = pygame.Rect(200, 200, 200, 50)
color2 = (0, 255, 0)
speed_2_x = 0
speed_2_y = 4 # 为了简化,rect2只在竖直方向上移动


def update_rect():
    global speed_1_x, speed_1_y,  speed_2_y
    ...

    rect2.y += speed_2_y
    # rect 和边界的碰撞:
    ...
    if rect2.top <= 0 and speed_2_y < 0 :
        speed_2_y *= -1
    elif rect2.bottom >= height and speed_2_y > 0:
        speed_2_y *= -1

    # rect1 和 rect2的碰撞
    collide_threshold = 20
    if rect1.colliderect(rect2): 
        if abs(rect1.top - rect2.bottom) < collide_threshold and speed_1_y < 0:
            speed_1_y *= -1
        elif abs(rect1.bottom - rect2.top) < collide_threshold and speed_1_y > 0:
            speed_1_y *= -1
        elif abs(rect1.left - rect2.right) < collide_threshold and speed_1_x < 0:
            speed_1_x *= -1
        elif abs(rect1.right - rect2.left) < collide_threshold and speed_1_x > 0:
            speed_1_x *= -1

    

    pygame.draw.rect(screen, color1, rect1)
    pygame.draw.rect(screen, color2, rect2)

完整案例

两个方块的碰撞。为了简化,rect2只在竖直方向上移动。

import sys
import time
import pygame


# Initialize Pygame
pygame.init()

# Set up the display
witdth = 800
height = 600
screen = pygame.display.set_mode((witdth, height))

# Set up the clock
clock = pygame.time.Clock()


# rect1
rect1 = pygame.Rect(100, 100, 50, 50)
color1 = (255, 255, 255)
speed_1_x = 5
speed_1_y = 5

# rect2
rect2 = pygame.Rect(200, 200, 300, 50)
color2 = (0, 255, 0)
speed_2_x = 0 
speed_2_y = 4 # 为了简化,rect2只在竖直方向上移动

def update_rect():
    global speed_1_x, speed_1_y, speed_2_x, speed_2_y
    rect1.x += speed_1_x
    rect1.y += speed_1_y

    #rect2.x += speed_2_x
    rect2.y += speed_2_y

    # rect 和边界的碰撞:
    if rect1.left <= 0 and speed_1_x <0:
        speed_1_x *= -1
    elif rect1.right >= witdth and speed_1_x > 0:
        speed_1_x *= -1

    if rect1.top <= 0 and speed_1_y < 0 :
        speed_1_y *= -1
    elif rect1.bottom >= height and speed_1_y > 0:
        speed_1_y *= -1
    
    
    if rect2.top <= 0 and speed_2_y < 0 :
        speed_2_y *= -1
    elif rect2.bottom >= height and speed_2_y > 0:
        speed_2_y *= -1
        #以 HH:MM:SS 的格式 输出当前时间 
        form_time1 = time.strftime("%H:%M:%S", time.localtime())
        print('rect2 to bottom', 'time= ', form_time1)

    # rect1 和 rect 2的碰撞
    collide_threshold = 20
    if rect1.colliderect(rect2): 
        if abs(rect1.top - rect2.bottom) < collide_threshold and speed_1_y < 0:
            speed_1_y *= -1
            
        if abs(rect1.bottom - rect2.top) < collide_threshold and speed_1_y > 0:
            speed_1_y *= -1
        
        if abs(rect1.left - rect2.right) < collide_threshold and speed_1_x < 0:
            speed_1_x *= -1
         
        if abs(rect1.right - rect2.left) < collide_threshold and speed_1_x > 0:
            speed_1_x *= -1
         

    # Draw the rect
    pygame.draw.rect(screen, color1, rect1)
    pygame.draw.rect(screen, color2, rect2)

while True:
    # Handle events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    
    screen.fill((30, 30, 30))
    update_rect()
    # Update the display
    pygame.display.flip()

    # Cap the frame rate
    clock.tick(60)
相关文章
|
3月前
|
Python
Pygame入门 2022 (2)
Pygame入门 2022 (2)
Pygame入门 2022 (2)
|
3月前
|
开发框架 开发者 UED
Pygame的主要模块有哪些?
【6月更文挑战第11天】Pygame的主要模块有哪些?
34 5
|
3月前
|
算法 Linux API
Pygame的主要优势
【6月更文挑战第12天】Pygame的主要优势
48 3
|
3月前
|
开发者 Python
Pygame
【6月更文挑战第10天】Pygame
45 4
|
3月前
|
开发者 Python
Pygame提供了一套全面的工具和接口
【6月更文挑战第11天】,Pygame提供了一套全面的工具和接口
28 4
|
3月前
|
Python
Pygame基础9-射击
Pygame基础9-射击
Pygame基础9-射击
|
3月前
|
数据可视化 Python
Pygame基础10-物理模拟
Pygame基础10-物理模拟
|
3月前
|
Python
Pygame入门 2022 (3)
Pygame入门 2022 (3)
|
3月前
|
开发工具 图形学 Python
Pygame入门 2022 (1)
Pygame入门 2022 (1)
|
3月前
|
Python
Pygame基础3-动画
Pygame基础3-动画