Posts Tagged ‘ pygame

How can I modify a Python attribute any time it is accessed?

Originally posted on my Python Wiki

I was designing a UI for a PyGame program I am working on, and needed a way to pass a value defining a “row height” into the functions that rendered my text to the screen. Since the UI could change, I didn’t want to have to hard-code positions into each element, later to modify it and have to redo all the positions.
What I came up with was a simple class with a single usable attribute, called val. Through using properties, I’m able to control how the attr behavies at time time its value is queried:

class Row(object):
    # class to store the current row location in the UI
    # Each time it is called, it will increment its value
    def __init__(self, val):
        self._val = 0
        self.orig = val
    @property
    def val(self):
        self._val = self._val + self.orig
        return self._val
row = Row(16)

print row.val, row.val, row.val, row.val
# 16 32 48 64

Properties have getter, setter, and deleter methods, but the default is getter, which I used above. So as you can see, each time I call to print, it accesses the val property (via the getter), and updates the internal counter.
This is a PyGame code snippet showing it in use:

overlay.blit(bubble, (8, row.val))
overlay.blit(toggleText, (8, row.val))
overlay.blit(lmb, (8, row.val))

Rather than having to specify a Y value for the last arg of the tuple, I can simply pass in my object, and it passes out the current new position, based on how many times it was called before.

I have no doubt there is probably some slicker way in Python, but it’s what I came up with on the spot :)

PyGame Wiki created

It was only a matter of time:  I find Tiddlywiki’s a great way to store online notes.  I currently have made them for a variety of subjects (as shown on the left sidebar of my page).  They can be hosted for free through tiddlyspot.com.  Other than the funny name, and trying to explain it to people, they’re a wonderful data-publication medium in my opinion.

Based on my previous posts on ‘what to make a game in’ (1, 2, 3, 4, 5), I finally settled on PyGame, and have had a local copy of my ‘PyGame’ wiki for a few months now.  But today, I’ve got it hosted online.  Not a huge amount of info on it yet, but no doubt it will grow over time.  Enjoy

http://pygamewiki.tiddlyspot.com/

BubblePaint v0.01

BubblePaint.001

This is the results of my latest efforts to learn PyGame using PyMunk, a Python wrapper around the Chipmunk 2D physics engine.  Eventually I hope to use this knowledge in a physics-based tank game, but right now, I’m just having fun ‘painting’ with the ‘bubbles’.  There’s no great magic going on in my opinion, just some weekend coding fun.

In a nutshell:

  • You paint with “bubbles” on the canvas using the mouse.  It expects you have a 3-button mouse with a scroll wheel in the middle (because that’s what I have).  Since its physics based, the bubbles will push each other around, and none will be overlapping (if given time to settle).
  • LMB-drag draws bubbles
  • MMB-drag up\down: changes bubble size. Bigger bubbles get darker, smaller bubbles get lighter.
  • RMB-drag up\down: change brush hue
  • Mouse-wheel: change pressure of bubbles (number applied at once, from 1->10)
  • ‘s’ will save ‘test.png’ in the install dir.

You can find the Python source here:

And you can find a zipped Windows executable here:

Future plans for this include:

  • Shapes other than circles (square, triangle, random-polygon)
  • Ability to enable gravity, and add static rigid bodies (more of a physics sandbox at that point)
  • Images for the ‘bubbles’ rather than just solid color.
  • The ability to ‘dry’ the canvas to allow for multiple layers of painting.
  • A smarter way to save images.
  • A toggleable overlay layer showing stats.
  • Change the background color.
  • User defined resolution.  Currently set to 768×768

But we’ll see how much of that happens, I have family coming into two for the next few weeks :)

SohCahToa!

Time to get back to the basics.  I use trig at work, and at home in PyGame\Processing, but I like understanding the fundamentals of how it works.  So I sat down this afternoon and made up a “SohCahToa” PyGame program that really illustrates (to me at least)  what the values behind sine, cosine and tangent mean.  They are after all, ratios of the sides of a triangle.

So the mnemonic device is “Soh-Cah-Toa”, which means:

  • Sine = Opposite / Hypotenuse
  • Cosine = Adjacent / Hypotenuse
  • Tangent = Opposite / Adjacent

I wanted a visual way to see this in action, and that’s what this little program does:

sohCahToa01

Click through (twice) to larger image...

It plots a triangle defined by the opposite, adjacent, and hypotenuse sides.  As time goes by ‘degrees \ radians \ pi’ values increase, and the triangle changes.  The lengths of each side are plotted, and at the bottom, the math behind the sin, cos, and tan are shown in real-time.

The source code is online here, feel free to grab it:
http://www.akeric.com/python/sohCahToa01.py

Also, with a lot of help from this post (and several followup emails from its author), I was able to (finally) turn my PyGame apps into Windows executable.  Find the zipped version here:
http://www.akeric.com/python/sohCahToa01.zip

I built it with Python 2.6.2 and PyGame 1.9.1, but nothing fancy is going on with either, so it should work with older versions.

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,