自學Python-tkinter-飛機大戰(簡易版)

最近有20天沒學習了,須要繼續加油啊!下面是自學的飛機大戰的思路和遇到的一些問題:canvas

一  先分析下包含的成員:app

  1. 運行的主窗口(win)dom

  2. 玩家操控的飛機(player)oop

  3. 飛機打出的子彈(bullet)學習

  4. 敵人(enemy)包含:小飛機(smallpalne)大飛機(bigpalne) 小蜜蜂(bee)spa

  5. 背景(background)  # 個人程序裏沒有添加,運行的時候會出現背景圖遮住其餘圖片的問題;一直沒搞定就不要了code

二  須要實現的功能:blog

  1. 自動產生敵機(enemy):小飛機  大飛機  小蜜蜂遊戲

  2. 子彈也是自動從(player)飛機頭處 產生 圖片

  3. 全部飛行物自動飛行(player除外)

  4. player 飛機能夠控制方向飛行

  5. 子彈能夠消滅敵機

  6. 不一樣的敵機有不一樣的血量以及損毀程度   # 這部分個人程序沒作,等後續有時間再添加上去

  7. player 飛機被敵機撞到,遊戲結束    # 此部分個人程序也沒作

三  具體運行的方法:

  1.  敵機,子彈,玩家均可以歸類爲飛行物(flyer),都具備中心點座標,長寬,飛行(move)

  2. 利用canvas.after() 不斷的運行,同時計數(count +=1);count控制敵機和子彈產生的數量,並用列表接收

  3. canvas.after() 每運行一次,全部飛行物運行一次

  4. 子彈消滅敵機:因子彈較小,直接用中心座標表示;經過判斷子彈座標是否在敵機大小的範圍內,來表示是否擊中

  5. 擊中的敵機和子彈 分別概括到一個集合中去,並與存在的敵機和子彈 進行集合相差,獲得新的存在的 敵機和子彈

四  此程序編寫時,我我的遇到的坑

  1. 最大的坑:  

    在主程序 class Win():__init__(self) 中,我將 tk以及canvas定義爲global全局變量,而後在其餘類.move中運行canvas的功能

    結果是:邏輯上徹底沒問題,但運行時各類問題,顯示徹底混亂。我的猜想:多是不在一個主程序中,tk的信息接收有問題。

    改正方法:__init__(self)中,self = tkinter.Tk(),而且全部的canvas功能都在Win()中完成,其餘類只提供數據型參數

  2. 沒解決的坑:

    2張背景圖交替在窗口內移動,單獨運行時徹底沒問題;但添加上飛機後,2張背景圖移動就出現快慢不一的問題,會出現空白。

    用canvas.move()的功能不行,用canvas.delete()和canvas.create_image()功能也不行;最後放棄了,就不添加背景了

  3. 其餘的坑:

    - 消滅敵機一開始沒想到用集合與集合相差的方法,走了很多彎路..... (當時只想到list遍歷再遍歷,當時有點傻:) ) 

    - 每一個敵機和子彈的標籤,開始用整數int表示,好像有問題;後來用str來表示,每次生成時計數並轉成str

五  如下爲個人代碼,附件爲圖片: (../  表示當前文件的上一級文件夾)

import tkinter
import random
import configparser


class Flyer():
    enemy_num = 0
    bullet_num = 0
    bg_num = 0
    hero_num = 0
    def move(self):
        if self.point_y > win_h - 2:
            return False
        else:
            self.point_x = self.point_x + self.move_x
            self.point_y = self.point_y + self.move_y
            self.point = (self.point_x, self.point_y)
            return self.point

class Smallplane(Flyer):
    def __init__(self):
        Flyer.enemy_num %= 100000
        Flyer.enemy_num += 1
        self.num = 'e' + str(Flyer.enemy_num)
        self.width = 49//px
        self.height = 36//px
        self.w = (self.width) // 2
        self.h = (self.height) // 2
        self.point_x = random.randint(5, win_w-5)
        self.point_y = -4
        self.point = (self.point_x, self.point_y)
        self.move_x = 0
        self.move_y = 1

