笑脸与挡板的碰撞检测
这里我们需要检查笑脸的底部中心刚好碰到挡板的左边一角和右边一角的临界状态,除此之外我们还要确定笑脸的y坐标也要在垂直的范围之内。
竖直方向
我们假设一个临界状态——笑脸底部和挡板顶部刚好接触:
pic_y + pic.get_height() = paddle_y
即笑脸距离屏幕顶部的距离加上笑脸的高度正好等于挡板距离屏幕顶部的距离。
还有一个临界状态——笑脸继续向下运动,笑脸的底部正好和挡板的底部重合接触:
pic_y + pic.get_height() = paddle_y + paddle_height
即笑脸距离屏幕顶部的距离加上笑脸的高度正好等于挡板距离屏幕顶部的距离加上挡板自身的高度。所以,我们可以控制笑脸在竖直方向的位置变化:
if pic_y + pic.get_height() >= paddle_y and pic_y + pic.get_height() <=
paddle_y + paddle_height:
如果没有第二个条件的限制,笑脸将会到达屏幕的底端,接着会继续反弹上来,但是我们不想这样,这样触碰到挡板是无效的,不能计算用户的得分。
还有一点就是,我们还要保证笑脸的竖直方向的速度是大于0的,即笑脸是朝下运动的。这样可以避免我们漏掉一个球之后,再次反弹时触碰到挡板。
speedy > 0
所以竖直方向的条件判断:
if pic_y + pic.get_height() >= paddle_y and pic_y + pic.get_height() <=
paddle_y + paddle_height and speedy > 0:
注意:斜杠字符“”运行我们将太长的代码折返到下一行。
水平方向——挡板左边
假设一个临界状态——笑脸的底部中心刚好在挡板的左上一角:
pic_x + pic.get_width()/2 = paddle_x
即笑脸距离屏幕左边的距离加上自身宽度的一半正好等于挡板距离屏幕左边的距离。
当笑脸往左或往右,这个临界状态都会被打破。
当笑脸往左的时候,pic_x在变小:
pic_x + pic.get_width()/2 < paddle_x
这样笑脸就不会碰到挡板了。
当笑脸往右的时候,pic_x在变大:
pic_x + pic.get_width()/2 > paddle_x
这样还是可以保证笑脸和挡板发生碰撞。
所以水平方向——左边的判断条件:
if pic_x + pic.get_width()/2 >= paddle_x:
假设一个临界状态——笑脸底部中心刚好处在挡板右上角:
pic_x + pic.get_width()/2 = paddle_x + paddle_width
即笑脸距离屏幕左边的距离加上自身宽度的一半正好等于挡板距离屏幕左边的距离加上挡板的宽度。
当笑脸往左或往右,这个临界状态同样都会被打破。
当笑脸往左的时候,pic_x在变小:
pic_x + pic.get_width()/2 < paddle_x + paddle_width
这样笑脸还是可以触碰到挡板的。
当笑脸往右的时候,pic_x在变大:
pic_x + pic.get_width()/2 > paddle_x + paddle_width
这样的话笑脸就离开了挡板,不会发生碰撞。
所以水平方向——右边的判断条件:
if pic_x + pic.get_width()/2 <= paddle_x + paddle_width
综合挡板左右两边的临界判断,最终水平方向的条件判断为:
if pic_x + pic.get_width()/2 >= paddle_x and pic_x + pic.get_width()/2
<= paddle_x + paddle_width:
所以,挡板和笑脸的碰撞判断完整代码:
import pygame # 导入模块
from pygame.locals import *
pygame.init() # 初始化模块
screen = pygame.display.set_mode((800,600)) # 创建一个Surface对象窗口
pygame.display.set_caption("Pong游戏") # 设置标题
keep_going = True # 循环标志
BLACK = (0,0,0)
clock = pygame.time.Clock()
# 挡板
WHITE = (255,255,255)
paddle_width = 200 # 挡板宽度
paddle_height = 25 # 挡板高度
paddle_x = 300 # 挡板left属性
paddle_y = 550 # 挡板top属性
# 笑脸图片
pic = pygame.image.load("Smile.bmp").convert_alpha()
colorkey = pic.get_at((0,0))
pic.set_colorkey(colorkey)
# 速度和位置
speedx = 5
speedy = 5
pic_x = 0
pic_y = 0
while keep_going:
for event in pygame.event.get():
if event.type == QUIT:
keep_going = False
pic_x += speedx
pic_y += speedy
# 墙壁碰撞检测
if pic_x <= 0 or pic_x + pic.get_width() >= 800:
speedx = - speedx
if pic_y <= 0 or pic_y + pic.get_height() >= 600:
speedy = -speedy
screen.fill(BLACK) # 填充背景
# 绘制挡板
paddle_x = pygame.mouse.get_pos()[0]
paddle_x -= paddle_width/2
pygame.draw.rect(screen,WHITE,(paddle_x,paddle_y,paddle_width,paddle_height))
# 绘制笑脸图片
screen.blit(pic,(pic_x,pic_y))
# 笑脸和挡板碰撞检测
if pic_y + pic.get_height() >= paddle_y and pic_y + pic.get_height() <=
paddle_y + paddle_height and speedy > 0:
if pic_x + pic.get_width()/2 >= paddle_x and pic_x + pic.get_width()/2
<= paddle_x + paddle_width:
speedy = -speedy
pygame.display.flip()
clock.tick(60) # 设置帧速率
pygame.quit()
自己可以动手尝试下,后面我们将加入游戏计分机制。
谢谢大家的关注与支持,有不足的地方欢迎指正和交流!
更多内容可以关注微信公众号【陪孩子一起学编程】
http://weixin.qq.com/r/hymfhyjEF3VorWzk93yV (二维码自动识别)