Posts Tagged ‘ Python

Physics in PyGame and Python

I’m on week two of my seven week sabbatical (yay), and part of what I’ve been up to is learning more about PyGame (see previous posts).  I have nothing major to show yet:  I started a ‘PyGame’ wiki (not yet online) and have a “tank” game where you can drive them around, bump into each other and obstacles, and I just got the ability to add independently transforming “turrets” to them (my son has had fun making the sprite graphics for them in Gimp).  My goal is to have them all powered via pseudo-accurate 2d (top down) physics.  I started developing this based on web-examples… but I quickly figured out a couple things:

  • I don’t know anything about physics, really.
  • Online examples only take you so far.

To help remedy this, and since I’m a sucker for paper in my hand, and have purchased these informative volumes:

Before I start in earnest though, it’s always good to see what other people have done, and I tracked down these two 2d physics engines for Python\PyGame:

Since I like the name “munk” more than “box”, I’ve recently installed PyMunk, and the examples were up and running in no time.  I look forward to strapping this into my PyGame projects.

Concurrent with that, I’ve just started reading the first two of my physics books, and to help me learn the actual nature of physics, I’ve been authoring some Python classes along with them.  Below are a few examples of what I’ve been up to.  And for me, it’s been both a good learning experience with simple physics, and for making Python classes themselves.  Especially the operator overloading stuff.

In the below example, I make several objects to represent different “units” of measurement:

  • Distance
  • Mass (omitted from below example)
  • Weight  (omitted from below example)
  • Time
  • more to come… (volume, etc…)

All of these objects have a superclass called ‘MeasureBase’, which defines their behaviors (mainly the operator overloading stuff).  Each class stores its data, no matter what type it is, in an attribute called ‘units’.  This allows me to multiply distance by time, for example.  Each class stores its units as a certain kind of units:  Distance stores everything as meters, no matter if you pass in inches, centimeters, miles, or kilometers.  Time stores everything as seconds, even if you pass in hours or days.

Finally, I have a class that actually does something interesting (hopefully the first of many) with all these units, called ‘DistanceFallen’: You pass in how long something has fallen, and it will return back how far it has fallen.  See code below (WordPress seems to be messing up the indentation… :-( )

I’ll conclude with:  This is just a start, for fun, on a Saturday afternoon.  But I think it’ll be a good learning tool moving forward, both for programming PyGame, and for physics concepts in general.

# units.py
import math

# gravitational constant: 9.8m/sec2
GRAVITY = 9.8

class MeasureBase(object):
    # Superclass inherited by measurement types.  Defines some default behavior.
    # self.units & .unitType is defined by subclasses

    inchToMeter = 39.3700787
    footToMeter = 3.2808399
    yardToMeter = 0.9144
    mileToMeter = 609.344
    ounceToKilogram = 0.0283495231
    poundToKilogram = 0.45359237    

    def __str__(self):
        return "%s %s" %(self.units, self.unitType)
    def __repr__(self):
        return str(self.units)
    def __float__(self):
        return self.units
    def __int__(self):
        return int(self.units)

    def __add__(self, dist):
        return self.__class__(self.units + float(dist))

    def __sub__(self, dist):
        return self.__class__(self.units - float(dist))

    def __mul__(self, dist):
        return self.__class__(self.units * float(dist))

    def __div__(self, dist):
        return self.__class__(self.units / float(dist))

    def __pow__(self, val):
        return math.pow(self.units, float(val))

    def __abs__(self):
        return self.__class__(abs(self.units))

class Distance(MeasureBase):
    # Internal measurements are stored as meters

    def __init__(self, units=0.0):
        MeasureBase.__init__(self)
        self.unitType = "meters"
        self.units = float(units)

    def apply_mm(self, mm):
        self.units += mm/1000.0

    def apply_cm(self, cm):
        self.units += cm/100.0        

    def apply_dm(self, dm):
        self.units += dm/10.0        

    def apply_m(self, m):
        self.units += m

    def apply_km(self, km):
        self.units += km*1000.0

    def apply_inch(self, inch):
        self.units += inch / MeasureBase.inchToMeter

    def apply_foot(self, foot):
        self.units += foot / MeasureBase.footToMeter

    def apply_yard(self, yard):
        self.units ++ yard / MeasureBase.yardToMeter

    def apply_mile(self, mile):
        self.units += mile / MeasureBase.mileToMeter

class Time(MeasureBase):
    # Internal measurements are stored as seconds

    def __init__(self, units=1.0):
        MeasureBase.__init__(self)
        self.unitType = "seconds"
        self.units = float(units)

    def apply_miliseconds(self, ms):
        self.units += ms*.001

    def apply_seconds(self, s):
        self.units += s

    def apply_minutes(self, m):
        self.units += m*60

    def apply_hours(self, h):
        self.units += h*3600

    def apply_days(self, d):
        self.units += d*86400

    def apply_years(self, y):
        self.units += y*31104000

class DistanceFallen(object):

    def __init__(self, time, grav=GRAVITY):
        # time is either in seconds, or a Time object
        self.time = Time(time)
        self.grav = Distance(grav)
        self.calcDistance()

    def __str__(self):
        return "Fallen %s in %s" %(self.distance, self.time)

    def set_time(self, time):
        # time is either in seconds, or a Time object
        self.time = Time(time)

    def set_gravity(self, grav):
        self.grav= Distance(grav)

    def calcDistance(self):
        self.distance = (self.grav * math.pow(float(self.time), 2)) * .5

    def getDistance(self):    
        self.calcDistance()
        return self.distance

Based on that, here’s a simple example of it in action:

time = Time(4)
print time
fallen = DistanceFallen(time)
print fallen

The result printed is:

4.0 seconds
Fallen 78.4 meters in 4.0 seconds
self,

What to make a game in, part 2

After some serious thinking (based on my previous post), I’ve decided to go with PyGame as my initial platform for making a game.  As much as I like Processing for making ‘interactive visuals’, the more I learn Python, the more I like it (as in, the language itself… Python has no great graphics abilities on its own).  The syntax is just so much cleaner than Java (Processing).  I also looked closely at XNA, but approaching C# doesn’t give me any great joy, based on its structural similarities to Java.  There is a huge XNA community, and I’ll probably come back to at during some point.  I also took a serious look at Blender, and its game creation system.  But since I’m so used to Maya as my DCC tool, switching to Blender was really hard.   You can’t change the hotkeys!  It’s just too much for me :)  Maybe when version 2.5 comes out…   So for now,  PyGame FTW!

I have picked up some books on the subjects to supliment the vast quantity of tutorials on the web:

PyGame:

XNA:

And while I was at it, got one on the Arduino, since you never know when that will come in handy 😉

I’ve already got a simple 2-‘player’ game up and running where you can drive two ‘tanks’ around the screen.  A pleasing start.

On a side note, my Xbox 360 got the RROD last night.  Sigh…

Visual guide to Tkinter widgets

Over on my Python Wiki, I’ve started making a ‘visual guide to Tkinter widgets’.  I’ve found a lot of good online Tkinter reference, but nothing with pictures… so I figured I’ll make my own :)  I find this to be a good exercise when first learning a new UI system, plus it makes for a nice quick-reference when authoring them later.

