Python?turtle編寫簡單的球類小游戲
1. 前言
turtle (小海龜) 是 Python 內(nèi)置的一個繪圖模塊,其實它不僅可以用來繪圖,還可以制作簡單的小游戲,甚至可以當成簡易的 GUI 模塊,編寫簡單的 GUI程序。
本文使用 turtle 模塊編寫一個簡單的小游戲,通過此程序的編寫過程聊一聊對 turtle 模塊的感悟。
編寫游戲,如果要做專業(yè)的、趣味性高的,還是請找 pygame,本文用 turtle 編寫游戲的目的是為了深度理解 turtle 的功能。
turtle 模塊的使用相對而言較簡單,對于基礎方法不做講解。只聊 turtle 模塊中稍難或大家忽視的地方。
2. 需求描述
程序運行時,畫布上會出現(xiàn)一個紅色的小球和很多綠色、藍色的小球。
剛開始紅色的小球會朝某一個方向移動,使用者可以通過按下上、下、左、右方向鍵控制紅色小球的運動方向。
綠色、藍色小球以初始的默認方向在畫布上移動。
當紅色的小球碰到綠色小球時,紅色小球球體會變大,當紅色小球碰到藍色小球時,紅色球體會變小。
當紅色小球球體縮小到某一個閾值時,游戲結束。

