Python入門 Junior-做個小遊戲-做個彈珠小遊戲吧(5)

書接上回:球與球之間沒有碰撞。:(

老規矩,先想想怎麼回事,再出手。


球與球之間的碰撞可以分為兩部分:

1、碰撞檢測:如果兩球心的間距等於球的直徑,就是碰撞了。這是數學問題,好解決。

2、碰撞後的行為怎麼辦?

想想在物理上學過什麼。如果你是個物理狂人+完美主義者,可以再學一次動量守恆、能量守恆,咱們的目標是PYTHON,所以簡化處理:兩個球互相交換速度和方向。當然,這是不符合現實世界的物理規則的。

在哪添加代碼呢?當然是 ball_move 。如下:

# 檢測球碰撞,每個球是否和其他的球的圓心距小於等於兩個半徑
# 把球碰撞當做完全彈性碰撞
# 球碰撞後如何處理
# 如果像碰壁一樣處理(X,Y SPEED* -1),效果完成不符合物理規則
# 可以兩個球互相交換速度
for other in balls:
if ball == other:
continue
# 判斷兩個球是否相撞
other_x, other_y = other['ball_center']
# 算兩個球的圓心距

center_distance = ((ball_x-other_x)**2 + (ball_y-other_y)**2)**0.5
# 相撞後:
if center_distance <= Ball_radius*2:
# 對心碰撞後,兩個球互換方向
ball['ball_xspeed'],other['ball_xspeed'] = other['ball_xspeed'],ball['ball_xspeed']
ball['ball_yspeed'], other['ball_yspeed'] = other['ball_yspeed'], ball['ball_yspeed']

new_x = ball_x + ball['ball_xspeed']
new_y = ball_y + ball['ball_yspeed']
ball['ball_center'] = new_x, new_y

new_x = other_x + other['ball_xspeed']
new_y = other_y + other['ball_yspeed']
other['ball_center'] = new_x, new_y

RUN試一下,效果如下:


Python入門 Junior-做個小遊戲-做個彈珠小遊戲吧(5)


可以算是達到要求了。

完整代碼如下:

import pygame
import random

WINDOW_WIDTH = 600 # 屏幕寬度
WINDOW_HIGH = 400 # 屏幕高度

Black = (0, 0, 0)
White = (255, 255, 255)

balls = []

Ball_radius = 20
Ball_xspeed = 1
Ball_yspeed = 4


# random.randint(-5,5)用於生成X,Y方向,如果其中一個是0,或者全是0
# 會造成生成的球垂直或水平或原地不動,不妥
# 故做以下函數
def my_randint(start, end):
while True:
x = random.randint(start, end)
if x != 0:
break
return x


def creat_ball(window, pos):
# 畫球
temp_ball = {
'ball_center': pos,
'ball_radius': Ball_radius,
'ball_xspeed': my_randint(-5,5),
'ball_yspeed': my_randint(-5,5)

}
balls.append(temp_ball)
# print(balls)
# 畫球
pygame.draw.circle(window, White, pos, Ball_radius, Ball_radius)

pygame.display.update() # flip後面用update


def ball_move():
# 計算每個球的新座標
for ball in balls:
# 獲取球的新的原點
ball_x, ball_y = ball['ball_center']
new_x = ball_x + ball['ball_xspeed']
new_y = ball_y + ball['ball_yspeed']

# 檢測兩邊的邊界
if new_x < ball['ball_radius']:
new_x = ball['ball_radius']
ball['ball_xspeed'] *= -1
elif new_x > WINDOW_WIDTH - ball['ball_radius']:
new_x = WINDOW_WIDTH - ball['ball_radius']
ball['ball_xspeed'] *= -1

# 檢測上下邊界
if new_y < ball['ball_radius']: # 上邊界
new_y = ball['ball_radius']
ball['ball_yspeed'] *= -1
elif new_y > WINDOW_HIGH - ball['ball_radius']: # 下邊界
new_y = WINDOW_HIGH - ball['ball_radius']
ball['ball_yspeed'] *= -1

# 修改圓心座標
ball['ball_center'] = new_x, new_y

# 檢測球碰撞,每個球是否和其他的球的圓心距小於等於兩個半徑
# 把球碰撞當做完全彈性碰撞
# 球碰撞後如何處理
# 如果像碰壁一樣處理(X,Y SPEED* -1),效果完成不符合物理規則

# 可以兩個球互相交換速度
for other in balls:
if ball == other:
continue
# 判斷兩個球是否相撞
other_x, other_y = other['ball_center']
# 算兩個球的圓心距
center_distance = ((ball_x-other_x)**2 + (ball_y-other_y)**2)**0.5
# 相撞後
if center_distance <= Ball_radius*2:

# 對心碰撞後,兩個球互換方向
ball['ball_xspeed'],other['ball_xspeed'] = other['ball_xspeed'],ball['ball_xspeed']
ball['ball_yspeed'], other['ball_yspeed'] = other['ball_yspeed'], ball['ball_yspeed']

new_x = ball_x + ball['ball_xspeed']
new_y = ball_y + ball['ball_yspeed']
ball['ball_center'] = new_x, new_y

new_x = other_x + other['ball_xspeed']
new_y = other_y + other['ball_yspeed']
other['ball_center'] = new_x, new_y


def ball_redraw(window):
window.fill(Black) # 窗口背景色重新置成黑色,球就沒了
for ball in balls:
pygame.draw.circle(window, White, ball['ball_center'],ball['ball_radius'])

pygame.display.update()
# 每10毫秒刷新一次
pygame.time.delay(10)


def main_game():
# 初始化遊戲
pygame.init()
# 定義窗體,指定大小
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HIGH))
# 指定窗體的標題
pygame.display.set_caption("PingPang")
# 指定窗體底色

window.fill(Black)
# 顯示窗體
pygame.display.flip()

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
creat_ball(window, event.pos)
ball_move()
ball_redraw(window)


if __name__ == '__main__':
main_game()



分享到:


相關文章: