# Scary stuff!  Don't look lest you be intimidated!



## eb7w5yfe (Oct 20, 2007)

Used to be titled: Simple graphics programming tutorial for non-programmers.

Edit: it has been brought to my attention that this information is probably overwhelming to most people, and I really don't want to scare any interested people away from programming.  So please don't look if you think you would get intimidated.  I'll work on finding a way to present the information such that it doesn't scare anyone off.  It really isn't very complicated, but it can look that way if it's not presented well.

In the mean time, I'd welcome suggestions from people who already know programming on how to make this as easy to learn as possible.  Or, if you don't know programming but are willing to spend a few hours actually learning new things without getting discouraged, you're welcome to read through this and let me know what you think.

Edit #2: I forgot to mention that I have some examples of the sort of thing this tutorial is working towards.  There are two submissions in my FA gallery which are relevant:
Playing with 2D metaballs
Bouncy Scrapplet
Both of these are programs that you can run.  The first one is an executable, with C source code supplied if you don't trust random programs or are not on Windows.  The second is a Java applet.

Index:
1) Introduction
2) Boring Preliminaries
3) Displaying Graphics
4) Animating Graphics
To Be Continued...

This is a tutorial on how to do simple graphics programming.  I'm going to try to start simple enough that people who have never tried programming before will be able to follow along.  It will take some effort to understand if you're new to programming, but I will try to keep it interesting enough to be fun.  If anything is too complicated or otherwise hard to get through, please let me know and I'll try to fix it.

Also feel free to point out typos or grammatical mistakes.  I've already spent quite a few hours typing up the first two sections, and I'd rather work on new parts than repeatedly proof read the existing areas.  I will however be happy to go back and fix errors that are brought to my attention.

My interest in programming was sparked largely by playing with simple but fun graphics.  I spent many hours playing with GWBasic and QBasic programs, making things that resembled screen savers or simple games.  I am a professional programmer now, working on much more boring stuff all day long.  I still occasionally find time to play with fun little programs, and I hope that by writing this tutorial I can introduce some other people to the same joy.

I'm going to write this tutorial using the Python programming language, and using Pygame to display the graphics.  Python and Pygame make for a combination that is extremely easy to use for simple 2D graphics.  The disadvantage is that they are slow; but they are still plenty fast enough for us to accomplish lots of interesting things.

This is not meant to be an in-depth or comprehensive introduction to programming.  I'm going to keep things as simple as possible and introduce the bare minimum of programming concepts.  I fully expect that the simplifications and omissions I make will leave real programmers cringing in horror.  The problem is that abstract programming ideas are boring to most people: I want to get to the fun part as quickly as possible, so that I scare off the minimum number of people with the preliminaries.

Requirements:
You will have to download and install Python and Pygame.  The Windows installers for these programs can be found here: Python Pygame.  These applications are also available for OSX and Linux.  

