日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python?turtle編寫簡單的球類小游戲_python

作者:一枚大果殼 ? 更新時間: 2022-06-02 編程語言

1. 前言

turtle?(小海龜) 是?Python?內置的一個繪圖模塊,其實它不僅可以用來繪圖,還可以制作簡單的小游戲,甚至可以當成簡易的?GUI?模塊,編寫簡單的?GUI程序。

本文使用?turtle?模塊編寫一個簡單的小游戲,通過此程序的編寫過程聊一聊對?turtle?模塊的感悟。

編寫游戲,如果要做專業的、趣味性高的,還是請找?pygame,本文用?turtle?編寫游戲的目的是為了深度理解?turtle?的功能。

turtle?模塊的使用相對而言較簡單,對于基礎方法不做講解。只聊?turtle?模塊中稍難或大家忽視的地方。

2. 需求描述

程序運行時,畫布上會出現一個紅色的小球和很多綠色、藍色的小球。

剛開始紅色的小球會朝某一個方向移動,使用者可以通過按下上、下、左、右方向鍵控制紅色小球的運動方向。

綠色、藍色小球以初始的默認方向在畫布上移動。

當紅色的小球碰到綠色小球時,紅色小球球體會變大,當紅色小球碰到藍色小球時,紅色球體會變小。

當紅色小球球體縮小到某一個閾值時,游戲結束。

3. 制作流程

3.1 初始化變量

本程序需要使用到?turtle、random、math?模塊,使用之前,先導入。

import turtle
import random
import math
'''
初始化游戲界面大小
'''
# 游戲區域的寬度
game_wid = 600  
# 游戲區域的高度
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 通用函數

隨機位置計算函數:?為小球們隨機生成剛開始出現的位置。

'''
隨機位置計算函數
'''
def rand_pos():
    # 水平有 30 個單元格,垂直有 20 個單元格
    x = random.randint(-14, 14)
    y = random.randint(-9, 9)
    return x * cell, y * cell

繪制指定填充顏色的小正方形:?在游戲里有一個虛擬區域,四周使用很多小正方形圍起來。

