pygame 模块学习四

如何移动图像?

许多不熟悉编程和图形的人都很难弄清楚如何使图像在屏幕上移动。如果不理解所有概念,可能会造成混乱。

首先我们要认识屏幕上只有像素

Pygame有一个显示对象Surface。这基本上是在屏幕上可见的图像,并且该图像由像素组成。更改这些像素的主要方法是调用blit()函数。这会将像素从一个图像复制到另一个图像上(这个在pygame学习二中中已经解释了)。

这是首先要了解的。将图像复制到屏幕上时,只是在更改屏幕上像素的颜色。不会添加或移动像素,我们只是更改屏幕上已经存在的像素的颜色。这些在屏幕上显示的图像也是pygame中的Surface,但它们绝不连接到显示Surface。当它们在屏幕上变白时,它们将被复制到显示器中,但是我们仍然拥有原始文件的唯一副本。

有了这个简短的描述。实际上,我们根本不移动任何东西。我们只是将图像调到新的位置。但是在将图像绘制到新位置之前,我们需要“擦除”旧图像。否则,图像将在屏幕上的两个位置可见。通过快速擦除图像并在新位置重新绘制图像,我们实现了运动的“幻觉”。

在这里我们可能已经有问题了。就像,我们如何在将其绘制到新位置之前“擦除”图像?


让我们退后一步
也许像素和图像的概念对我们来说还是有点陌生​​?好消息,在接下来的内容中,我们将使用代码来完成我们想要的一切,而不使用像素。我们将创建一个由6个数字组成的小python列表,并想象它代表了我们可以在屏幕上看到的一些奇妙的图形。

因此,让我们从创建屏幕列表开始,并用1s和2s的美丽风景填充它。

1 >>>screen= [1、2、2、2、1]
2 >>>print(screen)
3 [1、1、2、2、2、1]


现在,我们已经创建了背景。我们将创建一个用数字8表示的强大英雄。让我们将他粘在地图中间,看看它是什么样。

1 >>>screen[3] = 8
2 >>>print(screen)
3 [1、1、2、8、2、1]


如果使用pygame进行一些图形编程,那可能就已经达到了极限。屏幕上有一些漂亮的东西,但是它无法移动到任何地方。也许现在我们的屏幕只是一个数字列表,所以更容易看到如何移动他


使英雄数字8动起来
在我们开始移动角色之前。我们需要为他保留某种位置。在上一步骤,当我们绘制他时,我们只是选择了一个任意位置。

1 >>> playerpos = 3
2 >>> screen[playerpos] = 8
3 >>> print screen
4 [1, 1, 2, 8, 2, 1]


现在很容易将他转移到新职位。我们简单地更改playerpos的值,然后再次将其绘制在屏幕上。

>>> playerpos = playerpos - 1
>>> screen[playerpos] = 8
>>> print screen
[1, 1, 8, 8, 2, 1]


好了,现在我们可以看到两个英雄。一位在原来的位置,一位在新的位置。这正是我们在将英雄吸引到新位置之前需要“擦除”其旧位置的原因。要擦除他,我们需要将列表中的值更改回英雄出现之前的值。这意味着我们需要在英雄替换它们之前跟踪屏幕上的值。我们可以通过多种方式执行此操作,但是最简单的方法通常是保留初始屏幕背景的单独副本。这意味着我们需要对我们的小游戏进行一些更改。


创建地图
我们要做的是创建一个单独的列表,我们将其称为背景。我们将创建背景,使其看起来与原始屏幕一样,分别为1和2。然后,我们将每个项目从后台复制到屏幕。

 1 >>> background = [1, 1, 2, 2, 2, 1]
 2 >>> screen = [0]*6                         #在创建一个新的空屏幕
 3 >>> for i in range(6):
 4 ...     screen[i] = background[i]
 5 >>> print screen
 6 [1, 1, 2, 2, 2, 1]
 7 >>> playerpos = 3
 8 >>> screen[playerpos] = 8
 9 >>> print screen
10 [1, 1, 2, 8, 2, 1]

使英雄动弹(2)
这一次可以很容易地移动英雄。 首先,我们将删除英雄的旧职位。 为此,我们将背景的正确值复制到屏幕上。 然后,我们将在屏幕上的新位置绘制角色

1 >>> print screen
2 [1, 1, 2, 8, 2, 1]
3 >>> screen[playerpos] = background[playerpos]
4 >>> playerpos = playerpos - 1
5 >>> screen[playerpos] = 8
6 >>> print screen
7 [1, 1, 8, 2, 2, 1]

现在我们看到在移动了英雄8之后,原来的数值都没有改变这就是所谓的擦除效果。

