Pygame碰撞檢測


學習自小甲魚視頻教學(筆記)

功能實現:

在隨機位置生成若干個小球以隨機速度運動;

若小球運動出左邊界則從右邊界進入,上下邊界同理;

若兩小球相碰撞則都以相反速度運動分開。

 

代碼如下:

1.嘗試自己寫碰撞檢測函數(對比兩球之間的圓心距離和半徑即可)。

 

  1 import pygame
  2 import sys
  3 import math
  4 from pygame.locals import *
  5 from random import *
  6 
  7 
  8 # 面向對象的編程方法,定義一個球的類型
  9 class Ball(pygame.sprite.Sprite):
 10     def __init__(self, image, position, speed, bg_size):
 11         # 初始化動畫精靈
 12         pygame.sprite.Sprite.__init__(self)
 13 
 14         self.image = pygame.image.load(image).convert_alpha()
 15         self.rect = self.image.get_rect()
 16         # 將小球放在指定位置
 17         self.rect.left, self.rect.top = position
 18         self.speed = speed
 19         self.width, self.height = bg_size[0], bg_size[1]
 20 
 21     # 定義一個移動的方法
 22     def move(self):
 23         self.rect = self.rect.move(self.speed)
 24         # 如果小球的左側出了邊界,那么將小球左側的位置改為右側的邊界
 25         # 這樣便實現了從左邊進入,右邊出來的效果
 26         if self.rect.right < 0:
 27             self.rect.left = self.width
 28         if self.rect.left > self.width:
 29             self.rect.right = 0
 30         if self.rect.bottom < 0:
 31             self.rect.top = self.height
 32         if self.rect.top > self.height:
 33             self.rect.bottom = 0
 34 
 35 
 36 def collide_check(item, target):
 37     col_balls = []
 38     for each in target:
 39         distance = math.sqrt(
 40             math.pow((item.rect.center[0] - each.rect.center[0]), 2) +
 41             math.pow((item.rect.center[1] - each.rect.center[1]), 2))
 42         if distance <= (item.rect.width + each.rect.width) / 2:
 43             col_balls.append(each)
 44 
 45     return col_balls
 46 
 47 
 48 def main():
 49     pygame.init()
 50 
 51     ball_image = 'ball.png'
 52     bg_image = 'background.png'
 53     running = True
 54 
 55     # 根據背景圖片指定游戲界面尺寸
 56     bg_size = width, height = 1024, 500
 57     screen = pygame.display.set_mode(bg_size)
 58     pygame.display.set_caption('Collision Spheres')
 59 
 60     background = pygame.image.load(bg_image).convert_alpha()
 61 
 62     # 用來存放小球對象的列表
 63     balls = []
 64 
 65     # 創建6個位置隨機,速度隨機的小球
 66     BALL_NUM = 6
 67     for i in range(BALL_NUM):
 68         position = randint(0, width - 70), randint(0, height - 70)
 69         speed = [randint(1, 6), randint(1, 6)]
 70         ball = Ball(ball_image, position, speed, bg_size)
 71         while collide_check(ball, balls):
 72             ball.rect.left, ball.rect.top = randint(0, width - 70), randint(0, height - 70)
 73 
 74         balls.append(ball)
 75 
 76     clock = pygame.time.Clock()
 77 
 78     while running:
 79         for event in pygame.event.get():
 80             if event.type == QUIT:
 81                 sys.exit()
 82 
 83         screen.blit(background, (0, 0))
 84 
 85         for each in balls:
 86             each.move()
 87             screen.blit(each.image, each.rect)
 88 
 89         for i in range(BALL_NUM):
 90             item = balls.pop(i)
 91 
 92             if collide_check(item, balls):
 93                 item.speed[0] = -item.speed[0]
 94                 item.speed[1] = -item.speed[1]
 95 
 96             balls.insert(i, item)
 97 
 98         pygame.display.flip()
 99         clock.tick(60)
100 
101 
102 if __name__ == '__main__':
103     main()
View Code

 

