A beginner’s tutorial on the Python programming language for the TSA Software Development elective. This page is intended to teach Python from scratch even if students have never had any experience doing programming.
Basic number manipulation:
You can perform basic mathematical operations just like a calculator
>>> print 2 + 2
You can assign numbers to variables
>>> x = 2
>>> print x
You can use variables in operations
>>> y = x + 4
>>> print y
Changing one variable does NOT change the value of other variables that were assigned earlier
>>> x = 8
>>> print y
The = sign is an assignment, not an equation, so it can be used to change a single variable’s value
>>> x = x + 1
>>> print x
x = 17 y = 3 print x + y print x – y print y – x
Multiplication, division, modulo (remainder), floating point numbers, precedence
>>> print x * 3
>>> print 12 / 4
Division assumes whole numbers (integers)
>>> print 14 / 5
The modulo operator gives you the remainder
>>> print 14 % 5
Use decimal points if you want floating-point numbers
>>> print 14.0 / 5.0
Use parentheses to enforce order of operations
>>> print 2 + 3 * 5
>>> print (2 + 3) * 5
Sample program (note that variables should use long names to make the program more readable)
cookies = 23 people = 4 print cookies / people
Exercise: modify the program to show how many cookies will be left over after dividing them evenly among the people
You can print strings of text as well as numbers
>>> print “hello”
You can assign text to variables
>>> x = ‘blah’
>>> y = ‘yada’
You can “add” strings together using the addition operator
>>> print x + y
>>> print x + ‘ ‘ + y
You can print many copies of a string using the multiplication operator
>>> print x * 5
>>> print x * 5 + ‘ ‘
>>> print (x + ‘ ‘) * 5
Strings and numbers cannot be added
>>> x = ‘3’
>>> y = 2
>>> print x + y
but strings can be converted to numbers, and numbers can be converted to strings:
>>> print x + str(y)
>>> print int(x) + y
You can use this principle to create easy-to-read output messages:
>>> x = 12
>>> y = 4
>>> print str(x) + ‘ divided by ‘ + str(y) + ‘ is ‘ + str(x / y)
However, an even easier way to create mixtures of strings and numbers is to use the Python string formatter. The % format symbol can be used to combing ‘string’ % (data) by substituting pieces of data for each % symbol in the string, where %d, for example, means a decimal number:
>>> print ‘%d divided by %d is %d’ % (x, y, x/y)
cars = 7 minivans = 4 print 'there is room for %d students' % (cars * 3 + minivans * 5)
Exercise: add a variable for students, set to 100. Print how many students still need rides.
Programs can change their behavior and run different lines of code depending on True/False conditions using the “if” statement, and the “else” statement
>>> x = 7
>>> if x < 10 : print “less”
>>> if x > 10 : print “more”
grade = 95 if grade < 65 : print '%d is a failing grade' % g else : print '%d is a passing grade' % g
Exercise: add an if statement that will tell us if the grade is an A (greater than or equal to 90)
Any time that a Python statement has a colon (:) after it, it can be followed by more than one line of indented code, meaning that all of the indented code is “inside” the original statement.
grade = 97 if grade > 90 : print '%d is an A' % grade print 'good work!' if grade < 65 : print '%d is failing' % grade print 'end of report'
Note that the ‘end of report’ line will always print. It is not considered part of the condition because it is not indented
You can create lists of things and assign them to variables, such as…
…lists of numbers
>>> grades = [85, 97, 73, 89]
…and lists of strings
>>> colors = [‘red’, ‘green’, ‘blue’, ‘yellow’]
You can change the values anywhere in the list (keep in mind that they start with 0!)
>>> grades = 95
>>> print grades
You can also add single items to the end of a list
>>> print colors
You can add lists together with the plus operator:
>>> allgrades = grades + [97, 85, 93]
>>> print allgrades
You can sort lists very easily:
>>> print grades
>>> print colors
Use “len” to find the length of an array, or a string
>>> print len(grades)
>>> print len(‘hello’)
Programs can use “for” to perform operations on each item in a list.
grades = [85, 97, 62, 73] for g in grades : print 'grade: %d' % g
You can put multi-part statements inside other statements, as well:
grades = [85, 97, 62, 73] for g in grades : print 'grade: %d' % g if g < 65 : print 'that is failing.' else : print 'that is passing.'
Note how the print statements inside the “if” and “else” statements are indented again, indicating that not only are they inside the “for” statement, but they are also inside the “if” statement, which is inside the “for” statement.
Exercise : modify the program to show the average grade in the list. Hint: start by adding total = 0 at the beginning. Inside the “for” loop, add the grade to the total. After the loop is over, calculate and print the average.
Sometimes, you write code that you want to use over and over again. A function has optional input parameters and an optional output value. Use “def” to define a function. Sample program:
def showsquare(x) : print 'the square of %d is %d' % (x, x*x) showsquare(3) showsquare(7) showsquare(12)
Perhaps you want the function to make a calculation and then give back the result. Use the “return” keyword for that:
def squareof(x) : s = x * x return s y = squareof(5) print y
This can make calculations more readable and make it more obvious what the code is trying to do, resulting in code that looks like this.
hypotenuse = squareroot(squareof(base) + squareof(height))
instead of this:
hyp = Math.sqrt(b * b + h * h)
The second may be shorter, but it’s harder to read and understand what it’s doing and why. In the first instance, it’s easy to see that it’s a Pythagorean theorem calculation.
The most common use for functions is to shorten long, complex calculations into a single statement.
def average(numbers) : total = 0 for n in numbers : total += n return total / len(numbers) grades = [85, 97, 73, 89] print average(grades)
It is now possible to use average(listname) any time you want the average value from a list.
For this elective, in order to write games in Python, it is necessary to use the custom-built TSA gaming library, “tsagame”. This creates an object called “game” which contains functionality pertaining to the entire game.
The most basic game program contains just two lines of code:
from tsagame import * game.run()
This sets up everything needed to run a game. It will display a white screen with nothing in it, which can be closed by hitting the escape key or clicking the close button with the mouse.
There are two things to notice here. First is the use of dot-notation. When you see objectname.membername, that is referring to a function name or variable name that only exist “inside” that object. Much like the listname.sort() function that sorts just that list, the game.run() function runs the game. Also, note that the open/close () syntax indicates a function with no parameters. That is used to differentiate it from a variable. (“bob” is a variable. “bob(3)” is a function being passed 3 as a parameter. “bob()” is function being passed no parameters)
Speaking of objects, let’s add an object to the game:
from tsagame import * Object() game.run()
Now run the game. Suddenly there’s a gray box on the screen. What if we want the object to be something other than a gray box?
The game library has several pre-defined object definitions. You can use one of these as the parameter for creating the object:
Now the object is a red circle instead of a gray box. You can also specify a starting location.
Also, the white background is also pretty boring. Use the game.setbackground function to change that.
A complete list of the default images is under the gfx folder. You can use your own images, but they must be .png files and should have correct transparent areas; images look terrible in a game if they’re inside black squares, which happens with .jpg files. Use a program such as www.gimp.org to edit your images and store them as .png files.
game.setbackground('paper') Object(CIRCLE, 4, 3)
So far, there is no motion in this game, and no interactivity. Let’s change that. If we’re going to talk about motion, though, we have to first discuss the coordinate system.
Everything in the TSA gaming library is done in terms of game units. How big are they? That’s entirely up to you. Depending on what sort of game you’re building, a unit could be thought of as a centimeter, or a foot, or a meter, or whatever. Since all values are decimal and can hold any number, it’s completely arbitrary. For the purpose of this documentation, we will use meters as units.
By default, the game screen is six meters high. By default, each object is one unit high and one unit wide. By default, the density of each object is 1.0, meaning 1 kilogram per square meter (this is relevant not only in object collisions but for the move/spin forces, which are in newtons.) Those things can be changed at any time, but that explains why things are the size they are, and what the numbers mean, when you run a game for the first time.
In order to add interactivity, we will have to tell the circle to change its behavior depending on user input. To change the behavior of an object, you have to declare a function that will be used to define that object. Just like the “average” function that was created earlier, an object function is a function that takes a single object variable as a parameter, such as the “runcircle” function in the following sample:
from tsagame import * def runcircle(c) : c.moveto(2, game.mouse) game.setbackground('paper') Object(CIRCLE, 4, 3, runcircle) game.run()
Notice that now the Object line says Object(CIRCLE, 4, 2, runcircle) meaning that this is now an object with a specific behavior: Every time the game engine has to draw the screen and animate the game objects, it will automatically call “runcircle” with the object itself as the parameter, so “c” will be a variable which temporarily refers to that object. Note that all it does is tell the circle to move towards the mouse at 2 meters per second.
The next program sample will demonstrate several new principles. First, a design suggestion: don’t put too much code indented all the way to the left. That code is part of the “main program” which means that it will only get executed once. That may seem like a good idea for the code that is being used to create the objects, since that only needs to be done once, but eventually that will change. Later, you may want to add a menu with a high score table, credits, options, etc., and with a “play game” button. Once you do that, aren’t you going to want to set up the game from scratch each time the user hits “play game?” (hint: yes.) That means you will need to do it more than once.
The best way to do this is to put all of the code that starts things up into a function, such as “startgame” that does all of the work. That way, you can call it at any time and it will re-start the whole game from scratch. (Likewise, later you will want functions for startmenu, startcredits, etc., to set up those modes of operation.)
Also, in this example, two new objects have been added which green circles. Note that the Object function can return a variable that you can use to refer to that object immediately.
from tsagame import * def runcircle(c) : c.moveto(2, game.mouse) def runcrate(c) : if not c.isonscreen() : c.moveto(2, game.mouse) def startgame() : Object(CIRCLE, 4, 3, runcircle) Object(BOX, 2, 1, runcrate) Object(BOX, 6, 1, runcrate) startgame() game.run()
This sample code demonstrates some important ideas.
All setup has been put in a “startgame” function. For now, that’s only being run once, just before running the game.
There is a new “runcrate” function that defines how a box object should behave. If it goes off the screen, it switches to moving towards the mouse.
You will notice that the runcrate function also has “c” as a parameter. Wait…doesn’t “c” refer to the red circle? How can we use that same variable for something else? This raises a very important point: All variables are temporary. The “c” or “x” or “y” inside a function only exists inside that function and nowhere else. Variables that are members of objects (game.mouse, game.player, game.player.health), on the other hand, are permanent as long as those objects exist.
Notice that both of the boxes use runcrate as their function. That’s perfectly fine. What will happen is that the game still has to handle all objects automatically, so it will call runcrate for the first box, so c will refer to that object. Then it will call runcrate for the second box, so c will refer to the second box. It’s merely a temporary variable pointing at whatever object is being manipulated at that moment.
Now, what if we wanted six boxes instead of two? We could copy and paste the code, of course. But what if we wanted 20 boxes, or 100? It makes more sense to use a for loop, just like when we were calculating averages. Change the startgame function to look like this:
def startgame() : Object(CIRCLE, 4, 3, runcircle) for i in range(2, 8) : Object(BOX, i, 1, runcrate)
The for loop will execute the Object creation 6 times, each time with a new value of “i” being 2, 3, 4, etc., so it will create a whole row of boxes.
At some point, you will have to decide if your game is a top-down view game or a side view game. If it’s a side view game, you may want to use gravity. We could add gravity now, but all of the objects would fall off the bottom of the screen, so we’ll need to add gravity and a platform at the bottom to catch everything.
Add these two lines to the startgame function:
Object(PLATFORM, 4, 5)
This sets the gravity to be downward in the vertical direction. Note that you can set gravity to any value, including negative, and in any direction, which is why there is both a horizontal and vertical component.
The platform isn’t quite wide enough, though. This introduces one more concept: How do you create your own object definitions? The built-in ones are good for experimenting, but ultimately you’ll want to create your own.
Your object definitions should always go at the very beginning of the file. The way to create a definition is to use a copy of an existing one and modify only the elements you want to modify. Try this version.
from tsagame import * BLOCK = copy(BOX) BLOCK.image = 'blocks' FLOOR = copy(PLATFORM) FLOOR.width = 10 FLOOR.height = 0.2 def runcircle(c) : c.moveto(2, game.mouse) def runcrate(c) : if not c.isonscreen() : c.moveto(2, game.mouse) def startgame() : game.setgravity(0, 5) Object(FLOOR, 4, 5) Object(CIRCLE, 4, 3, runcircle) for i in range(2, 8) : Object(BLOCK, i, 1, runcrate) startgame() game.run()
This shows how the image, width and height part of the definitions can be modified. It also illustrates that you only need to change the definition once and it can be reused as many times as you like, as with the blocks in this example. A complete list of the elements of an object definition can be found in the documentation.