欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python?Pygame實現可控制的煙花游戲

 更新時間:2022年01月27日 10:15:26   作者:DogMonkeys  
大家好,本篇文章主要講的是Python?Pygame實現可控制的煙花游戲,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下

自控煙花升空 實現效果描述效果代碼地址解析main.pycore.pyfireworks.py 寫在最后

實現效果描述

這大過年的不弄點有意思的怎么行呢?可以考慮用編程實現一個煙花升空-爆炸-絢麗地效果。隨機的煙花也玩習慣了,這次我們用pygame實現用戶鼠標點擊屏幕實現放煙花并在指定高度綻放~

效果

效果圖

鼠標點擊時,煙花點會從屏幕底部正中心發(fā)射至鼠標點擊點處并綻放出隨機的顏色,煙花顆粒符合物理規(guī)律,看上去很和諧,并且會隨機消失做出閃爍的效果。
那么一起來看看是如何實現的吧~

代碼地址

https://gitee.com/DogMonkeys/daily-script/tree/master/fireworks 直接訪問即可

解析

main.py

import core

def main():
    core.init()
    while True:
        core.loop()

if __name__ == "__main__":
    main()

很簡單,調用core模塊中的初始化函數和主循環(huán)函數

core.py

import pygame
from fireworks import Fireworks

g_fireworks = None  # 煙花主類

def init():
    global g_fireworks
    pygame.init()
    screen = pygame.display.set_mode([800, 600])
    pygame.mouse.set_visible(1)
    pygame.display.set_caption("煙花")
    g_fireworks = Fireworks(screen)

clock = pygame.time.Clock()

def loop():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        else:
            g_fireworks.run(event)
    clock.tick(24)
    pygame.display.update()

這里為了簡化,直接使用全局變量g_fireworks保存游戲運行主類。
初始化函數中,調用pygame庫提供的初始化各項參數方法,包括設定窗口大小和標題,設定鼠標可見,等等

然后設定全局變量clock用來控制全局的幀率。(我也不知道為啥要弄一個global,但是當時就這么寫的懶得改了反正沒啥大問題,這部分的源碼未經優(yōu)化,許多地方都可以改得讓其更順暢,更符合標準。)

最后是loop主循環(huán)函數,不斷遍歷pygame事件表,如果有退出信號就退出(很正常,點擊“X”或者按alt+F4都會觸發(fā))。其他事件交給firework主類完成。

遍歷完事件后就進行迭代更新工作,不用解釋,刷新屏幕和控制幀率

接下來最重要的部分來了,控制煙花的運行!

fireworks.py

先貼出全部代碼吧:

import math
import pygame
from random import randint
from math import sin, cos, radians, tan

class Point:
    def __init__(self, idx, pos, screen, color) -> None:
        self.rad = radians(idx*6)
        self.x = pos[0]
        self.y = pos[1]
        self.t = 0
        self.screen = screen
        self.color = color
        self.v0 = 2  # 初速度
        self.limit = 51

    def get_pos(self) -> list:
        self.t += 1
        self.x += self.v0 * cos(self.rad)
        self.y -= self.v0 * sin(self.rad) - 0.08 * self.t
        return [self.x, self.y]

    def draw(self) -> None:
        if self.t >= 31:
            self.limit = randint(35, 50)
        if self.limit < self.t:
            return
        pygame.draw.circle(self.screen, self.color, self.get_pos(), 2)


class Fireworks:
    def __init__(self, screen) -> None:
        self.screen = screen
        self.pos = [-1, -1]
        # 一次只能發(fā)射一個煙花,免得出問題,刷新圖層蓋住就不好了
        self.can_fire = True

    def run(self, event) -> None:
        if event.type == pygame.MOUSEBUTTONDOWN:
            if not self.can_fire:
                return
            self.pos = pygame.mouse.get_pos()
            self.fire_to()

    def fire_to(self) -> None:
    	# 一個煙花放映過程中不允許另一個進來,不然會混亂
        self.can_fire = False
        color = (randint(0, 255), randint(0, 255), randint(0, 255))
        try:
            k = (600 - self.pos[1]) / (self.pos[0] - 400)
        except ZeroDivisionError:
            # x==400!
            # 指針指向屏幕最中間,除零錯
            pass
        tmp_x, tmp_y = 400, 600
        # 分類討論(可能有更好的算法,但這個最好理解)
        if self.pos[0] > 400:
            dX = 0.5
            dY = - dX * k
        elif self.pos[0] == 400:
            dX = 0
            dY = -0.5
        else:
            dX = -0.5
            dY = - dX * k
        v0 = 1  # 目標速度,根據dX與dY求解dX'和dY'
        # 斜方向速度
        dV = math.sqrt(dX**2 + dY**2)
        # 相似成比例求解
        dX *= v0 / dV
        dY *= v0 / dV
        while round(tmp_y) != self.pos[1]:
            tmp_x += dX
            tmp_y += dY
            self.screen.fill((0, 0, 0))
            pygame.draw.circle(self.screen, color, [tmp_x, tmp_y], 2)
            pygame.display.update()

        # 到達位置,炸開!
        self.bomb(color)
        self.can_fire = True

    def bomb(self, color) -> None:
        self.screen.fill((0, 0, 0))
        pygame.display.update()
        ps = []
        for i in range(60):
            ps.append(Point(i, self.pos, self.screen, color))
        for j in range(100):
            print(".")  # 減緩爆炸
            self.screen.fill((0, 0, 0))
            for point in ps:
                point.draw()
                print(".")  # 經測試,還是太快了
            pygame.display.update()
        self.screen.fill((0, 0, 0))

