好了,接着昨天的继续,今天我要实现的是游戏中各个元素的互动,这里用到的是pygame.sprite.collide_rect(firs_sprite,secend_sprite)这个函数,在pygame中提供很丰富的冲突检测方法。具体如下
pygame.sprite.collide_rect() 两个精灵间的矩形冲突检测
pygame.sprite.collide_rect.ratio()上一个函数的变种,可以提供一个参数(浮点数)对碰撞体积进行同比缩放
pygame.sprite.collide_circle()两个精灵之间的圆形检测(如果有radius属性,就使用radius,如果没有那么函数就会自己计算)
pygame.sprite.collide_circle.ratio()上一个函数的变种,可以提供一个参数(浮点数)对碰撞体积进行同比缩放
pygame.sprite.spritecollide() 精灵和组之间的矩形冲突,如果给函数传递True参数,那么所有的冲突精灵都会被删掉。
pygame.sprite.spritecollideany()上一个函数的变种,返回一个布尔值
pygame.sprite.groupcollide() 两个组之间的矩形冲突检测,这个函数返回一个字典,包含所有冲突精灵信息
我估计有写小伙伴和我一样,找了很久都没找到一个圆形,一个矩形的冲突检测函数。是的,他确实没有,我查了很多资料都没有找到。如果那个小伙伴知道的话还不吝赐教。 所以,在这里有两个选择。第一个,使用矩形冲突(当然,这基本上能够满足我们的需求),第二个,就是我们自己写一个冲突检测函数。通过查阅资料我知道了pygame的冲突检测是通过检查精灵的坐标集是否重叠来实现的。 所以,根据这个思路我开始写一个我想要的圆形和矩形之间的冲突检测,不过今天没有写完,这个函数我会单独写一篇博客的。今天先用pygame里带的矩形检测函数。
首先我们要检测的是,挡板和球之间的冲突,如果小球碰到挡板,那么小球被反弹。
def collide(first_sprite,secend_sprite):
collide = pygame.sprite.collide_rect(first_sprite,secend_sprite)
if collide:
first_sprite.valy = -first_sprite.valy
然后我们要检测的是,小球和砖块之间的冲突,如果小球碰到砖块,那么删除砖块,同时让小球反弹
def update_block(first_sprite,secend_sprite):
for sprite in secend_sprite:
collide = pygame.sprite.collide_rect(first_sprite,sprite)
if collide:
secend_sprite.remove(sprite)
first_sprite.valy = - first_sprite.valy
OK 那么这两个检测就完成了,好了,我们来看看效果。
好了 似乎还像那么回事。
到此,我们这个打砖块的游戏主题部分算是基本都实现了。接下来我会对游戏进行完善,比如添加积分系统,或者是添加更多的关卡,也或者是使用自己写的冲突检测方法让碰撞更加的精确。
好了今天就先到这里吧,源代码如下
#!usr/bin/python
#!coding=utf-8
import pygame,sys,random,math
from pygame.sprite import Sprite,Group
class Paddle(Sprite):
def __init__(self,screen):
super().__init__()
self.screen = screen
self.image = pygame.image.load('paddle.png')
self.rect = self.image.get_rect()
self.rect.bottom = 490
self.paddle_left = False
self.paddle_right = False
def update(self):
if self.paddle_left and self.rect.left > 0:
self.rect.centerx -= 8
if self.paddle_right and self.rect.right < 600:
self.rect.centerx += 8
def blitme(self):
self.screen.blit(self.image,self.rect)
class Ball(Sprite):
def __init__(self,screen,paddle):
super().__init__()
self.screen = screen
self.paddle = paddle
self.image = pygame.image.load('ball.png')
self.rect = self.image.get_rect()
self.radius = self.rect.width / 2
self.valx = 4.5
self.valy = 2
self.start = False
def update(self):
if self.start is False:
self.rect.bottom = self.paddle.rect.top
self.rect.centerx = self.paddle.rect.centerx
elif self.start is True:
self.rect.x += self.valx
self.rect.y += self.valy
if self.rect.right >= 600 or self.rect.left <= 0:
self.valx = -self.valx
elif self.rect.top <= 0 :
self.valy = -self.valy
def blitme(self):
self.screen.blit(self.image,self.rect)
class Block(Sprite):
def __init__(self,screen):
super().__init__()
self.screen = screen
self.mast_image = pygame.image.load('Block.png')
self.rect = self.mast_image.get_rect()
self.frame_rect = self.rect.copy()
self.frame_rect.width = self.frame_rect.width / 4
self.frame_rect.height = self.frame_rect.height / 2
self.frame = 0
self.last_frame = 7
self.level_01 = (1,3,3,3,1
,4,1,5,1,4
,4,1,0,1,4
,4,1,5,1,4
,1,3,3,3,1)
self.level = self.level_01
def update(self):
self.frame_rect.x = self.frame % 4 * self.frame_rect.width
self.frame_rect.y = self.frame // 4 * self.frame_rect.height
self.image = self.mast_image.subsurface(self.frame_rect)
self.rect = self.frame_rect
self.rect.x = 0
self.rect.y = 0
def blitme(self):
self.screen.blit(self.block_image,self.rect)
def collide(first_sprite,secend_sprite):
collide = pygame.sprite.collide_rect(first_sprite,secend_sprite)
if collide:
first_sprite.valy = -first_sprite.valy
def update_block(first_sprite,secend_sprite):
for sprite in secend_sprite:
collide = pygame.sprite.collide_rect(first_sprite,sprite)
if collide:
secend_sprite.remove(sprite)
first_sprite.valy = - first_sprite.valy
pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption('打方块')
paddle = Paddle(screen)
block = Block(screen)
blocks = Group()
ball = Ball(screen,paddle)
for pos in block.level:
block_wall = Block(screen)
block_wall.frame = pos
block_wall.update()
blocks.add(block_wall)
x = 0
y = 0
for bx in blocks:
bx.rect.x += (x+50)
x += 100
bx.rect.y += (y+30)
if bx.rect.x >= 400:
y += 20
x = 0
timer = pygame.time.Clock()
while True:
timer.tick(50)
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
paddle.paddle_left = True
elif event.key == pygame.K_RIGHT:
paddle.paddle_right = True
elif event.key == pygame.K_SPACE:
ball.start = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
paddle.paddle_left = False
if event.key == pygame.K_RIGHT:
paddle.paddle_right = False
screen.fill((224,255,255))
paddle.update()
collide(ball,paddle)
update_block(ball,blocks)
ball.update()
ball.blitme()
paddle.blitme()
blocks.draw(screen)
pygame.display.flip()