pygame入门_PyGame –入门

pygame入门

PyGame is a Python wrapper for the SDL library. SDL is a cross-platform library for accessing computer multimedia hardware components (sound, video, input, etc.). SDL is an extremely powerful tool for building all kinds of things, but it’s written in C, and C is hard, so we use PyGame.

PyGameSDL库的Python包装器。 SDL是用于访问计算机多媒体硬件组件(声音,视频,输入等)的跨平台库。 SDL是用于构建各种事物的极其强大的工具,但是它是用C编写的,并且C很难,因此我们使用PyGame。

pygame logo

In this tutorial we’ll go over the basic PyGame logic and collision detection as well as drawing to the screen and loading outside files into our game.

在本教程中,我们将介绍基本的PyGame逻辑和碰撞检测,以及绘制到屏幕上并将外部文件加载到我们的游戏中。

NOTE: This tutorial assumes you have a basic understanding of the Python syntax, file structure, and OOP.

注意 :本教程假定您对Python语法,文件结构和OOP有基本的了解。

建立 (Setup)

Navigate to the PyGame download page, and find the proper binary package for your operating system and version of Python. If you’re using Python 3, make sure you download version 1.9.2.

导航到PyGame下载页面 ,并找到适合您的操作系统和Python版本的二进制程序包。 如果您使用的是Python 3,请确保下载版本1.9.2

Create a new .py file and input the following code:

创建一个新的.py文件并输入以下代码:

1
1
2
2
3
3
4
4

As with all Python programs, we begin by importing the modules we want to use. In this case we will be importing pygame itself and pygame.locals, which we will use later for some of the constants. The last line initializes all the PyGame modules, it must be called before you do anything else with PyGame.

与所有Python程序一样,我们从导入要使用的模块开始。 在这种情况下,我们将导入pygame本身和pygame.locals ,稍后将用于一些常量。 最后一行初始化所有PyGame模块,在使用PyGame进行任何其他操作之前必须先调用它。

建筑模块 (Building Blocks)

屏幕对象 (Screen Objects)

First things first: We need something to draw on, so we will create a “screen” which will be our overall canvas. In order to create a screen to display on, we call the set_mode() method of pygame.display and then pass set_mode() a tuple with the width and height of the window we want (800×600 in this case):

首先,我们需要画些东西,因此我们将创建一个“ 屏幕 ”,它将成为我们的整体画布。 为了创建要显示的屏幕,我们调用pygame.displayset_mode()方法,然后将set_mode()传递给具有所需窗口宽度和高度的元组(在这种情况下为800×600):

1
1
2
2
3
3
4
4
5
5
6
6

If you run this now you’ll see our window pop up briefly and then immediately disappear as the program exits. Not very impressive, is it? In the next section we will introduce our main game loop to ensure that our program only exits when we give it the correct input.

如果您现在运行此程序,您会看到我们的窗口短暂弹出,然后在程序退出时立即消失。 不是很令人印象深刻,是吗? 在下一节中,我们将介绍我们的主游戏循环,以确保仅当我们输入正确的程序后程序才会退出。

游戏循环 (Game Loop)

The main game/event loop is where all the action happens. It runs continuously during gameplay, updating the game state, rendering the screen, and collecting input. When we create our loop we need to make sure that we have a way to get out of the loop and exit the application. To that end we will introduce some basic user input at the same time. All user input (and some other events we will get into later) go into the PyGame event queue, which you can access by calling pygame.event.get(). This will return a list of all the events in the queue, which we will loop through and respond to according to the type of event. For now all we care about are KEYDOWN and QUIT events:

游戏/事件的主要循环是所有动作发生的地方。 它在游戏过程中连续运行,更新游戏状态,渲染屏幕并收集输入。 创建循环时,我们需要确保有一种方法可以退出循环并退出应用程序。 为此,我们将同时介绍一些基本的用户输入。 所有用户输入(以及稍后将讨论的其他事件)都进入PyGame事件队列,您可以通过调用pygame.event.get()进行访问。 这将返回队列中所有事件的列表,我们将循环浏览并根据事件的类型进行响应。 目前,我们只关心KEYDOWNQUIT事件:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15

Add these lines to the previous code and run it. You should see an empty window. It wont go away until you press the ESC key or trigger a QUIT event by closing the window.

将这些行添加到先前的代码中并运行它。 您应该看到一个空窗口。 直到您按下ESC键或通过关闭窗口触发QUIT事件,它才会消失。

表面和矩形 (Surfaces and Rects)

