[关闭]
@yanglt7 2018-12-09T12:22:48.000000Z 字数 8082 阅读 1276

Pygame03_transform 模块

Pygame


3.1 显示模式

通过 display 模块的 set_mode() 方法来指定界面大小,并返回一个 Surface 对象。

set_mode() 方法:

  1. set_mode(resolution = (0, 0), flags = 0, depth = 0) - > Surface

此处输入图片的描述

3.2 设置全屏

开启全屏模式只需设置第二个参数为 FULLSCREEN 即可,同时可以加上硬件加速 HWSURFACE:

  1. screen = pygame.display.set_mode((640, 480), FULLSCREEN | HWSURFACE)

还需添加一个快捷键使得全屏模式得到控制:

  1. ...
  2. fullscreen = False
  3. ...
  4. # 全屏(F11)
  5. if event.key == K_F11:
  6. fullscreen = not fullscreen
  7. if fullscreen:
  8. screen = pygame.display.set_mode((1920, 1080), FULLSCREEN | HWSURFACE)
  9. else:
  10. screen = pygame.display.set_mode(size)
  11. ...

为了确保可以正常关闭程序,使用 F11 作为切换全屏模式到窗口模式的快捷键,这里已知显示器的当前分辨率是 1920 * 1080 像素,所以设置全屏后的尺寸为显示器的尺寸。由于不同机器的显示器分辨率不完全相同,所以应获取当前显示器支持的分辨率。可以用 list_modes 方法实现:

此处输入图片的描述

3.3 使窗口尺寸可变

Pygame 的窗口默认是不可通过拖动边框来修改尺寸的。可以通过设置 RESIZABLE 选项实现窗口尺寸可变:

例 3

  1. ...
  2. # 用户调整窗口尺寸
  3. if event.type == VIDEORESIZE:
  4. size = event.size
  5. width, height = size
  6. print(size)
  7. screen = pygame.display.set_mode(size, RESIZABLE)
  8. ...

此处输入图片的描述

开启了窗口尺寸可修改选项后,一旦用户调整窗口尺寸,Pygame 就会发送一条带有最新尺寸的 VIDEORESIZE 事件到事件序列中。程序随即做出响应,重新设置 width 和 height 的值并重建一个新尺寸的窗口。

3.4 图像的变换

Pygame 的 transform 模块可以对图像(即 Surface 对象)做各种变换动作,并返回变换后的 Surface 对象。

此处输入图片的描述

其实 transform 模块的这些方法都是像素转换,原理是通过使用一定的算法对图片进行像素位置修改。大多数方法在变换后难免会有一些精度的损失(flip() 方法不会),因此不建议对变换后的 Surface 对象进行再次变换。

在前面的例子中,就是采用 flip() 方法让小乌龟可以在撞墙后自动“掉头”。

例 4 实现小乌龟的缩放。

  1. ...
  2. # 设置放大缩小的比例
  3. ratio = 1.0
  4. oturtle = pygame.image.load("turtle.png")
  5. turtle = oturtle
  6. oturtle_rect = oturtle.get_rect()
  7. position = turtle_rect = oturtle_rect
  8. ...
  9. # 放大、缩小小乌龟(=\-),空格键恢复原始尺寸
  10. if event.key == K_EQUALS or event.key == K_MINUS or event.key == K_SPACE:
  11. # 最大只能放大一倍,缩小50%
  12. if event.key == K_EQUALS and ratio < 2:
  13. ratio += 0.1
  14. if event.key == K_MINUS and ratio > 0.5:
  15. ratio -= 0.1
  16. if event.key == K_SPACE:
  17. ratio = 1.0
  18. turtle = pygame.transform.smoothscale(oturtle, \
  19. (int(oturtle_rect.width * ratio), \
  20. int(oturtle_rect.height * ratio)))
  21. # 相应修改龟头两个朝向的 Surface 对象,否则一单击移动就打回原形
  22. l_head = turtle
  23. r_head = pygame.transform.flip(turtle, True, False)
  24. # 获得小乌龟缩放后的新尺寸
  25. turtle_rect = turtle.get_rect()
  26. position.width, position.height = turtle_rect.width, turtle_rect.height
  27. ...

