前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pygame基础8-碰撞

Pygame基础8-碰撞

作者头像
一只大鸽子
发布2024-04-11 13:05:03
840
发布2024-04-11 13:05:03
举报

Collisions

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

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

代码语言:javascript
复制
Rect1.colliderect(Rect2)
# collision -> return Ture 
# else -> return False

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

代码语言:javascript
复制
Rect1.collidepoint(x, y)
# x,y is the point on a Rect

collidepoint可能漏掉某些碰撞

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

结合矩形位置判断碰撞方向

案例

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

代码语言:javascript
复制
# 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()
    ...

添加第二个矩形

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

碰撞后反复移动

代码语言:javascript
复制
# 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只在竖直方向上移动。

在这里插入图片描述

代码语言:javascript
复制
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)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一只大鸽子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Collisions
  • 案例
    • 一个矩形(和边框的碰撞)
      • 添加第二个矩形
      • 完整案例
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档