Surfaces and Rects are basic building blocks in PyGame. Think of surfaces as a blank sheet of paper that you can draw whatever you want onto. Our screen object is also a Surface. They can hold images as well. Rects are a representation of a rectangular area that your Surface encompasses.

表面Rects在pygame的基本组成部分。 将表面视为一张空白纸,您可以在其上绘制任何内容。 我们的屏幕对象也是一个Surface。 它们也可以保存图像。 矩形表示表面所包围的矩形区域。

Let’s create a basic Surface that’s 50 pixels by 50 pixels, then let’s fill in the Surface with a color. We’ll use white because the default window background is black and we want it to be nice and visible. We’ll then call the get_rect() method on our Surface to get the rectangular area and the x, y coordinates of our surface:

让我们创建一个50像素乘50像素的基本Surface,然后用一种颜色填充Surface。 我们将使用白色,因为默认的窗口背景是黑色,并且我们希望它漂亮且可见。 然后,我们将在Surface上调用get_rect()方法,以获取矩形区域以及曲面的x,y坐标:

1
1
2
2
3
3
4
4
5
5

翻转和翻转 (Blit and Flip)

Just creating our Surface isn’t actually enough to see it on the screen. To do that we need to Blit the Surface onto another Surface. Blit is just a technical way to say draw. You can only Blit from one Surface object to another – but remember, our screen is just another Surface object. Here’s how we’ll draw our surf to the screen:

实际上,仅创建Surface不足以在屏幕上看到它。 为此,我们需要将曲面Blit到另一个曲面上。 Blit只是说平局的一种技术方法。 您只能从一个Surface对象到另一个对象Blit –但是请记住,我们的屏幕只是另一个Surface对象。 这是我们将surf画到屏幕上的方法:

1
1
2
2
3
3

blit() takes two arguments: The Surface to draw and the location to draw it at on the source Surface. Here we use the exact center of the screen, but when you run the code you’ll notice our surf does not end up centered on the screen. This is because blit() will draw surf starting at the top left position.

blit()有两个参数:要绘制的Surface和在源Surface上绘制它的位置。 在这里,我们使用屏幕的确切中心,但是当您运行代码时,您会发现我们的surf最终并未在屏幕上居中。 这是因为blit()将从左上角开始绘制冲浪。

Notice the call to pygame.display.flip() after our Blit. Flip will update the entire screen with everything that has been drawn since the last flip. Without a call to flip(), nothing will show.

注意在Blit之后对pygame.display.flip()的调用。 翻转将使用自上次翻转以来绘制的所有内容更新整个屏幕。 如果没有调用flip() ,则不会显示任何内容。

精灵 (Sprites)

What are Sprites? In programming terms a Sprite is a 2d representation of something on the screen. Essentially, a Sprite is a picture. Pygame provides a basic class called Sprite, which is meant to be extended and used to hold one or several graphical representations of an object that you want to display on the screen. We will extend the Sprite class so that we can use its built in methods. We’ll call this new object Player. Player will extend Sprite and have only two properties for now: surf and rect. We will also give surf a color (white in this case) just like the previous surface example except that now the Surface belongs to the Player:

什么是精灵? 用编程术语来说,Sprite是屏幕上某物的2D表示。 本质上,精灵是图片。 Pygame提供了一个称为Sprite的基本类,该类旨在进行扩展并用于保存要在屏幕上显示的对象的一个​​或多个图形表示。 我们将扩展Sprite类,以便我们可以使用其内置方法。 我们将这个新对象称为PlayerPlayer将扩展Sprite并仅具有两个属性: surfrect 。 我们也将给surf一种颜色(在这种情况下为白色),就像前面的曲面示例一样,只是现在Surface属于Player

1
1
2
2
3
3
4
4
5
5
6
6


Let’s put it all together!

让我们放在一起!

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40
41
41
42
42
43
43
44
44
45
45
46
46

Run this code. You’ll see a white rectangle at roughly the middle of the screen:

运行此代码。 您将在屏幕的大约中间看到一个白色矩形:

pygame part one

What do you think would happen if you changed screen.blit(player.surf,(400,300)) to screen.blit(player.surf, player.rect)? Once changed, try printing player.rect to the console. The first two attributes of the rect() are x, y coordinates of the top left corner of the rect(). When you pass Blit a Rect, it will use those coordinates to draw the surface. We will use this later to make our player move!

