Python Pygame制作雪夜煙花景
運(yùn)行截圖
運(yùn)行效果:
什么?你說(shuō)你看不清煙花?那我換一種顏色,請(qǐng)點(diǎn)開(kāi)看。
實(shí)現(xiàn)過(guò)程
準(zhǔn)備工作
使用語(yǔ)言和框架:python、pygame。
安裝pygame:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn pygame
你需要知道的基礎(chǔ)知識(shí)
首先,pygame渲染是同步的,所以同屏渲染的點(diǎn)過(guò)多之后,就會(huì)造成卡頓的情況。
其次,pygame的代碼邏輯是,周期性渲染一系列的屏,從而產(chǎn)生連續(xù)的動(dòng)畫(huà)。
你需要掌握的框架基礎(chǔ)知識(shí):
初始化過(guò)程
import pygame pygame.init() pygame.mixer.init() pygame.font.init()
獲取字體
myfont = pygame.font.SysFont('simHei', 30) textsurface = myfont.render(a[i], False, random_color(150, 255)) screen.blit(textsurface, (80, 30))
畫(huà)圈
pygame.draw.circle(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2], snow_list[i][3] - 3)
加載背景音樂(lè)
screen = pygame.display.set_mode(bg_size) pygame.display.set_caption("新年快樂(lè)") bg = pygame.image.load(bg_img) pygame.mixer.music.load('D:\\CloudMusic\\小時(shí)姑娘 - 霞光-《精靈世紀(jì)》片尾曲.mp3')
核心代碼
基礎(chǔ)架子
首先,需要實(shí)現(xiàn)一個(gè)基礎(chǔ)的事件循環(huán)的架子,如下:
def main(): ? ? global show_n ? ? global fk_list ? ? bg_size = (WIN_W, WIN_H) ? ? screen = pygame.display.set_mode(bg_size) ? ? pygame.display.set_caption("新年快樂(lè)") ? ? pygame.mixer.music.load('D:\\CloudMusic\\小時(shí)姑娘 - 霞光-《精靈世紀(jì)》片尾曲.mp3') ? ? font_values = ['新年快樂(lè)'] ? ? grand_has = set() ? ? clock = pygame.time.Clock() ? ? while True: ? ? ? ? if not pygame.mixer.music.get_busy(): ? ? ? ? ? ? pygame.mixer.music.play() ? ? ? ? for event in pygame.event.get(): ? ? ? ? ? ? if event.type == pygame.QUIT: ? ? ? ? ? ? ? ? exit() ? ? ? ? screen.fill((0, 0, 0)) ? ? ? ? ... ... ? ? ? ? pygame.display.update() ? ? ? ? time_passed = clock.tick(50) if __name__ == '__main__': ? ? main()
下雪的過(guò)程
現(xiàn)在,需要實(shí)現(xiàn)下雪的過(guò)程,首先,考慮定義定義一堆初始化的下雪點(diǎn)
def init_xue(bg_size): snow_list = [] for i in range(200): x_site = random.randrange(0, bg_size[0]) # 雪花圓心位置 y_site = random.randrange(0, bg_size[1]) # 雪花圓心位置 X_shift = random.randint(-1, 1) # x 軸偏移量 radius = random.randint(4, 6) # 半徑和 y 周下降量 xxxxx = random_color(150, 255) snow_list.append([x_site, y_site, X_shift, radius, 255, 255, 255]) return snow_list
然后實(shí)現(xiàn)渲染雪的過(guò)程
def draw_xue(snow_list: [], screen, bg_size: [], grand_has: set, grand_list: []): # 雪花列表循環(huán) # todo 空中的雪 for i in range(len(snow_list)): # 繪制雪花,顏色、位置、大小 pygame.draw.circle(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2], snow_list[i][3] - 3) # 移動(dòng)雪花位置(下一次循環(huán)起效) snow_list[i][0] += snow_list[i][2] snow_list[i][1] += snow_list[i][3] # 如果雪花落出屏幕,重設(shè)位置 if snow_list[i][1] > bg_size[1]: # tmp = [] snow_list[i][1] = random.randrange(-50, -10) snow_list[i][0] = random.randrange(0, bg_size[0]) x = snow_list[i][0] y = bg_size[1] while (grand_has.__contains__(x * 10000 + y)): y = y - snow_list[i][3] grand_has.add(x * 10000 + y) grand_list.append( [x, y, snow_list[i][2], snow_list[i][3], snow_list[i][4], snow_list[i][5], snow_list[i][6]])
集成到上面的架子中,效果如下:
不過(guò)目前的下雪沒(méi)有質(zhì)感,可以考慮在底部堆一些雪,只需要在雪落到地上做特判即可。
雪落到地上堆起來(lái)的過(guò)程
在前面的下雪過(guò)程的代碼中,我們維護(hù)了一個(gè)Grand_list的數(shù)組,目的就是維護(hù)堆雪的效果
min_height = 100000 # todo 地上的積雪 for i in range(len(grand_list)): if grand_list[i][0] < 375: min_height = min(min_height, grand_list[i][1])
然后進(jìn)入維護(hù)程序:
draw_xue(snow_list, screen, bg_size, grand_has, grand_list)
最后再將雪畫(huà)出來(lái)
for i in range(len(grand_list)): pygame.draw.circle(screen, (grand_list[i][4], grand_list[i][5], grand_list[i][6]), grand_list[i][:2], grand_list[i][3] - 3)
效果圖如上。
實(shí)現(xiàn)煙花的過(guò)程
首先定義出煙花類(lèi):
class Fireworks(): ? ? is_show = False ? ? x, y = 0, 0 ? ? vy = 0 ? ? p_list = [] ? ? color = [0, 0, 0] ? ? v = 0 ? ? def __init__(self, x, y, vy, n=300, color=[0, 255, 0], v=10): ? ? ? ? self.x = x ? ? ? ? self.y = y ? ? ? ? self.vy = vy ? ? ? ? self.color = color ? ? ? ? self.v = v ? ? ? ? for i in range(n): ? ? ? ? ? ? self.p_list.append([random.random() * 2 * math.pi, 0, v * math.pow(random.random(), 1 / 3)]) ? ? def run(self): ? ? ? ? global show_n ? ? ? ? for p in self.p_list: ? ? ? ? ? ? p[1] = p[1] + (random.random() * 0.6 + 0.7) * p[2] ? ? ? ? ? ? p[2] = p[2] * 0.97 ? ? ? ? ? ? if p[2] < 1.2: ? ? ? ? ? ? ? ? self.color[0] *= 0.9999 ? ? ? ? ? ? ? ? self.color[1] *= 0.9999 ? ? ? ? ? ? ? ? self.color[2] *= 0.9999 ? ? ? ? ? ? if max(self.color) < 10 or self.y > WIN_H + p[1]: ? ? ? ? ? ? ? ? show_n -= 1 ? ? ? ? ? ? ? ? self.is_show = False ? ? ? ? ? ? ? ? break ? ? ? ? self.vy += 10 * t1 ? ? ? ? self.y += self.vy * t1
然后,我們需要畫(huà)出煙花釋放前上升的過(guò)程點(diǎn),這部分與下雪的初始化差不多。
def init_yanhua(bg_size): yanhua_list = [] for i in range(5): x_site = random.randrange(0, WIN_W) # 雪花圓心位置 y_site = WIN_H # 雪花圓心位置 X_shift = 0 # x 軸偏移量 radius = random.randint(6, 10) # 半徑和 y 周上升降量 xxxxx = random_color(150, 255) red = xxxxx[0] green = xxxxx[1] blue = xxxxx[2] yanhua_list.append([x_site, y_site, X_shift, radius, red, green, blue]) return yanhua_list
然后是畫(huà)上升過(guò)程
def draw_yanhua(yanhua_list: [], screen, bg_size: []): ? ? global fk_list ? ? for i in range(len(yanhua_list)): ? ? ? ? # 繪制雪花,顏色、位置、大小 ? ? ? ? pygame.draw.circle(screen, (yanhua_list[i][4], yanhua_list[i][5], yanhua_list[i][6]), yanhua_list[i][:2], ? ? ? ? ? ? ? ? ? ? ? ? ? ?yanhua_list[i][3] - 3) ? ? ? ?? ? ? ? ? yanhua_list[i][0] += yanhua_list[i][2] ? ? ? ? yanhua_list[i][1] -= yanhua_list[i][3] ? ? ? ? if yanhua_list[i][1] <= 0: ? ? ? ? ? ? # tmp = [] ? ? ? ? ? ? yanhua_list[i][1] = WIN_H ? ? ? ? ? ? yanhua_list[i][0] = random.randrange(0, bg_size[0]) ? ? ? ? if yanhua_list[i][1] <= random.randint(200, 400): ? ? ? ? ? ? # todo 放煙花 ? ? ? ? ? ? fk = Fireworks(yanhua_list[i][0], yanhua_list[i][1], -20, n=300, color=red_random(1, 150), v=10) ? ? ? ? ? ? fk_list.append(fk) ? ? ? ? ? ? yanhua_list[i][1] = WIN_H ? ? ? ? ? ? yanhua_list[i][0] = random.randrange(0, bg_size[0])
效果圖如下:
圈出來(lái)的就是上升過(guò)程的煙花。
最后就是綻放部分,其實(shí)在上升過(guò)程的代碼中有維護(hù),如果超過(guò)某個(gè)隨機(jī)高度,就會(huì)生成一個(gè)煙花,只是沒(méi)有渲染,現(xiàn)在我們把渲染加上。
for fk in fk_list: fk.run() for p in fk.p_list: x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0]) if random.random() < 0.055: screen.set_at((int(x), int(y)), (255, 255, 255)) else: screen.set_at((int(x), int(y)), (int(fk.color[0]), int(fk.color[1]), int(fk.color[2]))) tmp = [] for fk in fk_list: for p in fk.p_list: x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0]) if y < WIN_H - 1000: tmp.append(fk) break fk_list = tmp
最終的運(yùn)行效果就如最頂上的效果一樣。
完整代碼
將上述過(guò)程進(jìn)行組合,結(jié)果如下,感興趣的朋友可以按自己的需求進(jìn)行優(yōu)化。
import pygame import random import math pygame.init() pygame.mixer.init() pygame.font.init() WIN_W = 2200 WIN_H = 1300 t1 = 0.18 ?# 時(shí)間流速 show_n = 0 show_frequency = 0.0015 ?# 煙花綻放頻率,數(shù)值越大頻率越高 color_list = [ ? ? [255, 0, 0] ] yanhua_map = {} fk_list = [] class Fireworks(): ? ? is_show = False ? ? x, y = 0, 0 ? ? vy = 0 ? ? p_list = [] ? ? color = [0, 0, 0] ? ? v = 0 ? ? def __init__(self, x, y, vy, n=300, color=[0, 255, 0], v=10): ? ? ? ? self.x = x ? ? ? ? self.y = y ? ? ? ? self.vy = vy ? ? ? ? self.color = color ? ? ? ? self.v = v ? ? ? ? for i in range(n): ? ? ? ? ? ? self.p_list.append([random.random() * 2 * math.pi, 0, v * math.pow(random.random(), 1 / 3)]) ? ? def run(self): ? ? ? ? global show_n ? ? ? ? for p in self.p_list: ? ? ? ? ? ? p[1] = p[1] + (random.random() * 0.6 + 0.7) * p[2] ? ? ? ? ? ? p[2] = p[2] * 0.97 ? ? ? ? ? ? if p[2] < 1.2: ? ? ? ? ? ? ? ? self.color[0] *= 0.9999 ? ? ? ? ? ? ? ? self.color[1] *= 0.9999 ? ? ? ? ? ? ? ? self.color[2] *= 0.9999 ? ? ? ? ? ? if max(self.color) < 10 or self.y > WIN_H + p[1]: ? ? ? ? ? ? ? ? show_n -= 1 ? ? ? ? ? ? ? ? self.is_show = False ? ? ? ? ? ? ? ? break ? ? ? ? self.vy += 10 * t1 ? ? ? ? self.y += self.vy * t1 def random_color(l, r): ? ? return [random.randint(l, r), random.randint(l, r), random.randint(l, r)] def red_random(l, r): ? ? return [255, random.randint(l, r), random.randint(l, r)] def init_yanhua(bg_size): ? ? yanhua_list = [] ? ? for i in range(5): ? ? ? ? x_site = random.randrange(0, WIN_W) ?# 雪花圓心位置 ? ? ? ? y_site = WIN_H ?# 雪花圓心位置 ? ? ? ? X_shift = 0 ?# x 軸偏移量 ? ? ? ? radius = random.randint(6, 10) ?# 半徑和 y 周上升降量 ? ? ? ? xxxxx = random_color(150, 255) ? ? ? ? red = xxxxx[0] ? ? ? ? green = xxxxx[1] ? ? ? ? blue = xxxxx[2] ? ? ? ? yanhua_list.append([x_site, y_site, X_shift, radius, red, green, blue]) ? ? return yanhua_list def init_xue(bg_size): ? ? snow_list = [] ? ? for i in range(200): ? ? ? ? x_site = random.randrange(0, bg_size[0]) ?# 雪花圓心位置 ? ? ? ? y_site = random.randrange(0, bg_size[1]) ?# 雪花圓心位置 ? ? ? ? X_shift = random.randint(-1, 1) ?# x 軸偏移量 ? ? ? ? radius = random.randint(4, 6) ?# 半徑和 y 周下降量 ? ? ? ? xxxxx = random_color(150, 255) ? ? ? ? # red = xxxxx[0] ? ? ? ? # green = xxxxx[1] ? ? ? ? # blue = xxxxx[2] ? ? ? ? snow_list.append([x_site, y_site, X_shift, radius, 255, 255, 255]) ? ? return snow_list def draw_xue(snow_list: [], screen, bg_size: [], grand_has: set, grand_list: []): ? ? # 雪花列表循環(huán) ? ? # todo 空中的雪 ? ? for i in range(len(snow_list)): ? ? ? ? # 繪制雪花,顏色、位置、大小 ? ? ? ? pygame.draw.circle(screen, (snow_list[i][4], snow_list[i][5], snow_list[i][6]), snow_list[i][:2], ? ? ? ? ? ? ? ? ? ? ? ? ? ?snow_list[i][3] - 3) ? ? ? ? # 移動(dòng)雪花位置(下一次循環(huán)起效) ? ? ? ? snow_list[i][0] += snow_list[i][2] ? ? ? ? snow_list[i][1] += snow_list[i][3] ? ? ? ? # 如果雪花落出屏幕,重設(shè)位置 ? ? ? ? if snow_list[i][1] > bg_size[1]: ? ? ? ? ? ? # tmp = [] ? ? ? ? ? ? snow_list[i][1] = random.randrange(-50, -10) ? ? ? ? ? ? snow_list[i][0] = random.randrange(0, bg_size[0]) ? ? ? ? ? ? x = snow_list[i][0] ? ? ? ? ? ? y = bg_size[1] ? ? ? ? ? ? while (grand_has.__contains__(x * 10000 + y)): ? ? ? ? ? ? ? ? y = y - snow_list[i][3] ? ? ? ? ? ? grand_has.add(x * 10000 + y) ? ? ? ? ? ? grand_list.append( ? ? ? ? ? ? ? ? [x, y, snow_list[i][2], snow_list[i][3], snow_list[i][4], snow_list[i][5], ? ? ? ? ? ? ? ? ?snow_list[i][6]]) def draw_yanhua(yanhua_list: [], screen, bg_size: []): ? ? global fk_list ? ? for i in range(len(yanhua_list)): ? ? ? ? # 繪制雪花,顏色、位置、大小 ? ? ? ? pygame.draw.circle(screen, (yanhua_list[i][4], yanhua_list[i][5], yanhua_list[i][6]), yanhua_list[i][:2], ? ? ? ? ? ? ? ? ? ? ? ? ? ?yanhua_list[i][3] - 3) ? ? ? ? # 移動(dòng)雪花位置(下一次循環(huán)起效) ? ? ? ? yanhua_list[i][0] += yanhua_list[i][2] ? ? ? ? yanhua_list[i][1] -= yanhua_list[i][3] ? ? ? ? # 如果雪花落出屏幕,重設(shè)位置 ? ? ? ? if yanhua_list[i][1] <= 0: ? ? ? ? ? ? # tmp = [] ? ? ? ? ? ? yanhua_list[i][1] = WIN_H ? ? ? ? ? ? yanhua_list[i][0] = random.randrange(0, bg_size[0]) ? ? ? ? if yanhua_list[i][1] <= random.randint(200, 400): ? ? ? ? ? ? # todo 放煙花 ? ? ? ? ? ? fk = Fireworks(yanhua_list[i][0], yanhua_list[i][1], -20, n=300, color=red_random(1, 150), v=10) ? ? ? ? ? ? fk_list.append(fk) ? ? ? ? ? ? yanhua_list[i][1] = WIN_H ? ? ? ? ? ? yanhua_list[i][0] = random.randrange(0, bg_size[0]) def show_shi(a: list, n, screen): ? ? i = 2 * n - 1 ? ? j = 2 * n ? ? if i >= len(a): ? ? ? ? i = len(a) - 2 ? ? ? ? j = len(a) - 1 ? ? if i >= 0: ? ? ? ? myfont = pygame.font.SysFont('simHei', 30) ? ? ? ? textsurface = myfont.render(a[i], False, random_color(150, 255)) ? ? ? ? screen.blit(textsurface, (WIN_W / 2, 30)) ? ? if j >= 0: ? ? ? ? myfont = pygame.font.SysFont('simHei', 100) ? ? ? ? textsurface = myfont.render(a[j], False, red_random(1, 1)) ? ? ? ? screen.blit(textsurface, (WIN_W / 2 - 200, 50)) def main(): ? ? global show_n ? ? global fk_list ? ? bg_size = (WIN_W, WIN_H) ? ? screen = pygame.display.set_mode(bg_size) ? ? # bg_img = "./1.png" ? ? pygame.display.set_caption("新年快樂(lè)") ? ? # bg = pygame.image.load(bg_img) ? ? pygame.mixer.music.load('D:\\CloudMusic\\小時(shí)姑娘 - 霞光-《精靈世紀(jì)》片尾曲.mp3') ? ? grand_list = [] ? ? font_values = ['新年快樂(lè)'] ? ? grand_has = set() ? ? clock = pygame.time.Clock() ? ? yanhua_list = init_yanhua(bg_size) ? ? snow_list = init_xue(bg_size) ? ? # 游戲主循環(huán) ? ? while True: ? ? ? ? if not pygame.mixer.music.get_busy(): ? ? ? ? ? ? pygame.mixer.music.play() ? ? ? ? for event in pygame.event.get(): ? ? ? ? ? ? if event.type == pygame.QUIT: ? ? ? ? ? ? ? ? exit() ? ? ? ? screen.fill((0, 0, 0)) ? ? ? ? draw_yanhua(yanhua_list, screen, bg_size) ? ? ? ? if len(fk_list) != 0: ? ? ? ? ? ? print(len(fk_list)) ? ? ? ? # # 放煙花 ? ? ? ? show_shi(font_values, 0, screen) ? ? ? ? for fk in fk_list: ? ? ? ? ? ? fk.run() ? ? ? ? ? ? for p in fk.p_list: ? ? ? ? ? ? ? ? x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0]) ? ? ? ? ? ? ? ? if random.random() < 0.055: ? ? ? ? ? ? ? ? ? ? screen.set_at((int(x), int(y)), (255, 255, 255)) ? ? ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? ? ? screen.set_at((int(x), int(y)), (int(fk.color[0]), int(fk.color[1]), int(fk.color[2]))) ? ? ? ? tmp = [] ? ? ? ? for fk in fk_list: ? ? ? ? ? ? for p in fk.p_list: ? ? ? ? ? ? ? ? x, y = fk.x + p[1] * math.cos(p[0]), fk.y + p[1] * math.sin(p[0]) ? ? ? ? ? ? ? ? if y < WIN_H - 1000: ? ? ? ? ? ? ? ? ? ? tmp.append(fk) ? ? ? ? ? ? ? ? ? ? break ? ? ? ? fk_list = tmp ? ? ? ? min_height = 100000 ? ? ? ? # todo 地上的積雪 ? ? ? ? for i in range(len(grand_list)): ? ? ? ? ? ? if grand_list[i][0] < 375: ? ? ? ? ? ? ? ? min_height = min(min_height, grand_list[i][1]) ? ? ? ? draw_xue(snow_list, screen, bg_size, grand_has, grand_list) ? ? ? ? for i in range(len(grand_list)): ? ? ? ? ? ? pygame.draw.circle(screen, (grand_list[i][4], grand_list[i][5], grand_list[i][6]), grand_list[i][:2], ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?grand_list[i][3] - 3) ? ? ? ? pygame.display.update() ? ? ? ? time_passed = clock.tick(50) if __name__ == '__main__': ? ? main()
以上就是Python Pygame制作雪夜煙花景的詳細(xì)內(nèi)容,更多關(guān)于Python Pygame的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Pygame框架實(shí)現(xiàn)飛機(jī)大戰(zhàn)
- python飛機(jī)大戰(zhàn)pygame游戲框架搭建操作詳解
- python使用pygame框架實(shí)現(xiàn)推箱子游戲
- 基于Python+Pygame實(shí)現(xiàn)經(jīng)典賽車(chē)游戲
- Python Pygame實(shí)戰(zhàn)之飛機(jī)大戰(zhàn)的實(shí)現(xiàn)
- Python Pygame實(shí)戰(zhàn)之賽車(chē)游戲的實(shí)現(xiàn)
- Python?Pygame實(shí)戰(zhàn)之歡樂(lè)打地鼠游戲
- 基于python?的Pygame最小開(kāi)發(fā)框架
相關(guān)文章
Pandas查詢(xún)數(shù)據(jù)df.query的使用
本文主要介紹了Pandas查詢(xún)數(shù)據(jù)df.query的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Python 實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)-堆棧和隊(duì)列的操作方法
隊(duì)、棧和鏈表一樣,在數(shù)據(jù)結(jié)構(gòu)中非?;A(chǔ)一種數(shù)據(jù)結(jié)構(gòu),同樣他們也有各種各樣、五花八門(mén)的變形和實(shí)現(xiàn)方式。這篇文章主要介紹了Python 實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)-堆棧和隊(duì)列的操作方法,需要的朋友可以參考下2019-07-07python datetime時(shí)間格式的相互轉(zhuǎn)換問(wèn)題
這篇文章主要介紹了python datetime時(shí)間格式的相互轉(zhuǎn)換問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Python實(shí)現(xiàn)獲取亂序列表排序后的新下標(biāo)的示例
本文主要介紹了Python實(shí)現(xiàn)獲取亂序列表排序后的新下標(biāo)的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04