class Bigplane(Flyer):
    def __init__(self):
        Flyer.enemy_num %= 100000
        Flyer.enemy_num += 1
        self.num = 'e' + str(Flyer.enemy_num)
        self.width = 69//px
        self.height = 99//px
        self.w = (self.width) // 2
        self.h = (self.height) // 2
        self.point_x = random.randint(7, win_w-7)
        self.point_y = -6
        self.point = (self.point_x, self.point_y)
        self.move_x = 0
        self.move_y = 2

class Bee(Flyer):
    def __init__(self):
        Flyer.enemy_num %= 100000
        Flyer.enemy_num += 1
        self.num = 'e' + str(Flyer.enemy_num)
        self.width = 60//px
        self.height = 50//px
        self.w = (self.width)//2
        self.h = (self.height)//2
        self.point_x = random.randint(7, win_w-7)
        self.point_y = -5
        self.point = (self.point_x, self.point_y)
        self.move_x = random.choice([1, -1])
        self.move_y = 1

    def move(self):
        if self.point_y > win_h - 2:
            return False
        else:
            if self.point_x < 5 or self.point_x > win_w - 5:
                self.move_x *= -1
            self.point_x = self.point_x + self.move_x
            self.point_y = self.point_y + self.move_y
            self.point = (self.point_x, self.point_y)
            return self.point




class Player():
    def __init__(self):
        self.num = str(0)
        self.width = 97//px
        self.height = 123//px
        self.point_x = win_w//2
        self.point_y = win_h - 20
        self.point = (self.point_x, self.point_y)

    def move(self, move_x=0, move_y=0):
        move_point_x = self.point_x + move_x
        move_point_y = self.point_y + move_y
        if move_point_x < 4 or move_point_x > win_w-4:
            pass
        elif move_point_y < 10 or move_point_y > win_h-10:
            pass
        else:
            self.point_x = move_point_x
            self.point_y = move_point_y
            self.point = (self.point_x, self.point_y)
        return self.point

class Bullet(Flyer):
    def __init__(self, h_pointx, h_pointy):
        Flyer.bullet_num %= 100000
        Flyer.bullet_num += 1
        self.num = 'b' + str(Flyer.bullet_num)
        self.width = 8//px
        self.height = 14//px
        self.point_x = h_pointx
        self.point_y = h_pointy - 10
        self.point = (self.point_x, self.point_y)
        self.move_x = 0
        self.move_y = -1
    def move(self):
        if self.point_y < 6:
            return False
        else:
            self.point_x = self.point_x + self.move_x
            self.point_y = self.point_y + self.move_y
            self.point = (self.point_x, self.point_y)
            return self.point


