主題: 002.04 Tkinter 星空大戰

爲了更加熟練 Tkinter 的應用,決定只用 Tkinter 來寫一個遊戲,而不是用 Pygame, 在過程當中,出了不少很大的問題,最後留了一點已知的問題,不想在花時間去找出來,不過整個程序算跑的沒大問題.

1. 遊戲要求:

  • 星空中,羣星隨着宇宙飛船的前進,而相對運動移動
  • 敵機羣左右移動再下移,碰到安全線,玩家少一條命;敵機羣徹底被消滅後提高一關,速度再加快.
  • 玩家按鍵有左右鍵能夠左右移動,空格鍵能夠發射子彈,長按均可以持續動做,按鍵 Q 能夠隨時離開遊戲,按鍵 ESC 能夠暫停及恢復遊戲的進行.
  • 子彈碰到敵機,二者一塊兒消滅,獲得一分.

  • 屏幕中顯現關數,分數,以及玩家所剩的生命數

2. 程序撰寫說明:

  • 星空移動:轉換 3D 的星球座標 (x,y,z)/ 半徑 (r) 爲 2D 遊戲屏幕座標 (x0,y0)/ 半徑 (r0)

    factor = x - here
    x0 = y/factor
    y0 = z/factor
    r0 = r/factor複製代碼
  • 宇宙飛船及敵機

    先創建背景可透明的圖檔 (.png), 其 alpha 層透明的點值爲 0, 這樣的圖像在背景上移動,才能只顯示圖像主體,背景的星球移動纔不會被遮住。在窗口中就能夠隨便擺放或移動圖像,tkinter 做法爲以下:
    root = Tk()                                   #創建窗口
    canvas = Canvas(root,width=win.width,height=win.height) #在窗口上創建畫布 
    canvas.pack()                                 #擺上畫布
    im = Image.open('filename.png')               #開啓圖檔
    photo = ImageTk.PhotoImage(image=im)          #轉成PhotoImage物件
    Id = canvas.create_image(x, y, image=photo)   #放到畫布(x,y)位置
                                                #Id則做之後面要做任何動做的依據
    canvas.coords(Id, x, y)                       #移動位置複製代碼
  • 星球及子彈:

    基本上以畫圓來表示,左上角座標 (x0,y0), 右下角座標 (x1,y1), 填上顏色 color
    canvas.create_oval(x0, y0, x1, y1, fill=color) # 畫(橢)圓在畫布上
    canvas.coords(Id, x0, y0, x1, y1)              # 更動位置
    # 顯示及消失: 基本上以canvas.create_image及canvas.create_oval來顯示, 
    # 以canvas.delete(Id)來刪除.複製代碼
  • 多線程控制:

    設置多少毫秒之後執行 function, 如下方式就能夠起動,並定時執行。必須注意多線程互相之間可能形成問題,儘量避免,不然出錯很是難找到問題所在。除了星球,敵機及子彈的自行運動,按鍵的重複觸發也可使用,好比系統自己自帶的第一次觸發會比較慢,或觸發的間隔時間不符合要求,也能夠多線程的方式自行屏蔽處理.
    def function():
    pass    # do somthing here
    root.after(time, function)
    root.after(time, function)複製代碼
  • 碰撞偵測

    tkinter 能夠找到在某一塊區域中全部圖像的對象,並以 tag 的方式來區隔所要的對象。在敵機 create_image 及子彈 create_oval 中加入選項 tags=' 標籤 ', 咱們就能夠用 ' 標籤 ' 找到子彈與敵機的碰撞,進而消除子彈與敵機.
    overlap = canvas.find_overlapping(x0, y0, x1, y1)   # 找到對象列表
    overlap[index] in canvas.find_withtag(tag)          # 確認帶有該標籤tag的對象複製代碼
  • 透明文字:

    在畫布中的文字是沒法透明的,我是以在新建透明圖像中,畫上文字的方式來達成要求.
    font = ImageFont.truetype("filename.ttf", font_size) # 創建字型及其大小
    im = Image.new('RGBA', (width, height))              # 創建含有alpha層的空圖像
    im.putalpha(0)                                       # 設置alpha層的內容都爲0(透明)
    draw = ImageDraw.Draw(im)                            #改成ImageDraw物件
    draw.text((x,y), text, fill=color, font=font)        # 畫上文字
    image = ImageTk.PhotoImage(im)                       # 轉成PhotoImage物件
    Id = canvas.create_image(x, y, image= image)         # 放到畫布(x,y)位置複製代碼

3. 其餘說明

  • IDE

    原本用的的 Pyscripter, 可是在選寫程序中,常會出錯,而 Tkinter 中的 root.mainloop () 常會形成沒有響應沒法中止,惟一的方法只有停掉 Pyscripter, 還有在 Pyscripter 中程序執行完,仍是會殘留在系統中,尤爲是 Tkinter, 每次執行的結果都不同,更糟的是沒法執行,所以換了 Spyder, 問題就解決了,不過其偵錯的功能就沒 Pyscripter 好用,不過反正在 Tkinter 中,其偵錯的功能也沒用.
  • 在程序撰寫過程當中,最常碰到的幾個問題

    程序庫:首先,基本上找不到最完整的說明書,再來就是全部的參數沒有徹底一致的定義或用法,另外就是每一個程序庫都是別人的一片天地,要搞懂所有的內容真的很難。所以在使用時,定義,用法,功能常會出錯,又受限於制定的內容而功能不齊,不時的上網找答案.

    邏輯問題:事件處理的前後,方式,常會形成難度或產生不一樣的問題,好比使用 class, fuction, method 來撰寫一個一個的模塊,整個流程會更清楚,找起問題也會容易。像這個遊戲我大約寫了六個版本,最後才定調,其中天然是浪費了不少時間在重寫,找問題除錯,修改等等.

    已知問題:有時候子彈發射會馬上停住,但不影響遊戲的進行,子彈沒少;還有些 list 的 index 會超出範圍,同樣不影響遊戲的進行.

4. 輸出畫面

5. 程序說明

如下爲完整的程序,分爲兩部份,一個是遊戲常數,避免常要宣告 global, 因此放在另外一個檔案,便於尋找修改。原本想用 configparser 中的 config.ini 的方式來做變量的宣告,後來以爲又是另外一個主題,因此就沒有做下去。不過內容仍然保留在主程序 read_configuration () 中;其中還加了表達式功能,改成 a = '@b+c', y 就能夠讀入處理;另外就是使用 exec (public) 來做 global 宣告,exec (command) 來執行 python 的每一行輸入。程序中沒有加上任何說明,由於做者累了,哈哈哈哈!請見量,不過使用的變量名已經儘可能用來講明該變量的意義.

交流羣:887934385 須要源代碼請加羣獲取,免費提供python

相關文章
相關標籤/搜索