pygame游戏精灵(上)-碰撞检测

Python
321
0
0
2022-10-11
pygame.sprite 模块是属于pygame进阶的内容,通常应用于比较复杂的游戏,或者说游戏角色比较多的游戏。通过它可以很好的管理游戏角色,比如游戏角色的碰撞检测,游戏角色的增加与删除等。


常用方法

pygame.sprite 模块包含很多的类以及一些方法。常使用的有:

1.精灵类

  • pygame.sprite.Sprite() 单个游戏对象类
  • pygame.sprite.Group() 多个游戏对象类

2.两个精灵碰撞检测方法

  • pygame.sprite.collide_rect() 矩形检测
  • pygame.sprite.collide_circle() 圆形检测
  • pygame.sprite.collide_mask() 像素检测

3.多个精灵碰撞检测方法

...


创建精灵对象

比如以非面向对象的方式创建一个圣诞帽游戏角色和糖果角色:

img

圣诞帽精灵

# 利用精灵类生成一个hat对象
hat = pygame.sprite.Sprite()
# 给hat对象添加一个image属性,同时赋值为一个圣诞帽surface对象
hat.image = pygame.image.load('hat.png')
# 给hat对象添加一个rect属性,同时赋值为一个rect元组
hat.rect = hat.image.get_rect()
# 渲染 hat到屏幕上
screen.blit(hat.image, hat.rect)

糖果精灵

# 利用精灵类生成一个candy对象
candy = pygame.sprite.Sprite()
# 给candy对象添加一个image属性,同时赋值为一个糖果surface对象
candy.image = pygame.image.load('candy.png')
# 给candy对象添加一个rect属性,同时赋值为一个rect元组
candy.rect = candy.image.get_rect()
# 渲染 candy 到屏幕上
screen.blit(candy.image,candy.rect)


demo

import pygame
import sys
import math

# 初始化pygame
pygame.init()
# 设置窗口的大小,单位为像素
screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption('标题')

hat = pygame.sprite.Sprite()
hat.image = pygame.image.load('hat.png')
hat.rect = hat.image.get_rect()

candy = pygame.sprite.Sprite()
candy.image = pygame.image.load('candy.png')
candy.rect = candy.image.get_rect()
candy.rect = candy.rect.move(400,400)

clock = pygame.time.Clock()
# 程序主循环
while True:
    # 事件处理 
    for event in pygame.event.get():
        # 判断事件是否为退出事件 
        if event.type == pygame.QUIT:
            # 退出pygame
            pygame.quit()
            # 退出系统
            sys.exit()

    screen.fill((0, 0, 80))
    screen.blit(hat.image, hat.rect)
    screen.blit(candy.image,candy.rect)

    pygame.display.update()
    clock.tick(30)

img


让帽子动起来

同时让x,y坐标改变

hat.rect = hat.rect.move(1,1)

完整代码

import pygame
import sys
import math

# 初始化pygame
pygame.init()
# 设置窗口的大小,单位为像素
screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption('标题')

hat = pygame.sprite.Sprite()
hat.image = pygame.image.load('hat.png')
hat.rect = hat.image.get_rect()

candy = pygame.sprite.Sprite()
candy.image = pygame.image.load('candy.png')
candy.rect = candy.image.get_rect()
candy.rect = candy.rect.move(400,400)

clock = pygame.time.Clock()
# 程序主循环
while True:
    # 事件处理 
    for event in pygame.event.get():
        # 判断事件是否为退出事件 
        if event.type == pygame.QUIT:
            # 退出pygame
            pygame.quit()
            # 退出系统
            sys.exit()

    hat.rect = hat.rect.move(1,1)

    screen.fill((0, 0, 80))
    screen.blit(hat.image, hat.rect)
    screen.blit(candy.image,candy.rect)

    pygame.display.update()
    clock.tick(30)

img


加上矩形边框

import pygame
import sys
import math

# 初始化pygame
pygame.init()
# 设置窗口的大小,单位为像素
screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption('标题')

hat = pygame.sprite.Sprite()
hat.image = pygame.image.load('hat.png')
hat.rect = hat.image.get_rect()

candy = pygame.sprite.Sprite()
candy.image = pygame.image.load('candy.png')
candy.rect = candy.image.get_rect()
candy.rect = candy.rect.move(400,400)

clock = pygame.time.Clock()
# 程序主循环
while True:
    # 事件处理 
    for event in pygame.event.get():
        # 判断事件是否为退出事件 
        if event.type == pygame.QUIT:
            # 退出pygame
            pygame.quit()
            # 退出系统
            sys.exit()

    hat.rect = hat.rect.move(1,1)

    screen.fill((0, 0, 80))
    screen.blit(hat.image, hat.rect)
    screen.blit(candy.image,candy.rect)
    # 矩形框
    pygame.draw.rect(screen,(255,0,0),hat.rect,1)
    pygame.draw.rect(screen, (255, 0, 0), candy.rect, 1)

    pygame.display.update()
    clock.tick(30)

img

img

矩形碰撞检测

pygame.sprite.collide_rect 方法用于检测两个精灵是否有碰到,没碰到result返回0,碰到返回1.

result = pygame.sprite.collide_rect(hat,candy)

img

import pygame
import sys
import math

# 初始化pygame
pygame.init()
# 设置窗口的大小,单位为像素
screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption('标题')

