主题: 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

相关文章
相关标签/搜索