You will also need a text editor for writing the code in.  I generally use SPE, but that can be a little complicated to install.  There is an editor called IDLE that comes with Python, and while not perfect, it should be sufficient for our needs.  I will assume that you're using IDLE for the tutorial, but if you're feeling ambitious you can try to get SPE, or use any other editor (even notepad world work, though I wouldn't recommend it).

References:
Whenever you are working on a program, it's extremely useful to have the relevant documentation close at hand.  For these tutorials, I'd highly recommend having a browser open to the Python Tutorial and the Pygame Documentation.


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

Boring Preliminaries

There are some basic programming concepts that it is necessary to understand before we can get to even the simplest of graphics.  I'll get through these as quickly as possible.  For a much more comprehensive introduction to programming, I recommend that you read The Python Tutorial.

Despite the name of this section, I don't want it to be so dry that it scares everyone off.  I'll happily entertain suggestions for making it more interesting.

Although I only go over each concept briefly, there is a lot of information to absorb here if you've never done programming before.  Don't be intimidated if you have trouble grasping it all at once: these ideas are something that would typically take an entire 4-credit introduction to programming course to get through in college, although such a course would go into more depth.  

If you want to, feel free to skip ahead to the more interesting parts where we start playing with graphics.  You might not understand what is going on, but you can always come back to this section later.

I recommend that you follow along with these examples by typing them in and running them.  The ideas stick a lot better that way than by just reading them.  Also feel free to experiment and try different things; that's the best way to learn.

*Basic Math*

Programming is at its core nothing but math and logic.  Don't worry if you're bad at math: the math required for programming is of the very simple variety.  There's no long division here; we let the computer handle that for us.

I assume that at this point you have installed Python.  Let's fire it up and give it a try.  Start the program called IDLE, and you should see something like this:

```
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.

    ****************************************************************
    Personal firewall software may warn about the connection IDLE
    makes to its subprocess using this computer's internal loopback
    interface.  This connection is not visible on any external
    interface and no data is sent to or received from the Internet.
    ****************************************************************
    
IDLE 1.2      
>>>
```
This is python's interactive shell.  This means that you can type commands and immediately see a response to them.  This is very useful for testing single statements or small programs.  When we get to larger programs, we will write the program in a text editor, save the file, and tell Python to run the whole file full of commands at once.  For now, let's see what the interactive shell can do.

Try typing some math, and then hitting enter:
>>> 2 + 2
4
>>>

Look at that!  We have a fancy calculator.  How smart is the calculator?
>>> 4 * 20
80
>>> 45 / 5
9
>>> ((5 * 5) - 1) / 3
8
>>> (5 + 5 - 1) / 3
3
>>> 

It supports all the basic math operations, and parenthesis to control which operations happen first.  Let us see what happens if we do a division which results in a fraction of a number:
>>> 12 / 10
1

That isn't what you'd expect to see, was it?  What happened here is that when Python sees numbers like 12 and 10, it assumes that they are integers (whole numbers).  When it divides an integer by an integer, it gives an integer as a result.  You can use the modulus operator (%) to get the remainder:
>>> 12 % 10
2

You can also use 12.0 and 10.0 to let Python know that these are floating point numbers (numbers with decimal places):
>>> 12.0 / 10.0
1.2

Let's try one last mathematical operation:
>>> 10 / 0

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    10 / 0
ZeroDivisionError: integer division or modulo by zero

What happened here?  Well, if you remember your math, you know that it is not possible to divide by zero: the result would be infinity (when you divide by smaller and smaller numbers, the result keeps getting bigger).  Python lets you know that something was wrong with your instructions, and an error occurred.  

Seeing errors reported is something that you will see quite often while programming.  The division by zero is pretty rare, but there are lots of other errors that can happen when Python goes to execute the instructions you provide for it.  If something goes wrong, your program will stop, and there will be an error message like this displayed.  By looking at the error message and the line that it occurred at, you can go and fix the problem and try it again.

*Strings*

You've seen that there are two types of numbers; integers (whole numbers) and floats (numbers with decimal places).  Numbers are handy, and we use them for almost everything in programming, but they are not good for everything.  What if you want to display a message on the screen, or store a name?  We need to be able to handle text as well, and in programming terms we call pieces of text 'strings'.

To show that something is a string, just put in in quotes:
>>> "Hello World!"
'Hello World!'

You can even perform some mathematical operations on strings:
>>> "Hello" + "World"
'HelloWorld'

but not others:
>>> "Hello" - "World"

Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    "Hello" - "World"
TypeError: unsupported operand type(s) for -: 'str' and 'str'
>>> 

*Variables*

A variable is named storage location.  You can think of it as a box with a label on it.  You can put anything that you want into the box, or take something out of the box and put something else into it.  The box can only hold one "thing" at a time.

To create a variable in Python, just type in a name and set it equal to something:
>>> a = 5
>>> a
5

The variable a now holds the value of 5.  You can change what it holds:
>>> a = 'this is a string'
>>> a
'this is a string'

You can treat the variable as if it were whatever it is holding.  For instance, if the variable has a number in it, you can perform mathematical operations on it:
>>> a = 5
>>> a + 2
7

You can take the result of an operation and store it in a variable:
>>> a = 5
>>> b = a * 2
>>> b
10

You can even set a variable equal to an operation that involves that variable.  The operation will be performed first, and then the result copied into the variable:
>>> a = 10
>>> a = a * 2
>>> a
20
>>> a = a * 2
>>> a
40

*Print Statement*

You may have noticed that to see what is in a variable, you can just type the name of the variable and hit Enter.  This works fine while we're in Python's interactive mode, but what if we want to display something while a program is executing?  For this we use the print statement:
>>> print 5
5
>>> print "Hello World"
Hello World
>>> a = 10
>>> print a
10
>>> print a * 3
30
>>> print "Hello" + "World"
HelloWorld

At this point it is useful to start writing instructions into a separate file and executing them all at once.  In IDLE, select File->New Window.  This will open up a separate windows that you can type programs into.  You can still go back to the Python Shell window at any time if you want to test a command immediately.

In the new window, type in a simple program:
*print* 'Hello World!'
*print* 'Five times 3 is:', 5 * 3


After you have entered this, or some similar simple thing, save the file.  It does not matter where you save the file or what name you give it, but it should have the extension '.py'.  For instance, you can save the file to your desktop with the name "test1.py".

After you have saved the file, select Run->Run Module from the menu, or press F5.  This instructs Python to run everything in the file the same as if you had typed it all in to the shell.  The results will be displayed in the shell window.

*Comments*

When writing a computer program, it is often helpful to make notes about what the code is doing.  These are called comments.  In order to prevent Python from trying to run these comments as if they were code, you have to use a special symbol: "#".  Like so:
_# This displays a message on the screen_
*print* "saying something something..."

_# If you earn $10/hour and work for 35 hours/week,_
_# how much will you have earned in a week?_
dollars_per_hour = 10
hours_per_week = 35
*print* "you will have earned", dollars_per_hour * hours_per_week, "dollars"


If you execute this program, you will see the following output:

```
saying something something...
you will have earned 350 dollars
```

This is also a good review of some of the concepts covered so far.  Do you understand what the second part of the program is doing?  How could you modify it to take out a 20% tax before reporting the amount earned?

*Functions*

Very frequently in programming you will want to re-use a given piece of code multiple times.  For example, maybe you want to calculate the weekly salary as in the previous example, but you want to do so for 3 different people.  You could copy and paste the code:
_# calculate Arabeth's weekly salary_
dollars_per_hour = 12
hours_worked = 40
amount_earned = dollars_per_hour * hours_worked
*print* 'Arabeth earned', amount_earned, 'dollars'

_# calculate Beauford's weekly salary_
dollars_per_hour = 8
hours_worked = 25
amount_earned = dollars_per_hour * hours_worked
*print* 'Beauford earned', amount_earned, 'dollars'

_# calculate Clint's weekly salary_
dollars_per_hour = 9
hours_worked = 35
amount_earned = dollars_per_hour * hours_worked
*print* 'Clint earned', amount_earned, 'dollars'


The output is:

```
Arabeth earned 480 dollars
Beauford earned 200 dollars
Clint earned 315 dollars
```

This works, but it doesn't seem very efficient, does it?  The same thing is being done over and over.  We can put the repeating code into a function, which can be used multiple times:

```
def calculate_salary(dollars_per_hour, hours_worked):
    amount_earned = dollars_per_hour * hours_worked
    return amount_earned
```
 
In Python, you start a function using the word "def" (short for define, as in: here's the definition of the function).  The function can take some number of variables as input, which is this case are dollars_per_hour and hours_worked.  The input parameters are placed in parenthesis.  The colon marks the end of the parameters and the beginning of the commands that are executed when the function is called.  

Any of the lines which are indented are part of the function.  The function can have any number of commands which it executes.  When the calculations are done, the result can be returned using the 'return' statement.

There is actually no need to use the amount_earned variable.  We can take it out and the function will behave the same:

```
def calculate_salary(dollars_per_hour, hours_worked):
    return dollars_per_hour * hours_worked
```
So now that we have a function, how do we use it?  Like this:

amount_earned = calculate_salary(10, 40)


This would calculate the amount earned for someone who makes $10/hour and has worked for 40 hours and store the result in amount_earned.

So lets see what our previous example looks like if we use the function:

```
def calculate_salary(dollars_per_hour, hours_worked):
    return dollars_per_hour * hours_worked

# calculate Arabeth's weekly salary
amount_earned = calculate_salary(12, 40)
print 'Arabeth earned', amount_earned, 'dollars'

# calculate Beauford's weekly salary
amount_earned = calculate_salary(8, 25)
print 'Beauford earned', amount_earned, 'dollars'

# calculate Clint's weekly salary
amount_earned = calculate_salary(9, 35)
print 'Clint earned', amount_earned, 'dollars'
```

That's a little cleaner, isn't it?  It's a long way from perfect though.  Can you write a function that will both calculate someone's earnings and print out the result all at once?  Hint: you can pass the person's name as another parameter to the function.

*Lists and Tuples*

Lists and tuples are both ways of storing multiple pieces of data in one container.  Here is an example of each:

lst = [1, 2, 3, 'red', 'blue']
tup = (4, 5, 6, 'white', 'black')

*print* "this is a list:  ", lst
*print* "this is a tuple: ", tup


As you can see, they look pretty similar.  Lists are created with square brackets, while tuples are created with parenthesis.

In this example, lst and tup are variables.  Do you notice something odd here?  I said previously that variables only store one thing at a time, but here are variables with multiple things in them!  Except that they really aren't.  The variable lst contains only one thing: a list.  And the variable tup contains only a tuple.  Now, it is true that the list and the tuple contain multiple values, but as far as a variable is concerned they're only one item.

If you have a list or tuple with many items in it, you can get at the individual items using an index.  An index is a number in square brackets which references a specific item in the list or tuple, starting with the first item at index 0 and counting up from there.  So the first item in the list is at index 0, the second item in the list is at index 1, the third item is at index 2, and so on.

This numbering may seem a little counter-intuitive  It actually makes a lot of sense if you know what computers are doing under the hood.  I'm not going to get into that here. but essentially the number is an offset from the starting location.  The first item is at 0 because it is at the starting location, the second item is at 1 because it is 1 past the starting location, and so on.

Anyway, it looks like this:
>>> lst = ["cat", "dog", "manatee", "elephant", "vole"]
>>> lst[0]
'cat'
>>> lst[3]
'elephant'
>>> tup = ("chair", "desk", "lamp")
>>> tup[1]
'desk'

Although they look the same so far, tuples and lists are significantly different.  They both store multiple things, but tuples are generally used to temporarily group a small number of things, while lists are used to store a large number of things for a longer time.  Tuples are sort of once-off: once you create one, you can't modify it.  Lists can have items added to and removed from them at any time.  A list is like a neatly organized and labeled parts cabinet), while a tuple is like a rubber band.

So what do you use them for?  Well, let's say that you have a bunch of items which are a specific color, and you want to report what color they are:

```
item1_name = "Apple"
item1_color = "Red"

item2_name = "Bear"
item2_color = "Brown"

item3_name = "Car"
item3_color = "Red"

def report_color(name, color):
    print 'The', name, 'is', color

report_color(item1_name, item1_color)
report_color(item2_name, item2_color)
report_color(item3_name, item3_color)
```

The output looks like this:

```
The Apple is Red
The Bear is Brown
The Car is Red
```

This is rather unwieldy, isn't it?  We can make it look a little better by combining an item's name and its color into a tuple:


```
item1 = ("Apple", "Red")
item2 = ("Bear", "Brown")
item3 = ("Car", "Red")

def report_color(item):
    print "The", item[0], "is", item[1]

report_color(item1)
report_color(item2)
report_color(item3)
```

That's looking a little cleaner now, isn't it?  But we're still repeating a lot of code that looks the same.  That is generally an indication that there's a better way to do things.  Let's put all the items into a list now:

```
all_items = [("Apple", "Red"), ("Bear", "Brown"), ("Car", "Red")]

def report_color(item):
    print "The", item[0], "is", item[1]

report_color(all_items[0])
report_color(all_items[1])
report_color(all_items[2])
```

Do you see what happened here?  We made a list and filled it up with tuples!  Yes, you can put tuples in lists, or lists in tuples, or lists in lists, and so on.  Remember, a variable holds one of anything, and a list or tuple counts as only one thing!

*For Loops*

This still doesn't look very nice though, does it?  We still have 3 lines that look awfully similar there, which are calling the function.  What can we do about that?

There is a construct called a for loop which looks like this:

```
for one_item in many_items:
    do_stuff()
```

In a way, this looks similar the the function definition that we're seen.  It's a single line that to set things up, and then multiple indented commands which are run.

many_items has to be something like a list or tuple which contains multiple individual things.  The body (indented part) of the loop will run once for each item that is in the list.  one_item is a variable that will be set equal to each item from the list before the body of the loop runs.  For instance:

```
>>> lst = ["This", "is", "a", "list", "of", "strings"]
>>> for one_word in lst:
	print "one_word is:", one_word
```


```
one_word is: This
one_word is: is
one_word is: a
one_word is: list
one_word is: of
one_word is: strings
```

Do you see how this can apply to our example of items with colors?

```
all_items = [("Apple", "Red"), ("Bear", "Brown"), ("Car", "Red")]

def report_color(item):
    print "The", item[0], "is", item[1]

for item in all_items:
    report_color(item)
```
 
We have gotten rid of a lot of needless repetition now, and the program looks a lot nicer.  Actually, we probably don't event need that report_color function any more: the print statement could just be moved right into the for loop.

*Range Function*

One thing that you often want to do in programming is to repeat a task a certain number of times.  In Python, there's a built in function called range.  This generates a list of numbers sequential numbers with a given starting and stopping point.  For instance:

```
>>> range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
This generated a list from the given starting point (0), up until just before the given ending point (10).

This can be combined with the for loop in order to execute a statement a given number of times.  For instance:

```
>>> for index in range(0, 5):
	print "REPEAT THAT"

REPEAT THAT
REPEAT THAT
REPEAT THAT
REPEAT THAT
REPEAT THAT
```

You can also make use of the generated numbers if you want to:

```
>>> for index in range(0, 5):
	print index * 2

0
2
4
6
8
```

Oh no!  My message is too long!  I'm going to try splitting it here.


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

Boring Preliminaries Continued 

*Classes*

Classes are a way of grouping together related variables and functions.  Unlike lists and tuples, each thing in the group has a name that can be used to refer to it.  

For instance, you might be storing some information about a person.  Let us say that a person has these properties: a name, an age, a weight, a height, a certain number of arms, and a certain number of legs (hey, this is all theoretical: we can have 20-armed people if we want to).  A person also has things that they can do: for out example, a person can tell you about them self, can grow (gaining weight and height), and can mutate (gaining arms and legs).

We can make a class to store the properties and actions of a person.  The properties of the person become variables, and the actions that a person can perform become functions.

The class just describes what a person is; it does not define a specific person.  If we use the class as a template to create an actual person, that is called creating an instance of the class.  An instance of a class is called an object.  So a class is the template for something, while an object is an instance of that thing.

This is what an almost empty class looks like:


```
class Person:
    pass
```
 
The format of a class is similar to what we've already seen for methods and loops: the name of the class comes first, and everything indented under that is part of the class.

That 'pass' statement is a special command that just means to do nothing.  It is necessary here, because you can't have a completely empty class.

There is a special function associated with classes called __init__ (short for initialize).  This is a function which is called when you use the class to create an object.


```
class Person:

    def __init__(self):
        pass
```
 
If you look at the __init__ function, you can see that it takes a single parameter.  All functions for the class take one parameter called (normally called 'self') which can be used to access the variables and functions associated with the particular object that is being used.  For instance, if you call a 'tell me your name' function for a person, there has to be some way to access the 'name' variable for that specific person.

Let us add the properties to the Person class as variables:


```
class Person:

    def __init__(self, name):

        self.name = name
        self.age = 5
        self.height = 3
        self.weight = 50
        self.arms = 2.0
        self.legs = 2.0
```

Can you make sense of everything that is going on here?  The first thing we did is add another parameter to the constructor (the __init__ function) which is a name.  This will require us to provide a name for each person that we create.

The second thing that we did is create class variables for all the various properties of a person.  The '.' is how we access an object's variables or functions.

We can now create objects from the Person class and do thing with those objects:

```
bob = Person("Bob")
print bob.name, 'is', bob.age, 'years old and', bob.height, 'feet tall'

bob.age = 10
bob.height = 5
print bob.name, 'is', bob.age, 'years old and', bob.height, 'feet tall'
```

If you run this code, you should see:

```
Bob is 5 years old and 3 feet tall
Bob is 10 years old and 5 feet tall
```

We create a Person named Bob, and print out some information about him.  We then change Bob's age and height, and print out the information again.  Try creating some other people and setting their parameters.

Instead of printing out a person's information manually, lets give a Person the ability to report their own statistics:

```
class Person:

    def __init__(self, name):

        self.name = name
        self.age = 5
        self.height = 3
        self.weight = 50
        self.arms = 2.0
        self.legs = 2.0

    def tell_about_self(self):

        print 'My name is', self.name
        print 'I am', self.age, 'years old'
        print 'I weigh', self.weight, 'pounds, and am', self.height, 'feet tall'
        print 'I have', self.arms, 'arms and', self.legs, 'legs'
```
 
So now we can create a person and ask them about themselves:

```
bob = Person("Bob")
bob.tell_about_self()
```


```
My name is Bob
I am 5 years old
I weigh 50 pounds, and am 3 feet tall
I have 2.0 arms and 2.0 legs
```

This is much more convenient than manually printing out Bob's information every time we want to know what he looks like.  

Let's try adding some more actions for Person:


```
class Person:

    def __init__(self, name):

        self.name = name
        self.age = 5
        self.height = 3
        self.weight = 50
        self.arms = 2.0
        self.legs = 2.0

    def tell_about_self(self):

        print 'My name is', self.name
        print 'I am', self.age, 'years old'
        print 'I weigh', self.weight, 'pounds, and am', self.height, 'feet tall'
        print 'I have', self.arms, 'arms and', self.legs, 'legs'

    def grow(self):

        self.age = self.age + 1
        self.height = self.height + 1
        self.weight = self.weight + 25

    def mutate(self):

        self.arms = self.arms * 1.4
        self.legs = self.legs * 1.2
```
 
Now we can try doing some interesting things to a person:


```
bob = Person("Bob")
bob.tell_about_self()

bob.grow()
bob.tell_about_self()

bob.grow()
bob.grow()
bob.tell_about_self()

for i in range(0, 5):
    bob.mutate()
bob.tell_about_self()
```

Look at what we've done to Bob!

```
My name is Bob
I am 5 years old
I weigh 50 pounds, and am 3 feet tall
I have 2.0 arms and 2.0 legs
My name is Bob
I am 6 years old
I weigh 75 pounds, and am 4 feet tall
I have 2.0 arms and 2.0 legs
My name is Bob
I am 8 years old
I weigh 125 pounds, and am 6 feet tall
I have 2.0 arms and 2.0 legs
My name is Bob
I am 8 years old
I weigh 125 pounds, and am 6 feet tall
I have 10.75648 arms and 4.97664 legs
```

*Conditionals*

Another important part of programming is being able to do things conditionally.  You have to be able to say: If (condition is true) then (do thing 1) otherwise (do thing 2).  This lets you look at some kind of data and perform a different action depending on what you see.  Without this capability, the program would be limited to just doing the same sequence of steps and nothing would change.

To compare two variables, you can use operators such as '==' (equal to), '<' (less than), '>' (greater than), '<=' (less than or equal to), '>=' (greater than or equal to), '!=' (not equal to).  You can also use the words 'not', 'and', 'or' to combine comparisons.  Make special note that the 'is equal to' sign is '==', a double equal sign.  Single equal sign means assignment (like setting a variable equal to 5).  Try switching to the Python Shell and playing with different comparisons:

```
>>> 1 == 1
True
>>> 1 == 5
False
>>> 1 != 5
True
>>> "apple" == "pear"
False
>>> "apple" == "apple"
True
>>> 5 == "apple"
False
>>> True == False
False
>>> not True
False
>>> (5 == 1) or (3 == (1 + 2))
True
```

So how do you use these comparisons in code?  You use the if statement.  It looks like this:

```
if x == 10:
    print 'x is equal to 10'
else:
    print 'x is not equal to 10'
```
 
Pretty simple, isn't it?  You can also leave off the else part if you want to.

Here is a function which can tell you if a number if odd ising an if statement:

```
def is_odd(x):
    # remember, the modulus operator (%) calculates
    # the remainder of an integer division operation
    if x % 2 == 0:
        print x, 'is even'
    else:
        print x, 'is odd'
```
 
Can you figure out how to modify the function such that it returns True or False instead of printing a message?  Hint: remember the 'return' statement.  Second hint: you can actually do this in one line and without using an if statement.

*While Loop*
Now that you know how conditionals work, I can introduce a type of loop other than the for loop.  A while loop keeps repeating as long as a condition remains true.  This is useful if you want to loop until something happens (or stops happening) rather than looping for all items in a list or for a certain number of times.  Here's an example:


```
x = 1
while x < 100:
    x = x + x
    print 'x is now', x
```
 

```
x is now 2
x is now 4
x is now 8
x is now 16
x is now 32
x is now 64
x is now 12
```

*Import Statement*

Python lets you use a certain set of basic operations without doing anything special.  Things like variables, lists, and loops will always work.  However, more advanced or specialized abilities are not available by default.  Since most programs will not use all of the specialized functions, leaving them out keeps the environment cleaner and not so cluttered up with features.

To pull in one of the specialized modules, you use the 'import' statement.  This is also how you access external libraries that didn't come with Python at all, such as Pygame that we'll be using soon.

For example, this is how you would get access to a function which generates random numbers:

```
import random

print random.random()
print random.random()
print random.random()
```

If you needed to calculate a square root, you would import the math module:

```
import math

print math.sqrt(25)
print math.sqrt(100)
```

You can find information about these modules and many more in the Python Documentation

*Standard Program Structure*
So far we have been typing in code in the source file the same way that we would in the interpreter.  There is actually a litle bit of structure that is normally used for Python programs:

```
def main():
    pass

if __name__ == '__main__':
    main()
```

This declares a main() function which is run when the program is started.  The purpose of the if statement is to execute main only if the file is run directly.  The problem is that any '*.py' file can be imported as a module by any other file, and you don't want your program to run if someone imports it by accident.

*The End*
That's it for the preliminaries!  In the next section we'll actually get started with graphics.


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

Displaying Graphics

There are a few basics of how computer graphics work that I have to go over before getting to the code.  Don't worry, this will be a very short and simple explanation; nothing like the introduction to programming I went through earlier.

*Computer Graphics Basics*

Computer monitors are essentially just a big grid of very small lights.  Each pixel is actually 3 lights: one red, one green, one blue.  You can actually see this if you look at your monitor really closely (use a magnifying glass or camera on macro mode or such). 

Each color of every pixel can be turned to different brightnesses.  By mixing brightnesses of red, green, and blue, we can achieve the appearance of any other colors.  We generally write a color as 3 numbers which indicate the red, green, and blue levels like this: (red, green, blue).  The intensity can vary either from 0.0 (off) to 1.0 (full), or from 0 (off) to 255 (full).  We'll use the 0 - 255 range because that is what Pygame uses.

So here are some examples of colors and their corresponding numbers:
black (0,0,0)
white (255,255,255)
medium gray (128,128,128)
bright red (255,0,0)
medium red (128,0,0)
bright green (0,255,0)
bright blue (0,0,255)
yellow (255,255,0)
cyan (0,255,0)
magenta (255,0,255)

To draw something on the screen, you just instruct the computer to change the brightness of these little lights in a specific area.  For instance, if you want a black background with a white diagonal line, you can tell the computer to set all the pixels to (0,0,0), and then set all the pixels along the diagonal to (255,255,255)

Of course, doing this requires us to be able to specify a specific point on the screen to set.  We do this using pixel coordinates.

You should remember number lines from early school:

```
<---|-----|-----|-----|-----|-----|-----|--->
   -3    -2    -1     0     1     2     3
```
Using a number line we could specify the location of any point in one dimension.  However, this is not very useful to us on a two dimensional screen.

Maybe you remember geometry class, where you learned to specify the location of a point by using one horizontal number line (the x-axis) and one vertical number line (the y-axis):

```
^ 
                   |
  (-2,2)          (2)         (2,2)
                   |
                   |
                  (1)
                   |
                   |
<--(-2)---(-1)----(0)----(1)----(2)--->
                   |
                   |
                 (-1)
                   |
                   |
  (-2,2)         (-2)          (2,-2)
                   |
                   V
```
We can use something like this to specify a location on the computer screen.  However, we don't want to deal with negative numbers, so we move the (0,0) location to the corner of the screen:

```
^
   |
4  -        (2,4)
   |
   |
3  -
   |
   |
2  -               (3,2)
   |
   |
1  -   (1,1)
   |
   |
0  +-----|-----|-----|-----|--->
   0     1     2     3     4
```
This isn't quite how you specify a location on the screen either.  The (0,0) location is actually in the top left corner of the screen, so it looks more like this:

```
0     1     2     3     4
0  +-----|-----|-----|-----|--->
   |
   |
1  -   (1,1)
   |
   |
2  -               (3,2)
   |
   |
3  -
   |
   |
4  -         (2,4)            
   |
   V
```
That is how the coordinates are laid out.  So if you draw a circle at location (0,0), it will appear in the upper left of the computer screen.  If you screen is 640x480 pixels, a circle at (320,240) would be right in the middle, while a circle at (639, 479) would be at the lower right corner.

*Importing Pygame*

We'll start with the basic program framework that the first section of this guide ended with:

```
def main():
    pass

if __name__ == '__main__':
    main()
```
 
The first thing you have to do is import pygame.  Up above the main function, add the import statement:
*import* *pygame*


This will give us access to all of the pygame functions and variables.

*Initializing Pygame*

The next step is to initialize Pygame.  This has to be done before we can use it for anything.  Add this statement to the main function:
pygame.init()


You can also remove the pass statement, since main isn't empty any more.

We also have a pygame function to call before the program exits, to ensure that everything from it is cleaned up (if you don't use this, in some cases you might see a window stick around when it should be closed).  Put this function call at the end of main:
pygame.quit

*Displaying a Window*

At this point, pygame is ready to be used.  The first thing we want to do is create a window to draw things in.

To create a pygame window, we call pygame.display.set_mode().  You can look at the documentation for this function to see the details.  What we're interested in is that we have to pass it the size of the window to create, and it returns a surface which we can draw on.

Pygame uses a surfaces for everything.  A surface is sort of like a picture that we can modify: we can draw things onto it, and we can copy one surface onto another.  When you call pygame.display.set_mode, it returns a special surface which is linked to the window that you just created.  Whenever you draw to this surface, whatever you draw will appear in the window.

Add this code to main, in between the pygame initialization and the pygame cleanup:
screen = pygame.display.set_mode((640, 480))


This will create a window of size 640x480 pixels, and save the returned surface to the variable called screen.

This is what our program should look like so far:

```
import pygame

def main():

    # initialize the pygame module
    pygame.init()

    # create a window of size (640, 480) and store the returned
    # surface in the variable screen
    screen = pygame.display.set_mode((640, 480))

    # clean up pygame before exiting
    pygame.quit()

if __name__ == '__main__':
    main()
```
 
You can run the code now if you want to.  Pygame will take a second to initialize, the window will pop up, and then it will immediately go away.  Can you tell why?

In the main function, the window is created.  The next command after that is to quit pygame.  The computer does exactly what we tell it to, even if it doesn't make much sense: it makes a window, then immediately quits.

What can we do about this?  We could add an infinite loop after the window is displayed.  An infinite loop is a loop that never exits.  If the loop never exits, then pygame never quits.  Try adding this code right after where the window is created:

```
while True:
    pass
```
 
You can run the program now and the window will stick around.  I don't recommend it though; since there will be no way to exit!  The window will not respond to you trying to close it.

*Events*

In order to allow some way of exiting the program, we have to use Pygame Events.  Events are things that happen when the user interacts with the program.  The user presses a key on the keyboard?  An event occurs.  User clicks a mouse button?  Another event.  User minimizes the window?  Also a type of event.  The event that we're interested in is called the Quit event.  This is what happens when you try to close the Pygame window.

What we have to do is call the function pygame.event.get, which gets a list of all the events that have happened since the last time we called pygame.event.get.  The events will be in the order that they occurred, and there will probably be a lot of them that we don't care about.  There are events that occur every time the mouse is moved, for example.  

We will have to get the list of events that occurred, and then loop through it looking at each event.  If a quit event we should do something about it, but any other event we can ignore.

This event loop should go in the infinite loop that we added already (this infinite loop is also called the main loop).  That way, the program will continually check for new events and act on them.

Modify your program to look like this:

```
import pygame
import sys

def main():

    # initialize the pygame module
    pygame.init()

    # create a window of size (640, 480) and store the returned
    # surface in the variable screen
    screen = pygame.display.set_mode((640, 480))

    # start an infinite loop
    while True:

        # process all events that have occurred
        for event in pygame.event.get():

            # if a quit event occurs, exit the program
            if event.type == pygame.QUIT:

                # clean up after pygame
                pygame.quit()

                # exit immediately
                sys.exit()

if __name__ == '__main__':
    main()
```
 
Now in the main loop, the program will process all events.  If it sees a quit event in the list, it exits the program.  It cleanly quits Pygame, and then calls sys.exit.  Sys.exit is a function which will make the program immediately exit from that point.  Note that we have had to import the sys module in order to have this function available.

You can now run the program and it will behave as expected.  A window appears and sticks around, but it does exit when you close it.

*Sleep*

If you look at task manager while your program is running, you may notice that the program is using 100% of the CPU!  This isn't good: the program is doing nothing at all.

Actually, that's not really true.  What the program is doing is checking for events.  Over and over again, as fast as it possibly can.  It really isn't necessary to check for events millions of times a second, so we should make the program wait just a little while in between each run of the loop.

Add this line in the main loop (outside of the event checking):
pygame.time.wait(10)


You can look at the documentation for this function.  What it does is make your program go to sleep for a little while, and lets other programs execute.  It will wait for at least the time given, but possibly a little more (because other programs on the computer have gotten started working on something while yours was sleeping, and take a little time to give control of the CPU back).  The time is in milliseconds, which are thousandths of a second.  So this command will make our program wait for at least 10/1000 second, which means it will run the main loop at most 100 times per second.  That should be plenty. 

You can run the program again, and it should be much better behaved now.

*Filling the screen*

So far, we haven't drawn anything to the screen.  It has defaulted to a black background.  What if we want a different colored background?

If you look at the documentation for Surface, there's a function called fill.  This fills the surface with a given color.

So, let's try it.  Add this code before the main loop, but after the window is created:

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


This should fill the screen with white.  But if you try running the program, it doesn't work.  Why not?

*Double Buffering*
Pygame uses something called double buffering to eliminate flicker.  What this means is that when you draw to the screen, the things that you draw do not actually show up immediately.  You have to call pygame.display.flip(), and then everything that you've drawn will show up all at once.

How does this reduce flicker?  Imagine if you are animating a ball moving across the screen.  Each time the ball moves a little bit, you have to clear the screen before re-drawing it.  Otherwise it will leave a trail like a snail, because it will still be visible in all the old locations.  However, if the things you draw show up immediately, then the ball will flash: every time you erase the screen it disappears, and every time you draw it again it appears.  Double buffering prevents this by not updating the screen until after you have both erased and re-drawn the ball.

So add this right after your screen fill:
pygame.display.flip()


If you run the program now, you should have a screen with a white background.

*Organizing the program*

Let's reorganize the program a little by breaking it up into separate functions.  Why don't we break out all the drawing code so that we can more easily modify it in the future, and break out the event handling code so that the main loop doesn't look so messy:


```
import pygame
import sys

def main():

    # initialize the pygame module
    pygame.init()

    # create a window of size (640, 480) and store the returned
    # surface in the variable screen
    screen = pygame.display.set_mode((640, 480))

    # draw stuff onto the screen
    draw_things(screen)

    # flip the screen so that everything drawn becomes visible
    pygame.display.flip()
    
    # start an infinite loop (the main loop)
    while True:

        # handle events
        handle_events()
        
        # Wait a little while so that we don't suck up 100% of the CPU.
        # Waiting for 10ms means that the main loop while will run
        # at most 100 times per second.
        pygame.time.wait(10)        


# draw stuff to the screen in this function
def draw_things(screen):

    # fill the screen with white
    screen.fill((255,255,255))
    

# this function handles pygame events
def handle_events():
    
    # process all events that have occurred
    for event in pygame.event.get():

        # if a quit event occurs, exit the program
        if event.type == pygame.QUIT:

            # clean up after pygame
            pygame.quit()

            # exit immediately
            sys.exit()


if __name__ == '__main__':
    main()
```
 
Now when we want to draw different things we can just make the changes in the draw function, and leave the rest of the program alone.

*Displaying Basic Shapes*

If you look in the pygame.draw module, you can see that there are a few different basic shapes.  We'll stick to circles, rectangles, and lines for now.  Let's try drawing one of each by modifying the draw_things function:


```
# draw stuff to the screen in this function
def draw_things(screen):

    # create a few color variables so the code is easier to read
    white = (255,255,255)
    black = (0,0,0)
    red = (255,0,0)
    green = (0,255,0)
    blue = (0,0,255)
    
    # fill the screen with white
    screen.fill(white)
    
    # draw a blue rectangle at position (20,20) with width and height (40,40)
    pygame.draw.rect(screen, blue, ((20,20),(40,40)))
    
    # draw a red circle centered at location (100,100) with a radius of 50
    pygame.draw.circle(screen, red, (100,100), 50)
    
    # draw some lines that go across the entire screen horizontally,
    # and are different widths
    pygame.draw.line(screen, black, (0,175), (639,175), 1)
    pygame.draw.line(screen, black, (0,180), (639,180), 2)
    pygame.draw.line(screen, black, (0,185), (639,185), 4)
```

If you run this program, you should get a window that looks like this:






*Generating Images Programatically*

We can use loops to construct complex images without manually entering all the information.  For instance, this code will create a grid pattern of circles:

```
for x in range(20, 640, 20):
    for y in range(20, 480, 20):
        pygame.draw.circle(screen, (0,0,0), (x,y), 5)
```






Can you figure out how this worked?  There are a couple of new concepts here.  

The range function is familiar, but when we saw it before we were only using it with two parameters: a start value and a stop value.  If you look at the documentation, you will see that range() takes an optional third parameter, called the step.  This is how much it advances by each time.  So if you use range(0, 10) it will return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], but if you use range(0, 10, 2) it will instead return [0, 2, 4, 6, 8,].

The other new thing is nested for loops.  It's not really anything new, but it might look a little odd at first.  What this says is that it loops through many x values, and for each x value, it loops through many y values.  So for each column of circles, it drawn every circle in turn from the top of the screen to the bottom, and then moves on the the next column and starts over at the top.

Here is a much less orderly image that we can generate.  This loop adds 500 different circles to the picture, but every circle has a random position, random size, and random color:


```
for i in range(0, 500):

        red = random.randint(0,255)
        green = random.randint(0,255)
        blue = random.randint(0,255)
        color = (red, green, blue)
        
        x = random.randint(0, 639)
        y = random.randint(0, 479)
        position = (x, y)
        
        radius = random.randint(5, 100)
        
        pygame.draw.circle(screen, color, position, radius)
```






Don't forget to also import the 'random' module so for this code to work.  random.randint is a new function, but you can see how it works by checking the documentation.

You can combine different shapes to achieve more complex effects.  Here's an example that uses a separate function to draw individual items on the screen.  The main drawing routine calls the function multiple times to draw each object:

```
# draw stuff to the screen in this function
def draw_things(screen):
    
    # fill the screen with white
    screen.fill((255,255,255))
    
    for i in range(0, 5):

        x = random.randint(0, 639)
        y = random.randint(0, 479)
        
        draw_compound_shape(screen, (x, y))
    
def draw_compound_shape(screen, pos):
    
    # draw a rectangle which is centered on the given position
    upper_left_point = (pos[0] - 50, pos[1] - 50)
    pygame.draw.rect(screen, (0,128,0), (upper_left_point, (101, 101)))
    
    # draw a circle centered on the same position and with the same radius
    pygame.draw.circle(screen, (0,0,128), pos, 50)
    
    # draw a pair of lines through the point
    top_point = (pos[0], pos[1] - 50)
    bottom_point = (pos[0], pos[1] + 50)
    left_point = (pos[0] - 50, pos[1])
    right_point = (pos[0] + 50, pos[1])
    pygame.draw.line(screen, (128,0,0), top_point, bottom_point, 10)
    pygame.draw.line(screen, (128,0,0), left_point, right_point, 10)
```






That's a pretty ugly graphic, isn't it?  Well, I never said it was a pretty picture that we were making.  Do you understand the math that is going on to figure out where to draw the rectangle and lines?  The position marks the center of the object, so we have to add or subtract the radius or the object in order to find the edges.

Here is an example of drawing a graphic using a function that calls itself.  This is called a recursive function.  Each time the function calls itself, the parameters it uses must be different in some way, and there must be some condition where the function stops calling itself.  Otherwise we would get an infinite loop of function calls!  In this case, the circle gets a little smaller each time, and the function stops when the circle is too small.


```
# draw stuff to the screen in this function
def draw_things(screen):
    
    # fill the screen with white
    screen.fill((255,255,255))
    
    draw_repeating_circles(screen, (100, 100), 100, (0,0,255))
    draw_repeating_circles(screen, (200, 200), 50, (255,128,64))
    draw_repeating_circles(screen, (100, 300), 75, (128, 64, 128))
    
def draw_repeating_circles(screen, position, radius, color):
    
    # draw the circle
    pygame.draw.circle(screen, color, position, radius)
    
    # then draw a smaller circle at the right edge of this one,
    # but only if the radius is still big enough to see the circle
    position = (position[0] + int(radius), position[1])
    radius = radius * 0.8
    if radius > 1:
        draw_repeating_circles(screen, position, radius, color)
```






Do you notice anything new in this code?  How about that int() function?  What this does is force a number to be an integer (whole number) rather than a float (number with decimal places).  This is done because the circle radius is a float, but the circle position should be an integer.  You can likewise turn an integer into a float using float(), or turn numbers into strings using string(), or even turn strings into numbers using  int() and float()!

I think that this is all we'll do with static graphics for now.  You should try experimenting on your own though; that is the best way to learn.  You can do a lot by playing around with different combinations of what has already been covered, or you can go look at the Pygame documentation to figure out some new functions.

Coming up next is animated graphics, where things get really interesting!


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

That's it for now.  I haven't written the part about animated graphics yet.  That's where it gets really fun though, so hopefully it will not take me too long.

Please let me know what you think!  I have ideas for quite a few more sections if there's enough interest expressed.


----------



## Eevee (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

I must question the practicality of introducing a non-programmer to Python, basic syntax, imperative programming, abstract data types, object-oriented programming, recursion, event-driven programming, and presumably things like blitting all in one go.  Non-programmers are probably going to get very lost very fast.


----------



## TheGru (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

I now I already am...


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*



			
				Eevee said:
			
		

> I must question the practicality of introducing a non-programmer to Python, basic syntax, imperative programming, abstract data types, object-oriented programming, recursion, event-driven programming, and presumably things like blitting all in one go.  Non-programmers are probably going to get very lost very fast.


But it's all so _easy_!   

The problem is that it takes some knowledge to get to the point where things are interesting.  I know I really enjoyed playing with simple programs and GWBasic and graphics in QBasic even though I had no idea what I was really doing.  Do you have any suggestion on how to replicate that experience for someone in a modern computing environment?

I considered jumping right in with example programs, and just telling people where to change things without explaining what all the extra stuff was.  Do you think that would be a better approach?  I know it bugs me when there are things going on and I don't understand _why_, but maybe for absolute beginners it's better to say "ignore all this other stuff you see; you don't need to know about it"?


----------



## Zero_Point (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*

Actually, according to an uber-programmer nerd friend of mine Python is a VERY easy language to learn, easier than JAVA, C++, Lua, and many others.
Hell, at least it isn't Whitespace.


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*



			
				Zero_Point said:
			
		

> Actually, according to an uber-programmer nerd friend of mine Python is a VERY easy language to learn, easier than JAVA, C++, Lua, and many others.
> Hell, at least it isn't Whitespace.


That's why I chose Python for this tutorial.  It has an absolute minimum of syntax overhead to learn.  There's a reason why it is sometimes referred to as "executable pseudocode".

However, I do present a lot of important ideas in a very short time.  I don't go in to depth in any of them, and I avoid as much jargon as possible, but it's still a lot of new concepts to absorb.  It may be that covering everything up front is not a good idea.


----------



## eb7w5yfe (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*



			
				TheGru said:
			
		

> I now I already am...


If you (or anyone else) are honestly trying to follow this and have trouble understanding something, just let me know what part you're stuck on.  I'll do my best to explain.  Sometimes things have to be re stated in different terms before they make sense.


----------



## Eevee (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*



			
				eb7w5yfe said:
			
		

> But it's all so _easy_!


Well of course!  But I've been doing it for ten years  8)



			
				eb7w5yfe said:
			
		

> The problem is that it takes some knowledge to get to the point where things are interesting.  I know I really enjoyed playing with simple programs and GWBasic and graphics in QBasic even though I had no idea what I was really doing.  Do you have any suggestion on how to replicate that experience for someone in a modern computing environment?


Link them to DosBox and QBasic 4.5?



			
				eb7w5yfe said:
			
		

> I considered jumping right in with example programs, and just telling people where to change things without explaining what all the extra stuff was.  Do you think that would be a better approach?


No, then you risk getting people who either think they are leet haxorz or people who want to do something else but don't even know where to start touching the rest of the code.

I don't think it's really a good idea to toss people into the SDL without _solidly_ knowing how to use a language first; maybe split this into two threads and try to expand the first before doing the second.  It's twice as hard if you have to keep going back to the language reference (and don't know how general programming works in the first place!) in the middle of trying to learn the API.



			
				Zero_Point said:
			
		

> Actually, according to an uber-programmer nerd friend of mine Python is a VERY easy language to learn, easier than JAVA, C++, Lua, and many others.


Java is needlessly wordy and has a confounding type system.
C++ is too low-level for new programmers.
Lua?  I don't think Lua is all that hard.  It's conceptually similar to Javascript with more Ruby-like syntax.


----------



## Zero_Point (Oct 20, 2007)

*RE: Simple graphics programming tutorial for non-programmers*



			
				Eevee said:
			
		

> Java is needlessly wordy and has a confounding type system.



My friend's conclusion exactly.



> Lua?  I don't think Lua is all that hard.  It's conceptually similar to Javascript with more Ruby-like syntax.



My friend thinks Lua is a "terribly ugly" language. He knows how to program in everything from BASIC to Brainfuck, but I do not so I wouldn't know.


----------



## Eevee (Oct 21, 2007)

Er.  It has fairly C-like syntax, except that (a) it has a real function system where functions are first-class objects, wrappable, nestable, etc and (b) braces are swapped for an 'end' keyword -- which takes exactly the same number of characters.


----------