你觉得如果你改变会发生screen.blit(player.surf,(400,300))screen.blit(player.surf, player.rect) 更改后,尝试将player.rect打印到控制台。 所述的前两个属性rect()是x,顶部的y坐标离开的角rect() 当您通过“倾斜矩形”时,它将使用这些坐标绘制表面。 我们稍后将使用它来使我们的玩家移动!

用户输入 (User Input)

Here’s where the fun starts! Let’s make our player controllable. We discussed earlier that the keydown event pygame.event.get() pulls the latest event off the top of the event stack. Well, Pygame has another event method called pygame.event.get_pressed(). The get_pressed() method returns a dictionary with all the keydown events in the queue. We will put this in our main loop so we get the keys at every frame.

这就是乐趣的开始! 让我们的播放器可控。 前面我们讨论了keydown事件pygame.event.get()将最新事件移出事件堆栈的顶部。 好吧,Pygame还有另一个名为pygame.event.get_pressed() 事件方法get_pressed()方法返回一个字典,其中包含队列中的所有get_pressed()事件。 我们将其放入主循环中,以便在每一帧都获得关键点。

1
1

Now we’ll write a method that will take that dictionary and define the behavior of the sprite based off the keys that are pressed. Here’s what it might look like:

现在,我们将编写一个方法,该方法将使用该字典并根据所按下的键定义精灵的行为。 可能是这样的:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9

K_UP, K_DOWN, K_LEFT, and K_RIGHT correspond to the arrow keys on the keyboard. So we check that key, and if it’s set to True, then we move our rect() in the relevant direction. Rects have two built-in methods for moving; here we use “move in place” – move_ip() – because we want to move the existing Rect without making a copy.

K_UPK_DOWNK_LEFTK_RIGHT对应于键盘上的箭头键。 因此,我们检查该键,如果将其设置为True ,则将rect()朝相关方向移动。 矩形有两种内置的移动方法: 在这里,我们使用“ 原地移动 ” – move_ip() –因为我们希望在不复制的情况下移动现有Rect。

Add the above method to our Player class and put the get_pressed() call in the main loop. Our code should now look like this:

将上述方法添加到Player类中,并将get_pressed()调用放入主循环中。 现在,我们的代码应如下所示:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40
41
41
42
42
43
43
44
44
45
45

Now you should be able to move your rectangle around the screen with the arrow keys. You may notice though that you can move off the screen, which is something we probably don’t want. So let’s add a bit of logic to the update method that tests if the rectangle’s coordinates have moved beyond our 800 by 600 boundary; and if so, move it back to the edge:

现在,您应该能够使用箭头键在屏幕上移动矩形。 您可能会注意到,尽管可以移出屏幕,但这可能是我们不想要的。 因此,让我们在update方法中添加一些逻辑,以测试矩形的坐标是否已超出我们800 x 600的边界。 如果是这样,请将其移回边缘:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19

Here instead of using a move method, we just alter the corresponding coordinates for top, bottom, left, or right.

在这里,我们不使用move方法,而只是更改了上,下,左或右的相应坐标。

Now let’s add some enemies!

现在,让我们添加一些敌人!

First let’s create a new sprite class called ‘Enemy’. We will follow the same formula we used for the player class:

首先,我们创建一个名为“ Enemy”的新精灵类。 我们将遵循用于播放器类的相同公式:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12

There are a couple differences here that we should talk about. First off, when we call get_rect() on our surface, we are setting the center property x coordinate to 820, and our y coordinate to a random number generated by random.randint().

这里我们应该讨论几个不同之处。 首先,当我们在表面上调用get_rect()时,将中心属性x坐标设置为820,将y坐标设置为random.randint()生成的随机数。

Random is a python library that we will import at the beginning of our file in the complete code (import random). Why the random number? Simple: We want our incoming enemies to start past the right side of the screen (820), at a random place (0-600). We also use random to set a speed property for the enemies. This way we will have some enemies that are fast and some that are slow.

Random是一个python库,我们将以完整的代码在文件的开头import randomimport random )。 为什么是随机数? 简单:我们希望传入的敌人在任意位置(0-600)越过屏幕的右侧(820)。 我们还使用random为敌人设置速度属性。 这样,我们将有一些快的敌人和一些慢的敌人。

Our update() method for the enemies takes no arguments (we don’t care about input for enemies) and simply moves the enemy toward the left side of the screen at a rate of speed. And the last if statement in the update method tests to see if the enemy has gone past the left side of the screen with the right side of its rectangle (so that they don’t just disappear as soon as they touch the side of the screen). When they pass the side of the screen we call Sprites’ built-in kill() method to delete them from their sprite group thereby preventing them from being rendered. Kill does not release the memory taken by the enemy and relies on you no longer having a reference to it so the Python garbage collector will take care of it.

