pygame学习手册(三):精灵与碰撞检测

第一部分写的对打乒乓是用像素进行碰撞判定的,这样会导致有许多的问题,这次我们改用精灵(Sprite)来修改pygame学习手册(一) 中的内容。

继承pygame.sprite.Sprite

首先要创建一个自己的精灵类,把修改精灵坐标的方法封装一下,方便外界调用。

class MySprite(pygame.sprite.Sprite):
    def __init__(self, image):
        pygame.sprite.Sprite.__init__(self) 
        #图片可以使用pygame.image.load("filename").convert_alpha()
        self.image = image
        #rect 最好使用 Rect(x,y,width,height)来创建
        self.rect = image.get_rect()
    #X 属性
    def _getx(self): return self.rect.x
    def _setx(self,value): self.rect.x = value
    X = property(_getx,_setx)

    #Y 属性
    def _gety(self): return self.rect.y
    def _sety(self,value): self.rect.y = value
    Y = property(_gety,_sety)

    #position 属性
    def _getpos(self): return self.rect.topleft
    def _setpos(self,pos): self.rect.topleft = pos
    position = property(_getpos,_setpos)    

碰撞检测有

两个精灵之间的矩形检测

pygame.sprite.collide_rect(first, second) #返回布尔值

精灵与组之间的矩形检测

#第一个参数是精灵,
#第二个参数是精灵组,
#第三个参数为True,则碰撞检测后,组中所有碰撞的精灵被删除
#返回 组中被碰撞的精灵
collide_list = pygame.sprite.spritecollide(sprite,group,False)

两个组之间的矩形检测

#前两个参数都是组
#后两个参数,代表发生碰撞时,是否删除精灵
#该函数返回一个字典
#第一个组中的每一个精灵都会添加到字典中
#第二组中与之碰撞的精灵会添加到字典相应的条目中
hit_list = pygame.sprite.groupcollide(group1,group2,True,False)

人机乒乓

#作者:znw
#日期:2018年8月17日

import sys, time, random, math, pygame
from pygame.locals import *

class MySprite(pygame.sprite.Sprite):
    def __init__(self, image):
        pygame.sprite.Sprite.__init__(self) #extend the base Sprite class
        self.image = image
        self.rect = image.get_rect()
    #X 属性
    def _getx(self): return self.rect.x
    def _setx(self,value): self.rect.x = value
    X = property(_getx,_setx)

    #Y 属性
    def _gety(self): return self.rect.y
    def _sety(self,value): self.rect.y = value
    Y = property(_gety,_sety)

    #position 属性
    def _getpos(self): return self.rect.topleft
    def _setpos(self,pos): self.rect.topleft = pos
    position = property(_getpos,_setpos)    

#打印文字
def print_text(font, x, y, text, color=(255,255,255)):
    imgText = font.render(text, True, color)
    screen.blit(imgText, (x,y))

pygame.init()
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption("人机乒乓"")

#设置游戏帧数
framerate = pygame.time.Clock()
font = pygame.font.Font(None, 18)

#创建两个精灵组
group_player = pygame.sprite.Group()
group_ball = pygame.sprite.Group()


#创建玩家精灵
#player.png是一个10X50像素的白色方块
playerimg = pygame.image.load("player.png").convert_alpha()
player1 = MySprite(playerimg)
#设置玩家一初始位置
player1.position = (100,100)
group_player.add(player1)

player2 = MySprite(playerimg)
player2.position = (500,300)
group_player.add(player2)

#ball.png是一个10x10的白色方块
ballimg = pygame.image.load("ball.png").convert_alpha()
ball = MySprite(ballimg)
ball.position = 400,300
group_ball.add(ball)

#球的速度
ball_vel_x = 2
ball_vel_y = 1
#玩家的速度
player_vel_x = 3
player_vel_y = 2

#看看是不是找到了对的终点,AI用
right_target = False
#Ai计算小球到达墙壁需要多少时间
move_time = 0
while True:
    framerate.tick(60)
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == MOUSEMOTION:
            player1.position = event.pos
    screen.fill((0,0,0))
    #默认电脑在右边
    if ball_vel_x > 0 and not right_target:
        move_time = (790-ball.X)//ball_vel_x
        #从小球运动的路线上随机选取一个时间
        target_time = random.randint(1,move_time)
        #计算落点
        end_pos_x = ball.X + ball_vel_x * target_time
        end_pos_y = ball.Y + ball_vel_y * target_time
        if end_pos_y > 600:
            end_pos_y = 1200 - end_pos_y
        elif end_pos_y < 0:
            end_pos_y = -end_pos_y    
        right_target = True

    #让电脑玩家前往它选定的落点
    if ball_vel_x < 0 \
        or player2.Y < end_pos_y < player2.Y \
        and player2.X < end_pos_x < player2.X:
        pass
    else:
        if player2.Y < 0 :
            player2.position = (player2.X,0)
        elif player2.Y > 550:
            player2.position = (player2.X,550)
        if player2.X < 400:
            player2.position = (400,player2.Y)
        elif player2.X > 790:
            player2.position = (790,player2.Y)
        else:
            if player2.Y - end_pos_y > 0:
                player2.Y -= player_vel_y
            else:
                player2.Y += player_vel_y
            if player2.X - end_pos_x > 0:
                player2.X -= player_vel_x
            else:
                player2.X += player_vel_x
    #保证小球落在屏幕内
    if ball.X > 790 or ball.X < 0 :
        ball_vel_x = -ball_vel_x
    if ball.Y > 590 or ball.Y < 0 :
        ball_vel_y = -ball_vel_y
    #检测小球是否和玩家碰撞,碰撞则反向
    if pygame.sprite.spritecollide(ball, group_player, False):
        right_target = False
        ball_vel_x = -ball_vel_x
    #移动小球
    ball.X += ball_vel_x
    ball.Y += ball_vel_y

    #打印电脑玩家选择的落点
    print_text(font,5,5,str(end_pos_x)+","+str(end_pos_y))

    #画
    group_player.draw(screen)
    group_ball.draw(screen)
    pygame.display.update()       

当时这个游戏仍然有很多问题,就希望读者自己去完善了。

  • 10
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值