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


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

書接上回,還有下面的問題沒解決:

* 下面有一個紅色的小條,會隨著鼠標移動。小條就是個能移動的擋板,只能隨著鼠標水平移動,不能上下移動。

* 小球碰到紅色小條會反彈,沒碰到就消失了,死掉了 :(


先說第一個問題。是不是感覺和以前創建小球差不多?這就對了。

不過這次是畫個矩形,而且在遊戲一開始就畫好。

矩形的移動是隨著鼠標的X分量進行移動。


那就開始。

先定義紅色,檔板的長、寬和移動速度。

Red = (255, 0, 0) 
lines = []
Line_length = 100
Line_weigh = 10
Line_color = Red
Line_speed = 2

為了給以後留擴展空間(比如人機對戰),我們像處理多個小球一樣,把檔板定義成一個列表變量。這樣,以後需要的時候就可以方便的創建多個檔板。

然後,需要定義幾個函數

create_line()

line_move()

line_redraw()

函數作用就不用多說了,從名字上就看得出來。

代碼如下:

def create_line(window):
# 在指定的位置畫線
# 保存線的信息
line_start_point = (WINDOW_WIDTH/2-Line_length/2, WINDOW_HIGH-Line_weigh)
line_end_point = (WINDOW_WIDTH/2+Line_length/2, WINDOW_HIGH-Line_weigh)
temp_line = {
'line_start_point': line_start_point,
'line_end_point': line_end_point,
'line_length': Line_length
}
lines.append(temp_line)
# 畫線
pygame.draw.line(window, Line_color, line_start_point, line_end_point, Line_weigh)

pygame.display.update() # 第一次flip後面用update


def line_move():
pos = pygame.mouse.get_pos()
line_start_point = (pos[0]-Line_length/2, WINDOW_HIGH-Line_weigh)
line_end_point = (pos[0] + Line_length / 2, WINDOW_HIGH-Line_weigh)

lines[0]['line_start_point'] = line_start_point
lines[0]['line_end_point'] = line_end_point


def line_redraw(window):
pygame.draw.line(window, Line_color, lines[0]['line_start_point'], lines[0]['line_end_point'], Line_weigh)
pygame.display.update()
pygame.time.delay(50)

有了函數,在哪調用呢?

肯定在main_game()。但是要想一想。

  • create_line()需要在窗口初始化時就調用,因為要顯示出檔板。所以放到while循環之前。
  • line_move()和line_redraw()需要不停的循環調用,所以放到while循環內。

RUN一下試試,效果如下:


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


問題來了:檔板是有了,但沒起作用。 :(

下節解決這個問題。


以下為全部代碼:

import pygame
import random

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

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

lines = []
Line_length = 100
Line_weigh = 10
Line_color = Red
Line_speed = 2

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 create_line(window):
# 在指定的位置畫線
# 保存線的信息
line_start_point = (WINDOW_WIDTH/2-Line_length/2, WINDOW_HIGH-Line_weigh)
line_end_point = (WINDOW_WIDTH/2+Line_length/2, WINDOW_HIGH-Line_weigh)
temp_line = {
'line_start_point': line_start_point,
'line_end_point': line_end_point,
'line_length': Line_length
}
lines.append(temp_line)
# 畫線
pygame.draw.line(window, Line_color, line_start_point, line_end_point, Line_weigh)

pygame.display.update() # 第一次flip後面用update


def line_move():
pos = pygame.mouse.get_pos()
line_start_point = (pos[0]-Line_length/2, WINDOW_HIGH-Line_weigh)
line_end_point = (pos[0] + Line_length / 2, WINDOW_HIGH-Line_weigh)

lines[0]['line_start_point'] = line_start_point
lines[0]['line_end_point'] = line_end_point


def line_redraw(window):
pygame.draw.line(window, Line_color, lines[0]['line_start_point'], lines[0]['line_end_point'], Line_weigh)
pygame.display.update()
pygame.time.delay(50)


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()

create_line(window)

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)

line_move()
line_redraw(window)


if __name__ == '__main__':
main_game()


分享到:


相關文章: