python中的pygame小练习(3)碰撞精灵和碰撞检测

    技术2025-06-15  16

    五个小球随机出现,随机速度,在窗口中乱逛。

    import pygame import sys from pygame.locals import * from random import * class Ball(pygame.sprite.Sprite): #这是pygame的碰撞基类,继承就行了 def __init__(self, image, position,speed, bg_size): #球的图片,球的位置,球的速度 pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(image).convert_alpha() #加载 图片进来 self.rect = self.image.get_rect() #球的矩形判断框就是 图片的 位置 self.rect.left, self.rect.top = position self.speed = speed self.width, self.height = bg_size[0], bg_size[1] def move(self): self.rect = self.rect.move(self.speed) if self.rect.right < 0: #图片右侧 小于0,到了最左了 self.rect.left = self.width #图片左侧等于窗口右边框 elif self.rect.left > self.width: #图片左侧大于窗口宽度,到了最右了 self.rect.right = 0 #图片右侧等于0,放到窗口最左边 elif self.rect.bottom< 0: #图片顶端过高 self.rect.top = self.height #放到最下面 elif self.rect.top > self.height: #图片底端过低 self.rect.bottom = 0 def main(): pygame.init() ball_image = "images/gray_ball.png" bg_image = "images/background2.jpg" running = True bg_size = width,height = 1366, 768 screen = pygame.display.set_mode(bg_size) #窗口 大小就是背景图片大小 pygame.display.set_caption(" Play the ball") background = pygame.image.load(bg_image).convert_alpha() balls = [] #球集合 for i in range(5): position = randint(0, width-100), randint(0, height-100) #随机位置 speed = [randint(-10, 10), randint(-10, 10)] #随机速度 ball = Ball(ball_image, position, speed,bg_size) #球是ball类,参数是图片,位置,速度,也就是 ball的init 函数 balls.append(ball) clock = pygame.time.Clock() while running: for event in pygame.event.get(): if event.type == QUIT: sys.exit() screen.blit(background, (0, 0)) for each in balls: each.move() screen.blit(each.image, each.rect) pygame.display.flip() clock.tick(30) if __name__ == "__main__": main()

    结果: 检测

    import pygame import sys import math from pygame.locals import * from random import * class Ball(pygame.sprite.Sprite): #这是pygame的碰撞基类,继承就行了 def __init__(self, image, position,speed, bg_size): #球的图片,球的位置,球的速度 pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(image).convert_alpha() #加载 图片进来 self.rect = self.image.get_rect() #球的矩形判断框就是 图片的 位置 self.rect.left, self.rect.top = position self.speed = speed self.width, self.height = bg_size[0], bg_size[1] def move(self): self.rect = self.rect.move(self.speed) if self.rect.right < 0: #图片右侧 小于0,到了最左了 self.rect.left = self.width #图片左侧等于窗口右边框 elif self.rect.left > self.width: #图片左侧大于窗口宽度,到了最右了 self.rect.right = 0 #图片右侧等于0,放到窗口最左边 elif self.rect.bottom< 0: #图片顶端过高 self.rect.top = self.height #放到最下面 elif self.rect.top > self.height: #图片底端过低 self.rect.bottom = 0 #碰撞检测,距离小于半径之和的时候就是碰撞了 def collide_check(item, target): #参数是本球,其他球列表 col_balls = [] #与item发生碰撞的其他小球,如果空说明没有发生碰撞 for each in target: distance = math.sqrt(math.pow((item.rect.center[0] - each.rect.center[0]), 2) + \ math.pow((item.rect.center[1] - each.rect.center[1]), 2)) if distance <= (item.rect.width + each.rect.width) / 2: col_balls.append(each) return col_balls def main(): pygame.init() ball_image = "images/gray_ball.png" bg_image = "images/background2.jpg" running = True bg_size = width,height = 1366, 768 screen = pygame.display.set_mode(bg_size) #窗口 大小就是背景图片大小 pygame.display.set_caption(" Play the ball") background = pygame.image.load(bg_image).convert_alpha() balls = [] #球集合 #创建5个小球 ball_number = 5 for i in range(ball_number): position = randint(0, width-100), randint(0, height-100) #随机位置 speed = [randint(-10, 10), randint(-10, 10)] #随机速度 ball = Ball(ball_image, position, speed,bg_size) #球是ball类,参数是图片,位置,速度,也就是 ball的init 函数 while collide_check(ball, balls): ball.rect.left, ball.position = randint(0, width-100), randint(0, height) balls.append(ball) clock = pygame.time.Clock() while running: for event in pygame.event.get(): if event.type == QUIT: sys.exit() screen.blit(background, (0, 0)) for each in balls: each.move() screen.blit(each.image, each.rect) #检测小球 for i in range(ball_number): item = balls.pop(i) if collide_check(item, balls): item.speed[0] = -item.speed[0] item.speed[1] = -item.speed[1] balls.insert(i, item) pygame.display.flip() clock.tick(30) if __name__ == "__main__": main()

    上面这些都是练习,只是实现了圆的碰撞检测,没有多边形。 其实有个碰撞检测函数,继承pygame.sprite.Sprite碰撞基类,就是为了调用这个函数。 用于检测某个精灵,与某个精灵组中的其他精灵发生碰撞。 spritecollide(sprite, group, dokill, collided = None) sprite:指定被检测的精灵; group:待检测的精灵组,由sprite.Group()生成; dokill:设置是否从组中删除检测到碰撞的精灵,True为删除 ; collided:指定一个回调函数,用于定特殊的检测方法,如果忽略的话,默认检测精灵之间的right属性。 例:

    import pygame import sys from pygame.locals import * from random import * class Ball(pygame.sprite.Sprite): #这是pygame的碰撞基类,继承就行了 def __init__(self, image, position,speed, bg_size): #球的图片,球的位置,球的速度 pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(image).convert_alpha() #加载 图片进来 self.rect = self.image.get_rect() #球的矩形判断框就是 图片的 位置 self.rect.left, self.rect.top = position self.speed = speed self.width, self.height = bg_size[0], bg_size[1] def move(self): self.rect = self.rect.move(self.speed) if self.rect.right < 0: #图片右侧 小于0,到了最左了 self.rect.left = self.width #图片左侧等于窗口右边框 elif self.rect.left > self.width: #图片左侧大于窗口宽度,到了最右了 self.rect.right = 0 #图片右侧等于0,放到窗口最左边 elif self.rect.bottom< 0: #图片顶端过高 self.rect.top = self.height #放到最下面 elif self.rect.top > self.height: #图片底端过低 self.rect.bottom = 0 def main(): pygame.init() ball_image = "images/gray_ball.png" bg_image = "images/background2.jpg" running = True bg_size = width,height = 1366, 768 screen = pygame.display.set_mode(bg_size) #窗口 大小就是背景图片大小 pygame.display.set_caption(" Play the ball") background = pygame.image.load(bg_image).convert_alpha() balls = [] #球集合 group = pygame.sprite.Group() # 创建碰撞检测函数适用的group for i in range(5): position = randint(0, width-100), randint(0, height-100) #随机位置 speed = [randint(-10, 10), randint(-10, 10)] #随机速度 ball = Ball(ball_image, position, speed,bg_size) #球是ball类,参数是图片,位置,速度,也就是 ball的init 函数 while pygame.sprite.spritecollide(ball, group, False): ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100) balls.append(ball) group.add(ball) clock = pygame.time.Clock() while running: for event in pygame.event.get(): if event.type == QUIT: sys.exit() screen.blit(background, (0, 0)) for each in balls: each.move() screen.blit(each.image, each.rect) for each in group: group.remove(each) if pygame.sprite.spritecollide(each, group, False): each.speed[0] = -each.speed[0] each.speed[1] = -each.speed[1] group.add(each) pygame.display.flip() clock.tick(30) if __name__ == "__main__": main()

    但这检测的是两个矩形的碰撞,但我们的是小球,有的碰撞就会看起来明明没撞就算成撞了,这样不好 。 修改这个问题可以用到 collide_circle(left, right)

    import pygame import sys from pygame.locals import * from random import * class Ball(pygame.sprite.Sprite): #这是pygame的碰撞基类,继承就行了 def __init__(self, image, position,speed, bg_size): #球的图片,球的位置,球的速度 pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(image).convert_alpha() #加载 图片进来 self.rect = self.image.get_rect() #球的矩形判断框就是 图片的 位置 #将小球放到指定位置 self.rect.left, self.rect.top = position self.speed = speed self.width, self.height = bg_size[0], bg_size[1] #定义小球半径 self.radius = self.rect.width / 2 #移动到边框 def move(self): self.rect = self.rect.move(self.speed) if self.rect.right < 0: #图片右侧 小于0,到了最左了 self.rect.left = self.width #图片左侧等于窗口右边框 elif self.rect.left > self.width: #图片左侧大于窗口宽度,到了最右了 self.rect.right = 0 #图片右侧等于0,放到窗口最左边 elif self.rect.bottom< 0: #图片顶端过高 self.rect.top = self.height #放到最下面 elif self.rect.top > self.height: #图片底端过低 self.rect.bottom = 0 def main(): pygame.init() ball_image = "images/gray_ball.png" bg_image = "images/background2.jpg" running = True bg_size = width,height = 1366, 768 screen = pygame.display.set_mode(bg_size) #窗口 大小就是背景图片大小 pygame.display.set_caption(" Play the ball") background = pygame.image.load(bg_image).convert_alpha() balls = [] #球集合 group = pygame.sprite.Group() # 创建碰撞检测函数适用的group for i in range(5): position = randint(0, width-100), randint(0, height-100) #随机位置 speed = [randint(-10, 10), randint(-10, 10)] #随机速度 ball = Ball(ball_image, position, speed,bg_size) #球是ball类,参数是图片,位置,速度,也就是 ball的init 函数 while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle): ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100) balls.append(ball) group.add(ball) clock = pygame.time.Clock() while running: for event in pygame.event.get(): if event.type == QUIT: sys.exit() screen.blit(background, (0, 0)) for each in balls: each.move() screen.blit(each.image, each.rect) for each in group: group.remove(each) if pygame.sprite.spritecollide(each, group, False,pygame.sprite.collide_circle): each.speed[0] = -each.speed[0] each.speed[1] = -each.speed[1] group.add(each) pygame.display.flip() clock.tick(30) if __name__ == "__main__": main()

    素材(随便找的):

    Processed: 0.012, SQL: 9