用python的tkinter做游戏 系列:
用python自带的tkinter做游戏(一)—— 贪吃蛇 篇
用python自带的tkinter做游戏(二)—— 俄罗斯方块 篇
用python自带的tkinter做游戏(三)—— 推箱子简易版 篇
用python的tkinter做游戏(四)—— 推箱子重制版 篇
用python的tkinter做游戏(五)—— 魔塔 篇
用python的tkinter做游戏(六)—— 坦克大战或射击游戏Demo 篇
用python的tkinter做游戏(七)—— 双人射击游戏Demo(类的应用) 篇
在tkinter里并没有提供图片自动缩放的功能,这导致游戏过程中画面无法放大或缩小。
这个问题我之前就想到了,也百度了一下,的确是有人已经完成了自动缩放,不过只是在初始的阶段自动匹配,并不是游戏过程中随时随地的调整大小。
于是我在前人的基础上,略作改动,使之可以随意改变大小。
缩小后的效果:
全屏放大也是可以的,效果我就不展示了,还是来谈谈是怎么实现的吧。
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,欢迎来交流~
# -*- 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()