強(qiáng)化學(xué)習(xí)Agent系列(一)——PyGame游戲編程,Python 貪吃蛇制作實(shí)戰(zhàn)教學(xué)
一、前言
大家好,未來(lái)的開發(fā)者們請(qǐng)上座
隨著人工智能的發(fā)展,強(qiáng)化學(xué)習(xí)基本會(huì)再次來(lái)到人們眼前,遂想制作一下相關(guān)的教程。強(qiáng)化學(xué)習(xí)第一步基本離不開虛擬環(huán)境的搭建,下面用大家耳熟能詳?shù)呢澇陨哂螒驗(yàn)榛A(chǔ),制作一個(gè)Agent,完成對(duì)這個(gè)游戲的絕殺。
萬(wàn)里長(zhǎng)城第一步:用python開發(fā)貪吃蛇游戲
1、pygame介紹
用Python進(jìn)行游戲開發(fā)的首選模塊就是PyGame。
pygame 是一個(gè)流行的跨平臺(tái)Python模塊,專為電子游戲設(shè)計(jì),包含圖像、聲音等,創(chuàng)建在SDL(Simple DirectMedia Layer)基礎(chǔ)上,允許實(shí)時(shí)電子游戲研發(fā)而不會(huì)被低級(jí)語(yǔ)言,如C語(yǔ)言或是更低級(jí)的匯編語(yǔ)言束縛?;谶@樣一個(gè)設(shè)想,所有需要的游戲功能和理念(主要是圖像方面)都完全簡(jiǎn)化為游戲邏輯本身,所有的資源結(jié)構(gòu)都可以由高級(jí)語(yǔ)言(如Python)提供。它提供了一套豐富的功能,使得游戲開發(fā)者可以輕松地創(chuàng)建圖形、動(dòng)畫、音效和游戲邏輯。
以下是 pygame 的一些關(guān)鍵特性:
注:不需要特地去記,一開始只需要知道pygame有哪些關(guān)鍵特性,哪些功能他可以實(shí)現(xiàn)即可。
-
顯示
pygame 提供了一種簡(jiǎn)單的方式來(lái)創(chuàng)建和管理游戲窗口以及渲染圖形。
它支持多種圖像格式,包括 BMP、JPG、PNG、GIF 等。 -
事件
pygame 有一個(gè)事件系統(tǒng),可以處理鍵盤、鼠標(biāo)、游戲手柄等輸入設(shè)備的事件。
開發(fā)者可以輕松地查詢和響應(yīng)用戶的交互。 -
圖形
pygame 提供了基本的2D圖形繪制功能,包括線條、形狀、圖像渲染等。
它也支持圖像的變換,如縮放、旋轉(zhuǎn)和翻轉(zhuǎn)。 -
音效和音樂(lè)
pygame 可以播放音效和音樂(lè)文件,支持多種音頻格式。
它提供了音量控制、播放控制等基本的音頻操作。 -
精靈
pygame 的精靈(Sprite)系統(tǒng)可以幫助管理游戲中的對(duì)象。
精靈類可以用來(lái)表示游戲中的每一個(gè)元素,如角色、物品等。 -
時(shí)鐘
pygame 的時(shí)鐘(Clock)功能可以幫助控制游戲的幀率,確保游戲以均勻的速度運(yùn)行。 -
碰撞檢測(cè)
pygame 提供了簡(jiǎn)單的碰撞檢測(cè)功能,可以檢測(cè)兩個(gè)元素是否相互接觸或重疊。 -
字體和文本
pygame 支持字體渲染,可以在游戲中顯示文本。 -
跨平臺(tái)
pygame 可以運(yùn)行在多種操作系統(tǒng)上,包括 Windows、Mac OS X 和 Linux。
安裝 pygame 通常很簡(jiǎn)單,只需使用 pip 命令即可:
2、 安裝Pygame
pip install pygame
一旦安裝了 pygame,你就可以開始創(chuàng)建游戲窗口、加載圖像、處理用戶輸入和創(chuàng)建游戲邏輯了。pygame 的社區(qū)活躍,有大量的教程和文檔可供學(xué)習(xí),這使得即使是編程新手也能夠開始他們的游戲開發(fā)之旅。
3. Pygame常用模塊
Pygame做游戲開發(fā)的優(yōu)勢(shì)在于不需要過(guò)多地考慮底層相關(guān)的內(nèi)容,可以把工作中心放在游戲邏輯上。例如,PyGame中集成了很多和底層相關(guān)的模塊,如訪問(wèn)顯示設(shè)備、管理事件、使用字體等。
Pygame常用模塊如下:
模塊名 | 功能 |
---|---|
pygame.display | 訪問(wèn)顯示設(shè)備。 |
pygame.draw | 繪制形狀、線和點(diǎn)。 |
pygame.event | 管理事件。 |
pygame.font | 使用字體。 |
pygame.image | 加載和存儲(chǔ)圖片。 |
pygame.key | 讀取鍵盤按鍵。 |
pygame.mixer | 聲音。 |
pygame.mouse | 鼠標(biāo)。 |
pygame.movie | 播放視頻。 |
pygame.music | 播放音樂(lè)。 |
pygame.rect | 管理矩形區(qū)域。 |
pygame.sndarray | 操作聲音數(shù)據(jù)。 |
pygame.sprite | 操作移動(dòng)圖像。 |
pygame.surface | 管理圖像和屏幕。 |
pygame.surfarray | 管理點(diǎn)陣圖像數(shù)據(jù)。 |
pygame.time | 管理時(shí)間和幀信息。 |
pygame.transform | 縮放和移動(dòng)圖像。 |
二、pygame 入門
1、窗口初始化與事件初認(rèn)識(shí)
使用Pygame的display模塊和event模塊創(chuàng)建一個(gè)PyGame窗口,代碼結(jié)構(gòu)主要分三部分:
- 模塊導(dǎo)入
- pygame窗口初始化
- 游戲主體
初始化涉及到的pygame與sys函數(shù):
模塊名 | 功能 |
---|---|
pygame.init() | 初始化所有的pygame模塊,使用其他模塊之前基本一定要調(diào)用init方法 |
pygame.display.set_mode() | 初始化窗口的寬高,并返回游戲屏幕(后續(xù)對(duì)象都需要畫到游戲屏幕上) |
pygame.display.set_caption() | 初始化窗口的名字 |
pygame.event.get() | 鍵盤、鼠標(biāo)、手柄 事件響應(yīng) |
pygame.QUIT | 點(diǎn)擊窗口右上角紅X的事件 |
sys.exit() | 程序退出 |
pygame.quit() | 程序終止前調(diào)用,卸載所有pygame模塊 |
# -*- coding: utf-8 -*-
# 一、模塊導(dǎo)入
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
# 二、pygame窗口初始化
pygame.init() # 初始化pygame
size = width, height = 320, 240 # 設(shè)置窗口尺寸
screen = pygame.display.set_mode(size) # 顯示窗口
# 設(shè)置標(biāo)題
pygame.display.set_caption('窗口初始化測(cè)試')
# 三、游戲主體
# 執(zhí)行死循環(huán),確保窗口一直顯示,同時(shí)監(jiān)聽關(guān)閉按鈕事件
while True:
# 檢查事件
for event in pygame.event.get(): # 遍歷所有事件
if event.type == pygame.QUIT: # 如果單擊關(guān)閉按鈕
pygame.quit() # 卸載所有pygame模塊
sys.exit() # 終止當(dāng)前程序
運(yùn)行結(jié)果如下:
這樣子你就創(chuàng)建了一個(gè)窗口,點(diǎn)擊關(guān)閉按鈕,程序捕捉到pygame.QUIT事件,pygame.quit()卸載完pygame模塊后,運(yùn)行 sys.exit() 退出程序。
這樣子就開始了基于pygame制作游戲的第一步。窗口初始化
2、創(chuàng)建綠色方塊并鍵盤移動(dòng)
涉及到游戲基本就離不開控制角色移動(dòng),遂就將其當(dāng)做第二課
運(yùn)行結(jié)果如下:
該課程涉及到的pygame函數(shù)(不重復(fù)上一課學(xué)習(xí)到的了):
模塊名 | 功能 |
---|---|
pygame.time.Clock() | 創(chuàng)建時(shí)鐘對(duì)象,用于控制屏幕繪制速度 – 刷新頻率 |
clock.tick(60) | 時(shí)鐘對(duì)象(一定要放在整個(gè)游戲循環(huán)最后,不然會(huì)起不到穩(wěn)定控制游戲刷新速度的效果),設(shè)置頻率為60。如果你的游戲邏輯和渲染非常快,tick 方法將會(huì)使程序暫停,以保持 60 FPS 的速度,如果速度慢于60則不會(huì)等待 |
pygame.key.get_pressed() | 獲取當(dāng)前全部鍵盤key的狀態(tài),沒(méi)按下的按鈕值為False,按下的按鈕值為True |
screen.fill() | 快捷填充背景色 |
pygame.draw.rect() | 繪制矩陣(游戲屏幕,顏色,矩陣(x,y,width,height),width(矩陣粗細(xì),沒(méi)有則填充整個(gè)矩陣)) |
pygame.display.update() | 更新屏幕畫面 |
注:額外知識(shí)點(diǎn)補(bǔ)充游戲中的坐標(biāo)系:
具體的邏輯代碼如下
使用Pygame的創(chuàng)建綠色方塊并鍵盤移動(dòng),代碼結(jié)構(gòu)主要分三部分:
- 模塊導(dǎo)入
- pygame窗口初始化
- 游戲主體
3. 1 游戲內(nèi)對(duì)象初始化
3. 2 監(jiān)聽按鍵、鼠標(biāo)事件并設(shè)置事件內(nèi)容,修改方塊位置
3. 3 依據(jù)方塊的位置寬高,重新渲染畫面和方塊
# -*- coding: utf-8 -*-
# 一、模塊導(dǎo)入
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
# 二、pygame窗口初始化
pygame.init() # 初始化pygame
size = width, height = 320, 240 # 設(shè)置窗口尺寸
screen = pygame.display.set_mode(size) # 顯示窗口
# 設(shè)置標(biāo)題
pygame.display.set_caption('創(chuàng)建綠色方塊并鍵盤移動(dòng)')
# 三、游戲主體
# 執(zhí)行死循環(huán),確保窗口一直顯示,同時(shí)監(jiān)聽關(guān)閉按鈕事件
## 3.1 游戲內(nèi)對(duì)象初始化
# 設(shè)置矩陣的屬性
rect_color = (0, 255, 0) # 綠色
rect_len = 20 # 矩陣的邊長(zhǎng)
rect_pos = [width // 2, height // 2] # 矩陣的初始位置
rect_speed = [2, 2] # 矩陣的速度
# 定義時(shí)鐘對(duì)象
clock = pygame.time.Clock()
while True:
# 3.2 監(jiān)聽按鍵、鼠標(biāo)事件并設(shè)置事件內(nèi)容,修改方塊的值
# 檢查事件
for event in pygame.event.get(): # 遍歷所有事件
if event.type == pygame.QUIT: # 如果單擊關(guān)閉按鈕
pygame.quit() # 卸載所有pygame模塊
sys.exit() # 終止當(dāng)前程序
# 檢查按鍵,并對(duì)上下左右每一個(gè)按鍵,綁定事件
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
rect_pos[0] -= rect_speed[0]
if keys[pygame.K_RIGHT]:
rect_pos[0] += rect_speed[0]
if keys[pygame.K_UP]:
rect_pos[1] -= rect_speed[1]
if keys[pygame.K_DOWN]:
rect_pos[1] += rect_speed[1]
# 3.3 依據(jù)方塊的位置寬高,重新渲染畫面和方塊
#確保方塊不會(huì)移出屏幕
rect_pos[0]=max(0,min(width-rect_len,rect_pos[0]))
rect_pos[1]=max(0,min(height-rect_len,rect_pos[1]))
# 填充背景色(每次用黑色的背景覆蓋掉舊有的畫面)
screen.fill((0,0,0))
#畫矩陣
pygame.draw.rect(screen,rect_color,(*rect_pos,rect_len,rect_len))
# 更新屏幕
pygame.display.update()
# 控制游戲刷新速度
clock.tick(60)
上述代碼中,添加了鍵盤事件檢測(cè)。pygame.key.get_pressed()能夠獲取鍵盤狀態(tài),查詢目標(biāo)按鈕的狀態(tài)并添加相應(yīng)的事件,如:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
rect_pos[0] -= rect_speed[0]
if keys[pygame.K_RIGHT]:
rect_pos[0] += rect_speed[0]
if keys[pygame.K_UP]:
rect_pos[1] -= rect_speed[1]
if keys[pygame.K_DOWN]:
rect_pos[1] += rect_speed[1]
如果按下left,則rect的x值減少,按下right,則rect的x值增加。如果按下up,則y值減少,按下down,y值增加。具體對(duì)應(yīng)關(guān)系可參考上面的pygame中的游戲坐標(biāo)系進(jìn)行理解。
3、控制綠色方塊吃掉紅色果子
游戲基本一定會(huì)涉及到游戲內(nèi)物體的交互,一個(gè)游戲的玩法核心就是交互,在設(shè)計(jì)游戲玩法的時(shí)候,各位帥哥美女們可以參考下面,設(shè)計(jì)一下交互規(guī)則。
創(chuàng)建交互規(guī)則如下:
- 1、玩家控制綠色方塊移動(dòng)
- 2、如果地圖中沒(méi)有紅色果子,在地圖任意位置,隨機(jī)生成一個(gè)果子
- 3、綠色方塊的位置與紅色果子位置一致時(shí),紅色果子刷新位置
具體的邏輯代碼如下
初始化隨機(jī)生成一個(gè)果子的位置,并渲染出來(lái)
當(dāng)二者左上角的位置距離<8 px的時(shí)候,果子刷新位置
該課程涉及到的pygame函數(shù)(不重復(fù)上一課學(xué)習(xí)到的了):
模塊名 | 功能 |
---|---|
random.randint(0, 30) | 隨機(jī)從0到30這31個(gè)數(shù)抽一個(gè)數(shù) |
np.linalg.norm(3,4)= 5 | 求一個(gè)向量的長(zhǎng)度,與sqrt(pow(x, 2) + pow(y, 2))等價(jià) |
*迭代對(duì)象(比如程序中的:*foodPosition) | 列表解包,比如:將foodPosition拆成零散的變量,而不是之前的元組 |
額外補(bǔ)充知識(shí):
具體代碼如下:
# -*- coding: utf-8 -*-
# 一、模塊導(dǎo)入
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
import random # 導(dǎo)入random模塊
import numpy as np
# 二、pygame窗口初始化
pygame.init() # 初始化pygame
size = width, height = 320, 240 # 設(shè)置窗口尺寸
screen = pygame.display.set_mode(size) # 顯示窗口
# 設(shè)置標(biāo)題
pygame.display.set_caption('3、控制綠色方塊吃掉紅色果子')
# 三、游戲主體
# 執(zhí)行死循環(huán),確保窗口一直顯示,同時(shí)監(jiān)聽關(guān)閉按鈕事件
## 3.1 游戲內(nèi)對(duì)象初始化
# 設(shè)置矩陣的屬性
rect_color = (0, 255, 0) # 綠色
rect_len = 20 # 矩陣的邊長(zhǎng)
rect_pos = [width // 2, height // 2] # 矩陣的初始位置
rect_speed = [2, 2] # 矩陣的速度
# 設(shè)置果子的初始屬性
food_color = (255,0,0 ) # 果子顏色:紅色
food_len = 15 # 果子大?。?5像素
foodPosition = (random.randint(0, width - 30) , random.randint(0, height - 30) ) # 果子的初始位置
# 定義時(shí)鐘對(duì)象
clock = pygame.time.Clock()
while True:
# 3.2 監(jiān)聽按鍵、鼠標(biāo)事件并設(shè)置事件內(nèi)容,修改方塊的值
# 檢查事件
for event in pygame.event.get(): # 遍歷所有事件
if event.type == pygame.QUIT: # 如果單擊關(guān)閉按鈕
pygame.quit() # 卸載所有pygame模塊
sys.exit() # 終止當(dāng)前程序
# 檢查按鍵,并對(duì)上下左右每一個(gè)按鍵,綁定事件
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
rect_pos[0] -= rect_speed[0]
if keys[pygame.K_RIGHT]:
rect_pos[0] += rect_speed[0]
if keys[pygame.K_UP]:
rect_pos[1] -= rect_speed[1]
if keys[pygame.K_DOWN]:
rect_pos[1] += rect_speed[1]
if np.linalg.norm((rect_pos[0]-foodPosition[0],rect_pos[1]-foodPosition[1]))<8:
foodPosition = (random.randint(0, width - 30) , random.randint(0, height - 30) ) # 果子的初始位置
# 3.3 依據(jù)方塊的位置寬高,重新渲染畫面和方塊
# 確保方塊不會(huì)移出屏幕
rect_pos[0] = max(0, min(width - rect_len, rect_pos[0]))
rect_pos[1] = max(0, min(height - rect_len, rect_pos[1]))
# 填充背景色(每次用黑色的背景覆蓋掉舊有的畫面)
screen.fill((0, 0, 0))
# 畫果子
pygame.draw.rect(screen, food_color, (*foodPosition, food_len, food_len))
# 畫矩陣
pygame.draw.rect(screen, rect_color, (*rect_pos, rect_len, rect_len))
# 更新屏幕
pygame.display.update()
# 控制游戲刷新速度
clock.tick(60)
4、控制綠色方塊吃掉紅色果子,身體長(zhǎng)度加一節(jié)
定義游戲名字:貪吃蛇
創(chuàng)建交互規(guī)則如下:
- 1、玩家控制綠色蛇移動(dòng)
- 2、如果地圖中沒(méi)有紅色果子,在地圖任意位置,隨機(jī)生成一個(gè)果子
- 3、綠色方塊的位置與紅色果子位置一致時(shí),蛇身長(zhǎng)度長(zhǎng)一節(jié)
- 4、綠色方塊的位置與紅色果子位置一致時(shí),紅色果子刷新位置
翻譯成代碼邏輯:
初始化隨機(jī)生成一個(gè)果子的位置,并渲染出來(lái)
蛇吃果子代碼邏輯:當(dāng)二者重疊超過(guò)百分之七十時(shí)候,果子刷新位置
蛇移動(dòng)代碼原理:每次在監(jiān)聽鍵盤,如果有移動(dòng)操作導(dǎo)致頭部發(fā)生改變,那么在新的位置繪制一個(gè)矩形,并插入蛇的身體列表開頭做為新的頭部。
如果這一步?jīng)]有吃到果子則彈出尾巴,有就不彈出。
該課程涉及到的pygame函數(shù)(不重復(fù)上一課學(xué)習(xí)到的了):
模塊名 | 功能 |
---|---|
pygame.Rect(x,y,width,height) | 生成pygame中的Rect對(duì)象(后面碰撞檢測(cè)會(huì)用到) |
rect1.clip(rect2) | 求兩個(gè)Rect對(duì)象的重疊矩陣 |
代碼邏輯如下:
# -*- coding: utf-8 -*-
# 一、模塊導(dǎo)入
import sys # 導(dǎo)入sys模塊
import pygame # 導(dǎo)入pygame模塊
import random # 導(dǎo)入random模塊
import numpy as np
# 二、pygame窗口初始化
pygame.init() # 初始化pygame
size = width, height = 320, 240 # 設(shè)置窗口尺寸
screen = pygame.display.set_mode(size) # 顯示窗口
# 設(shè)置標(biāo)題
pygame.display.set_caption('3、控制綠色方塊吃掉紅色果子')
# 三、游戲主體
# 執(zhí)行死循環(huán),確保窗口一直顯示,同時(shí)監(jiān)聽關(guān)閉按鈕事件
## 3.1 游戲內(nèi)對(duì)象初始化
# 設(shè)置矩陣的屬性
rect_color = (0, 255, 0) # 綠色
rect_len = 20 # 矩陣的邊長(zhǎng)
snake_len = 3
body0 = pygame.Rect(width // 2, height // 2, rect_len, rect_len) # 矩形
rect_snake_body = [body0] # 矩陣的初始位置
rect_speed = [2, 2] # 矩陣的速度
# 設(shè)置果子的初始屬性
food_color = (255, 0, 0) # 果子顏色:紅色
food_len = 15 # 果子大?。?5像素
foodPosition = (random.randint(0, width - 30), random.randint(0, height - 30)) # 果子的初始位置
food_body = pygame.Rect(*foodPosition, food_len, food_len)
# 定義時(shí)鐘對(duì)象
clock = pygame.time.Clock()
while True:
# 3.2 監(jiān)聽按鍵、鼠標(biāo)事件并設(shè)置事件內(nèi)容,修改方塊的值
# 檢查事件
for event in pygame.event.get(): # 遍歷所有事件
if event.type == pygame.QUIT: # 如果單擊關(guān)閉按鈕
pygame.quit() # 卸載所有pygame模塊
sys.exit() # 終止當(dāng)前程序
rect_pos = [rect_snake_body[0].x, rect_snake_body[0].y]
# 檢查按鍵,并對(duì)上下左右每一個(gè)按鍵,綁定事件
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
rect_pos[0] -= rect_speed[0]
if keys[pygame.K_RIGHT]:
rect_pos[0] += rect_speed[0]
if keys[pygame.K_UP]:
rect_pos[1] -= rect_speed[1]
if keys[pygame.K_DOWN]:
rect_pos[1] += rect_speed[1]
# 3.3 根據(jù)上一步的數(shù)值變化進(jìn)行,二次處理處理功能:1、不會(huì)移出屏幕。2、吃掉果子。3、蛇身移動(dòng)
# 1、確保蛇不會(huì)移出屏幕
rect_pos[0] = max(0, min(width - rect_len, rect_pos[0]))
rect_pos[1] = max(0, min(height - rect_len, rect_pos[1]))
# 2、吃掉果子邏輯
overRect = food_body.clip(rect_snake_body[0])
if overRect.width * overRect.height >= food_body.width * food_body.height * 0.7:
foodPosition = food_body.x, food_body.y = random.randint(0, width - 30), random.randint(0,height - 30) # 果子的隨機(jī)位置
snake_len += 1 # 蛇的身長(zhǎng)加1
# 3、移動(dòng)
if rect_pos[0] != rect_snake_body[0].x or rect_pos[1] != rect_snake_body[0].y:
newHead = pygame.Rect(*rect_pos, rect_len, rect_len)
rect_snake_body.insert(0, newHead)
if len(rect_snake_body) >= snake_len:
rect_snake_body.pop()
# 3.4 渲染
# 填充背景色(每次用黑色的背景覆蓋掉舊有的畫面)
screen.fill((0, 0, 0))
# 畫果子
pygame.draw.rect(screen, food_color, food_body)
# 倒序畫蛇身
for i in range(len(rect_snake_body)):
# 畫矩陣
p=rect_snake_body[len(rect_snake_body)-i-1]
pygame.draw.rect(screen, rect_color, p)
pygame.draw.rect(screen, (200,200,200), p,1)
# 更新屏幕
pygame.display.update()
# 控制游戲刷新速度
clock.tick(60)
三、pygame初級(jí)
經(jīng)過(guò)前面的學(xué)習(xí),想必各位帥哥美女對(duì)怎么用pygame寫交互邏輯有了一些初步的認(rèn)知?,F(xiàn)在讓我們學(xué)習(xí)一下:1、圖片導(dǎo)入。2、文本。3、游戲結(jié)束和重新開始。4、空格游戲暫停
初級(jí)的博客在個(gè)人博客里可以搜到,后續(xù)看反響,如果還行整理成視頻在b站發(fā)布。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-812257.html
中級(jí)的話就是工程開發(fā),將以上的全部,按照工程標(biāo)準(zhǔn)分多個(gè)文件開發(fā)。后面也會(huì)提到文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-812257.html
到了這里,關(guān)于強(qiáng)化學(xué)習(xí)Agent系列(一)——PyGame游戲編程,Python 貪吃蛇制作實(shí)戰(zhàn)教學(xué)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!