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)

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-06 06:48:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-06 06:48:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-06 06:48:01       87 阅读
  4. Python语言-面向对象

    2024-04-06 06:48:01       96 阅读

热门阅读

  1. SFTP服务详解:安全高效的文件传输新选择

    2024-04-06 06:48:01       34 阅读
  2. 数据结构——顺序表(C语言)

    2024-04-06 06:48:01       33 阅读
  3. python学习笔记——函数

    2024-04-06 06:48:01       38 阅读
  4. 【接口】HTTP(4)|Session、Cookie、token有什么区别?

    2024-04-06 06:48:01       31 阅读
  5. WPF OnStartup

    2024-04-06 06:48:01       39 阅读
  6. WPF中TextWrapping

    2024-04-06 06:48:01       39 阅读
  7. 探索ChatGPT的学术应用:写出优质论文的突破之道

    2024-04-06 06:48:01       42 阅读