tags:

views:

102

answers:

4

In my program, I draw some quads. I want to add the functionality for them to scale up, then down, then go back to being static (to draw attention). In the quads I have:

self.scale = 10

Making scale change according to sin would be nice. But adding frequency, amplitude and logic to my already bloated quad class is something I take as a challenge to avoid.

Something like this:

class mysin:
    def __init__(self):
     self.tick = 0.0
     self.freq = 1.0
     self.ampl = 1.0

    def update(self, amount):
     self.tick += amount

    def value(self):
     return math.sin(self.tick)

That class would also add itself to the logic system (getting update calls every frame). I would then do:

quad.scale = 10 # for static quad
quad.scale = mysin() # for cool scaling quad

The problem is that some calculations expect scale to hold a value. I could of course add another class where value() returns a (previously saved) constant value and adapt all the calculations.

What I want to know now is... does this have a name, is it a valid technique? I read the wiki article on functional programming and this idea sprung to mind as a wacky implementation (although Im not sure it qualifies as FP). I could very well have been driven mad by that article. Put me back in line fellow coders.

A: 

It's sort of like lazy-evaluation. It is definitely a valid tecnique when used properly, but I don't think this is the right place to use it. It makes the code kind of confusing.

Zifre
So your suggestion is that I should add tick, amplitude and frequency to the quad class along with a state flag indicating if it should be updated or not as well as add it to the logic system in the code? While a valid point, I doubt this other way of tackling it is any less confusing.
mizipzor
No, I would have a `QuadController` class that would hold a reference to a `Quad`. The logic system would call update on the `QuadController`, which would scale the `Quad`. (If you have more than one geometric primitive, you could make it into a `GeometryController` that could control any shape.)
Zifre
A: 

It sure is a valid technique, but a name? Having an object.value() instead of an int? Uhm. Object orientation? :)

If the methods that use this value requires an integer, and won't call any method on it, you could in fact create your own integer class, that behaves exactly like an integer, but changes the value.

Lennart Regebro
+4  A: 

The distinction between

quad.scale= 10

and

quad.scale= MySin()

Is minor. Within the Quad class definition the "scale" attribute can be a property with proper getter and setter functions.

class Quad( object ):
    @property
    def scale( self ):
        return self._scale

    @scale.setter
    def set_scale( self, value ):
        # handle numeric and MySin() values appropriately.

Alternate version with the explicit property function (which I prefer).

class Quad( object ):
    def get_scale( self ):
        return self._scale
    def set_scale( self, value )
        # Handle numeric and MySin() values 
    scale = property( get_scale, set_scale )

Any other class should NOT know or care what type of value scale has. If some client does this

quad.scale * 2

Then you have design issues. You haven't properly encapsulated your design and Quad's client classes are too friendly with Quad.

If you absolutely must do this -- because you can't write a method function of Quad to encapsulate this -- then you have to make MySin a proper numeric class so it can respond to quad.scale * 2 requests properly.

S.Lott
Im getting errors trying this, are the setter decorators python 3.0 only?
mizipzor
2.6+ only, yes.
Miles
+1  A: 

It sounds like you want your quads to be dumb, and to have an animator class which is smart. So,here are some suggestions:

  1. Give the quads an attribute which indicates how to animate them (in addition to the scale and whatever else).
  2. In an Animator class, on a frame update, iterate over your quads and decide how to treat each one, based on that attribute.
  3. In the treatment of a quad, update the scale property of each dynamically changing quad to the appropriate float value. For static quads it never changes, for dynamic ones it changes based on any algorithm you like.

One advantage this approach is that it allows you to vary different attributes (scale, opacity, fill colour ... you name it) while keeping the logic in the animator.

Vinay Sajip