220 likes | 260 Views
Games Development 2 Scripting for Games. CO3301 Week 5. Contents. Why Scripting Scripting Considerations Scripting Languages Python: Language Overview. Why Scripting?. Ease of Development Higher-level – less prone to errors E.g. no pointers, memory allocation etc.
E N D
Games Development 2Scripting for Games CO3301 Week 5
Contents • Why Scripting • Scripting Considerations • Scripting Languages • Python: Language Overview
Why Scripting? • Ease of Development • Higher-level – less prone to errors • E.g. no pointers, memory allocation etc. • Less intricate - can be easier to write • By less experienced developers and maybe technical designers • Iteration Time • Much quicker to change and test • No recompilation, change at runtime • Similar rationale to text-based data files
Why Scripting? • Scripts as Assets • Possible to regard scripts as a data resource to cut down on the amount of game-specific embedded code • Use scripts to control entity behaviour in particular • Treat like any other resource, e.g. meshes, animations • Script loaded with other entity assets • Script support built into the resource manager • Makes entity behaviour editable outside the compilation process • For example, in a level editor • Allows entity behaviour to be added/modified at a later stage • Post-release modding • Scripting languages can be quite powerful • And customised for particular uses, e.g. AI
Scripting Drawbacks • Performance • Scripting languages are often interpreted • Some are part-compiled into bytecode (like Java) • Instructions for a virtual machine • However, still poor performance compared to C++, ten times slower or more • No control of memory management can also cause issues • Dynamic allocation of new variables • Automatic garbage collection • No control over timing, or amount of memory used • Tool support sometimes limited, but much better now • Errors can be hard to spot – usually occur at runtime • Need to write (clumsy) interface to our C++
Scripting Considerations • Performance may not be such an issue • If scripting limited to high-level game logic • Tricky if 1000's of scripted entities though • Don't necessarily need to use scripting languages • A simple, well defined game, with no need for modding • Otherwise, consider language to use based on: • Performance needs, memory footprint, feature-set • Developer can write a custom scripting language • E.g. UnrealScript • Developing a new language is tricky and usually unnecessary - only recommended for experts
Popular Scripting Languages • Python is a portable, interpreted, object-oriented programming language • Mature, well-used language with clear syntax • Notable for whitespace defining structure • Used on several games, especially MMOs (e.g. EVE) • Also built into Autodesk Maya and Max for plugin development • Large memory use makes it a choice for more heavyweight games • Lua is a lightweight scripting language • Not natively object-oriented • Small and simple feature-set • Small memory footprint • Very widely used, on PC and consoles
Python: Language Overview • We will look at Python in this week’s lab • Well suited to PC development • Python is a complete, high-level OO language • Reads a little like psuedo-code • It is dynamically typed • No need to declare variable types • It performs automatic garbage collection • No need to new / delete objects • No pointers • Blocks are defined by indentation • No braces (curly brackets)
Python: Variables / Blocks • Variable use (no types, equate several at once, no semicolons): x,y,z = 1,2,3 first, second = second, first a = b = 123 • Indentation defines blocks (plus logical operators): if x < 5 or (x > 10 and x < 20): print "The value is OK" if x < 5 or 10 < x < 20: print "The value is OK"
Python: Iteration / Input • Loops (and comments): for i in [1,2,3,4,5]: print "Iteration number", i # Print values from 0-99 inclusive for value in range(100): print value x = 10 while x >= 0: print "x is not negative" x = x – 1 • Simple input: x = input("Please enter a number: ") print "The square of that number is", x*x
Python: Lists • Lists, indexing and slicing fruit = ["plum", "pear", "apple", "banana", "fig"] print fruit[2], fruit[0] # Prints "apple plum" print fruit[-2] # Prints "banana" (counts from end) print len(fruit) # Prints "5" # Slicing is selecting sections of a list # Note: 1st example excludes last index in range print fruit[1:3] # Prints "pear apple" print fruit[:3] # Prints "plum pear apple" print fruit[3:] # Prints "banana fig" • Strings can be treated asread-onlylists x = "apple" print x[3] # Prints "l" x[0] = "e" # Error
Python: Dictionaries / Functions • A dictionary is a map tel = {"Joe":123, "Jim":555, "Jane":999} person = {'Job':'Builder', 'DOB':'12/12/66'} # '=" print tel["Jane"] # Prints 999 print person["Job"] # Prints "Builder" • Functions (use keyword def): def Square(x): return x*x print Square(3)
Python: Functions • Simple parameters are passed by value def square(x): x = x*x return x y = 3 print square(y), y # Prints "9 3", y unchanged by fn • But lists / dictionaries are affected in a function def change_list(l): l[0] = "apple" fruit = ["pear", "orange", "fig"] change_list(fruit) print fruit # Prints "apple orange fig"
Python: Strings • Wide range of string support: # Basic operations print 'Hello ' + 'World' # Hello World print "Spam "*4 # Spam Spam Spam Spam # Strings can’t be written to – easy to get round str = "Hello World" newstr = 'M' + str[2:] # Mello World # Example of other methods print len( "Piece of String" ) # Output 15 print "london".capitalize() # Output London print "too times too".replace( "too", "two" ) # Output two times two folderlist = "C:\Work\Python".split("\\") # folderlist = ["C:", "Work", "Python“]
Further Conditions • More Conditions # Set membership primes = [1,2,3,5,7,11,13,17,19,23,29] if x in primes: print "x is prime" if year not in range(2000, 2100, 4): # 2000->2100 step 4 print "Not a leap year" # String / List comparison "one" < "two" # true – lexicographical comparison [1,2,3] < [1,2,4] # Compare elements [1,3] < [1,2,3] # Shorter list always less than
Working with Lists • List operations # Working with this list a = [66.25, 333, 333, 1, 1234.5] # Counting instances of a value print a.count(333), a.count(66.25), a.count('x') # Output: 2 1 0 # Insertion (anywhere), appending (at the end) a.insert(2, -1) # Location, value a.append(333) print a # Output [66.25, 333, -1, 333, 1, 1234.5, 333]
Working with Lists • More list operations # Working with this list a = [66.25, 333, -1, 333, 1, 1234.5, 333] # Removal (by location) x = a.pop() # Remove last element y = a.pop(2) # Remove specific element print a, x, y # Output [66.25, 333, 333, 1, 1234.5] 333 -1 # Removal (by value) a.remove(333) # Remove first instance of 333 print a # Output[66.25, 333, 1, 1234.5]
Working with Lists • List reordering # Working with this list a = [66.25, 333, 1, 1234.5] # Reversal a.reverse() print a # Output [1234.5, 1, 333,66.25] # Sorting a.sort() print a # Output[1, 66.25, 333, 1234.5]
Functional List Creation • List creation using functions # map – applies function to list elts to create new list def Square(x): return x*x print map(Square, range(1, 11)) # Output [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] # filter – uses boolean function to filter elts in a list def NotDiv3(x): return x % 3 != 0 filter(NotDiv3, range(1, 15)) # Output [1, 2, 4, 5, 7, 8, 10, 11, 13, 14] # List comprehension – powerful list creation def Square(x): return x*x primes = [1,2,3,5,7,11,13,17,19,23,29] print [Square(x) for x in primes if x%10 < 5] # Output [1,4,9,121,169,529]
Function Techniques • More function techniques # Argument passing by name def AddRecord( name, ID = 0, job = "Unemployed” ): ... AddRecord( "Bill", 5 ) # Normal style AddRecord( job="Builder", name="Bob" ) # By name # Argument unpacking def VectorLength( x, y ): ... vector = (10, 15) print VectorLength( *vector ) # * unpacks 1 argument to 2 # Documentation – first line can be string literal def Square(x): "Returns the square of the argument" return x*x
Libraries • Can import support libraries: # Mathematics – as in C import math print math.cos( math.pi / 3 ) # Output 0.5 # Random numbers import random print random.choice(['apple', 'pear', 'banana']) print random.random() # random float 0-1 print random.randrange(6) # random integer from 0-5 # 5 random samples from list, e.g. [30,83,16,4,8] print random.sample(range(100), 5)
Python: Classes • Class definition (each fn has extra 'self' argument): class Person: # __init__ is a constructor __init__(self, name, job="Unemployed"):# Default self.name = name self.job = job def output(self): print self.name, "the", self.job guy1 = Person("Bob", "Builder") guy2 = Person("Bill") guy1.output() # Prints "Bob the Builder" guy2.output() # Prints "Bill the Unemployed"