Keeping it Small and Simple

2007.05.27

Pygame tutorial #2: drawing lines

Filed under: Graphics Programming, Pygame, Pygame Tutorial, Python Programming — Lorenzo E. Danielsson @ 02:46

Welcome to part 2 in my pygame tutorial. This time we will build upon what you learned last time as we start drawing onto surfaces. We will continue to move very slowly so that everybody gets a chance to learn.

Drawing a line

You draw a line by using pygame.draw.line. You can also use pygame.draw.aaline which draws an anti-aliased line. Using anti-aliasing can make the line appear less jagged in some cases at the expense of the function call being much slower.

To draw a blue line from (0, 0) to (200, 100) (note: we are measuring in pixels) onto the surface screen you do:


pygame.draw.line(screen, (0, 0, 255), (0, 0), (200, 100))

You could also do this:


blue = 0, 0, 255
point1 = 0, 0
point2 = 200, 100
pygame.draw.line(screen, blue, point1, point2)

This is will do exactly the same thing as the previous example, but is (possibly) more readable. Let’s try to put this together to a little program. We will draw two diagonal lines: one going from the top left-hand corner to the bottom right-hand corner and one from the top right-hand corner to the bottom left-hand corner. We will use pygame.draw.line for one of the lines and pygame.draw.aaline for the other.

 1 #! /usr/bin/env python
 2 
 3 import pygame
 4 
 5 screen = pygame.display.set_mode((640, 480))
 6 running = 1
 7 
 8 while running:
 9     event = pygame.event.poll()
10     if event.type == pygame.QUIT:
11         running = 0
12 
13     screen.fill((0, 0, 0))
14     pygame.draw.line(screen, (0, 0, 255), (0, 0), (639, 479))
15     pygame.draw.aaline(screen, (0, 0, 255), (639, 0), (0, 479))
16     pygame.display.flip()

I hope you recognize most of the code from the first tutorial. If you run the program you should see a big blue ‘x’ across the window.

Exercises

  1. Improve the program by getting rid of “magic numbers”. Declare two variables width and height and initialize them to the width and the height of the window. Then modify the rest of the program to use these variables instead of actual numbers. To verify that you have made all the required changes, try setting width and height to different values and confirm that you still get two diagonal lines and that each line’s end points are at one of the corners of the window.
  2. Improve the program further by declaring variables called linecolor, topleft, bottomright and so on. Modify the program to make use of the variables.
  3. Modify the program to draw the two lines in different colors.
  4. Write a program that instead draws one horizontal and one vertical line. The lines should both be centered.
  5. Write a program that draws four lines: the diagonal lines as in the example as well has the horizontal and vertical lines as in the last exercise. Each line should be in a different color. The program should take the height and width of the window as command-line arguments.
  6. Write a program that draws the following pattern:
    fishnet.png
    Once you have solved it for the upper left hand corner, repeat it so that the same pattern is drawn in all four corners of the screen. You should be able to draw all in all corners with a single loop and four calls to pygame.draw.line.

Moving things around

Now that we know how to draw lines on the screen with pygame, let’s start moving them around. Moving lines around is simple. we store the line coordinates in variables. Inside the event loop we modify the values of those variables. Let’s draw a line that jumps up and down.

 1 #! /usr/bin/env python
 2 
 3 import pygame
 4 
 5 y = 0
 6 dir = 1
 7 running = 1
 8 width = 800
 9 height = 600
10 screen = pygame.display.set_mode((width, height))
11 linecolor = 255, 0, 0
12 bgcolor = 0, 0, 0
13 
14 while running:
15     event = pygame.event.poll()
16     if event.type == pygame.QUIT:
17         running = 0
18 
19     screen.fill(bgcolor)
20     pygame.draw.line(screen, linecolor, (0, y), (width-1, y))
21 
22     y += dir
23     if y == 0 or y == height-1: dir *= -1
24 
25     pygame.display.flip()

There we go. The y-position of the line is determined by the variable y which increased by dir in each iteration of the event loop. The value of dir is 1 when the line is moving downwards, or -1 when the line is moving upwards. Simple, isn’t it?

Exercises

  1. Comment out the line screen.fill(bgcolor) and run the program. What happens?
  2. Extend the program to also include a vertical line that moves across the screen.

Drawing a color bar

Our final example for today will draw a single color bar (“copper bar” if you’ve ever owned an Amiga). Just like our last example, this one will also jump.

 1 #! /usr/bin/env python
 2 
 3 import pygame
 4 
 5 y = 0
 6 dir = 1
 7 running = 1
 8 barheight = 124
 9 screen = pygame.display.set_mode((800, 600));
10 
11 barcolor = []
12 for i in range(1, 63):
13     barcolor.append((0, 0, i*4))
14 for i in range(1, 63):
15     barcolor.append((0, 0, 255 - i*4))
16 
17 while running:
18     event = pygame.event.poll()
19     if event.type == pygame.QUIT:
20         running = 0
21 
22     screen.fill((0, 0, 0))
23     for i in range(0, barheight):
24         pygame.draw.line(screen, barcolor[i], (0, y+i), (799, y+i))
25 
26     y += dir
27     if y + barheight > 599 or y < 0:
28         dir *= -1
29 
30     pygame.display.flip()

