Pygame(七) 碰撞检测

Pygame(七) 碰撞检测

前情提要

第六课内容提要

作业分析:

作业内容:

  • 设计一个碰到墙壁就反弹的pygame实现

完整代码

# /usr/bin/python3

# Author: 爱编程的章老师
# @Time: 2021/1/5 0005
# E-mail: Bluesand2010@163.com

import pygame
import sys
import time

def homeworkd():
    pygame.init()
    s = pygame.display.set_mode((800, 600))
    rect = pygame.Rect(400,300, 100,100)
    GREEN = 0, 255, 0
    BLACK = 0,0,0
    pygame.draw.rect(s, GREEN, rect)
    pygame.display.update()

    dx = 5
    while 1:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                sys.exit()
        if dx == 5 and rect.right > 795:
            dx = -5
        elif rect.left <=0:
            dx = 5
        rect.move_ip(dx, 0)
        s.fill(BLACK)
        pygame.draw.rect(s, GREEN, rect)
        pygame.display.update()
        time.sleep(0.01)

if __name__ == '__main__':
    homeworkd()

代码分析

移动后要检测有没有撞到屏幕边缘,如果碰到了,就改变运动方向.
核心代码:

if dx == 5 and rect.right > 795:
    dx = -5
elif rect.left <=0:
    dx = 5

效果图:

碰撞反弹效果图

本节提要

本节提要

内容详解

游戏中,两个角色的碰撞是经常会发生的事情.比如飞机大战的子弹与敌机,子弹与主机,敌机与主机之间都需要进行碰撞检测
再比如动作游戏的主角与敌人之间的对战的碰撞检测也是必须的.
当然,这一节,我们不涉及不规则形状的碰撞.我们只探讨考虑两个(多个)矩形之间的碰撞逻辑与检测

自主实现

  • 两个矩形的碰撞检测不实现
    逻辑分析:
    两个矩形的碰撞,无外乎以下几种情况
  • 正面碰撞
    效果图如下:
    7_2_1.gif
  • 斜向碰撞
    7_2_2.gif

在我们事先已经知道是哪种情况下的碰撞,那代码写起来会简单很多.
先看第一种情况,我们只需要检测左边矩形的右边与右边矩形的左边的值的大小即可
代码如下:

def pong1():
    pygame.init()
    s = pygame.display.set_mode((800, 600))
    rect1 = pygame.Rect(100,300, 100,100)
    rect2 = pygame.Rect(400,300,100,100)
    GREEN = 0, 255, 0 # 绿色
    BLUE = 0, 0, 255  # 蓝色
    BLACK = 0,0,0  # 黑色
    pygame.draw.rect(s, GREEN, rect1)
    pygame.draw.rect(s, BLUE, rect2)

    pygame.display.update()

    while 1:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                sys.exit()
        if rect2.left > rect1.right:
            print("未碰撞")
            rect2.move_ip(-5, 0)
        else:
            print("碰撞成功")
        s.fill(BLACK)
        pygame.draw.rect(s, BLUE, rect2)
        pygame.draw.rect(s, GREEN, rect1)
        pygame.display.update()
        time.sleep(0.1)

效果图如下
7_3.gif

可以看到,没有碰撞的时候,输出的是未碰撞.
碰撞成功的时候,输出的是碰撞成功
可以成功检测到碰撞情形

  • 第二种情况斜撞
    我们只需要考虑左边矩形的上边< 右侧矩形的下边 且 左边矩形的右边< 右边矩形的左边的时候就是未碰撞.否则就是碰撞成功.这里代码就不再写了

但是实际场景中,我们很难确定两个矩形是哪一种碰撞逻辑.因此,我们要把两种碰撞的八种情况都写一遍.显然这样的代码会很复杂.
因此,实际工作中,我们通常采用反法(即证未碰撞)
image.png
未碰撞的四种情形
R2.bottom> R1.top
R3.right < R1.left
R4.top > R1.bottom
R5.left > R1.right
当然 在实际的时候,周边四个矩形是同一个矩形的四种位置.
因此,代码可以写成如下形式:

c1 = rect2.bottom > rect1.top
c2 = rect2.right < rect1.left
c3 = rect2.top > rect1.bottom
c4 = rect2.left > rect1.right
if c1 or c2 or c3 or c4:
    print("矩形2与矩形1没有碰撞")
else:
    print("两个矩形碰撞成功")

具体的代码这边就不再展开了.
因为pygame为我们做这项工作,可以让我们直接使用

pygame实现

rect1.colliderect(rect2)

用来判断rect1 与 rect2是否碰撞的.返回值为True 或 False

改进的代码:

