手把手教你使用Python語(yǔ)言的Pygame繪制動(dòng)圖

在推上看到一張有意思的圖片,黑點(diǎn)在多個(gè)交叉的圓上做圓周運(yùn)動(dòng),看上去會(huì)有波浪的效果。我想這個(gè)Python的Pygame就可以實(shí)現(xiàn)啊。馬上動(dòng)手,下面是程序運(yùn)行的效果:

Peek2019-08-08 14-27.gif

本文會(huì)從零開(kāi)始演示如何實(shí)現(xiàn)上述圖片效果,如果你對(duì)Python語(yǔ)言和Pygame很陌生,歡迎你光臨www.icoding.pub收看我的使用Python語(yǔ)言制作游戲視頻教程。這個(gè)教程面向初學(xué)者,教你在編寫游戲中學(xué)習(xí)Python語(yǔ)言。本文的內(nèi)容我也制作了視頻放在www.icoding.pub上,歡迎訪問(wèn)。

注意,本文的程序需用到笛卡爾坐標(biāo)系和三角函數(shù)。

Ok。首先你需要已經(jīng)安裝Python和Pygame。安裝過(guò)程我的視頻教程中有,此處略過(guò)。首先啟動(dòng)IDLE,啟動(dòng)新建文件,然后另存為,為你的文件起一個(gè)名字,記住擴(kuò)展名應(yīng)為.py,還要記住保存文件的目錄。

在新建文件中輸入以下內(nèi)容:

# 引入pygame和sys模塊
import pygame, sys
from pygame.locals import *

# 設(shè)置窗口寬度和高度
WIDTH = 500
HEIGHT = 400

# 設(shè)置圓半徑
RADIUS = 25

# 初始化pygame
pygame.init()

# 設(shè)置窗口與窗口標(biāo)題
windowSurface = pygame.display.set_mode((500,400),0,32)
pygame.display.set_caption('Circle')

# 設(shè)置顏色
BLACK = (0,0,0)
WHITE = (255,255,255)

# to do

# 事件循環(huán)
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    # 填充背景
    windowSurface.fill(WHITE)

    # 繪制窗口到屏幕上
    pygame.display.update()

上面的代碼中,首先通過(guò)兩個(gè)import語(yǔ)句引入了需用到的pygamesys模塊以及pygame的常量。pygame用于繪制圖形,sys用于結(jié)束程序。然后是pygme的初始化,任何使用pygame的程序都需要初始化。下面是設(shè)置窗口的尺寸和標(biāo)題,這個(gè)例子中設(shè)置的尺寸為寬度500、高度400。接下來(lái)設(shè)置了兩個(gè)顏色常量BLACKWHITE,設(shè)置常量為了便于修改。最后進(jìn)入窗口事件監(jiān)聽(tīng)循環(huán),后面通過(guò)調(diào)用windowSurfacefill方法填充白色背景,接下來(lái)通過(guò)update刷新屏幕。

這是程序的整體結(jié)構(gòu),我們先在to do部分寫代碼。要在屏幕上畫圓,我們首先要確定圓的圓心。在to do下增加以下代碼:

xs = list(range(0, WIDTH + RADIUS, int(RADIUS*1.2)))
ys = list(range(0, HEIGHT + RADIUS, int(RADIUS*1.2)))

以上語(yǔ)句生成了x方向和y方向序列。注意,range的3個(gè)參數(shù),第一個(gè)表示起始,第二個(gè)表示結(jié)束,第三個(gè)表示步長(zhǎng)。第二個(gè)參數(shù)如果不加上RADIUS,窗口右邊和下邊的圓將顯示不完成。注意:這個(gè)程序的任何部分任何參數(shù)你都可以修改并運(yùn)行以查看效果。特別是第三個(gè)參數(shù),你可以調(diào)整這個(gè)數(shù)值查看生成圓的間距。

在程序windowSurface.fill(WHITE)pygame.display.update上增加以下代碼,注意縮進(jìn)與二者相同:

for x in xs:
        for y in ys:
            pygame.draw.circle(windowSurface,BLACK,(x,y),RADIUS,1)

保存,運(yùn)行,會(huì)出現(xiàn)以下畫面:


2019-08-08 20-47-35 的屏幕截圖.png

下面的任務(wù)是繪制圓上的點(diǎn)。我們不能使用pygamepoint,因?yàn)橐粋€(gè)像素的點(diǎn)太小了難以看清。我們?cè)诿總€(gè)圓的圓周上繪制circle對(duì)象,不過(guò)這個(gè)circle是實(shí)心的,半徑僅為幾個(gè)像素。問(wèn)題來(lái)了,我們知道了每個(gè)圓的圓心坐標(biāo)為(x,y),怎么確定圓周上點(diǎn)的坐標(biāo)呢?這就用到三角函數(shù)了。請(qǐng)看下圖:

2019-08-08 20-53-27 的屏幕截圖.png

