自学Python-tkinter-飞机大战(简易版)

最近有20天没学习了,需要继续加油啊!下面是自学的飞机大战的思路和遇到的一些问题:

一  先分析下包含的成员:

  1. 运行的主窗口(win)

  2. 玩家操控的飞机(player)

  3. 飞机打出的子弹(bullet)

  4. 敌人(enemy)包含:小飞机(smallpalne)大飞机(bigpalne) 小蜜蜂(bee)

  5. 背景(background)  # 我的程序里没有添加,运行的时候会出现背景图遮住其他图片的问题;一直没搞定就不要了

二  需要实现的功能:

  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('', self.move_up)
        self.bind('', self.move_down)
        self.bind('', self.move_left)
        self.bind('', 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()

 

 

 

  

 

转载于:https://www.cnblogs.com/lzybb/p/10613508.html

你可能感兴趣的:(自学Python-tkinter-飞机大战(简易版))