def pong2():
    pygame.init()
    s = pygame.display.set_mode((800, 600))
    rect1 = pygame.Rect(100,300, 100,100)
    rect2 = pygame.Rect(400,300,100,100)
    GREEN = 0, 255, 0 # 绿色
    BLUE = 0, 0, 255  # 蓝色
    BLACK = 0,0,0  # 黑色
    pygame.draw.rect(s, GREEN, rect1)
    pygame.draw.rect(s, BLUE, rect2)

    pygame.display.update()

    while 1:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                sys.exit()
        # 以下是改进的代码
        if rect1.colliderect(rect2):
            print("碰撞成功")
        else:
            print("未碰撞")
            rect2.move_ip(-5, 0)
        # 改动到这里结束
        s.fill(BLACK)
        pygame.draw.rect(s, BLUE, rect2)
        pygame.draw.rect(s, GREEN, rect1)
        pygame.display.update()
        time.sleep(0.1)

改动过的地方已经作出了标志.
效果同上,不再上图了.

碰撞是检测由外而内的相遇过程
有时候,我们也有可能会遇到,一个角色在另一个角色内活动.出去就会触发特殊效果的情况.
比如,我们开了一个无敌的护罩.大小是200的正方形.当主角在护罩内时无敌才有效果.出了这个护罩就无效了.
这个时候如果采用自主实现的方法,就是判断主角的矩形四个方向的边是否在大矩形的四个边之内即可.

pygame同样帮我们实现了这样的判断方法

rect1.contains(rect2)

如果rect2在rect1内,就返回True, 否则就返回False

看一下示例代码

def pygame_contains():
    pygame.init()
    s = pygame.display.set_mode((800, 600))
    rect1 = pygame.Rect(100, 100, 600, 400)
    rect2 = pygame.Rect(400, 300, 100, 100)
    GREEN = 0, 255, 0  # 绿色
    BLUE = 0, 0, 255  # 蓝色
    BLACK = 0, 0, 0  # 黑色
    pygame.draw.rect(s, BLUE, rect2)
    pygame.draw.rect(s, GREEN, rect1)

    pygame.display.update()

    while 1:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                sys.exit()
        if rect1.contains(rect2):
            print("我是无敌的")
        else:
            print("我感觉我活不久了")
        rect2.move_ip(4, 0)
        s.fill(BLACK)
        pygame.draw.rect(s, GREEN, rect1)
        pygame.draw.rect(s, BLUE, rect2)
        pygame.display.update()
        time.sleep(0.1)

效果图:
包含检测
注意观察左下角的输出内容
当蓝色矩形在绿色矩形内时,输出是无敌的.当蓝色矩形不完全在绿色矩形内时,输出是我感觉我活不久了.

关于矩形的操作,还有很多.比如,我们捡到一把枪,把枪装备到角色上,相当于把两个矩形合成了一个.pygame也帮我们实现了.
这些复杂的操作.我们在后续的内容中慢慢给到大家.

作业

自由落体

  1. 画一个棕色的扁长方形当地板
  2. 画一个蓝色小正方形(有能力的可以画球)当小球
  3. 小球自上而下.起始高度差200
  4. 每次落地后反弹高度为掉落高度的一半.直到反弹高度<5时停止
  5. 不考虑加速度.即速度在下落与反弹过程中假高是恒定的
  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
pygame提供了两种方法来实现碰撞检测。第一种方法是使用`pygame.sprite.groupcollide()`函数,该函数可以检测两个精灵组中所有精灵的碰撞。具体的函数调用形式为`pygame.sprite.groupcollide(group1, group2, dokill1, dokill2, collided=None)`。 第二种方法是使用`pygame.sprite.spritecollide()`函数,该函数可以检测一个精灵与一个精灵组中的其他精灵是否发生碰撞。具体的函数调用形式为`pygame.sprite.spritecollide(sprite, group, dokill, collided=None)`。 需要注意的是,这两种方法都需要创建精灵组并将精灵添加到组中,才能进行碰撞检测。 在实现飞机大战游戏中的碰撞检测时,可以参考一些相关的操作技巧。例如,可以使用矩形边界框来表示精灵的形状,并使用`pygame.Rect`类来管理矩形边界框。然后,使用碰撞检测方法来检测飞机与敌人飞机、子弹与敌人飞机之间的碰撞,从而触发相应的游戏逻辑。 总结起来,pygame提供了`pygame.sprite.groupcollide()`和`pygame.sprite.spritecollide()`两种方法来实现碰撞检测,可以根据具体的需求选择适合的方法来进行碰撞检测操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [(十)通过pygame来进行碰撞检测](https://blog.csdn.net/fjswcjswzy/article/details/106102953)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [python飞机大战pygame碰撞检测实现方法分析](https://download.csdn.net/download/weixin_38736018/12857108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的章老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值