用python的tkinter做游戏(八)—— 实现图片在tkinter中自适应大小(自动匹配窗口)

用python的tkinter做游戏 系列:

用python自带的tkinter做游戏(一)—— 贪吃蛇 篇
用python自带的tkinter做游戏(二)—— 俄罗斯方块 篇
用python自带的tkinter做游戏(三)—— 推箱子简易版 篇
用python的tkinter做游戏(四)—— 推箱子重制版 篇
用python的tkinter做游戏(五)—— 魔塔 篇
用python的tkinter做游戏(六)—— 坦克大战或射击游戏Demo 篇
用python的tkinter做游戏(七)—— 双人射击游戏Demo(类的应用) 篇

在tkinter里并没有提供图片自动缩放的功能,这导致游戏过程中画面无法放大或缩小。

这个问题我之前就想到了,也百度了一下,的确是有人已经完成了自动缩放,不过只是在初始的阶段自动匹配,并不是游戏过程中随时随地的调整大小。
于是我在前人的基础上,略作改动,使之可以随意改变大小。

随手拿了张之前魔塔的图片举例:
用python的tkinter做游戏(八)—— 实现图片在tkinter中自适应大小(自动匹配窗口)_第1张图片

缩小后的效果:
用python的tkinter做游戏(八)—— 实现图片在tkinter中自适应大小(自动匹配窗口)_第2张图片
全屏放大也是可以的,效果我就不展示了,还是来谈谈是怎么实现的吧。

def resize(w, h, w_box, h_box, pil_image):
    """
    resize a pil_image object so it will fit into 
    a box of size w_box times h_box, but retain aspect ratio 
    对一个pil_image对象进行缩放,让它在一个矩形框内,还能保持比例 
    """
    f1 = w_box/w
    f2 = h_box/h  
    factor = min(f1,f2)
    width  = int(w*factor)  
    height = int(h*factor)
    return pil_image.resize((width, height), Image.ANTIALIAS)  

这是我复制前人的代码,思路就是根据图片和窗口尺寸之间的比例,重新推算出图片缩放后所需要的尺寸,再用PIL改变其尺寸。

def pic_with_win_auto_size(w_box, h_box):
    global canvas,tk_image
    pil_image = Image.open('e.png')
    w, h = pil_image.size
    pil_image_resized = resize(w, h, w_box, h_box, pil_image)
    tk_image = ImageTk.PhotoImage(pil_image_resized)
    canvas = tk.Canvas(window, width=w_box, height=h_box)
    canvas.place(x=0,y=0)
    canvas.create_image(w_box//2, h_box//2, image=tk_image)
    window.geometry("%dx%d" % (w_box, h_box))

用刚才resize函数重新实例化成tk_image就行了,但只是如此的话只能在启动游戏时自动匹配,怎么做到游戏过程中随时自动匹配呢?

答案很简单,就是实时刷新即可。

def auto_size():
    """
    先记录窗口大小的数据,若数据发生变化,则变化图片的尺寸。
    """
    w_box = window.winfo_width()
    h_box = window.winfo_height()
    temp = [w_box,h_box]
    win_size.append(temp)
    
    if len(win_size) > 2:
        del win_size[0]
    
    if len(win_size) == 2 and win_size[0] != win_size[1]:
        pic_with_win_auto_size(w_box, h_box)

当然了,每秒数次的刷新图片尺寸也没那必要,先跟踪下窗口大小的尺寸,发现有变化了再执行即可,可以减轻些CPU负担。

def game_loop():
    global loop
    auto_size()
    loop = window.after(100, game_loop)


def close_win():
    window.after_cancel(loop)
    window.destroy()


win_size =[]
window = tk.Tk()
w_box = 576
h_box = 416
pic_with_win_auto_size(w_box, h_box)
game_loop()
window.protocol('WM_DELETE_WINDOW', close_win)
window.mainloop()

这里提一句,在after函数使用后别忘了实例化一下(loop),以便关闭窗口时可以停止循环,不然会有出错报警。

最后放上原图,改名为e.png即可。

本人WX:znix1116,欢迎来交流~

用python的tkinter做游戏(八)—— 实现图片在tkinter中自适应大小(自动匹配窗口)_第3张图片
附上代码:

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 27 12:46:27 2022

@author: Juni Zhu (wechat:znix1116)
"""

 
from PIL import Image, ImageTk  
import tkinter as tk  


def resize(w, h, w_box, h_box, pil_image):
    """
    resize a pil_image object so it will fit into 
    a box of size w_box times h_box, but retain aspect ratio 
    对一个pil_image对象进行缩放,让它在一个矩形框内,还能保持比例 
    """
    f1 = w_box/w
    f2 = h_box/h  
    factor = min(f1,f2)
    width  = int(w*factor)  
    height = int(h*factor)
    return pil_image.resize((width, height), Image.ANTIALIAS)  
  

def auto_size():
    """
    先记录窗口大小的数据,若数据发生变化,则变化图片的尺寸。
    """
    w_box = window.winfo_width()
    h_box = window.winfo_height()
    temp = [w_box,h_box]
    win_size.append(temp)
    
    if len(win_size) > 2:
        del win_size[0]
    
    if len(win_size) == 2 and win_size[0] != win_size[1]:
        pic_with_win_auto_size(w_box, h_box)


def pic_with_win_auto_size(w_box, h_box):
    global canvas,tk_image
    pil_image = Image.open('e.png')
    w, h = pil_image.size
    pil_image_resized = resize(w, h, w_box, h_box, pil_image)
    tk_image = ImageTk.PhotoImage(pil_image_resized)
    canvas = tk.Canvas(window, width=w_box, height=h_box)
    canvas.place(x=0,y=0)
    canvas.create_image(w_box//2, h_box//2, image=tk_image)
    window.geometry("%dx%d" % (w_box, h_box))
    

def game_loop():
    global loop
    auto_size()
    loop = window.after(100, game_loop)


def close_win():
    window.after_cancel(loop)
    window.destroy()


win_size =[]
window = tk.Tk()
w_box = 576
h_box = 416
pic_with_win_auto_size(w_box, h_box)
game_loop()
window.protocol('WM_DELETE_WINDOW', close_win)
window.mainloop()


你可能感兴趣的:(python,游戏,tkinter)