下面一部分一部分地分析

首先,導入要用到的庫,包括數學庫,隨機庫的隨機整數方法,數學庫的三角函數和弧度轉換,還有主角pygame。

Point類先放放,先說Fireworks。首先初始化類成員,然后run方法提供對事件的判斷,如果鼠標按下(pygame中,左右鍵都會觸發(fā)這個事件),就看看能不能發(fā)射(即現在有沒有煙花運行中),如果不能就提前退出,免得繼續(xù)下面的運算。
如果能,就獲取鼠標坐標并保存,然后調用發(fā)射的方法。

fire_to()方法。首先調整狀態(tài)機使之不能再發(fā)射下一個煙花;然后獲取一個隨機的顏色,然后嘗試計算一下屏幕底部中點(400, 600)到目標點的路徑斜率(pygame的坐標系:原點在左上角,x,y分別以右和下為+)。這里需要使用try,因為直線垂直于x軸時斜率不存在,即tan(2/π)=∞ (勉強理解吧…)

然后,計算坐標的增量(初步)

計算坐標增量-1

第一種情況,目標C在底部中點A的右側,即self.pos[0]>400,此時計算的k值實質上是∠A的正切,應該是正數(還是坐標系的問題,并非經典笛卡爾坐標系)。
因此煙花在x方向需要+方向運動,y使用需要-方向。設定x方向增量dX為定值0.5.那么對應的步長dY可以根據tanA乘上dX算出來。注意需要加一個負號,因為dX=0.5>0, k>0.

第二種,垂直發(fā)射,只需要y軸負增量就夠了,定值-0.5吧

第三種,如圖,C在A左側

情況三

同理計算,只是把dX設為負值,dY的表達式不變,因為此時直線AB傾角θ的正切是負值.(即k),所以乘出來dY仍為負值

計算完水平和豎直增量,如果直接測試會發(fā)現一個問題,速度分布十分不均勻,我們想實現的效果是,煙花在A->C方向上速度恒定為v0=1
這個問題可以用相似三角形解。首先根據dX和dY計算斜方向速度大?。ü垂啥ɡ恚?,然后根據v0成比例,等比縮放dX和dY即可。如下:

        v0 = 1  # 目標速度,根據dX與dY求解dX'和dY'
        # 斜方向速度
        dV = math.sqrt(dX**2 + dY**2)
        # 相似成比例求解
        dX *= v0 / dV
        dY *= v0 / dV

在后面,幾乎不怎需要數學計算:

        while round(tmp_y) != self.pos[1]:
            tmp_x += dX
            tmp_y += dY
            self.screen.fill((0, 0, 0))
            pygame.draw.circle(self.screen, color, [tmp_x, tmp_y], 2)
            pygame.display.update()

只需要解釋這個round,對tmp_y進行四舍五入,這樣就可以保證他是個整數,就可以正常根據slef.pos[1]的值合適的時候退出。
注意,這里不能用x比較,因為萬一 x==400?

接下來,如果while退出,那么進入bomb:

        ps = []
        for i in range(60):
            ps.append(Point(i, self.pos, self.screen, color))
        for j in range(100):
            print(".")  # 減緩爆炸
            self.screen.fill((0, 0, 0))
            for point in ps:
                point.draw()
                print(".")  # 經測試,還是太快了
            pygame.display.update()
        self.screen.fill((0, 0, 0))

(省略了兩行很普通的代碼.)
首先構建60個Point對象,分別存入索引,爆炸點,屏幕,顏色
然后重復構建100幀,每一幀都同時刷新60個顆粒的坐標。這里有一個特殊用法,就是在大批量循環(huán)里加入一個print調用,這樣可以減緩虛擬機運行,讓我們能夠看清煙花的效果,就是慢慢落下并消失(有更好的方法,懶),很直觀不是嗎(笑)
每一幀遍歷爆炸花并顯示,最后刷幀,很好理解。