2.使用sprite模塊提供的碰撞檢測函數。

 

sprite 模塊提供了一個 spritecollide() 函數,用於檢測某個精靈是否與指定組中的其他精靈發生碰撞。

 

spritecollide(sprite, group, dokill, collided = None)

 

第一個參數指定被檢測的精靈

 

第二個參數指定一個組,由 sprite.Group() 生成

 

第三個參數設置是否從組中刪除檢測到碰撞的精靈

 

第四個參數設置一個回調函數,用於定制特殊的檢測方法。如果該參數忽略,那么默認是檢測精靈之間的 rect 是否產生重疊。

注意:

  實現圓形的碰撞檢測,我們還需要指定 spritecollide() 函數的最后一個參數。

  sprite 模塊中正好有一個 collide_circle() 函數用於檢測兩個圓之間是否發生碰撞...

  這個函數需要你的精靈對象中必須有一個 radius(半徑)屬性才行。

 

 1 import pygame
 2 import sys
 3 from pygame.locals import *
 4 from random import *
 5 
 6 # 面向對象的編程方法,定義一個球的類型
 7 class Ball(pygame.sprite.Sprite):
 8     def __init__(self, image, position, speed, bg_size):
 9         # 初始化動畫精靈
10         pygame.sprite.Sprite.__init__(self)
11 
12         self.image = pygame.image.load(image).convert_alpha()
13         self.rect = self.image.get_rect()
14         # 將小球放在指定位置
15         self.rect.left, self.rect.top = position
16         self.speed = speed
17         self.width, self.height = bg_size[0], bg_size[1]
18         self.radius = self.rect.width / 2
19 
20     # 定義一個移動的方法
21     def move(self):
22         self.rect = self.rect.move(self.speed)
23         # 如果小球的左側出了邊界,那么將小球左側的位置改為右側的邊界
24         # 這樣便實現了從左邊進入,右邊出來的效果
25         if self.rect.right < 0:
26             self.rect.left = self.width
27         if self.rect.left > self.width:
28             self.rect.right = 0
29         if self.rect.bottom < 0:
30             self.rect.top = self.height
31         if self.rect.top > self.height:
32             self.rect.bottom = 0
33 
34 
35 def main():
36     pygame.init()
37 
38     ball_image = 'ball.png'
39     bg_image = 'background.png'
40     running = True
41 
42     # 根據背景圖片指定游戲界面尺寸
43     bg_size = width, height = 1024, 500
44     screen = pygame.display.set_mode(bg_size)
45     pygame.display.set_caption('Collision Spheres')
46 
47     background = pygame.image.load(bg_image).convert_alpha()
48 
49     # 用來存放小球對象的列表
50     balls = []
51     group = pygame.sprite.Group()
52 
53     # 創建6個位置隨機,速度隨機的小球
54     BALL_NUM = 6
55     for i in range(BALL_NUM):
56         position = randint(0, width - 70), randint(0, height - 70)
57         speed = [randint(1, 6), randint(1, 6)]
58         ball = Ball(ball_image, position, speed, bg_size)
59         while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle):
60             ball.rect.left, ball.rect.top = randint(0, width - 70), randint(0, height - 70)
61         balls.append(ball)
62         group.add(ball)
63 
64     clock = pygame.time.Clock()
65 
66     while running:
67         for event in pygame.event.get():
68             if event.type == QUIT:
69                 sys.exit()
70 
71         screen.blit(background, (0, 0))
72 
73         for each in balls:
74             each.move()
75             screen.blit(each.image, each.rect)
76 
77         for each in group:
78             group.remove(each)
79 
80             if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle):
81                 each.speed[0] = -each.speed[0]
82                 each.speed[1] = -each.speed[1]
83 
84             group.add(each)
85 
86         pygame.display.flip()
87         clock.tick(60)
88 
89 
90 if __name__ == '__main__':
91     main()
View Code

 

 

本演示圖片素材下載:https://files.cnblogs.com/files/GraceSkyer/20180203.zip

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM