Опубликован: 06.08.2013 | Доступ: свободный | Студентов: 974 / 64 | Длительность: 27:51:00
Лекция 2:

Pygame basics

< Лекция 1 || Лекция 2: 1234 || Лекция 3 >

Pixel Coordinates

The window that the "Hello World" program creates is just composed of little square dots on your screen called pixels. Each pixel starts off as black but can be set to a different color. Imagine that instead of a Surface object that is 400 pixels wide and 300 pixels tall, we just had a Surface object that was 8 pixels by 8 pixels. If that tiny 8x8 Surface was enlarged so that each pixel looks like a square in a grid, and we added numbers for the X and Y axis, then a good representation of it could look something like this:

8x8 Surface

Рис. 2.4. 8x8 Surface

We can refer to a specific pixel by using a Cartesian Coordinate system. Each column of the X- axis and each row of the Y-axis will have an "address" that is an integer from 0 to 7 so that we can locate any pixel by specifying the X and Y axis integers.

For example, in the above 8x8 image, we can see that the pixels at the XY coordinates (4, 0), (2, 2), (0, 5), and (5, 6) have been painted black, the pixel at (2, 4) has been painted gray, while all the other pixels are painted white. XY coordinates are also called points. If you've taken a math class and learned about Cartesian Coordinates, you might notice that the Y-axis starts at 0 at the top and then increases going down, rather than increasing as it goes up. This is just how Cartesian Coordinates work in Pygame (and almost every programming language).