class Win(tkinter.Tk):
    def __init__(self):
        global cfg
        cfg = configparser.ConfigParser()
        cfg.read(filenames='plane_pm.cfg', encoding='utf-8')

        global px
        px = cfg.getint('canvas', 'pixel')
        global win_w
        win_w = cfg.getint('canvas', 'width')//px
        global win_h
        win_h = cfg.getint('canvas', 'height')//px

        tkinter.Tk.__init__(self)
        self.title('李卓洋的飛機大戰')
        self.resizable(width=False, height=False)


        self.canvas = tkinter.Canvas(self, width=win_w*px, height=win_h*px)
        self.canvas.grid(row=0)

        self.small_img = tkinter.PhotoImage(file='../img/smallplane.gif')

        self.big_img = tkinter.PhotoImage(file='../img/bigplane.gif')

        self.bee_img = tkinter.PhotoImage(file='../img/bee.gif')

        self.hero_img = tkinter.PhotoImage(file='../img/hero.gif')

        self.bullet_img = tkinter.PhotoImage(file='../img/bullet.gif')

        self.count = 0
        self.enemy_list = list()
        self.bullet_list = list()


        self.h = 'hero'
        self.player = Player()
        self.canvas.create_image(self.player.point_x * px, self.player.point_y * px, anchor=tkinter.CENTER,
                                image=self.hero_img, tags=self.h)

        self.bind('<Key-Up>', self.move_up)
        self.bind('<Key-Down>', self.move_down)
        self.bind('<Key-Left>', self.move_left)
        self.bind('<Key-Right>', self.move_right)


        self.win_run()



        self.mainloop()


    def move_up(self, event):
        self.canvas.delete(self.h)
        self.player.move(0, -1)
        self.canvas.create_image(self.player.point_x * px, self.player.point_y * px, anchor=tkinter.CENTER,
                                image=self.hero_img, tags=self.h)
    def move_down(self, event):
        self.canvas.delete(self.h)
        self.player.move(0, 1)
        self.canvas.create_image(self.player.point_x * px, self.player.point_y * px, anchor=tkinter.CENTER,
                                 image=self.hero_img, tags=self.h)

    def move_left(self, event):
        self.canvas.delete(self.h)
        self.player.move(-1, 0)
        self.canvas.create_image(self.player.point_x * px, self.player.point_y * px, anchor=tkinter.CENTER,
                                 image=self.hero_img, tags=self.h)

    def move_right(self, event):
        self.canvas.delete(self.h)
        self.player.move(1, 0)
        self.canvas.create_image(self.player.point_x * px, self.player.point_y * px, anchor=tkinter.CENTER,
                                 image=self.hero_img, tags=self.h)

    def flyer_proudce(self):
        if self.count % 3 == 0:

            blt = Bullet(self.player.point_x, self.player.point_y)
            self.bullet_list.append(blt)
            self.canvas.create_image(blt.point_x*px, blt.point_y*px, anchor=tkinter.CENTER,
                                     image=self.bullet_img, tags=blt.num)

        if self.count % 12 == 0:
            s = Smallplane()
            self.enemy_list.append(s)
            self.canvas.create_image(s.point_x*px, s.point_y*px, anchor=tkinter.CENTER,
                                    image=self.small_img, tags=s.num)

        if self.count % 18 == 0:
            b = Bigplane()
            self.enemy_list.append(b)
            self.canvas.create_image(b.point_x*px, b.point_y*px, anchor=tkinter.CENTER,
                                    image=self.big_img, tags=b.num)

        if self.count % 24 == 0:
            bee = Bee()
            self.enemy_list.append(bee)
            self.canvas.create_image(bee.point_x*px, bee.point_y*px, anchor=tkinter.CENTER,
                                    image=self.bee_img, tags=bee.num)

    def hit(self):
        if len(self.enemy_list) == 0:
            pass
        else:
            del_enemys = set()
            del_bullets = set()
            for i in self.enemy_list:
                for j in self.bullet_list:
                    if i.point_x-i.w < j.point_x < i.point_x+i.w and i.point_y-i.h < j.point_y < i.point_y+i.h:
                        self.canvas.delete(i.num)
                        self.canvas.delete(j.num)
                        del_enemys.add(i)
                        del_bullets.add(j)
                        continue
                    else:
                        pass
            enemy_set = set(self.enemy_list)
            bullet_set = set(self.bullet_list)
            new_enemy_list = list(enemy_set-del_enemys)
            new_bullet_list = list(bullet_set-del_bullets)
            self.enemy_list = new_enemy_list
            self.bullet_list = new_bullet_list

    def flyer_run(self):

        if len(self.enemy_list) == 0:
            pass
        else:
            new_enemy_list = list()
            for i in self.enemy_list:
                j = i.move()
                self.canvas.move(i.num, i.move_x * px, i.move_y * px)
                if j == False:
                    self.canvas.delete(i.num)
                else:
                    new_enemy_list.append(i)
            self.enemy_list = new_enemy_list


        if len(self.bullet_list) == 0:
            pass
        else:
            new_bullet_list = list()
            for k in self.bullet_list:
                v = k.move()
                self.canvas.move(k.num, k.move_x*px, k.move_y * px)
                if v == False:
                    self.canvas.delete(k.num)
                else:
                    new_bullet_list.append(k)
            self.bullet_list = new_bullet_list



    def win_run(self):
        self.count %= 1000000
        self.count += 1

        self.flyer_proudce()
        self.hit()
        self.flyer_run()


        self.canvas.after(120, self.win_run)


if __name__ == '__main__':
    win = Win()
相關文章
相關標籤/搜索