|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 cjjJasonchen 于 2024-8-10 15:07 编辑
Pygame 游戏开发 —— 梦开始的地方
好久不见~
不知道各位在使用pygame自带的全屏功能的时候,有没有感觉到各种不顺手呢~
今天来教大家驯服pygame自带的全屏功能~~
(此教程为进阶pygame教程,萌新退散~~~)
在小甲鱼老师的旧版教程中,曾经提到过“不建议使用窗口的拖动变形功能,因为会导致动画精灵的变形,位置错误等问题”
但这次,我发现里拖动变形的正确打开方式:
(请看vcr )
上面的视频展示了拖动窗口、全屏,背景填充,鼠标位置的设定与读取等操作,下面先看看源码:
(大概扫一眼就行,这里放出来主要是给大家运行,玩一下,感受一下和普通窗口的区别,别忘了注意控制台哦。后面我会分段细讲代码)import pygame
import sys
from pygame.locals import *
# 颜色常量
WHITE = (255,255,255)
BLACK = (0,0,0)
# 常量
WHITE = 255, 255, 255
# 设定窗口
size = width, height = [1300, 700] # 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 [bool, bool]
[窗口现在是否应该处于全屏状态,是否需要修正窗口状态]
用于修改窗口状态(大小以及是否全屏,会自动修改full_bool的值)"""
if full_bool[0] and full_bool[1]: # 现在窗口应该处于全屏状态,并且没有处于全屏状态
window = pygame.display.set_mode(pygame.display.list_modes()[0], FULLSCREEN) # 全屏窗口
full_bool[1] = False
elif full_bool[1]: # 不处于全屏状态
window = pygame.display.set_mode(size, RESIZABLE) # 自由拖拽窗口
full_bool[1] = False
return window
# 是否全屏
full_bool = [False, False] # [是否全屏,是否需要修正窗口状态]
# 得到鼠标位置
# noinspection PyShadowingNames
def get_pos(offset, ratio):
"""接受两个参数(屏幕绘制的偏移,屏幕缩放比例)"""
pos = pygame.mouse.get_pos()
pos = [(pos[0]-offset[0])/ratio,
(pos[1]-offset[1])/ratio]
return pos
# 设置鼠标位置
# noinspection PyShadowingNames
def set_pos(pos, offset, ratio):
"""接受三个参数(鼠标位置,屏幕绘制的偏移,屏幕缩放比例)"""
pos = [pos[0]*ratio+offset[0],
pos[1]*ratio+offset[1]]
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[0], displayed_screen_size[1]],
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(
[600,400],
[displayed_screen_size[0], displayed_screen_size[1]],
ratio)
print(f"鼠标位置设定为屏幕[600,400](小白点)处")
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[0] = not full_bool[0]
full_bool[1] = True
# 按键抬起事件
if event.type == KEYUP:
pass
# 窗口背景
window.fill(WHITE)
#屏幕背景
screen.fill(BLACK)
#画 xxxx
# 一个圆
pygame.draw.circle(screen, [255,0,0], [300,300], 50, width = 3)
# 白点
pygame.draw.rect(screen, rect=[600,400,5,5],color=(255,255,255))
# 刷新xxx
# 调整绘制大小,使之填充窗口
screen_rect = screen.get_rect()
window_rect = window.get_rect()
r1, r2 = abs(window_rect[2]/screen_rect[2]), abs(window_rect[3]/screen_rect[3])
if r1 < r2:
ratio = r1
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size[0], ratio*size[1]))
elif r1 > r2:
ratio = r2
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size[0], ratio*size[1]))
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 [bool, bool]
[窗口现在是否应该处于全屏状态,是否需要修正窗口状态]
用于修改窗口状态(大小以及是否全屏,会自动修改full_bool的值)"""
if full_bool[0] and full_bool[1]: # 现在窗口应该处于全屏状态,并且没有处于全屏状态
window = pygame.display.set_mode(pygame.display.list_modes()[0], FULLSCREEN) # 全屏窗口
full_bool[1] = False
elif full_bool[1]: # 不处于全屏状态
window = pygame.display.set_mode(size, RESIZABLE) # 自由拖拽窗口
full_bool[1] = False
return window
# 是否全屏
full_bool = [False, False] # [是否全屏,是否需要修正窗口状态]
先看第一个参数:window
这里先提一下本文中 window 和 screen 的定义:
小甲鱼曾经说过,pygame 通多 display.set_mode 创建的窗口(同样也是 Surface 对象),称为 window"窗口" 或 screen"屏幕" ,根据小甲鱼老师的习惯,我们一般把它称为 screen
但是,今天,我们把它称作 window , 因为 screen 还有其他任务要完成
所以,window 今天的任务就是成为一个优秀的窗口,而 screen 仅仅只负责“屏幕”(显示区域)
先看图:
上面视频中的窗口,我将他缩小了一些方便演示
这是上面视频和代码中的窗口,这一整个窗口是 "window", 但只有黑色部分属于 "screen"。
让我拖拽改变一下窗口大小:
这是拉长后的窗口
我将他拉长了,可以看到,白色的部分从上下两条变成了左右两条,屏幕变大了一些,说明此时窗口的宽度大于屏幕的宽度,高度与屏幕高度相等。
并且上面的红色圆和白色的点位置看起来没有发生变化。
所以,window的xy轴的长度都在能自由变化,而screen只是在比例缩放而已
其他的所有动画精灵等等对象可以像以前一样绘制在 screen 上,再把 screen 绘制再window上就ok辣!
好,现在大家已经知道window是什么了,我们回到代码看下一个参数~
full_bool:
这个参数中传入的就是函数后定义的列表,由两个bool值组成,第一个表示现在window是不是处于全屏状态,第二个是窗口的实际全屏状态是否与第一个布尔值的状态不一致
(在后续事件判定的代码中会判定是否全屏,但只是判定,不是修改,所以需要上面这个函数每帧修改全屏状态。)
(第二个布尔值的存在是为了防止重复重新设置屏幕全屏状态)
第三个参数size:
窗口在解除全屏后应该设置的大小
然后我们看下一段代码吧~
【约41-56行】# 得到鼠标位置
# noinspection PyShadowingNames
def get_pos(offset, ratio):
"""接受两个参数(屏幕绘制的偏移,屏幕缩放比例)"""
pos = pygame.mouse.get_pos()
pos = [(pos[0]-offset[0])/ratio,
(pos[1]-offset[1])/ratio]
return pos
# 设置鼠标位置
# noinspection PyShadowingNames
def set_pos(pos, offset, ratio):
"""接受三个参数(鼠标位置,屏幕绘制的偏移,屏幕缩放比例)"""
pos = [pos[0]*ratio+offset[0],
pos[1]*ratio+offset[1]]
pygame.mouse.set_pos(pos)
这两个函数差不多,但是可能有的鱼油不知道有什么用,为什么不用pygame默认的鼠标交互函数嘞?
上图:
拉长的窗口(带数值
如果使用pygame自带的鼠标位置计算函数:
得到的鼠标位置是[x1 + x2, y]
但如果使用上面我提供的函数:
鼠标位置是[x2 * 屏幕缩放比例,y * 屏幕缩放比例]
这问题产生的原因再上面代码讲到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[2]/screen_rect[2]), abs(window_rect[3]/screen_rect[3])
if r1 < r2:
ratio = r1
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size[0], ratio*size[1]))
elif r1 > r2:
ratio = r2
displayed_screen = pygame.transform.smoothscale(screen,
(ratio*size[0], ratio*size[1]))
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 怎么样
|
评分
-
查看全部评分
|