我们对敌人的update()方法不带任何参数(我们不在乎对敌人的输入),而只是以一定速度将敌人移向屏幕的左侧。 然后update方法中的最后一个if语句进行测试,以查看敌人是否以矩形的右侧越过了屏幕的左侧(这样,它们一旦触及屏幕的一侧就不会消失)。 当它们经过屏幕的一侧时,我们调用Sprites的内置kill()方法将其从其sprite组中删除,从而阻止了它们的呈现。 Kill不会释放敌人占用的内存,并且依赖您不再引用它,因此Python垃圾收集器将负责处理它。

团体 (Groups)

Another super useful object that PyGame provides are Sprite groups. They are exactly what they sound like – Groups of Sprites. So why do we use Sprite Groups instead of a list? Well, sprite groups have several methods built into them that will help us later with collisions and updating. Let’s make a Group right now that will hold all the Sprites in our game. After we create it, we will add the Player to the Group since that’s our only Sprite so far. We can create another group for enemies as well. When we call a Sprite’s kill() method, the sprite will be removed from all groups that it is a part of.

PyGame提供的另一个超级有用的对象是Sprite 。 它们确实就是它们的声音–精灵组。 那么为什么我们要使用Sprite Groups而不是列表呢? 好吧,精灵组内置了几种方法,这些方法将在以后帮助我们进行碰撞和更新。 现在让我们创建一个可以容纳游戏中所有Sprite的组。 创建它之后,我们将把Player添加到组中,因为到目前为止这是我们唯一的Sprite。 我们也可以为敌人创建另一个小组。 当我们调用Sprite的kill()方法时,该sprite将从其所属的所有组中删除。

1
1
2
2
3
3

Now that we have this all_sprites group, let’s change how we are rendering our objects so that we render all objects in this group.

现在我们有了all_sprites组,让我们更改渲染对象的方式,以便渲染该组中的所有对象。

1
1
2
2

Now anything we put into all_sprites will be rendered.

现在,我们放入all_sprites都将被渲染。

自订活动 (Custom Events)

Now we have a Sprite Group for our enemies but no actual enemies. So how do we get some enemies on the screen? We could just create a bunch of them at the beginning, but then our game wouldn’t last more than a few seconds. So we will create a custom event that will fire off every few seconds and trigger the creation of a new enemy. We listen for this event in the same way that we listened for key presses or quit events. Creating a custom event is as easy as naming it:

现在,我们为敌人建立了一个Sprite Group,但没有实际的敌人。 那么我们如何在屏幕上看到一些敌人呢? 我们可以在一开始就创建一堆游戏,但是随后我们的游戏将持续不到几秒钟。 因此,我们将创建一个自定义事件,该事件每几秒钟触发一次,并触发新敌人的创建。 我们侦听此事件的方式与侦听按键或退出事件的方式相同。 创建自定义事件就像命名它一样容易:

1
1

That’s it! Now we have an event called ADDENEMY that we can listen for in our main loop. The only gotcha to keep in mind here is that we need our custom event to have a unique value that is greater than the value of USEREVENT. That’s why we set our new event to equal USEREVENT + 1. One small note for anyone curious about about these events: They are at their core just integer constants. USEREVENT has a numeric value and any custom event we create needs to be an integer value that is greater than USEREVENT (because all the values less than USEREVENT are already taken by built-ins).

而已! 现在我们有了一个名为ADDENEMY的事件,我们可以在主循环中侦听该事件。 这里要记住的唯一陷阱是,我们需要使自定义事件的唯一值大于USEREVENT的值。 这就是为什么我们将新事件设置为USEREVENT + 1 。 对于任何对这些事件感到好奇的人,请注意以下几点:它们的核心只是整数常量。 USEREVENT有一个数值,我们创建的任何自定义事件都必须是一个大于USEREVENT的整数值(因为所有小于USEREVENT的值USEREVENT被内置函数占用)。

Now that we’ve defined our event, we need to insert it into the event queue. Since we need to keep creating them over the course of the game, we will set a timer. To do this we use PyGame’s time() object.

现在我们已经定义了事件,我们需要将其插入事件队列。 由于我们需要在游戏过程中继续创建它们,因此我们将设置一个计时器。 为此,我们使用PyGame的time()对象。

1
1