此处输入图片的描述

例 5 通过 rotate() 方法让小乌龟实现贴边行走。

rotate(Surface, angle) 方法的第二个参数 angle 指定旋转的角度,是按逆时针方向旋转的。

此处输入图片的描述

  1. import pygame
  2. import sys
  3. from pygame.locals import *
  4. pygame.init()
  5. size = width, height = 800, 800
  6. bg = (255, 255, 255)
  7. clock = pygame.time.Clock()
  8. screen = pygame.display.set_mode(size)
  9. pygame.display.set_caption("初次见面,请多多关照!")
  10. turtle = pygame.image.load("turtle.png")
  11. position = turtle_rect = turtle.get_rect()
  12. # 小乌龟顺时针行走
  13. speed = [5, 0]
  14. turtle_right = pygame.transform.rotate(turtle, 90)
  15. turtle_top = pygame.transform.rotate(turtle, 180)
  16. turtle_left = pygame.transform.rotate(turtle, 270)
  17. turtle_bottom = turtle
  18. # 刚开始走顶部
  19. turtle = turtle_top
  20. l_head = turtle
  21. r_head = pygame.transform.flip(turtle, True, False)
  22. while True:
  23. for event in pygame.event.get():
  24. if event.type == pygame.QUIT:
  25. sys.exit()
  26. position = position.move(speed)
  27. if position.right > width:
  28. turtle = turtle_right
  29. # 变换后矩形的尺寸发生改变
  30. position = turtle_rect = turtle.get_rect()
  31. # 矩形尺寸的改变导致位置也有变化
  32. position.left = width - turtle_rect.width
  33. speed = [0, 5]
  34. if position.bottom > height:
  35. turtle = turtle_bottom
  36. position = turtle_rect = turtle.get_rect()
  37. position.left = width - turtle_rect.width
  38. position.top = height - turtle_rect.height
  39. speed = [-5, 0]
  40. if position.left < 0:
  41. turtle = turtle_left
  42. positon = turtle_rect = turtle.get_rect()
  43. position.top = height - turtle_rect.height
  44. speed = [0, -5]
  45. if position.top < 0:
  46. turtle = turtle_top
  47. position = turtle_rect = turtle.get_rect()
  48. speed = [5, 0]
  49. screen.fill(bg)
  50. screen.blit(turtle, position)
  51. pygame.display.flip()
  52. clock.tick(30)

此处输入图片的描述

3.5 裁剪图像

第一次拖动鼠标左键确定裁剪的范围,如下图所示:

此处输入图片的描述

第二次拖动鼠标左键裁剪范围内的图像,如下图所示:

此处输入图片的描述

第三次单击则表示重新开始,如下图所示:

此处输入图片的描述

使用 draw.rect() 来绘制矩形:

  1. rect(Surface, color, Rect, width = 0) -> Rect

裁剪操作可以利用 subsurface() 方法来获得指定位置的子图像,然后 copy() 出来:

  1. capture = screen.subsurface(select_rect).copy()

