pygame窗口:任意缩放
本帖最后由 cjjJasonchen 于 2024-8-10 15:07 编辑Pygame游戏开发 —— 梦开始的地方
好久不见~
不知道各位在使用pygame自带的全屏功能的时候,有没有感觉到各种不顺手呢~{:10_297:}
今天来教大家驯服pygame自带的全屏功能~~
(此教程为进阶pygame教程,萌新退散~~~)
在小甲鱼老师的旧版教程中,曾经提到过“不建议使用窗口的拖动变形功能,因为会导致动画精灵的变形,位置错误等问题”
但这次,我发现里拖动变形的正确打开方式:
https://www.bilibili.com/video/BV1owY5eCEzq/?spm_id_from=333.999.0.0&vd_source=541f9ab6e8c1eb21e01b17c4cc2c9785
(请看vcr{:10_328:} )
上面的视频展示了拖动窗口、全屏,背景填充,鼠标位置的设定与读取等操作,下面先看看源码:
(大概扫一眼就行,这里放出来主要是给大家运行,玩一下,感受一下和普通窗口的区别,别忘了注意控制台哦。后面我会分段细讲代码)
import pygame
import sys
from pygame.locals import *
# 颜色常量
WHITE = (255,255,255)
BLACK = (0,0,0)
# 常量
WHITE = 255, 255, 255
# 设定窗口
size = width, height = # 16*50 : 9*60
window = pygame.display.set_mode(size, RESIZABLE)# 自由拖动大小
screen = pygame.Surface(size)
pygame.display.set_caption("可拖动窗口")
window_bg = WHITE
clock = pygame.time.Clock() # 时钟
delay = 60# 延时计时器(1秒)
# 检测和修正全屏
# noinspection PyShadowingNames
def check_full(window, full_bool, size):# -> None
"""接受参数 fullscreen
[窗口现在是否应该处于全屏状态,是否需要修正窗口状态]
用于修改窗口状态(大小以及是否全屏,会自动修改full_bool的值)"""
if full_bool and full_bool:# 现在窗口应该处于全屏状态,并且没有处于全屏状态
window = pygame.display.set_mode(pygame.display.list_modes(), FULLSCREEN)# 全屏窗口
full_bool = False
elif full_bool:# 不处于全屏状态
window = pygame.display.set_mode(size, RESIZABLE)# 自由拖拽窗口
full_bool = False
return window
# 是否全屏
full_bool = # [是否全屏,是否需要修正窗口状态]
# 得到鼠标位置
# noinspection PyShadowingNames
def get_pos(offset, ratio):
"""接受两个参数(屏幕绘制的偏移,屏幕缩放比例)"""
pos = pygame.mouse.get_pos()
pos = [(pos-offset)/ratio,
(pos-offset)/ratio]
return pos
# 设置鼠标位置
# noinspection PyShadowingNames
def set_pos(pos, offset, ratio):
"""接受三个参数(鼠标位置,屏幕绘制的偏移,屏幕缩放比例)"""
pos = *ratio+offset,
pos*ratio+offset]
pygame.mouse.set_pos(pos)
displayed_screen_size = size# 屏幕的矩形大小
ratio = 1# 屏幕缩放率
# 背景颜色设定
bg_color = BLACK
running = True
while running:
# 设定帧数
clock.tick(60)
# 延时计时器刷新
if delay == 0:
delay = 60
delay -= 1
# 检测并修改全屏状态
window = check_full(window, full_bool, size)
# 得到鼠标位置
pos = get_pos(, displayed_screen_size],
ratio)
# 事件检测
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# 鼠标
if event.type == MOUSEBUTTONDOWN:
if event.button == 1: # 左键按下,设置鼠标位置
pos = pygame.mouse.get_pos()
set_pos(
,
, displayed_screen_size],
ratio)
print(f"鼠标位置设定为屏幕(小白点)处")
elif event.button == 3:# 右键按下,显示鼠标位置
print(pos)
# 按键按下事件
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
#F11切换全屏
if event.key == K_F11:
full_bool = not full_bool
full_bool = True
# 按键抬起事件
if event.type == KEYUP:
pass
# 窗口背景
window.fill(WHITE)
#屏幕背景
screen.fill(BLACK)
#画 xxxx
# 一个圆
pygame.draw.circle(screen, , , 50, width = 3)
# 白点
pygame.draw.rect(screen, rect=,color=(255,255,255))
# 刷新xxx
# 调整绘制大小,使之填充窗口
screen_rect = screen.get_rect()
window_rect = window.get_rect()
r1, r2 = abs(window_rect/screen_rect), abs(window_rect/screen_rect)
if r1 < r2:
ratio = r1
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size, ratio*size))
elif r1 > r2:
ratio = r2
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size, ratio*size))
else:
ratio = 1
displayed_screen = screen
displayed_screen_size = displayed_screen.get_rect()
displayed_screen_size.center = window_rect.center
window.blit(displayed_screen,displayed_screen_size)
# 刷新界面
pygame.display.update()
好的,下面我们开始逐一讲解代码:
(默认各位都有pygame基础,有很多能网上轻易查到的和注释写的就不细说了)
首先看这段修改和检测窗口拖动与全屏模式的函数【约24-39行】
# 检测和修正全屏
# noinspection PyShadowingNames
def check_full(window, full_bool, size):# -> None
"""接受参数 fullscreen
[窗口现在是否应该处于全屏状态,是否需要修正窗口状态]
用于修改窗口状态(大小以及是否全屏,会自动修改full_bool的值)"""
if full_bool and full_bool:# 现在窗口应该处于全屏状态,并且没有处于全屏状态
window = pygame.display.set_mode(pygame.display.list_modes(), FULLSCREEN)# 全屏窗口
full_bool = False
elif full_bool:# 不处于全屏状态
window = pygame.display.set_mode(size, RESIZABLE)# 自由拖拽窗口
full_bool = False
return window
# 是否全屏
full_bool = # [是否全屏,是否需要修正窗口状态]
先看第一个参数:window
这里先提一下本文中 window 和 screen 的定义:
小甲鱼曾经说过,pygame 通多 display.set_mode 创建的窗口(同样也是 Surface 对象),称为 window"窗口" 或 screen"屏幕" ,根据小甲鱼老师的习惯,我们一般把它称为 screen
但是,今天,我们把它称作 window , 因为 screen 还有其他任务要完成{:10_275:}
所以,window 今天的任务就是成为一个优秀的窗口,而 screen 仅仅只负责“屏幕”(显示区域)
先看图:
这是上面视频和代码中的窗口,这一整个窗口是 "window", 但只有黑色部分属于 "screen"。
让我拖拽改变一下窗口大小:
我将他拉长了,可以看到,白色的部分从上下两条变成了左右两条,屏幕变大了一些,说明此时窗口的宽度大于屏幕的宽度,高度与屏幕高度相等。
并且上面的红色圆和白色的点位置看起来没有发生变化。
所以,window的xy轴的长度都在能自由变化,而screen只是在比例缩放而已
其他的所有动画精灵等等对象可以像以前一样绘制在 screen 上,再把 screen 绘制再window上就ok辣!
好,现在大家已经知道window是什么了,我们回到代码看下一个参数~
full_bool:
这个参数中传入的就是函数后定义的列表,由两个bool值组成,第一个表示现在window是不是处于全屏状态,第二个是窗口的实际全屏状态是否与第一个布尔值的状态不一致
(在后续事件判定的代码中会判定是否全屏,但只是判定,不是修改,所以需要上面这个函数每帧修改全屏状态。)
(第二个布尔值的存在是为了防止重复重新设置屏幕全屏状态)
第三个参数size:
窗口在解除全屏后应该设置的大小
{:10_275:}
然后我们看下一段代码吧~
【约41-56行】
# 得到鼠标位置
# noinspection PyShadowingNames
def get_pos(offset, ratio):
"""接受两个参数(屏幕绘制的偏移,屏幕缩放比例)"""
pos = pygame.mouse.get_pos()
pos = [(pos-offset)/ratio,
(pos-offset)/ratio]
return pos
# 设置鼠标位置
# noinspection PyShadowingNames
def set_pos(pos, offset, ratio):
"""接受三个参数(鼠标位置,屏幕绘制的偏移,屏幕缩放比例)"""
pos = *ratio+offset,
pos*ratio+offset]
pygame.mouse.set_pos(pos)
这两个函数差不多,但是可能有的鱼油不知道有什么用,为什么不用pygame默认的鼠标交互函数嘞?
上图:
如果使用pygame自带的鼠标位置计算函数:
得到的鼠标位置是
但如果使用上面我提供的函数:
鼠标位置是
这问题产生的原因再上面代码讲到window和screen定义时用加粗字表示出来了,没看到的可以爬楼回去看哦~
第一个参数pos:
和pygame的set_pos一样,设置鼠标的位置,但是不同的是我设置鼠标在screen中的位置,而pygame设置了在window中的位置
第二个参数:offset
可以理解为是 x1 的部分
第三个参数:ratio
可以理解为screen缩放的比例
(当然后面两个参数都在每帧代码末尾已经算好了,你们只需要填写第一个参数就可以啦~)
下一段【约134-151】:
# 调整绘制大小,使之填充窗口
screen_rect = screen.get_rect()
window_rect = window.get_rect()
r1, r2 = abs(window_rect/screen_rect), abs(window_rect/screen_rect)
if r1 < r2:
ratio = r1
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size, ratio*size))
elif r1 > r2:
ratio = r2
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size, ratio*size))
else:
ratio = 1
displayed_screen = screen
displayed_screen_size = displayed_screen.get_rect()
displayed_screen_size.center = window_rect.center
window.blit(displayed_screen,displayed_screen_size)
这一段负责调整screen,将其放大或缩小(这里是按window短边比例计算,实际应用时可以灵活调整,按照长边或各计算50%都是可以的)
首先,得到窗口和屏幕的大小,
得到x轴和y轴长度比例,
判断得出短边,将screen大小改变为刚好顶满短边。
然后把screen放在window中间~
好啦,讲解结束~鱼油们学会了吗~~~
通俗来讲呢,上面这套框架的使用方法就是:
将原版游戏中绘制在原本screen上(本文中称window)的任何东西,都绘制在新的screen上,把这个screen当成原来的screen一样用就可以了。
但是要注意鼠标的交互函数,set_pos 和 get_pos 不能再使用原来的,要根据教程使用上面我提供的。
同时,只需要移动,旋转,缩放screen,就可以完成"震动反馈""地图拖动"等等高端操作,
不过话说,这层screen已经有它的工作了,为何不再加一层呢?不如就叫 word 怎么样{:10_307:}
妹人吗 @不二如是 @KeyError @中英文泡椒 @歌者文明清理员 @zhangchenyvn @小甲鱼 @Mike_python小 @学习编程中的Ben @python爱好者. @过默 @凌凌祺 @学习学习在研究 @flyps @某一个“天” @tommyyu @陶远航 @zhangjinxuan @python爱好者. @liuhongrun2022 @zhangchenyvn @Ewan-Ahiouy @琅琊王朝
没人看喔,浅浅@一下{:10_259:} cjjJasonchen 发表于 2024-8-11 11:45
@不二如是 @KeyError @中英文泡椒 @歌者文明清理员 @zhangchenyvn @小甲鱼 @Mike_python小 @学习编程中的Be ...
{:10_275:}来了来了 支持一下~ cjjJasonchen 发表于 2024-8-11 11:45
@不二如是 @KeyError @中英文泡椒 @歌者文明清理员 @zhangchenyvn @小甲鱼 @Mike_python小 @学习编程中的Be ...
来啦来啦{:10_254:} {:10_256:}不错,好极了
就需要有这种探索精神的鱼油{:10_275:} \{:10_279:} 感谢分享 还需要更多热度@KeyError @中英文泡椒 @歌者文明清理员 @zhangchenyvn @小甲鱼 @Mike_python小 @学习编程中的Ben @python爱好者. @过默 @凌凌祺 @学习学习在研究 @flyps @某一个“天” @tommyyu @陶远航 @zhangjinxuan @python爱好者. @liuhongrun2022 @zhangchenyvn @Ewan-Ahiouy @琅琊王朝 支持 不二如是 发表于 2024-8-21 20:29
还需要更多热度@KeyError @中英文泡椒 @歌者文明清理员 @zhangchenyvn @小甲鱼 @Mike_python小 @学习编程 ...
已经支持,评分+淘帖 蛮有意思的,后续来学习这块 终于军训回来了,支持
页:
[1]