The Pygame framework often represents Cartesian Coordinates as a tuple of two integers, such as (4, 0) or (2, 2). The first integer is the X coordinate and the second is the Y coordinate (Cartesian Coordinates are covered in more detail in chapter 12 of "Invent Your Own Computer Games with Python" at http://invpy.com/chap12).

A Reminder About Functions, Methods, Constructor Functions, and Functions in Modules (and the Difference Between Them)

Functions and methods are almost the same thing. They can both be called to execute the code in them. The difference between a function and a method is that a method will always be attached to an object. Usually methods change something about that particular object (you can think of the attached object as a sort of permanent argument passed to the method).

This is a function call of a function named foo():

foo()

This is a method call of a method also named foo(), which is attached to an object stored in a variable named duckie:

duckie.foo()

A call to a function inside of a module may look like a method call. To tell the difference, you need to look at the first name and see if it is the name of a module or the name of a variable that contains an object. You can tell that sys.exit() is a call to function inside of a module, because at the top of the program will be an import statement like import sys.

A constructor function is the same thing as a normal function call, except that its return value is a new object. Just by looking at source code, a function and constructor function look the same. Constructor functions (also called simply a "constructor" or sometimes "ctor" ("see-tor") for short) are just a name given to functions that return a new object. But usually ctors start with a capital letter. This is why when you write your own programs, your function names should only begin with a lowercase letter.

For example, pygame.Rect() and pygame.Surface() are both constructor functions inside the pygame module that return new Rect and Surface objects. (These objects are described later.)

Here's an example of a function call, a method call, and a call to a function inside a module:

import whammy
fizzy()
egg = Wombat()
egg.bluhbluh()
whammy.spam()

Even though these names are all made up, you can tell which is a function call, a method call, and a call to a function inside a method. The name whammy refers to a module, since you can see it is being imported on the first line. The fizzy name has nothing before it and parentheses after it, so you know it is a function call.

Wombat() is also a function call, in this case it is a constructor function that returns an object. (The capital letter that it starts with isn't a guarantee that it's a constructor function rather than a regular function, but it is a safe bet.) The object is stored in a variable named egg. The egg.bluhbluh() call is a method call, which you can tell because bluhbluh is attached to a variable with an object in it.

Meanwhile, whammy.spam() is a function call, not a method call. You can tell it is not a method because the name whammy was imported as a module earlier.

Surface Objects and The Window

Surface objects are objects that represent a rectangular 2D image. The pixels of the Surface objec can be changed by calling the Pygame drawing functions (described later in this chapter) and the displayed on the screen. The window border, title bar, and buttons are not part of the display Surface object.

In particular, the Surface object returned by pygame.display.set_mode() is called the display Surface. Anything that is drawn on the display Surface object will be displayed on the window when the pygame.display.update() function is called. It is a lot faster to draw on a Surface object (which only exists in the computer's memory) than it is to draw a Surface object to the computer screen. Computer memory is much faster to change than pixels on a monitor.

Often your program will draw several different things to a Surface object. Once you are done drawing everything on the display Surface object for this iteration of the game loop (called a frame , just like a still image on a paused DVD is called) on a Surface object, it can be drawn to the screen. The computer can draw frames very quickly, and our programs will often run around 30 frames per second (that is, 30 FPS). This is called the "frame rate" and is explained later in this chapter.

Drawing on Surface objects will be covered in the "Primitive Drawing Functions" and "Drawing Images" sections later this chapter.

Colors

There are three primary colors of light: red, green and blue. (Red, blue, and yellow are the primary colors for paints and pigments, but the computer monitor uses light, not paint.) By combining different amounts of these three colors you can form any other color. In Pygame, we represent colors with tuples of three integers. The first value in the tuple is how much red is in the color. An integer value of 0 means there is no red in this color, and a value of 255 means there is the maximum amount of red in the color. The second value is for green and the third value is for blue. These tuples of three integers used to represent a color are often called RGB values.

Because you can use any combination of 0 to 255 for each of the three primary colors, this means Pygame can draw 16,777,216 different colors (that is, 256 x 256 x 256 colors). However, if try to use a number larger than 255 or a negative number, you will get an error that looks like "ValueError: invalid color argument".

For example, we will create the tuple (0, 0, 0) and store it in a variable named BLACK . With no amount of red, green, or blue, the resulting color is completely black. The color black is the absence of any color. The tuple (255, 255, 255) for a maximum amount of red, green, and blue to result in white. The color white is the full combination of red, green, and blue. The tuple (255, 0, 0) represents the maximum amount of red but no amount of green and blue, so the resulting color is red. Similarly, (0, 255, 0) is green and (0, 0, 255) is blue.

You can mix the amount of red, green, and blue to form other colors. Here are the RGB values for a few common colors:

Таблица 2.1.
Color RGB Values
Aqua ( 0, 255, 255)
Black ( 0, 0, 0)
Blue ( 0, 0, 255)
Fuchsia (255, 0, 255)
Gray (128, 128, 128)
Green ( 0, 128, 0)
Lime ( 0, 255, 0)
Maroon (128, 0, 0)
Navy Blue ( 0, 0, 128)
Olive (128, 128, 0)
Purple (128, 0, 128)
Red (255, 0, 0)
Silver (192, 192, 192)
Teal ( 0, 128, 128)
White (255, 255, 255)
Yellow (255, 255, 0)

Transparent Colors

When you look through a glass window that has a deep red tint, all of the colors behind it have a red shade added to them. You can mimic this effect by adding a fourth 0 to 255 integer value to your color values.

This value is known as the alpha value. It is a measure of how opaque (that is, not transparent) a color is. Normally when you draw a pixel onto a surface object, the new color completely replaces whatever color was already there. But with colors that have an alpha value, you can instead just add a colored tint to the color that is already there.

For example, this tuple of three integers is for the color green: (0, 255, 0). But if we add a fourth integer for the alpha value, we can make this a half transparent green color: (0, 255, 0, 128). An alpha value of 255 is completely opaque (that is, not transparency at all). The colors (0, 255, 0) and (0, 255, 0, 255) look exactly the same. An alpha value of 0 means the color is completely transparent. If you draw any color that has an alpha value of 0 to a surface object, it will have no effect, because this color is completely transparent and invisible.

In order to draw using transparent colors, you must create a Surface object with the convert_alpha()method. For example, the following code creates a Surface object that transparent colors can be drawn on:

anotherSurface = DISPLAYSURF.convert_alpha()

Once things have been drawn on the Surface object stored in anotherSurface, then anotherSurface can be "blitted" (that is, copied) to DISPLAYSURF so it will appear on the screen. (See the "Drawing Images with pygame.image.load() and blit()" section later in this chapter).

It’s important to note that you cannot use transparent colors on Surface objects not returned from a convert_alpha() call, including the display Surface that was returned from pygame.display.set_mode().

If we were to create a color tuple to draw the legendary Invisible Pink Unicorn, we would use (255, 192, 192, 0), which ends up looking completely invisible just like any other color that has a 0 for its alpha value. It is, after all, invisible.

Above is a screenshot of a drawing of the Invisible Pink Unicorn.

Рис. 2.5. Above is a screenshot of a drawing of the Invisible Pink Unicorn.

pygame.Color Objects

You need to know how to represent a color because Pygame’s drawing functions need a way to know what color you want to draw with. A tuple of three or four integers is one way. Another way is as apygame.Color object. You can create Color objects by calling the pygame.Color() constructor function and passing either three or four integers. You can store this Color object in variables just like you can store tuples in variables. Try typing the following into the interactive shell:

>>> import pygame
>>> pygame.Color(255, 0, 0)
(255, 0, 0, 255)
>>> myColor = pygame.Color(255, 0, 0, 128)
>>> myColor == (255, 0, 0, 128)
True
>>>

Any drawing function in Pygame (which we will learn about in a bit) that has a parameter for color can have either the tuple form or Color object form of a color passed for it. Even though they are different data types, a Color object is equal to a tuple of four integers if they both represent the same color (just like how 42 == 42.0 will evaluate to True).

Now that you know how to represent colors (as a pygame.Color object or a tuple of three or four integers for red, green, blue, and optionally alpha) and coordinates (as a tuple of two integers for X and Y), let’s learn about pygame.Rect objects so we can start using Pygame’s drawing functions.

Rect Objects

Pygame has two ways to represent rectangular areas (just like there are two ways to represent colors). The first is a tuple of four integers:

  1. The X coordinate of the top left corner.
  2. The Y coordinate of the top left corner.
  3. The width (in pixels) of the rectangle.
  4. Then height (in pixels) of the rectangle.

The second way is as a pygame.Rect object, which we will call Rect objects for short. For example, the code below creates a Rect object with a top left corner at (10, 20) that is 200 pixels wide and 300 pixels tall:

>>> import pygame
>>> spamRect = pygame.Rect(10, 20, 200, 300)
>>> spamRect == (10, 20, 200, 300)
True

The handy thing about this is that the Rect object automatically calculates the coordinates for other features of the rectangle. For example, if you need to know the X coordinate of the right edge of the pygame.Rect object we stored in the spamRect variable, you can just access the Rect object’s right attribute:

>>> spamRect.right
210

The Pygame code for the Rect object automatically calculated that if the left edge is at the X coordinate 10 and the rectangle is 200 pixels wide, then the right edge must be at the X coordinate 210. If you reassign the right attribute, all the other attributes are automatically recalculated:

>>> spam.right = 350
>>> spam.left
150

Here’s a list of all the attributes that pygame.Rectobjects provide (in our example, the variable where the Rect object is stored in a variable named myRect):

Таблица 2.2.
Attribute Name Description
myRect.left The int value of the X-coordinate of the left side of the rectangle.
myRect.right The int value of the X-coordinate of the right side of the rectangle.
myRect.top The int value of the Y-coordinate of the top side of the rectangle.
myRect.bottom The int value of the Y-coordinate of the bottom side.
myRect.centerx The int value of the X-coordinate of the center of the rectangle.
myRect.centery The int value of the Y-coordinate of the center of the rectangle.
myRect.width The int value of the width of the rectangle.
myRect.height The int value of the height of the rectangle.
myRect.size A tuple of two ints: (width, height)
myRect.topleft A tuple of two ints: (left, top)
myRect.topright A tuple of two ints: (right, top)
myRect.bottomleft A tuple of two ints: (left, bottom)
myRect.bottomright A tuple of two ints: (right, bottom)
myRect.midleft A tuple of two ints: (left, centery)
myRect.midright A tuple of two ints: (right, centery)
myRect.midtop A tuple of two ints: (centerx, top)
myRect.midbottom A tuple of two ints: (centerx, bottom)
< Лекция 1 || Лекция 2: 1234 || Лекция 3 >