定义:“ blit”
在下一部分中,我们将把程序从使用列表转换为使用屏幕上的真实图形。在显示图形时,经常使用术语blit。

BLIT:基本上,blit意味着将图形从一个图像复制到另一个图像。更为正式的定义是将数据数组复制到位图数组目标。您可以将blit视为“分配”像素。就像在上面的屏幕列表中设置值一样,bilt会分配图像中像素的颜色,就是将上面的数值全部用像素替代。

其他图形库将使用bitblt或blt一词,但他们在谈论同一件事。它基本上是将内存从一个地方复制到另一个地方。实际上,它比直接复制内存要先进一些,因为它需要处理诸如像素格式,剪切和扫描线间距之类的事情。


从列表移动到屏幕移动
要将上面我们看到的列表代码用作示例,并使它们与pygame一起使用非常简单。我们假装已经加载了一些漂亮的图形,并将它们命名为“ terrain1”,“ terrain2”和“ hero”。在我们将数字分配给列表之前,现在将图形拖到屏幕上。有一点不同的是,现在我们需要一个二维坐标,而不是将位置用作单个索引(0到5),因为在平面上没法通过一个索引确定位置。我们假设游戏中的每个图形都是10像素宽。

1 >>> background = [terrain1, terrain1, terrain2, terrain2, terrain2, terrain1]
2 >>> screen = create_graphics_screen()
3 >>> for i in range(6):
4 ...     screen.blit(background[i], (i*10, 0))
5 >>> playerpos = 3
6 >>> screen.blit(playerimage, (playerpos*10, 0))



1 >>> screen.blit(background [playerpos],(playerpos * 10,0))
2 >>> playerpos = playerpos-1
3 >>> screen.blit(playerimage,(playerpos * 10,0))

通过这段代码,我们展示了如何显示带有英雄图像的简单背景。然后,我们已将该英雄适当地向左移动了一个空格。我们要做的第一件事是找到一种更干净的方法来表示背景和玩家位置。然后也许是更平滑,真实的动画。


屏幕坐标
要将对象放置在屏幕上,我们需要告诉blit()函数将图像放置在何处。在pygame中,我们始终将位置传递为(X,Y)坐标。这表示距离左边的像素数x,向下放置图像的像素数y。曲面的左上角是坐标(0,0)。向右稍微移动将是(10,0),然后向右向下移动将是(10,10)。

Pygame带有一个方便的容器来存储这些坐标,它是Rect。 Rect在这些坐标中基本上表示一个矩形区域。它具有左上角(就是左上角的坐标值)和大小(长宽)。 Rect附带了许多方便的方法,可以帮助您移动和定位它们。在下一个示例中,我们将用Rect表示对象的位置。

还需要知道pygame中的许多函数都需要Rect参数。所有这些功能还可以接受包含4个元素(左,上,宽度,高度)的简单元组。另外,blit()函数可以接受Rect作为其位置参数,它只是将Rect的左上角坐标点用作实际位置。


改变背景
在前面的所有部分中,我们一直将背景存储为不同类型的列表。这是创建基于图块的游戏的一种好方法,但我们希望平滑滚动。为了使操作更简单,我们将背景更改为覆盖整个屏幕的单个图像。这样,当我们要“擦除”对象(在重画它们之前)时,我们只需要将已擦除背景的部分着色到屏幕上即可。

还要注意,最后,当我们完成绘制到屏幕上时,我们调用pygame.display.update(),它将显示我们在屏幕上绘制的所有内容。

平稳运动
为了使某些物体看起来平滑移动,我们只想一次移动几个像素。这是使对象在屏幕上平滑移动的代码,根据我们现在已经知道的内容,这看起来应该很简单。

 1 >>> screen = create_screen()
 2 >>> player = load_player_image()
 3 >>> background = load_background_image()
 4 >>> screen.blit(background, (0, 0))        # 绘制背景
 5 >>> position = player.get_rect()
 6 >>> screen.blit(player, position)          # 绘制玩家
 7 >>> pygame.display.update()                # 全部显示
 8 >>> for x in range(100):                   # 动画100帧播放
 9 ...     screen.blit(background, position, position) 
10 ...     position = position.move(2, 0)     # 移动玩家
11 ...     screen.blit(player, position)      # 绘制新玩家
12 ...     pygame.display.update()            # 全部显示
13 ...     pygame.time.delay(100)             # 将程序停止1/10秒

这是在屏幕上平滑地对对象进行动画处理所需的全部代码。我们甚至可以使用漂亮的背景字符。

在上面循环的结尾,我们还调用了pygame.time.delay()。这会稍微减慢我们的程序的速度,否则它可能会运行得很快,肉眼可能看不到他。

猜你喜欢

转载自www.cnblogs.com/Iloveyy/p/12704743.html