Topic outline

  • Kia ora Guest user

    Welcome to CGI506 Technical Development 1, S2-20. In this course you will be developing basic skills and knowledge of programming for animation and game development and to develop custom tools and functions for a successful production pipeline.

    On completion of this course you will be able to:

    1. Investigate and compare different programming languages used for animation, visual effects and real time applications. 
    2. Evaluate the effectiveness of different scripting/programming languages for selected applications. 
    3. Select and use a number of different scripting languages to achieve the desired effects and tools.  
    4. Create custom tools to facilitate a production scenario. 

    Alongside the class time and your project work, you will be provided with extra learning material, videos and tasks to help you improve your skills.  Work at your own pace spending roughly 4 hours a week on these. 

    All courses in this programme include an assessment of professionalism. Professionalism includes your active engagement in class activities, your ability to communicate with your peers and tutor, how you work in a team and more importantly how you manage your self.

    Usually we cover one session per week. Note this course content and schedule, may be adjusted as we understand more about our needs as a group of learners. 

  •  

    We are going to be learning quite a bit more about Python in this session, basic features and skills that will enable you to begin logically assembling programs. We'll individually cover important topics one at a time.

    Indentation:

    To make for cleaner and easier reading, python by design operates at indented levels. This means whenever you have a conditional statement or loop, it will operate only on the code which is indented below it. You can think of these as “clauses” or paragraphs. Having correct indentation is mandatory for correct python execution.

    Other software languages (for example, C) require the use of semi-colons (;) to end lines and braces {} to mark the start and end of clauses/paragraphs. And yet programmers of those languages will often indent their code anyways!

    For example (this is C, not Python!) Indentation is the programmer’s decision, C doesn’t care. C only cares about the braces, “{“ and “}”.

     

    So Python simplifies this by relying on indentation only, (which is more readable in my humble opinion)

     Iterables:

    An iterable is anything that can be passed to a loop or queried multiple times for items.

    Sets and Tuples:

    We are already familiar with lists, so I will describe now what sets and tuples are in Python. All of these objects are “iterable” which is to say that they can have any number of items and that Python makes it easy to loop through them.

    Where lists let you store same item multiple times, and remembers the order you store them, Sets are fundamentally different because they will not store the same item twice. They can be most useful for cleaning out multiple copies of the same item. 

    Tuples in Python can be thought of as being like lists or sets but with one exceptional property: they are “immutable” or in plain words, cannot be modified. And as such they have very few methods (functions) you can use on them.

    Here’s how the three look:

    >>> things = [1, 4, 3, 8, 2, 2, 2]
    >>> type(things)
    <type 'list'>
    >>> set(things)
    set([8, 1, 2, 3, 4])
    >>> tuple(things)
    (1, 4, 3, 8, 2, 2, 2)

    Notice how a set changes the items by removing copies?

    And in Python, you can instance any by name, the only requirement is that as an argument they receive are iterable (that’s why you see a list inside of each function):

    >>> x = list([1, 2, 3])
    >>> y = set([1, 2, 3])
    >>> z = tuple([1, 2, 3])

    Or by shorthand, the only difference is the kind of bracket used:

    >>> x = [1, 2, 3]
    >>> y = {1, 2, 3}
    >>> z = (1, 2, 3)

    Remember all these are iterables.

    Don’t be intimidated by all the brackets, it’s actually quite simple. Square brackets always indicate a regular good’ole list. Parentheses indicate a tuple (which is only good for reading from) or a set, if the word “set” is shown. Sets however can be made similarly to a dictionary by using braces but with keys only, and no values.

    >>> # this is a dictionary, note the semicolons matching values to their keys 
    ... d = {'house_key': 'front door', 'second key': 'back door'}
    >>> # this is a set, will not retain order but will not store copies either
    ... s = {'eins', 'zwei', 'drei'}

    If, Elif, and Else statements:

    When our programs execute, we will frequently want to switch behavior based on some condition. This is where if statements come in handy. The key word if is followed by an expression that when evaluates True, python will execute your code below it. Otherwise it will execute one “else” section if you should include it.

     if (expression goes here):
    Execute this code here
    elif (expression goes here):
    Execute this code instead
    else:
    Nothing was executed above, so run this instead.

    Note that elif, and else statements are optional. You can use a standalone if statement by itself, any number of attached elif statements.

    Moving on: 

    # favourite number
    guess = raw_input(‘Guess my favourite number between 1-10’)
    if guess > 3:
    print ‘Too high!’
    elif guess < 3:
    print ‘Too low!’
    else:
    print ‘Well done, 3 is my favorite number!

    # favourite colour
    guess = raw_input(‘Guess my favourite colour!’)
    if guess == ‘chartreuse’:
    print ‘Wow, lucky guess! You must have read the source code’
    elif guess != ‘blue’:
    print ‘Nope, not :’, guess
    else:
    print ‘Ew!’

     Can you guess in which case the last clause would print ‘Ew!’? 

    Let's look at Pseudocode:

    From Wiki/Infogalactic : Pseudocode is an informal high-level description of the operating principle of a computer program or other algorithm. It uses the structural conventions of a programming language, but is intended for human reading rather than machine reading.

    Let’s say that you want to do apply a burnt-in frame number for every image in a sequence. However you know that the sequence could optionally be stereoscopic-- or in other words-- one image for each eye, left and right. But optionally this could be single sequence.

    Your pseudocode could look like this:

    If sequence is stereo?
    Get two items list containing left and right eyes sequences
    Else (otherwise)
    Get one item list containing the sequence
    For every image in sequence
    Apply burn in

     Formulating your thoughts this way will go a long ways to helping you plan your code better. Let’s expand on our example:

    Is the sequence stereo?
    For each eye in left and right
    Get sequence
    Otherwise (else)
    Get one item list containing the sequence
    For every image in sequence
    Get path, and frame number
    Put together arguments for a function that applies the burn-in.
    Execute function

    Why pseudocode?

    The whole idea behind pseudocode, is to articulate one’s thoughts into text. The process one goes through in doing this will further clarify the ideas they have and potentially identify any challenging areas they’ll need to focus on.  Using pseudocode is the first step to implementing a program will help you plan more effectively.

    Exercise : Write pseudocode for something non-computer-related, Such as your choice of breakfast this morning, or how a keeper might manage food supplies for the animals at the zoo. Or what might a Tesla onboard computer do when it sees a large orange object moving on one camera?

    So what can we do with iterables? Loops!

    There are a couple of ways to loop in Python -- the for loop, and the while loop.

    Let’s look at each in turn:

    The way for loops work is like this, and note the trailing semicolon (:)

    for [Choose your variable name here] in [Something loopable or iterable here]:
    # Run all code in this block, with [variable name you chose] being updated each
    # time

    Here’s an example:

    my_list = [‘apples’, ‘feijoas’, ‘zebras’]
    for item in my_list:
    print item

    This will print each item on new lines:

    >
    apples
    feijoas
    zebras

    Let’s say you want to loop through a range of numbers. Let’s introduce you to a new function in Python, "range".

    for i in range(10):
    print i

    … will give you something like this

    0
    1
    2
    3
    ...

    The range function simply returns a list of numbers, from 0 to the argument you give it, unless you give it two:

    > print range(3,6)
    [3, 4, 5]
    > print range (2)
    [0, 1]

    Wait, why is 0 included but 10 isn’t?

    Python, like many programming languages, counts from 0, not 1. The first item or “index” in any list, will be 0, not 1.

    This may take a bit of getting used to, but it’s intuitive once you get the hang of it. Many things on the computer start from 0, whether it is memory values, hardware addresses, or hexadecimal numbers. 

    While Loop:

    While (statement here evaluates to True) -- loop here.

    A simple demonstration: How many times will this loop?

    x = 2
    while x < 10:
        x = x + 1

     

    Dicts and unpacking:

    The for loop will take any object you give it, and try to “iterate” through it by requesting it’s items. In the case of a dictionary, this’ll be the dictionary’s keys.

    french_dict = {‘hello’ : ‘bonjour’, ‘thank you’ : ‘merci’}
    for x in french_dict:
    print x
    # will print:
    # hello
    # thank you

    But what if you wanted to justs print the values in a dictionary? Or both the key and value?

    for x in french_dict.values():
    print x

    will print:

    bonjour
    merci

    Or:

    for key, value in french_dict.items():
    print value, key

    will print:

    bonjour hello 
    merci thank you

    How does it work?

    Well firstly, when you call items() on a dictionary, you’ll see a list of pairs returned like this:

    > print french_dict.items()
    [(‘hello’, ‘bonjour’),  (‘thank you’, ‘merci’)]

    Can you recognise the tuples inside the list? So when the loop iterates through dict.items() it will receive one tuple at a time.

    In python you can also unpack:

    > x, y, z = [‘one’, ‘two’ three’]
    > print y
    two

    So when we run this:

    for k, v in french_dict.items():

    Each time the loop is run, k and v will be unpacked from each tuple returned from the dictionary items().

    A note on variable names:

    In python a variable name must not contain spaces, cannot start with a number, or contain special characters.

    So these are not ok:

    1apple
    a##le
    $apple
    an apple

    But these will work:

    apple1
    apple_sauce
    x
    AppleJuice

    Take a breather:

    Whew. We’ve learned alot about python objects, and the basic types we can use.

    Next up we are going to learn about functions, which can take arguments and do things. This is the backbone of Python, and a good developer will break up their code into many small reusable functions. A function is like naming your code, much the same way variables name strings and numbers.

    https://www.youtube.com/watch?v=asjQNZn7vng

     

    Functions:

    The basic function looks like this:

    def [name goes here]( [zero or more “arguments” go here] ):
    [code goes here that is run when this function is called]
    [and optionally a return call, otherwise this function returns None]
    return [zero or more variables/objects]

    Or, here are some examples for you to type in and run:

    # this doesn’t take any arguments
    def print_none():
       print "there's nothing here!"

    # this only takes one argument
    def print_one(arg1):
       print 'arg1 is : {}'.format(arg1)

    # this only takes two arguments
    def print_two(arg1, arg2):
       print 'arg1 is : {} and arg2 is {}'.format(arg1, arg2)

    # having an asterisk before a var name means it will pack into a list, can have any number of arguments
    def print_all_args(*args):
       for arg in args:
           print args

    # by the time the interpreter gets here, the functions are defined
    # so we can call them with arguments now!
    print_all_args(‘as’, ‘many’, ‘as’, ‘I’, ‘want’, ‘even’, 139546)
    print_one(‘John’)
    print_two(‘John’, ‘Smith’)
    print_none()  # takes no arguments

     In Python def is short for “define function”. After you give it a name, adhering to the same rules about naming variables that we explained previously, You can then define any another number of variables “arguments” within the parentheses which will be passed into the function.

    The asterisk * is not often used this way in Python, but when it appears before a variable name, inside a set of parentheses, it will pack those variables into a list.

    Now functions can also define default variables, which hold a certain value by default unless the caller supplies the argument.        

    def inventory(yorkies=10, labradors=5, siamese=0):
       print 'We have {} yorkies, {} labradors, and {} siamese'

    > inventory(5, 8)
    We have 5 yorkies, 8 labradors, and 0 siamese
     
    > inventory(siamese=20)
    We have 10 yorkies, 5 labradors, and 0 siamese

    But probably the most important feature about functions is the ability to return a variable or object. Here we have a function which returns True if we have more yorkies then labradors.

    def is_more_yorkies(yorkies=0, labradors=0):
       if yorkies > labradors:
           return True
       else:
           # we have more labradors, or the same number
           return False

    > is_more_yorkies(5,4)
    True
    > is_more_yorkies(5,8)
    False
    > result = is_more_yorkies(10,10)
    > print result
    False 

    Time for a challenge:

    I’m going to challenge you to a text based game. First write pseudocode for it, then complete the program.

    The pseudocode could look something like:

    # multi choice story game
    # opening scenario
    print description of opening scene and give user a choice of 2 numbered options
    get raw input from user and store as variable
    if variable is equal to one, go to first scenario
    elif variable is equal to two, go to second scenario
    after a few multi choice storyline, finish program with life or death, success or failure 

    Reading & Writing Files:

    Reading and writing files in ascii (text) format or binary is easy in Python.

    Let’s begin by creating a new file and naming it “data” in the same directory as your working python files. (this can be done on repl.it or your local system Python if you are following with that.)

    It can contain something like this:

    Hi I am data!
    This is the second line.

    And finally, the last line.

     Next, create a new working file and type in the following example:

    from os.path import exists

    input_file = 'data'
    output_file = 'data_2'
     
    print 'copying from {} to {}'.format(input_file, output_file)

    # we could do these two on one line too, how?
    in_file = open(input_file)
    indata = in_file.read()
    in_file.close()

    print ‘Input file has a size of {:d} bytes'.format(len(indata))
    print 'Does the output file exist? {}'.format(exists(output_file))
    print 'CTRL- C to abort or Enter to continue and copy'
    raw_input()

    out_file = open(output_file, 'w')
    out_file.write(indata)
    out_file.close() 

    print 'Program complete.' 

    When we run this we can see that the program creates the output file before writing. You can compare now and see that the contents are the same.

    There are some new things to see here. We have two import lines at the top, and a new built-in function called “open”. We use this function to open a file handler for both reading and writing to files in Python. You can see the first argument it takes is a file path, and the 2nd argument is a string representing the access mode, or in our case “w” which stands for write access.

    Also new is the “exists” function, you can give this function a path to a file on disk and it will return true or false depending on if the file exists on disk.

    Errors & Exceptions:

    Often you’ll encounter an error which causes your program to abort. In Python, errors are called exceptions and it is these that you will be dealing with.

    An error can come from anywhere, perhaps one wrote the command incorrectly (that dreaded Syntax Error), or a file is not found, or perhaps something else has gone inexplicably wrong.

    Fortunately there are ways of catching errors and handling them in a graceful way.It’s time to introduce the “try” and “except” clause. These operate a little bit like “if” and “else” conditionals, whereas if Python encounters an error in the “try” clause, it will immediately execute any matching “except” statements.

    Let’s make a function which returns True if the given variable is a number, and False if a given variable is not.

    Firstly, we see an error raised if we try to convert a string into an integer:

    >>> int('blah')
    Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: 'blah'

    So, let’s make a function that handles this gracefully.

    def is_number(var):
       try:
           int(var)
           return True
       except ValueError:
           return False

    We saw the error encountered first was called the ValueError, and by specifying this as an exception, we could handle the error gracefully without interrupting our program.