In this example I create an array called colorbar (for the lack of a better name). This will hold values for the colorbar as it shifts from black to bright blue and back to black. Keep in mind that a color is composed of red, green and blue. Each one of these can be a value between 0 and 255.

If I change the blue value by one for each new line, I would get a really smooth gradient bar. But, the height would be 256 pixels from black to blue and another 256 pixels from blue back to black = 512 pixels, which is too high. There would hardly be enough space in our window to see the bar moving up and down.

So I have to decide on a bar height that I find acceptable. I settled on 124, which means I have 62 pixels from the black to blue gradient and another 62 for the blue to black gradient. This also means that I have to move from a blue value of 1 to a blue value of 255 in 62 pixels. The change in blue per line must be 4 per line.

I use two for loops to populate the barcolor array. The first loop pushes increasing values of blue to the array and the second one decreasing values of blue. It is important to notice that this array is nothing other than a lookup. It doesn’t contain the bar as you see it on the screen. It just contains color values.

Run it and see what it looks like. Once you’ve seen it run, analyze the code and make sure you understand exactly how it works. Then start experimenting with it.

Exercises

  1. The color bar example code is horrible. Full of “magic numbers” everywhere! Fix it.
  2. Try using pygame.draw.aaline for drawing the lines. Run the program. Do you notice any difference in speed?
  3. Change the color of the color bar.
  4. Write a program that draws three color bars in different colors. Take note of the height per bar, so that all three can fit and have some space for movement.

Conclusion

In this tutorial you have learned to draw lines. We will be staying with methods of drawing to the screen a little while longer, before we move on to other interesting things like loading and displaying images. In the next tutorial you will also learn a bit about mouse events.


2007.12.11:Added explanation of what the colorbar array does in the last example. Thanks to reader Sergy for pointing out that it needed some explanation.