3. 制作流程
3.1 初始化變量
本程序需要使用到 turtle、random、math 模塊,使用之前,先導入。
import turtle import random import math ''' 初始化游戲界面大小 ''' # 游戲區(qū)域的寬度 game_wid = 600 # 游戲區(qū)域的高度 game_hei = 400 # 磚塊的大小,以及每一個小球初始大小 cell = 20 # 紅球初始大小 red_size = cell # 紅色小球 red_ball = None # 存儲綠色小球的列表 green_balls = [] # 存儲藍色小球的列表 blue_balls = [] # 紅色小球的方向 當前方向 0 向右,90 向上 180 向左 -90 向下 dir = 0
上述代碼說明:
紅色小球只有一個,由變量 red_ball 保存,紅色小球在運動過程中可以改大小,red_size 保存其大小。
綠色和藍色小球會有很多,這里使用 green_balls 和 blue_balls 2 個列表存儲。
3.2 通用函數(shù)
隨機位置計算函數(shù): 為小球們隨機生成剛開始出現(xiàn)的位置。
'''
隨機位置計算函數(shù)
'''
def rand_pos():
# 水平有 30 個單元格,垂直有 20 個單元格
x = random.randint(-14, 14)
y = random.randint(-9, 9)
return x * cell, y * cell
繪制指定填充顏色的小正方形: 在游戲里有一個虛擬區(qū)域,四周使用很多小正方形圍起來。
'''
繪制一個指定填充顏色的正方形
填充顏色可以不指定
'''
def draw_square(color):
if color is not None:
# 的顏色就填充
turtle.fillcolor(color)
turtle.begin_fill()
for i in range(4):
turtle.fd(cell)
turtle.left(90)
if color is not None:
turtle.end_fill()
自定義畫筆形狀:
使用 turtle 制作游戲的底層思想:
當我們導入 turtle 模塊時,意味著我們有了一支可以在畫布上畫畫的畫筆,畫筆的默認形狀是一個小海龜。
本文稱這支默認畫筆叫主畫筆,可以使用 turtle 模塊中的 turtle.Turtle() 類創(chuàng)建更多畫筆 ,并且可以使用 ``turtle模塊提供的turtle.register_shape(name, shape)` 方法為每一支畫筆定制畫筆形狀。
如上所述,是使用 turtle 設計游戲的關鍵。
強調(diào)一下:
通過主畫筆創(chuàng)建更多的畫筆,以及為每一支畫筆設置不同的形狀。是編寫游戲的關鍵,游戲中的每一個角色,其本質是一支支畫筆,我們只是在控制畫筆在畫布上按我們設計好的軌跡移動。
本游戲中紅、綠、藍 3 種顏色的小球就是形狀為圓形的畫筆。
畫筆清單:
紅色小球畫筆一支。
綠色小球畫筆 n 支。
藍色小球畫筆 n 支。
'''
自定義畫筆形狀
name:畫筆名稱
color:可選項
'''
def custom_shape(name, size):
turtle.begin_poly()
turtle.penup()
turtle.circle(size)
turtle.end_poly()
cs = turtle.get_poly()
turtle.register_shape(name, cs)
turtle.register_shape(name, shape) 方法參數(shù)說明:
- name: 自定義形狀的名稱。
- shape: 由開發(fā)者繪制的形狀。
開發(fā)者繪制的哪一部分圖形用來充當畫筆形狀?
由 turtle.begin_poly() 記錄的第一點到由 turtle.end_poly() 記錄的最后一點之間的圖形作為畫筆形狀。
cs = turtle.get_poly() 可以理解為獲取到剛繪制的圖形,然后使用 turtle.register_shape(name, cs) 注冊畫筆形狀,以后就可以隨時使用此形狀。
如上代碼記錄了一個圓的繪制過程,也就是創(chuàng)建了一個圓形的畫筆形狀。
移動到某個位置函數(shù):
此函數(shù)用來讓某一支畫筆移到指定位置,不留下移動過程中的軌跡。
'''
移到某點
'''
def move_pos(pen, pos):
pen.penup()
pen.goto(pos)
pen.pendown()
參數(shù)說明:
pen: 畫筆對象。pos:要移到的目標地。
注冊鍵盤事件函數(shù):
使用者可以通過鍵盤上的方向鍵更改紅色小球的方向。
turtle 模塊提供有很多事件,可以以交互式的方式使用turtle。turtle 模塊中主要有 2 類事件:鍵盤事件、點擊事件。因 turtle 的工作重點還是繪制靜態(tài)圖案上,其動畫繪制比較弱,所以它的事件少而簡單。
'''
改變紅色小球 4 方向的函數(shù),
這些函數(shù)只有當使用者觸發(fā)按鍵后方可調(diào)用,故這些函數(shù)也稱為回調(diào)函數(shù)。
'''
def dir_right():
global dir
dir = 0
def dir_left():
global dir
dir = 180
def dir_up():
global dir
dir = 90
def dir_down():
global dir
dir = -90
'''
注冊鍵盤響應事件,用來改變紅球的方向
'''
def register_event():
for key, f in {"Up": dir_up, "Down": dir_down, "Left": dir_left, "Right": dir_right}.items():
turtle.onkey(f, key)
turtle.listen()
'''
當紅色小球遇到墻體后,也要修改方向
'''
def is_meet_qt():
global dir
if red_ball.xcor() < -220:
dir = 0
if red_ball.xcor() > 240:
dir = 180
if red_ball.ycor() > 140:
dir = -90
if red_ball.ycor() < -120:
dir = 90
紅色的小球在 2 個時間點需要改變方向,一是使用者按下了方向鍵,一是碰到了墻體。
3.3 游戲角色函數(shù)
繪制墻體函數(shù):
墻體是游戲中的虛擬區(qū)域,用來限制小球的活動范圍。
Tips: 墻體由主畫筆繪制。
'''
繪制四面的墻體
'''
def draw_blocks():
# 隱藏畫筆
turtle.hideturtle()
# 上下各30個單元格,左右各 20 個單元格
for j in [30, 20, 30, 20]:
for i in range(j):
# 調(diào)用前面繪制正方形的函數(shù)
draw_square('gray')
turtle.fd(cell)
turtle.right(90)
turtle.fd(-cell)
# 回到原點
move_pos(turtle, (0, 0))
創(chuàng)建小球畫筆: 此函數(shù)用來創(chuàng)建新畫筆。本程序中的紅色、藍色、綠色小球都是由此函數(shù)創(chuàng)建的畫筆,且外觀形狀是圓。
def init_ball(pos, color, shape):
# 由主畫筆創(chuàng)建新畫筆
ball = turtle.Turtle()
ball.color(color)
# 指定新畫筆的形狀,如果不指定,則為默認形狀
ball.shape(shape)
# 移到隨機位置
move_pos(ball, pos)
# 移動過程要不顯示任何軌跡
ball.penup()
return ball
參數(shù)說明:
pos: 創(chuàng)建畫筆后畫筆移動的位置。color:指定畫筆和填充顏色。shape: 已經(jīng)定義好的畫筆形狀名稱。
創(chuàng)建綠色、藍色小球:
def ran_gb_ball(balls, color):
# 隨機創(chuàng)建藍色、綠色小球的頻率,
# 也就是說,不是調(diào)用此函數(shù)就一定會創(chuàng)建小球,概率大概是調(diào)用 5 次其中會有一次創(chuàng)建
ran = random.randint(1, 5)
# 隨機一個角度
a = random.randint(0, 360)
# 1/5 的概率
if ran == 5:
turtle.tracer(False)
# 每一個小球就是一只畫筆
ball = init_ball(rand_pos(), color, 'ball')
ball.seth(a)
# 添加到列表中
balls.append(ball)
turtle.tracer(True)
為什么要設置一個概率值?
適當控制藍色、綠色小球的數(shù)量。
turtle.tracer(False) 方法的作用:是否顯示畫筆繪制過程中的動畫。False 關閉動畫效果,True 打開動畫效果。
這里設置為 False 的原因是不希望用戶看到新畫筆創(chuàng)建過程。
藍色、綠色小球的移動函數(shù):
藍色、綠色小球被創(chuàng)建后會移到一個隨機位置,然后按默認方向移動。
def gb_ball_m(balls):
s = 20
a = random.randint(0, 360)
r = random.randint(0, 10)
for b in balls:
b.fd(s)
if b.xcor() < -220 or b.xcor() > 240 or b.ycor() > 140 or b.ycor() < -120:
b.goto(rand_pos())
當小球碰到墻體后讓其再隨機移到墻體內(nèi)部(簡單粗粗暴?。。?/p>
紅色球是否碰到了藍色或綠色小球:
此函數(shù)邏輯不復雜,計算小球相互之間的坐標,判斷坐標是否重疊。
'''
紅球是否碰到綠、藍球
'''
def r_g_b_meet():
global red_size
# 紅色小球的坐標
s_x, s_y = red_ball.pos()
# 迭代綠色小球,藍色小球列表
for bs in [green_balls, blue_balls]:
for b in bs:
# 計算藍色或綠色小球坐標
f_x, f_y = b.pos()
# 計算和紅色球之間的距離
x_ = math.fabs(s_x - f_x)
y_ = math.fabs(s_y - f_y)
# 碰撞距離:兩個球的半徑之和
h = cell + red_size
if 0 <= x_ <= h and y_ >= 0 and y_ <= h:
if b in green_balls:
# 遇到綠色球紅球變大
red_size += 2
if b in blue_balls:
# 遇到藍色球紅球變大
red_size -= 2
# 關鍵代碼
custom_shape('red', red_size)
return True
return False
上述代碼整體邏輯不復雜。而 custom_shape('red', red_size) 是關鍵代碼,因紅色小球的半徑發(fā)生了變化,所以需要重新定制紅色小球的外觀形狀,這樣才能在畫布上看到半徑變化的紅色小球。
3.4 讓小球動起來
怎樣讓小球動起來?
每隔一定時間,讓小球重新移動。 turtle.ontimer(ball_move, 100) 是讓小球動起來的核心邏輯,每隔一定時間,重新移動紅、藍、綠外觀如圓形狀的小球。
def ball_move():
red_ball.seth(dir)
red_ball.fd(40)
# 檢查紅球是否碰到墻體
is_meet_qt()
# 隨機創(chuàng)建綠色小球
ran_gb_ball(green_balls, 'green')
# 隨機創(chuàng)建藍色小球
ran_gb_ball(blue_balls, 'blue')
# 讓綠色小球移動
gb_ball_m(green_balls)
# 讓藍色小球移動
gb_ball_m(blue_balls)
# 檢查紅球是否碰到藍色、綠色小球
r_g_b_meet()
# 定時器
turtle.ontimer(ball_move, 100)
主方法:
if __name__ == "__main__":
# 關閉動畫效果
turtle.tracer(False)
# 注冊事件
register_event()
# 定制 2 種畫筆形狀
for name in ['red', 'ball']:
custom_shape(name, cell)
# 主畫筆移動墻體的左上角
move_pos(turtle, (-300, 200))
# 繪制墻體
draw_blocks()
red_ball = init_ball(rand_pos(), 'red', 'red')
turtle.tracer(True)
# 讓紅球移動起來
ball_move()
#
turtle.done()
以上為此游戲程序中的每一個函數(shù)講解。
運行后,可以控制紅色小球,當遇到綠色球和藍色球時,紅色球體會變大或變小。
4. 總結
使用 turtle 模塊的過程說明了一個道理,沒有所謂簡單的知識,如果你認為簡單,那是因為你對它的認知太淺。只是學到了大家都學到的內(nèi)容。
如果要真正悟透知識點的內(nèi)核,需要多查閱官方文檔,把所有內(nèi)容吃透,并試著把這些知識向更高層面拔高。
到此這篇關于Python turtle編寫簡單的球類小游戲的文章就介紹到這了,更多相關Python turtle游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python中l(wèi)ist循環(huán)遍歷刪除數(shù)據(jù)的正確方法
這篇文章主要給大家介紹了關于Python中l(wèi)ist循環(huán)遍歷刪除數(shù)據(jù)的正確方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Python具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-09-09