'''
繪制一個指定填充顏色的正方形
填充顏色可以不指定
'''
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()?類創建更多畫筆 ,并且可以使用 ``turtle模塊提供的turtle.register_shape(name, shape)` 方法為每一支畫筆定制畫筆形狀。

如上所述,是使用?turtle?設計游戲的關鍵。

強調一下:

通過主畫筆創建更多的畫筆,以及為每一支畫筆設置不同的形狀。是編寫游戲的關鍵,游戲中的每一個角色,其本質是一支支畫筆,我們只是在控制畫筆在畫布上按我們設計好的軌跡移動。

本游戲中紅、綠、藍 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)?方法參數說明:

  • name:?自定義形狀的名稱。
  • shape:?由開發者繪制的形狀。

開發者繪制的哪一部分圖形用來充當畫筆形狀?

由?turtle.begin_poly()?記錄的第一點到由?turtle.end_poly()?記錄的最后一點之間的圖形作為畫筆形狀。

cs = turtle.get_poly()?可以理解為獲取到剛繪制的圖形,然后使用?turtle.register_shape(name, cs)?注冊畫筆形狀,以后就可以隨時使用此形狀。

如上代碼記錄了一個圓的繪制過程,也就是創建了一個圓形的畫筆形狀。

移動到某個位置函數:

此函數用來讓某一支畫筆移到指定位置,不留下移動過程中的軌跡。

'''
移到某點
'''
def move_pos(pen, pos):
    pen.penup()
    pen.goto(pos)
    pen.pendown()

參數說明:

  • pen?: 畫筆對象。
  • pos:要移到的目標地。

注冊鍵盤事件函數:

使用者可以通過鍵盤上的方向鍵更改紅色小球的方向。

turtle?模塊提供有很多事件,可以以交互式的方式使用turtle。turtle?模塊中主要有 2 類事件:鍵盤事件、點擊事件。因?turtle?的工作重點還是繪制靜態圖案上,其動畫繪制比較弱,所以它的事件少而簡單。

'''
改變紅色小球 4 方向的函數,
這些函數只有當使用者觸發按鍵后方可調用,故這些函數也稱為回調函數。
'''
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 游戲角色函數

繪制墻體函數:

墻體是游戲中的虛擬區域,用來限制小球的活動范圍。

Tips:?墻體由主畫筆繪制。

'''
繪制四面的墻體
'''
def draw_blocks():
    # 隱藏畫筆
    turtle.hideturtle()
    # 上下各30個單元格,左右各 20 個單元格
    for j in [30, 20, 30, 20]:
        for i in range(j):
            # 調用前面繪制正方形的函數
            draw_square('gray')
            turtle.fd(cell)
        turtle.right(90)
        turtle.fd(-cell)
    # 回到原點
    move_pos(turtle, (0, 0))

創建小球畫筆:?此函數用來創建新畫筆。本程序中的紅色、藍色、綠色小球都是由此函數創建的畫筆,且外觀形狀是圓。

def init_ball(pos, color, shape):
    #  由主畫筆創建新畫筆
    ball = turtle.Turtle()
    ball.color(color)
    # 指定新畫筆的形狀,如果不指定,則為默認形狀
    ball.shape(shape)
    # 移到隨機位置
    move_pos(ball, pos)
    # 移動過程要不顯示任何軌跡
    ball.penup()
    return ball

參數說明:

  • pos:?創建畫筆后畫筆移動的位置。
  • color:指定畫筆和填充顏色。
  • shape:?已經定義好的畫筆形狀名稱。

創建綠色、藍色小球:

def ran_gb_ball(balls, color):
    # 隨機創建藍色、綠色小球的頻率,
    # 也就是說,不是調用此函數就一定會創建小球,概率大概是調用 5 次其中會有一次創建
    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)

為什么要設置一個概率值?

適當控制藍色、綠色小球的數量。

turtle.tracer(False)?方法的作用:是否顯示畫筆繪制過程中的動畫。False?關閉動畫效果,True?打開動畫效果。

這里設置為?False?的原因是不希望用戶看到新畫筆創建過程。

藍色、綠色小球的移動函數:

藍色、綠色小球被創建后會移到一個隨機位置,然后按默認方向移動。

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

當小球碰到墻體后讓其再隨機移到墻體內部(簡單粗粗暴?。。?。

紅色球是否碰到了藍色或綠色小球:

此函數邏輯不復雜,計算小球相互之間的坐標,判斷坐標是否重疊。

'''
紅球是否碰到綠、藍球
'''
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)?是關鍵代碼,因紅色小球的半徑發生了變化,所以需要重新定制紅色小球的外觀形狀,這樣才能在畫布上看到半徑變化的紅色小球。

3.4 讓小球動起來

怎樣讓小球動起來?

每隔一定時間,讓小球重新移動。?turtle.ontimer(ball_move, 100)?是讓小球動起來的核心邏輯,每隔一定時間,重新移動紅、藍、綠外觀如圓形狀的小球。

def ball_move():
    red_ball.seth(dir)
    red_ball.fd(40)
    # 檢查紅球是否碰到墻體
    is_meet_qt()
    # 隨機創建綠色小球
    ran_gb_ball(green_balls, 'green')
    # 隨機創建藍色小球
    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()

以上為此游戲程序中的每一個函數講解。

運行后,可以控制紅色小球,當遇到綠色球和藍色球時,紅色球體會變大或變小。

4. 總結

使用?turtle?模塊的過程說明了一個道理,沒有所謂簡單的知識,如果你認為簡單,那是因為你對它的認知太淺。只是學到了大家都學到的內容。

如果要真正悟透知識點的內核,需要多查閱官方文檔,把所有內容吃透,并試著把這些知識向更高層面拔高。

原文鏈接:https://www.cnblogs.com/guo-ke/p/16079327.html

欄目分類
最近更新