This tells PyGame to fire our ADDENEMY event every 250 milliseconds (every quarter second). This goes outside of our game loop, but will still fire throughout the entire game. Now let’s add some code to listen for our event:

这告诉ADDENEMY每250毫秒(每四分之一秒) ADDENEMY一次ADDENEMY事件。 这超出了我们的游戏循环,但仍会在整个游戏中触发。 现在,让我们添加一些代码来监听我们的事件:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

Keep in mind that set_timer() is exclusively used for inserting events into the PyGame event queue – it doesn’t do anything else.

请记住, set_timer()仅用于将事件插入PyGame事件队列中-它不会做其他任何事情。

Now we are listening for our ADDENEMY event, and when it fires, we create a new instance of the Enemy class. Then we add that instance to the enemies Sprite Group (which we will later use to test for collision) and to the all_sprites Group (so that it gets rendered along with everything else).

现在,我们正在监听ADDENEMY事件,当事件触发时,我们将创建一个Enemy类的新实例。 然后,我们将该实例添加到enemies Sprite组(稍后将用于测试碰撞)和all_sprites组(以便将其与其他所有对象一起渲染)。

碰撞 (Collision)

This is why you will love PyGame! Writing collision code is hard, but PyGame has a LOT of collision detection methods, some of which you can find here. For this tutorial we will be using spritecollideany. The spritecollideany() method takes a Sprite object and a Sprite Group and tests if the Sprite object intersects with any of the Sprites in the Sprite group. So we will take our player Sprite and our enemies Sprite Group and test if our player has been hit by an enemy. Here’s what it looks like in code:

这就是为什么您会喜欢PyGame! 编写碰撞代码很困难,但是PyGame有很多碰撞检测方法,您可以在此处找到其中的一些方法。 在本教程中,我们将使用spritecollideanyspritecollideany()方法接受一个Sprite对象和一个Sprite组,并测试Sprite对象是否与Sprite组中的任何Sprite相交。 因此,我们将带走玩家Sprite和敌人Sprite Group,并测试我们的玩家是否被敌人击中。 这是代码中的样子:

1
1
2
2

We test if our player Sprite object collides with any Sprites in the enemies Sprite Group, and if it does, we call the kill() method on the player Sprite. Because we are only rendering sprites in the all_sprites Group, and the kill() method removes a Sprite from all its Groups, our player will no longer be rendered, thus ‘killing’ it. Let’s put it all together:

我们测试player Sprite对象是否与enemies Sprite组中的任何Sprite发生碰撞,如果确实发生冲突,我们在player Sprite上调用kill()方法。 因为我们只在all_sprites组中渲染精灵,并且kill()方法从其所有组中删除一个Sprite,所以我们的player将不再被渲染,从而“杀死”它。 让我们放在一起:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40
41
41
42
42
43
43
44
44
45
45
46
46
47
47
48
48
49
49
50
50
51
51
52
52
53
53
54
54
55
55
56
56
57
57
58
58
59
59
60
60
61
61
62
62
63
63
64
64
65
65
66
66
67
67
68
68
69
69
70
70
71
71
72
72
73
73
74
74
75
75
76
76
77
77
78
78
79
79
80
80
81
81
82
82
83
83
84
84
85
85
86
86
87
87
88
88
89
89
90
90
91
91
92
92
93
93
94
94
95
95
96
96
97
97
98
98
99
99

Test this out!

测试一下!

pygame part two

图片 (Images)

Now we have a game, but kind of an ugly game. Next we will replace all the boring white rectangles with cool images that will make the game feel like an actual game.

现在我们有了一个游戏,但是有点丑陋。 接下来,我们将用凉爽的图像替换所有无聊的白色矩形,这将使游戏看起来像实际的游戏。

In the previous code examples we used a Surface object filled with a color to represent everything in our game. While this is a good way to get a handle on what a surface is and how they work, it makes for an ugly game. We’re going to add some pictures for the enemies and the player. I like to draw my own images, so I made a little jet for the player and some missiles for the enemies, which you can download from the repo. You’re welcome to use my art, draw your own, or download some free game art assets to use.

在前面的代码示例中,我们使用了填充有颜色的Surface对象来表示游戏中的所有内容。 虽然这是掌握表面是什么以及它们如何工作的好方法,但它使游戏变得难看。 我们将为敌人和玩家添加一些图片。 我喜欢绘制自己的图像,所以我为玩家制作了一些喷气式飞机,并为敌人制造了一些导弹,您可以从仓库中下载。 欢迎您使用我的艺术作品,自己绘画或下载一些免费的游戏艺术资产来使用。

