rabbyt.anims - Rabbyt Reference

Documentation Index

# rabbyt.anims

This module provides Animators (or anims for short) for Rabbyt.

Anims are little objects that can implement a movement function, primarily meant to animate sprites. The movement functions are all implemented in C, so your sprites can be animated without any python call overhead.

For example, to linearly interpolate a sprite from x=0 to x=100 over the next second, you can do this:

>     sprite.x = rabbyt.lerp(0, 100, dt=1000)

Looks like magic?

It is! Sorta...

The `Sprite` class's `x` attribute is really a property. If you assign an anim to it, that anim will be called for it's value every time the sprite needs it's x position. Nearly all of `Sprite`'s properties work like this.

Anims support various arithmatic opperations. If you add two together, or add one with a constant number, a new anim will be returned. Here is a rather contrived example of doing that:

>     sprite.x = rabbyt.lerp(0, 100, dt=1000) + 20

(In this case, you would be better off interpolating from 20 to 120, but whatever.)

Here is a more useful example:

>     sprite2.x = sprite1.attrgetter('x') + 20

That will cause sprite2's x position to always be 20 more than sprite1's x position. (`Sprite.attrgetter()` returns an anim that gets an attribute.) This all happens in compiled C code, without any python call overhead. (That means you can have thousands of sprites doing this and it will still be fast.)

But sometimes you don't really need that much speed. You can use any python function as an anim as well. This example does the same as the last one:

>     sprite2.x = lambda: sprite1.x + 20

(`Sprite.x` will automatically wrap the function in an `AnimPyFunc` instance behind the scenes.)

## Classes

- Anim
- AnimConst
- AnimPyFunc
- AnimProxy

## Functions

### set_time

`set_time(t)`

Sets the time that `get_time()` should return.

If you are using any time based animations, (such as `lerp()`,) you should call this function every frame.

For example, if you are using pygame you can do this:

    rabbyt.set_time(pygame.time.get_ticks())

Using this function should make it easier to implement a pause feature.

Note that rabbyt makes no assumption about the unit that the time is in. You can use milliseconds or seconds or even something else. It's up to you.

### get_time

`get_time()`

Gets the time that was last set by `set_time()`

### add_time

`add_time(t)`

Adds `t` to the ... time ... (Is it just me or does that sound dorky?)

This is really just a short cut that does this:

>     set_time(get_time() + t)

The new time is returned.

### lerp

`lerp(start, end, [startt,] [endt,] [dt,] [extend])`

Linearly interpolates between `start` and `end` as time moves from `startt` to `endt`.

`startt` is the time to start. It defaults to `rabbyt.get_time()`.

To specify the ending time, use either `endt`, which is the absolute time, or `dt`, which is relative from `startt`.

For example, all of the following are equivalent:

>     lerp(0, 1, rabbyt.get_time(), rabbyt.get_time()+1000)
>     lerp(0, 1, rabbyt.get_time(), dt=1000)
>     lerp(0, 1, dt=1000)

`extend` is a string defining what to do before `startt` and after `endt`. Possible values are:

> `"constant"`
>   The value will be locked between `start` and `end`. This is the default.
> `"extrapolate"`
>   After the value hits `end` it just keeps going!
> `"repeat"`
>   After the value hits `end` it will start over again at `start`.
> `"reverse"`
>   After the value hits `end` it will reverse, moving back to `start`.

Check out the `extend_modes.py` example to see all four side by side.

`start` and `end` can either be numbers, or tuples of numbers. If they are tuples, a tuple of anims will be returned. For example, this line:

>     sprite.rgba = lerp((0,1,0,.5), (1,0,1,1), dt=1000)

is equivalent to this:

>     sprite.red   = lerp(0, 1, dt=1000)
>     sprite.green = lerp(1, 0, dt=1000)
>     sprite.blue  = lerp(0, 1, dt=1000)
>     sprite.alpha = lerp(.5,1, dt=1000)

### exponential

`exponential(start, end, [startt,] [endt,] [dt,] [extend])`

Exponentially interpolates between `start` and `end` as time moves from `startt` to `endt`, using a cosine function.

All arguments work the same as in `lerp()`.

The function looks like this:

    (e**t-1) / (e-1)

If you want to use another base besides `e`, drop me an email explaining why and I'll implement it. (YAGNI)

### cosine

`cosine(start, end, [startt,] [endt,] [dt,] [extend])`

Cosinely [1] interpolates between `start` and `end` as time moves from `startt` to `endt`.

All arguments work the same as in `lerp()`.

The function looks like this:

    1-cos(t * pi/2)

And if math makes your head hurt, that means that your sprite will start out slow and speed up as it nears `end`.

[1] | Ok, so 'cosinely' isn't a word :)

### sine

`sine(start, end, [startt,] [endt,] [dt,] [extend])`

Sinely [1] interpolates between `start` and `end` as time moves from `startt` to `endt`.

All arguments work the same as in `lerp()`.

The function looks like this:

    sin(t * pi/2)

And if math still makes your head hurt, you should give up game development.

Ok, ok, I give! Your sprite will start out fast and slow down by the time it reaches `end`. (Just the opposite of cosinely interpolating.)

[1] | Oh, you say 'sinely' isn't a word either? That must be a bug. Give me your dictionary and a pen and I'll fix it.

### bezier3

`bezier3(p0, p1, p2, p3, [startt,] [endt,] [dt,] [extend])`

Interpolates along a cubic bezier curve as defined by `p0`, `p1`, `p2`, and `p3`.

`startt`, `endt`, `dt`, and `extend` work as in `lerp()`.

`p0`, `p1`, `p2`, and `p3` can be tuples, but they must all be the same length.

### wrap

`wrap(bounds, parent, static=True) -> AnimWrap or tuple of AnimWraps`

Wraps a parent `Anim` to fit within `bounds`. `bounds` should be an object that supports item access for at least `bounds[0]` and `bounds[1]`. (A list or tuple with a length of 2 would work great.)

If `static` is `True`, `bounds` is only read once and stored in C variables for fast access. This is much faster, but doesn't work if `bounds` is an object you wish to mutate.

If `parent` is a iterable, a tuple of anims will be returned instead of a single one. (This is similar to `lerp()`.)

### to_Anim

`to_Anim(value) -> Anim subclass instance`

This is a convenience function to get `Anim` for a value.

If `value` is already an `Anim`, it is returned directly.

If `value` is callable, it is wrapped in an `AnimPyFunc`.

Otherwise, `value` is wrapped in an `AnimConst`.