設(shè)圓半徑為r,圓心坐標(biāo)(x_0,y_0),圓周上點(diǎn)的坐標(biāo)(小圓的圓心)為(x_1,y_1),點(diǎn)與圓心連線與X軸夾角為a,則x_1 = x_0 + r * cosa,y_1 = y_0 + r * sina。不熟悉三角函數(shù)的同學(xué)自行搜索補(bǔ)習(xí)一下。

我們先設(shè)角度為0。因?yàn)橐玫饺呛瘮?shù),我們要引入math庫(kù),在from pygame.locals import *下增加一行:

import math

還要設(shè)置點(diǎn)的半徑,在RADIUS = 25下增加一行:

POINT_RADIUS = 3

還需要設(shè)置角度變量,在 xs = ...上增加一行:

angle = 0

然后在pygame.draw.circle...下增加相同縮進(jìn)的以下3行:

x_point = x + RADIUS * (math.cos(angle))
y_point = y + RADIUS * (math.sin(angle))
pygame.draw.circle(windowSurface,BLACK,(int(x_point), int(y_point)), POINT_RADIUS)

前兩行是設(shè)置點(diǎn)的坐標(biāo),第三行繪制點(diǎn)?,F(xiàn)在,保存,運(yùn)行,會(huì)出現(xiàn)以下畫面:


2019-08-08 21-11-28 的屏幕截圖.png

試試將angle變量的值分別改為math.pi / 2, math.pi, math.pi * 3 / 2, math.pi *2等運(yùn)行,看看點(diǎn)會(huì)出現(xiàn)在什么位置,并想想為什么。

下面,我們要寫讓點(diǎn)移動(dòng)的代碼了。首先在程序首部import部分最后增加一行:

import time

我們要使用timesleep函數(shù)控制程序的刷新時(shí)間,否則因?yàn)橛?jì)算機(jī)運(yùn)行太快,畫面閃爍得看不清。在第二個(gè)pygame.draw.cirlce下增加一行,注意縮進(jìn)與for x in xs:相同:

angle += 0.2

我們讓程序每刷新一次,角度增加0.2。在程序末尾pygame.display.update()下增加相同縮進(jìn)的一行:

time.sleep(0.02)

讓程序20毫秒刷新1次。保存,運(yùn)行。

Peek 2019-08-08 21-26.gif

貌似還不錯(cuò),但沒(méi)有期望的波浪的效果。要想得到那種效果,需要每一行的點(diǎn)的位置有輕微的差別,我們需要為每一行圓周上的點(diǎn)設(shè)置不同的起始角度?,F(xiàn)在,在ys = list(range(0...下增加以下內(nèi)容:

angles = {}
for y in ys:
    angles[y] = angle
    angle += 0.5

我們建立了一個(gè)angles字典變量,用于存儲(chǔ)每一行(對(duì),每一行,因?yàn)槊恳恍械?code>y值相同)的角度,而每一行的角度比上一行多0.5。循環(huán)代碼塊的x_point=...y_point-...修改為:

x_point = x + RADIUS * (math.cos(angles[y]))
y_point = y + RADIUS * (math.sin(angles[y]))

我們還要在每個(gè)while循環(huán)里增加每行點(diǎn)的角度,在pygame.display.update()上增加一行相同縮進(jìn)的內(nèi)容:

for y in ys:
    angles[y] += 0.05

保存,運(yùn)行。


Peek 2019-08-08 21-42.gif

以下是全部代碼:

# 引入pygame和sys模塊
import pygame, sys
import math
from pygame.locals import *
import time

WIDTH = 500
HEIGHT = 400

RADIUS = 25
POINT_RADIUS = 3

# 初始化pygame
pygame.init()

# 設(shè)置窗口與窗口標(biāo)題
windowSurface = pygame.display.set_mode((WIDTH,HEIGHT),0,32)
pygame.display.set_caption('Circle')

# 設(shè)置顏色
BLACK = (0,0,0)
WHITE = (255,255,255)

angle = 0

# to do
xs = list(range(0, WIDTH + RADIUS, int(RADIUS*1.2)))
ys = list(range(0, HEIGHT + RADIUS, int(RADIUS*1.2)))

angles = {}
for y in ys:
    angles[y] = angle
    angle += 0.5

# 事件循環(huán)
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    windowSurface.fill(WHITE)

    for x in xs:
        for y in ys:
            pygame.draw.circle(windowSurface,BLACK,(x,y),RADIUS,1)
            x_point = x + RADIUS * (math.cos(angles[y]))
            y_point = y + RADIUS * (math.sin(angles[y]))
            pygame.draw.circle(windowSurface,BLACK,(int(x_point), int(y_point)), POINT_RADIUS)

    for y in ys:
        angles[y] += 0.05

    # 繪制窗口到屏幕上
    pygame.display.update()
    time.sleep(0.02)

OK。我已將本文寫代碼過(guò)程錄制為視頻并配有講解,如果你對(duì)本文內(nèi)容有不清楚的地方,可以光臨www.icoding.pub收看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容