Drawing in Python

Drawing operations that Pygame provides are at an intermediate level of complexity. A canvas or Pygame Surface can draw only pixels. Thus, anything more complicated has to be implemented in terms of the drawing of pixels. Lines, for example, are drawn by drawing pixels that lie on or near to the specified line. The method is referred to as, variously, Digital Differential Analyzer (DDA), scan conversion, or (usually) Bresenham’s algorithm. It will draw a line between two discrete points by setting pixels between them. While Pygame does allow us to set individual pixels, it is not convenient to only use that facility.

So, drawing a line is done using the line function in the draw package as follows:

pygame.draw.line(screen, color, start, end, thick)

This draws a line on the Surface named screen using the specific color, from the start point, a tuple that gives the x and y coordinates of the start point, to the specified end point, specified also as a tuple, with a line thickness of thick pixels. Four examples of the use of the line function are shown in Figure 7.2.

Drawing a circle is done using the circle function in the draw package as follows:

This draws a circle on the Surface named screen using the specific color, using the tuple center = (x, y) as the coordinates of the center point, and uses the floating point value radius as the radius of the circle with a line thickness of thick pixels. Color is as before.

This draws the circles seen in Figure 7.3. An important thing to notice is that the second set of six circles is drawn using a thickness of 0. This tells the draw­ing program to fill the circles with the specified fill color. That is also seen in the figure.

Drawing a rectangle is done using the rect function in the draw package as follows:

pygame.draw.rect(screen, color, rectangle, thick)

This draws a rectangle on the Surface named screen using the specific color, using the tuple rectangle = (x, y, w, h) as the coordinates of the upper left point (x, y) and the width and height of the rectangle, in pixels (w,h). The circle with a line thickness is thick pixels. Again, a thickness of 0 will fill the rectangle. Examples are shown in Figure 7.4.

Drawing a single pixel is done using the set_at function in the surface pack­age as follows:

screen.set at((x, y), color)

This draws a single pixel on the screen surface at the location (x,y) with the color specified by the tuple color.

Example: Create a Page of Note Paper

Note paper has blue lines separated by enough space to write or print text between them. It often has a red vertical line indicating an indentation level, and it serves as a place to begin writing. Drawing this is a matter of drawing a set of connected blue pixels in vertically separated rows, and then making a vertical column of red pixels. Here is one way to code this:

import pygame

width = 400 height = 600

screen = pygame.display.set mode((width, height))

clock = pygame.time.Clock()

pygame.init()

FPS = 10

while True:

clock.tick(FPS)
mouseX, mouseY = pygame.mouse.get pos()

for event in pygame.event.get():

if event.type == pygame.QUIT:

quit()

The output of this program is shown in Figure 7.5a. When the pixels are drawn immediately next to each other, they appear to be connected, and so in this case, they form horizontal and vertical lines. This does not easy to do for ar­bitrary lines; it is not obvious exactly which pixels to fill for a line between, say, (10, 20) and (99, 17). That’s why the line drawing functions exist.

Example: Creating a Color Gradient

When creating a visual on a computer, the first step is to have a clear picture of what it will look like. For this example, imagine the sky on a clear day. The horizon shows a lighter blue than the sky directly above, and the color changes continuously all of the way from the horizon to the zenith. If a realistic sky back­ground were needed, then it would be necessary to draw this using the tools avail­able. What would the method be?

First, decide on what the color is at the horizon (y=ymax) and at the highest point in the scene (y=ymin). Now ask: “how many pixels between those points?” The change in pixel color will be the color difference from ymax to ymin divided by the number of pixels. Now simply draw rows of pixels beginning with the horizon and moving up the image (i.e. decreasing Y value) changing the color by this amount each time.

Let’s assume that the color at the horizon is blue (40, 40, 255) and the top of the image is a darker blue (40, 40, 128). The height of the image is 400 pixels; the change in blue over that range is 127 units. Thus, the color change over each pixel is going to be 127.0/400, or about 0.32. A color cannot change a fractional amount, of course, but what this means is that the blue value decreases by ap­proximately 1 unit for every 3-pixel-increase in height. Do not forget that the horizon is at the bottom of the image, which has the greatest Y coordinate value, so that an increase in Y means a decrease in height and vice-versa.

The example program that implements this is as follows:

import pygame width = 400 height = 400

screen = pygame.display.set mode((width, height))

clock = pygame.time.Clock()

pygame.init()

FPS = 10

delta = 127.0/height

while True:

clock.tick(FPS)

mouseX, mouseY = pygame.mouse.get pos()

for event in pygame.event.get():

if event.type == pygame.QUIT:

quit()

screen.fill((255, 255, 255))

blue = 255

for y in range(0, height):

yy = height – y

for x in range(0, width):

screen.set at((x, yy), (100, 100, blue))

blue = blue – delta

pygame.display.update()

The gradient image looks like that in 7.5B (a full-color version of this and all images is on the accompanying disk).

1. Lines and Curves

Straight lines and curves are more complex objects than pixels, consisting of many pixels in an organized arrangement. A line is drawn by setting pixels. The fact that a line() function exists means that programmers do not have to figure out what pixels to draw and can focus on the higher level construct: the line or curve.

Example: Note Paper Again

The example of drawing a piece of note paper can be done using lines instead of pixels, and will be a little faster. Set the stroke color to blue and draw a col­lection of horizontal lines (i.e., that have the same Y coordinate at the endpoints) separated by 20 pixels, as before. Then draw a vertical red line for the margin. The program is a variation on the previous version (only the drawing portion of the code):

pygame.draw.line(screen, (255,    0,  0),  (25,  0),  (25,height), 1)

pygame.display.update()

The output from this program is the same as that for the version that drew pixels, which is shown in Figure 7.5a.

 

Source: Parker James R. (2021), Python: An Introduction to Programming, Mercury Learning and Information; Second edition.

Leave a Reply

Your email address will not be published. Required fields are marked *