例 6

  1. import pygame
  2. import sys
  3. from pygame.locals import *
  4. pygame.init()
  5. size = width, height = 600, 600
  6. bg = (255, 255, 255)
  7. clock = pygame.time.Clock()
  8. screen = pygame.display.set_mode(size)
  9. pygame.display.set_caption("FichC Demo")
  10. turtle = pygame.image.load("turtle.png")
  11. # 0 -> 未选择,1 -> 选择中, 2 -> 完成选择
  12. select = 0
  13. select_rect = pygame.Rect(0, 0, 0, 0)
  14. # 0 -> 未拖拽,1 -> 拖拽中, 2 -> 完成拖拽
  15. drag = 0
  16. position = turtle.get_rect()
  17. position.center = width // 2, height // 2
  18. while True:
  19. for event in pygame.event.get():
  20. if event.type == pygame.QUIT:
  21. sys.exit()
  22. elif event.type == MOUSEBUTTONDOWN:
  23. if event.button == 1:
  24. # 第一次点击,选择范围
  25. if select == 0 and drag == 0:
  26. pos_start = event.pos
  27. select = 1
  28. # 第二次点击,拖拽图像
  29. elif select == 2 and drag == 0:
  30. capture = screen.subsurface(select_rect).copy()
  31. cap_rect = capture.get_rect()
  32. drag = 1
  33. # 第三次点击,初始化
  34. elif select == 2 and drag == 2:
  35. select = 0
  36. drag = 0
  37. elif event.type == MOUSEBUTTONUP:
  38. if event.button == 1:
  39. # 第一次释放,结束选择
  40. if select == 1 and drag == 0:
  41. pos_stop = event.pos
  42. select = 2
  43. # 第二次释放,结束拖拽
  44. if select == 2 and drag == 1:
  45. drag = 2
  46. screen.fill(bg)
  47. screen.blit(turtle, position)
  48. # 实时绘制选择框
  49. if select:
  50. mouse_pos = pygame.mouse.get_pos()
  51. if select == 1:
  52. pos_stop = mouse_pos
  53. select_rect.left, select_rect.top = pos_start
  54. select_rect.width, select_rect.height = pos_stop[0] - pos_start[0], pos_stop[1] - pos_start[1]
  55. pygame.draw.rect(screen, (0, 0, 0), select_rect, 1)
  56. # 拖拽裁剪的图像
  57. if drag:
  58. if drag == 1:
  59. cap_rect.center = mouse_pos
  60. screen.blit(capture, cap_rect)
  61. pygame.display.flip()
  62. clock.tick(30)

此处输入图片的描述

3.6 转换图片

图像是特定像素的组合,而 Surface 对象是 Pygame 对图像的描述。

image.load() 载入图片后将返回一个 Surface 对象,如果直接用,没有对其进行转换,效率相对较低。如果希望 Pygame 尽可能高效地处理图片,那么应该在载入图片后调用 convert() 方法进行转换:

  1. background = pygame.image.load("background.jpg").convert()

这里转换的是“像素格式”,image.load() 返回的 Surface 对象中保留了原图像的像素格式。在调用 blit() 方法的时候,如果两个 Surface 对象的像素格式不同,那么 Pygame 会实时地进行转换,这是相当费时的操作。

一般情况下用 RGB 来描述一个颜色,而在游戏开发中常常用 RGBA 来描述。这个 A 是指 Alpha 通道,用于表示透明度,它的值也是 0~255,0 表示完全透明,255 表示完全不透明。 image.load() 支持多种格式的图片导入,对于包含 alpha 通道的图片,使用 convert_alpha() 转换格式,否则使用 convert():

  1. turtle = pygame.image.load("turtle.png").convert_alpha()

3.7 透明度分析

Pygame 支持三种类型的透明度设置:colorkeys, surface alphas 和 pixel alphas。

colorkeys 和 surface alphas 可以混合使用,而 pixel alphas 不能和其他类型混合。

简单来说,由 convert() 方法转换来的 Surface 对象支持 colorkeys 和 surface alphas 设置透明度并且可以混合设置。而 convert_alpha() 方法转换后是支持 pixel alphas,也就是这个图片本身每个像素都带有 alpha 通道(所以载入一个带 alpha 通道的 png 图片,可以看到该图片部分位置是透明的)。