(前方數學高能)

        self.v0 = 2  # 初速度
        self.limit = 51

    def get_pos(self) -> list:
        self.t += 1
        self.x += self.v0 * cos(self.rad)
        self.y -= self.v0 * sin(self.rad) - 0.08 * self.t
        return [self.x, self.y]

前面是初始化,后面是獲取當前坐標.這可能是最不能理解的模塊了。
首先設定一個合適的初速度,那個limit后面講。然后,每次迭代把時間自增1,模擬斜拋運動中時間的變化。
我們可以把切線方向初速度v0正交分解成x和y方向兩個速度,其中直接帶入時間變化量deltaT=1(因為self.t += 1),省的計算效率變慢。
根據水平位移公式:x=v[0]·cosθ·t,易證水平速度v1=v0cosθ
(由于math庫的三角函數要求傳參是弧度,在初始化預先轉換掉.)
縱向速度v2=v0sinθ-gt,相當于把重力給的加速度給它消掉一部分,向量加法
這里經過測試,取一個合適的重力加速度g=0.08(奇奇怪怪,但事實就是如此)

然后為了實現下落一部分時間就閃爍著消失,可以考慮讓每個顆粒自己隨機一個消失節(jié)點,到了就不畫,就能實現了。

    def draw(self) -> None:
        if self.t >= 31:
            self.limit = randint(35, 50)
        if self.limit < self.t:
            return
        pygame.draw.circle(self.screen, self.color, self.get_pos(), 2)

相關代碼,設定消失可以開始的閾值31,然后在35-50幀后消失,相關邏輯很好懂。

寫在最后

感謝一直讀到最后!通過今天的小煙花游戲希望能提高各位的編程和數學能力!

到此這篇關于Python Pygame實現可控制的煙花游戲的文章就介紹到這了,更多相關Python Pygame煙花游戲內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • pytorch下tensorboard的使用程序示例

    pytorch下tensorboard的使用程序示例

    我們都知道tensorflow框架可以使用tensorboard這一高級的可視化的工具,這篇文章主要介紹了pytorch下tensorboard的使用,需要的朋友可以參考下
    2021-10-10
  • python批量修改文件夾及其子文件夾下的文件內容

    python批量修改文件夾及其子文件夾下的文件內容

    這篇文章主要為大家詳細介紹了python批量修改文件夾及其子文件夾下的文件內容,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • python中global與nonlocal比較

    python中global與nonlocal比較

    這篇文章主要介紹了python中global與nonlocal比較,global關鍵字用來在函數或其他局部作用域中使用全局變量,nonlocal關鍵字用來在函數或其他作用域中使用外層(非全局)變量,需要的朋友可以參考下
    2014-11-11
  • Python減肥小工具輕松幫你瘦

    Python減肥小工具輕松幫你瘦

    今天小編就為大家分享一篇使用Python彈窗時刻提醒你減肥的小程序代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-09-09
  • python調用jenkinsAPI構建jenkins,并傳遞參數的示例

    python調用jenkinsAPI構建jenkins,并傳遞參數的示例

    這篇文章主要介紹了python調用jenkinsAPI構建jenkins,并傳遞參數的示例,幫助大家更好的理解和學習python,感興趣的朋友可以了解下
    2020-12-12
  • Python編程產生非均勻隨機數的幾種方法代碼分享

    Python編程產生非均勻隨機數的幾種方法代碼分享

    這篇文章主要介紹了Python編程產生非均勻隨機數的幾種方法代碼分享,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Python使用20行代碼實現微信聊天機器人

    Python使用20行代碼實現微信聊天機器人

    這篇文章主要介紹了Python使用20行代碼實現微信聊天機器人,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 設置python3為默認python的方法

    設置python3為默認python的方法

    我們知道在Windows下多版本共存的配置方法就是改可執(zhí)行文件的名字,配置環(huán)境變量。接下來通過本文給大家介紹設置python3為默認python的方法,一起看看吧
    2018-10-10
  • python如何查看微信消息撤回

    python如何查看微信消息撤回

    這篇文章主要為大家詳細介紹了python實現查看微信消息撤回的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • 聽歌識曲--用python實現一個音樂檢索器的功能

    聽歌識曲--用python實現一個音樂檢索器的功能

    本篇文章中主要介紹了用python實現一個音樂檢索器,類似于QQ音樂的搖一搖識曲,有興趣的同學可以了解一下。
    2016-11-11

最新評論