As an asside, I’ve also started this process for Maya’s Extended Layer Format (ELF) UI system on my Mel Wiki HERE.

See the growing Tkinter widget list HERE, but a few examples are pasted in below:

etc…

First PyGame program

Based on my previous post of researching viable applications to make a simple game in, I decided to delve a bit into PyGame.

Since my brain is so heavily inundated with making Processing sketches, I based the code structure around core Processing concepts (setup() function, draw() function, etc).  While it’s probably not the best solution for writing a PyGame app (the liberal usage of ‘global’ calls), it does actually run, which is all I wanted :)

What does it do?  Spawn a bunch of random circles and have them bounce around the screen.  Exciting?  Not very.  But, you gotta start somewhere 😉

# pyGameTest02.py
# Eric Pavey - 2009-04-06
# Writing a PyGame app that emulates the general program layout of a Processing sketch.
# Makes a bunch of random circles bounce around.

import pygame
from pygame.locals import *
import random

RES = [640, 480]
MAXCIR = 128
window = None
screen = None
circles = []

class Cir(object):
    # Make our circle objects

    def __init__(self):
        self.xPos = RES[0]/2
        self.yPos = RES[1]/2
        self.xDir = random.choice([random.uniform(0,2),random.uniform(-2,0)])
        self.yDir = random.choice([random.uniform(0,2),random.uniform(-2,0)])
        self.radius = random.uniform(8,64)
        self.width = random.uniform(2,8)

    def move(self):
        self.xPos = self.xPos + 1 * self.xDir
        if self.xPos + self.radius/2 + self.width > RES[0] or self.xPos < self.radius/2 + self.width:
            self.xDir = self.xDir * -1

        self.yPos = self.yPos + 1 * self.yDir
        if self.yPos + self.radius/2 + self.width > RES[1] or self.yPos < self.radius/2 + self.width:
            self.yDir = self.yDir * -1            

    def draw(self):
        # must make all vals int:
        pygame.draw.circle(screen, Color('white'), [int(self.xPos), int(self.yPos)], int(self.radius), int(self.width))

    def run(self):
        self.move()
        self.draw()

def setup():
    # Initialize startup parameters
    global window
    global screen

    pygame.init()
    window = pygame.display.set_mode(RES)
    pygame.display.set_caption('PyGame Test 02')
    screen = pygame.display.get_surface()
    screen.fill(Color('black'))

def draw():
    # Run main loop:
    global screen
    global circles

    run = True
    while run:
        screen.fill(Color('black'))
        for c in circles:
            c.run()
        if len(circles) < MAXCIR:
            circles.append(Cir())
        pygame.display.update()

        for e in pygame.event.get():
            if e.type == QUIT:
                run = False
                break

if __name__ == "__main__":
    setup()
    draw()

What to make a game in?

I’ve been wanting to do a simple interactive game for some time now.  Conceptually, it’d not be very complex, and stylistically, look like childrens drawings.

I’ve been teaching myself Processing for some time now, and am fairly well versed scripting in Python via my day to day tasks working in Maya.

Processing seems like a good medium for this, and I’ve seen some fairly complicated games written in it recently.  But it’s strengths are based more around making good quality  ‘generative art’ (in my opinion), rather than full-featured game applications.  Plus its provided IDE (coined the ‘Processing Development Environment‘) doesn’t seem robust enough to handle larger scale game dev.  And… I really don’t feel like tackling installing Eclipse, learning more about Java, and getting Processing to run in that (but it would be a more viable option at that point).

Python has a very extensive library called PyGame, that seems like a real contender.  Since I’m (currently) only interested in doing a 2D side-scroller, this could be the method of choice.

However, lately I’ve been researching Blender.  It’s a full featured 3D DCC that’s both open-source and based entirely on Python.  Furthermore, it comes with it’s own built-in game engine.  I find this whole package very attractive, but as of yet have no experience with it.

Finally, most robust (seemingly), but something I have the least amount of experience with, would be Microsoft’s XNA Game Studio Express.  You can use Visual Studio Expression Edition to author it (I believe this is in C#), and then play games directly on your Xbox 360.  Very slick.  But the most learning required.  More info at that XNA Creators Club.

So time will tell!  But the best part is whatever I choose, I still win.  Good fun.