19 Comments »

  1. nice tut

    Comment by dinky — 2007.09.06 @ 12:22

  2. Very nice!

    Comment by Karlisson — 2007.09.29 @ 20:42

  3. this is a great series! I’m already upto speed! no hiccups!

    Comment by DJ Fadereu — 2007.10.04 @ 13:30

  4. Hello, I’m completely new at programming, but I’ve found your tutorials extremely beginner-friendly unlike some others that I’ve been through. I’m commenting because I’m having a problem understanding your moving bar example. Could you please explain to me what exactly is going on in lines 11-15?

    Comment by Sergy — 2007.12.10 @ 22:11

  5. @Sergy: I guess you are referring to the lines:
    11 barcolor = []
    12 for i in range(1, 63):
    13 barcolor.append((0, 0, i*4))
    14 for i in range(1, 63):
    15 barcolor.append((0, 0, 255 – i*4))

    I hold color values in an array. The first for loop creates brighter and brighter shades of blue. The second loop goes back to darker and darker shades until we are back to black.

    Remember that a color consists of [ R, G, B ]. Each one of these can be 0-255.

    I want the blue value to go from 0 to 255 or at least as close to that as possible. If I use a step of one then the top of my bar will be 256 pixels high. The bottom will add another 256 pixels so I end up with a total of 512 pixels, which is too high.

    So instead I decide the bar height I want. I wanted mine to be around 124 pixels high. That means that I’ve got 62 pixels going from dark to bright and another 62 going from bright to dark.

    I have to go from 0 – ca. 255 in 62 pixels. That gives me a multiplier value of 4 per line, i.e. the blue value changes by a factor of 4 for every line in the bar.

    All this values are pushed into an array, so that I can later use them for drawing the bar.

    When you are trying to understand things like this I personally usually revert back to using pen and paper. Just keep a track of the values of all variables as you are going through the loop.

    Anyways, I hope that helps somewhat. I can be really lousy at explaining things at times. If you have more questions feel free to ask!

    And good luck with your pygame programming!

    Comment by Lorenzo E. Danielsson — 2007.12.10 @ 23:30

  6. great tutorial. im having some trouble with exercise 6 in the first part. i keep getting error messages. could someone please help me?

    Comment by skb126 — 2007.12.21 @ 23:48

  7. @skb126: Could you email me your code and if possible, yank and put the error message into the mail as well? My email is availabe on the “About” page.

    Comment by Lorenzo E. Danielsson — 2007.12.22 @ 14:57

  8. […] Step by Step for total beginners.  Check out PyGame Tutorial Part 1 – Getting Started :: PyGame Tutorial Part 2 – Drawing Lines :: PyGame Tutorial Part 3 – Mouse Events :: PyGame Tutorial Part 4 – More on Events :: PyGame […]

    Pingback by Python/PyGame Tutorials for Newbs | Newbie Game Programmers — 2008.01.03 @ 18:10

  9. Hi Lorenzo, and everyone else taking part in this tutorial! I was wondering if you could point me in the right direction for challenge #6, what kind of function is that exactly?

    Thanks in advance.
    PS: sorry for ressurecting something 8 months old!

    Comment by Dante Mochizuki — 2008.01.24 @ 21:55

  10. @Dante Mochizuki: the reason why I added that was actually to get you to sit down with pen and paper for a while. 😉

    Try to draw the patter on a piece of paper. For each line, consider that (x1, y1) is the point to the far left, and the point (x2, y2) is the “other” point (at the very top.

    Draw a dot quite far down the paper, against the left border. Draw another dot very close to the top left-hand corner of the paper. Draw a line between the dots.

    Draw another dot against the left border a little bit above the previous one. Draw a dot along the top of the paper, a little to the right of the previous one. Now draw another line connecting these two dots.

    You only need to draw 3-4 lines to get the general idea. You need to pay attention to the relationship between y1 and x2 as you draw each consecutive line.

    I’m not sure if my lousy explanation helps at all. If it does, by all means, give it a try in python. If my explanation was complete gibberish or you are still having problems solving it, just let me know and I’ll post a solution.

    Comment by Lorenzo E. Danielsson — 2008.01.24 @ 23:05

  11. Hey man,

    I really apreciate your tutorials. In pygame(the page)the tutorials just show you how to load images; images that allready exist cause they come with the pygame instalation, but that isnt thrue and I never got to load an image and do any graphic programation. I searched all the web and tried to paint a image in paint and save it in the file of the pygame package, but nothing resulted.

    So thanks to you I’ll can continue learning this weird world of programming.

    Comment by Max — 2008.02.01 @ 13:53

  12. @Max: thanks a lot. I write the way I do in part because I, for whatever reason (stupidity, lack of concentration, slow) usually struggle to learn new things. It doesn’t help that many of the people who write “tutorials” are more interested in displaying their own skills rather than actually teaching people something.

    That being said, I’m really happy about the amount of positive responses I get from people. I’ve never thought very highly of my own writing. I write these tutorials the way they would have me written in order for me to grasp it.

    Comment by Lorenzo E. Danielsson — 2008.02.01 @ 14:22

  13. Hi thanks so much for this tutorial it is helping me loads!

    with regards to exercise 6 i can see the pattern and whats supposed to happen to the pixels but i cannot figure out a proper loop for this, i have tried many but nothing seems to work right, either it wont work at all, it works but just skims across the screen without staying there or i get a blank screen.

    Thanks

    Comment by Kynan — 2008.02.11 @ 14:26

  14. @Kynan: that exercise it giving several people problems. I’ve decided to write a little extra tutorial to show you how to solve this one. Please give me a day or two (unfortunately I need to take care of a few work issues as well).

    Comment by Lorenzo E. Danielsson — 2008.02.14 @ 11:38

  15. Okay, all those who find exercise 6 in the section “Drawing lines” overly challenging can look at tutorial #7 where I go through step by step how to solve it.

    Comment by Lorenzo E. Danielsson — 2008.02.19 @ 23:55

  16. Thank you Lorenzo for a great tutorial. You seem to be a natural teacher. I really appreciate how you make the reader concentrate on having an image of the program in their head, before having them type it in. The exercises are superb, because they encougare tinkering and working with code. I’ve been dabbling with programming of and on throughout school, so I’ve read quite a lot of tutorials, but yours is truly tops. Cheers!

    Comment by Przem — 2008.03.19 @ 11:13

  17. Hi,

    First, thanks for your excellent tutorial.

    I was wondering other the performance side of the moving bar example (the simple red bar) – even reducing the frame refresh rate to 60 frames per second, and drawing just the single line (without bothering with the background), causes my 3.4 GHZ CPU to jump to 50% usage. Is there any way to optimize this code?

    Comment by eyal — 2008.03.21 @ 14:37

  18. @eyal: yeah there are. In tutorial #3 you will see one thing that helps quite a bit: avoid pygame.event.poll()./

    So why did I use poll() here if it is no good? Well, I have this idea to actually go through *all* of the pygame API, including the things that you shouldn’t use. Hopefully, by using them you’ll get the idea why to avoid them. 😉

    In a later tutorial I will also look at optimization in detail. But I need to go through all the gfx basics first.

    But also keep in mind two things about my examples. First, the python code is designed to be easy to understand rather than optimized. People who have python skills should be able to find quite a bit than can be optimized on python level. Those who don’t have the skills will sooner or later need to sit down and develop their python.

    Second, I write the samples to be a starting point for your own experimentation. That is what you will really learn from. You should take every single example I provide, rip it apart and reassemble in interesting ways. If you do that, you’re on the right path.

    I do have many, many more pygame tutorials planned. Sadly, real life and boring work gets in the way at times, so I’m progressing a bit slower than I had hoped.

    Comment by Lorenzo E. Danielsson — 2008.03.21 @ 15:17

  19. Thanks Lorenzo for your prompt reply – just read your 4th tutorial that addresses these performance issues: the pygame.event.poll() slightly improves things, but I’ll surely look into ways to optimize things further.

    Comment by eyal — 2008.03.21 @ 15:59


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.