hat = pygame.sprite.Sprite()
hat.image = pygame.image.load('hat.png')
hat.rect = hat.image.get_rect()

candy = pygame.sprite.Sprite()
candy.image = pygame.image.load('candy.png')
candy.rect = candy.image.get_rect()
candy.rect = candy.rect.move(400,400)

clock = pygame.time.Clock()
# 程序主循环
while True:
    # 事件处理 
    for event in pygame.event.get():
        # 判断事件是否为退出事件 
        if event.type == pygame.QUIT:
            # 退出pygame
            pygame.quit()
            # 退出系统
            sys.exit()

    hat.rect = hat.rect.move(1,1)

    # 矩形检测
    result = pygame.sprite.collide_rect(hat,candy)
    print(result,type(result))

    screen.fill((0, 0, 80))
    screen.blit(hat.image, hat.rect)
    screen.blit(candy.image,candy.rect)
    # 矩形框
    pygame.draw.rect(screen,(255,0,0),hat.rect,1)
    pygame.draw.rect(screen, (255, 0, 0), candy.rect, 1)

    pygame.display.update()
    clock.tick(30)


圆形碰撞检测

pygame.sprite.collide_circle 方法用于检测两个精灵是否有碰到,没碰到result返回False,碰到返回True.

img

import pygame
import sys
import math

# 初始化pygame
pygame.init()
# 设置窗口的大小,单位为像素
screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption('标题')

hat = pygame.sprite.Sprite()
hat.image = pygame.image.load('hat.png')
hat.rect = hat.image.get_rect()

candy = pygame.sprite.Sprite()
candy.image = pygame.image.load('candy.png')
candy.rect = candy.image.get_rect()
candy.rect = candy.rect.move(400,400)

clock = pygame.time.Clock()
# 程序主循环
while True:
    # 事件处理 
    for event in pygame.event.get():
        # 判断事件是否为退出事件 
        if event.type == pygame.QUIT:
            # 退出pygame
            pygame.quit()
            # 退出系统
            sys.exit()

    hat.rect = hat.rect.move(1,1)

    # 矩形检测 
    # result = pygame.sprite.collide_rect(hat,candy) 
    # print(result,type(result)) 
    # 圆形检测
    result = pygame.sprite.collide_circle(hat, candy)
    print(result, type(result))

    screen.fill((0, 0, 80))
    screen.blit(hat.image, hat.rect)
    screen.blit(candy.image,candy.rect)
    # 矩形框
    pygame.draw.rect(screen,(255,0,0),hat.rect,1)
    pygame.draw.rect(screen, (255, 0, 0), candy.rect, 1)
    # 外接圆形框
    pygame.draw.circle(screen,(255,0,0),hat.rect.center,math.sqrt((hat.rect.width//2)**2+(hat.rect.height//2)**2),1)
    pygame.draw.circle(screen, (255, 0, 0), candy.rect.center,math.sqrt((candy.rect.width//2)**2+(candy.rect.height//2)**2), 1)

    pygame.display.update()
    clock.tick(30)


像素碰撞检测

pygame.sprite.collide_mask 方法用于检测两个精灵是否有碰到,没碰到result返回None,碰到返回碰撞点坐标。

img

像素碰撞检测可以解决那些不规矩的游戏角色,比例有些有些素材有边框等。

import pygame
import sys
import math

# 初始化pygame
pygame.init()
# 设置窗口的大小,单位为像素
screen = pygame.display.set_mode((800, 600))
# 设置窗口标题
pygame.display.set_caption('标题')

hat = pygame.sprite.Sprite()
hat.image = pygame.image.load('hat.png')
hat.rect = hat.image.get_rect()

candy = pygame.sprite.Sprite()
candy.image = pygame.image.load('candy.png')
candy.rect = candy.image.get_rect()
candy.rect = candy.rect.move(400,400)

clock = pygame.time.Clock()
# 程序主循环
while True:
    # 事件处理 
    for event in pygame.event.get():
        # 判断事件是否为退出事件 
        if event.type == pygame.QUIT:
            # 退出pygame
            pygame.quit()
            # 退出系统
            sys.exit()

    hat.rect = hat.rect.move(1,1)

    # 矩形检测 
    # result = pygame.sprite.collide_rect(hat,candy) 
    # print(result,type(result)) 
    # 圆形检测 
    # result = pygame.sprite.collide_circle(hat, candy) 
    # print(result, type(result)) 
    # 像素检测
    result = pygame.sprite.collide_mask(hat, candy)
    print(result, type(result))
    screen.fill((0, 0, 80))
    screen.blit(hat.image, hat.rect)
    screen.blit(candy.image,candy.rect)
    # 矩形框
    pygame.draw.rect(screen,(255,0,0),hat.rect,1)
    pygame.draw.rect(screen, (255, 0, 0), candy.rect, 1)
    # 外接圆形框
    pygame.draw.circle(screen,(255,0,0),hat.rect.center,math.sqrt((hat.rect.width//2)**2+(hat.rect.height//2)**2),1)
    pygame.draw.circle(screen, (255, 0, 0), candy.rect.center,math.sqrt((candy.rect.width//2)**2+(candy.rect.height//2)**2), 1)

    pygame.display.update()
    clock.tick(30)

能够检测碰撞到后,后面就可以使用精灵组管理那些精灵显示和消失。

更多内容请看官方文档:

https://www.pygame.org/docs/ref/sprite.html

(全文完)