改变对象构造器 (Altering the Object Constructors)

Our current player constructor looks like this:

我们当前的播放器构造函数如下所示:

1
1
2
2
3
3
4
4
5
5
6
6

Our new constructor will look like this:

我们的新构造函数将如下所示:

1
1
2
2
3
3
4
4
5
5
6
6

We want to replace our Surface object with an image. We will use pygame.image.load() by passing it a path to a file. The load() method will actually return a Surface object. We then call convert() on that Surface object to create a copy that will draw more quickly on the screen.

我们要用图像替换Surface对象。 我们将通过向pygame.image.load()传递文件路径来使用它。 load()方法实际上将返回一个Surface对象。 然后,我们在该Surface对象上调用convert()以创建一个副本,该副本将在屏幕上更快地绘制。

Next we call the set_colorkey() method on our image. The set_colorkey method sets the color in the image that PyGame will render as transparent. In this case I chose white, because that’s the background of my jet image. RLEACCEL is a optional parameter that will help PyGame render faster on non-accelerated displays.

接下来,我们在图像上调用set_colorkey()方法。 set_colorkey方法将set_colorkey渲染为透明的图像的颜色设置为透明。 在这种情况下,我选择白色,因为这是我的喷射图像的背景。 RLEACCEL是一个可选参数,可帮助PyGame在非加速显示器上更快地渲染。

Lastly, we get our rect object in the same way as before: By calling get_rect() on our image.

最后,我们以与以前相同的方式获取rect对象:通过在图像上调用get_rect()

Remember the image is still a surface object; it now just has a picture painted on it.

记住图像仍然是表面物体; 现在只画了一张画。

Let’s do the same thing with the enemy constructor:

让我们对敌人的构造函数做同样的事情:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9

Now we have the same game we had before but nicely skinned with some cool images. I think it’s missing something, though. Let’s add a few clouds going past to give the impression of a jet flying through the sky. To do this we are going to use the exact same principles we used before. First, we will create the Cloud object with an image of a cloud and an update() method that continuously moves the cloud toward the left side of the screen. Then we will create a custom event to spawn our clouds at a set interval (we will also add the spawned clouds to the all_sprites group). Here’s what our cloud object will look like:

现在,我们拥有与以前相同的游戏,但具有一些很酷的图像。 但我认为它缺少一些东西。 让我们添加一些过去的云层,给人以喷气式飞机在天上飞舞的印象。 为此,我们将使用以前使用的完全相同的原理。 首先,我们将创建一个Cloud对象,其中包含一个云的图像和一个update()方法,该方法将云不断向屏幕左侧移动。 然后,我们将创建一个自定义事件,以固定的时间间隔生成云(还将生成的云添加到all_sprites组中)。 这是我们的云对象的样子:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13

That should all look familiar, as should this event creation code, which we will put right below our enemy creation event:

这一切都应该看起来很熟悉,就像这个事件创建代码一样,我们将其放置在敌人创建事件的下面:

1
1
2
2

And let’s create a new Sprite Group for them:

让我们为他们创建一个新的Sprite Group:

1
1

Now in our main game loop, where we step through our event queue, we need to start listening for our ADDCLOUD event.

现在,在我们的主要游戏循环中,我们逐步进入事件队列,我们​​需要开始侦听ADDCLOUD事件。

This:

这个:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

Will become this:

会变成这样:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14

We’re going to add the clouds to the all_sprites Group as well as the new clouds Group. We add them to both because we’re using all_sprites to render and clouds to call their update function. You might ask why we don’t add them to the existing enemies Group; after all, we’re calling nearly identical update functions on them. The reason is, we don’t want to test the player for collisions with the clouds. Our jet needs to pass cleanly through all the clouds. Now all that’s left is calling our clouds Group update() method.

我们将把云添加到all_sprites组以及新的all_sprites组。 我们将它们添加到都因为我们使用all_sprites渲染和clouds调用它们的更新功能。 您可能会问为什么我们不将它们添加到现有的enemies组中; 毕竟,我们在它们上调用几乎相同的更新函数。 原因是,我们不想测试玩家与云的碰撞。 我们的喷气机需要整齐地穿过所有云层。 现在剩下的就是调用我们的clouds组update()方法了。

结论 (Conclusion)

That’s it! Test it again, and you should see something like:

而已! 再次测试,您将看到类似以下内容的内容:

pygame part three

翻译自: https://www.pybloggers.com/2016/01/pygame-a-primer/

pygame入门

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值