例 7-1 载入 turtle.jpg,使用 set_colorkeys()方法视图将白色的背景透明化。

  1. import pygame
  2. import sys
  3. from pygame.locals import *
  4. pygame.init()
  5. size = width, height = 500, 300
  6. bg = (255, 255, 255)
  7. clock = pygame.time.Clock()
  8. screen = pygame.display.set_mode(size)
  9. pygame.display.set_caption("FichC Demo")
  10. turtle = pygame.image.load("turtle.jpg").convert()
  11. background = pygame.image.load("background.jpg").convert()
  12. position = turtle.get_rect()
  13. position.center = width // 2, height // 2
  14. turtle.set_colorkey((255, 255, 255))
  15. while True:
  16. for event in pygame.event.get():
  17. if event.type == pygame.QUIT:
  18. sys.exit()
  19. screen.blit(background, (0, 0))
  20. screen.blit(turtle, position)
  21. pygame.display.flip()
  22. clock.tick(30)

此处输入图片的描述

例 7-2 使用 set_alpha() 方法调节整个图片的透明度。

  1. ...
  2. turtle.set_alpha(200)
  3. ...

此处输入图片的描述

例 7-3 set_colorkey() 和 set_alpha() 混合使用。

  1. ...
  2. turtle.set_colorkey((255, 255, 255))
  3. turtle.set_alpha(200)
  4. ...

此处输入图片的描述

例 7-4 turtle1.png 是带有 alpha 通道的,并且背景被设置成透明,可直接载入

  1. ...
  2. turtle = pygame.image.load("turtle1.png").convert_alpha()
  3. ...

此处输入图片的描述

如果希望调整小乌龟自身的透明度,可以用 get_at() 获取单个像素的颜色,并用 set_at() 来修改。get_at() 和 set_at() 使用的是 RGBA 颜色,也就是带 Alpha 通道的 RGB 颜色:

例 7-5

  1. ...
  2. print(turtle.get_at(position.center))
  3. ...

此处输入图片的描述

例 7-6 逐个像素修改透明度,将整个小乌龟的透明度调整为 200。

  1. ...
  2. for i in range(position.width):
  3. for j in range(position.height):
  4. temp = turtle.get_at((i, j))
  5. if temp[3] != 0:
  6. temp[3] = 200
  7. turtle.set_at((i, j), temp)
  8. ...

此处输入图片的描述

例 7-7

1)首先创造一个不带 alpha 通道的小乌龟;
2)然后将小乌龟所在位置的背景覆盖上去;
3)此刻 temp 得到的是一个跟小乌龟尺寸一样大小、上边绘制着背景的 Surface 对象;
4)将带 alpha 通道的小乌龟覆盖上去;
5)由于 temp 是不带 alpha 通道的 Surface 对象,因此使用 set_alpha() 方法设置整个图片的透明度;
6)最后将设置好透明度的 temp “贴” 到指定位置上,完成任务。

  1. import pygame
  2. import sys
  3. from pygame.locals import *
  4. pygame.init()
  5. size = width, height = 500, 300
  6. bg = (255, 255, 255)
  7. clock = pygame.time.Clock()
  8. screen = pygame.display.set_mode(size)
  9. pygame.display.set_caption("FichC Demo")
  10. turtle = pygame.image.load("turtle1.png").convert_alpha()
  11. background = pygame.image.load("background.jpg").convert()
  12. position = turtle.get_rect()
  13. position.center = width // 2, height // 2
  14. def blit_alpha(target, source, location, opacity):
  15. x = location[0]
  16. y = location[1]
  17. temp = pygame.Surface((source.get_width(), source.get_height())).convert()
  18. temp.blit(target, (-x, -y))
  19. temp.blit(source, (0 ,0))
  20. temp.set_alpha(opacity)
  21. target.blit(temp, location)
  22. while True:
  23. for event in pygame.event.get():
  24. if event.type == pygame.QUIT:
  25. sys.exit()
  26. screen.blit(background, (0, 0))
  27. blit_alpha(screen, turtle, position, 200)
  28. pygame.display.flip()
  29. clock.tick(30)

此处输入图片的描述

摘自《零基础入门学习Python》

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注