Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

started on Win32 build

  • Loading branch information...
commit 5f622787539b10b1371d1a329bbe8fea371587ed 1 parent 5177e7d
@eilara authored
View
8 README.pod
@@ -822,11 +822,9 @@ Big thanks to:
Sam Hocevar, from 14 rue de Plaisance, 75014 Paris, France
https://raw.github.com/warrenm
-For his excellent AHEasing lib which C<SDLx-Tween> uses for easing
-functions. The license is in the C<tweencee/> dir. The library is at
-L<https://github.com/warrenm/AHEasing>.
-
-Check that page for some great info about easing functions.
+For his excellent AHEasing lib which C<SDLx-Betweener> uses for easing
+functions: L<https://github.com/warrenm/AHEasing>. Check that page for some
+great info about easing functions.
Huge thanks to Zohar Kelrich <lumimies@gmail.com> for patient listening and
advice.
View
4 TODO
@@ -19,13 +19,11 @@ TODO
- one time tick tween, like timer
- delay tween, there just for delaying until completion event
- add spawner non-linear ease
- - smooth seek with change targets
+ - seeker direct target should be weak ref and add target dead event
* Proxy decorators
- SDLx::Rect proxy for 2D paths
- face angle for path tweens
- add/remove to/from grid cell on move
- - event on weak proxy target missing so homing missile can
- change target or explode
* Timeline
- elastic speed of time, FFW/REW, seek progress
* API
View
2  eg/07-seeker.pl
@@ -46,7 +46,7 @@ package main;
$app->add_event_handler(sub {
my ($e, $app) = @_;
- if($e->type == SDL_QUIT) { $app->stop }
+ if ($e->type == SDL_QUIT ) { $app->stop }
elsif ($e->type == SDL_MOUSEMOTION) {
$player->[0] = $e->motion_x;
$player->[1] = $e->motion_y;
View
848 lib/SDLx/Betweener.pm
@@ -145,7 +145,7 @@ sub tween_seek {
my $speed = $args{speed} || die 'No "speed" given';
my $proxy = $Proxy_Lookup{ref $on} || die "unknown proxy type: $on";
- my ($from, $to) = extract_range($proxy, $on, %args);;
+ my ($from, $to) = extract_range($proxy, $on, %args);
$on = [%$on] if $proxy == METHOD_PROXY;
@@ -253,7 +253,7 @@ sub extract_completer {
return $done;
}
-# extracts "from" key from args
+# extracts range from args
sub extract_range {
my ($proxy, $on, %args) = @_;
my ($from, $to);
@@ -278,6 +278,848 @@ sub extract_range {
return ($from, $to);
}
-
1;
+=head1 NAME
+
+SDLx::Betweener - SDL Perl XS Tweening Animation Library
+
+=head1 SYNOPSIS
+
+ # simple linear tween
+ use SDLx::Betweener;
+
+ # if you are writting a Perl SDL program, you probably have an app object
+ $sdlx_app = SDLx::App->new(...);
+
+ # tweener is the tween factory, gets ticks from app
+ $tweener = SDLx::Betweener->new(app => $sdlx_app);
+
+ $xy = [0, 0]; # tween the position stored in this array ref
+
+ # animate the position $xy for 1 second from [0,0] to [640,480] linearly
+ $tween = $tweener->tween_path(on => $xy, t => 1_000, to => [640, 480]);
+
+ # tween will not do anything until started
+ $tween->start;
+
+ # xy will now be tweened between [0, 0] and [640, 480] for 1 second
+ # and then the tween will stop
+ $sdlx_app->run;
+
+ # tween accessors
+ $msec = $tween->get_cycle_start_time;
+ $msec = $tween->get_total_pause_time;
+ $msec = $tween->get_duration;
+ $bool = $tween->is_active;
+ $msec = $tween->is_paused;
+
+ # tween methods
+ $tween->set_duration($new_duration); # hasten/slow a tween
+ $tween->start($optional_ideal_cycle_start_time);
+ $tween->stop;
+ $tween->pause($optional_ideal_pause_time);
+ $tween->resume($optional_ideal_resume_time);
+
+ # tween types, each with its own constructor args, but all
+ # sharing a common set, see below for more info
+ $tween = $tweener->tween_int(...);
+ $tween = $tweener->tween_float(...);
+ $tween = $tweener->tween_path(...);
+ $tween = $tweener->tween_spawn(...);
+ $tween = $tweener->tween_rgba(...);
+ $tween = $tweener->tween_fade(...);
+
+ # seek behavior makes one position follow another at given speed
+ $tail = $timeline->tail(
+ speed => 50/1_000, # advance a distance of 50 pixels a sec
+ on => $xy, # array ref of xy to update
+ to => $target, # array ref of xy to follow
+ done => \&collide, # completer to call on collision
+ );
+
+
+=head1 DESCRIPTION
+
+C<SDLx::Betweener> is a library for animating Perl SDL elements. It lets you
+move game objects (GOBs) around in various ways, rotate and scale things,
+animate sprites and colors, make GOBs spawn at a given rate, and generally
+bring about changes in the game over time. It lets you do these things
+declaratively, without writing complex C<SDLx::Controller> C<move_handlers()>.
+
+See L</WHY> and L</FEATURES> for an introduction to tweening, or continue for
+the technical details.
+
+
+=head1 DECLARING TWEENING BEHAVIORS
+
+
+=head2 THE TWEEN FACTORY
+
+Use an C<SDLx::Betweener> object to create tweens. Create with an
+C<SDLx::App>:
+
+ $tweener = SDLx::Betweener->new(app => $app);
+
+There are some cases where you would want to create more than one
+tweener, see L</MULTIPLE TWEENERS>.
+
+
+=head2 THE TWEEN
+
+A tween is a behavior of some game property vs. time. It sets the target game
+property using a proxy, according to some path, at a time computed by an easing
+function, for a given duration.
+
+A tween is created from the tweener using the specific constructor for the tween
+type required. There are many options, described below, that you can configure
+through the tween constructor.
+
+Once you create the tween you can control its cycle: start/stop, pause/resume,
+and change cycle duration.
+
+The simplest tween uses the method proxy to call a game method with the tweened
+value. It uses the default linear path to tween a value between a range given
+by the C<range> arg. Speed of change will be constant, because the tween uses
+the default linear easing function.
+
+The simplest tween, animating a turret turning half a circle clockwise in 1
+second:
+
+ $tween = $timeline->tween_float(
+ on => {angle => $turret},
+ t => 1_000,
+ range => [0, pi], # pi from Math::Trig
+ );
+
+There are tween constructors like C<tween_float> for all kinds of tweens.
+
+
+=head2 TWEEN TYPES
+
+=over 4
+
+=item tween_int
+
+Tween a 1D integer value over a range.
+
+ # print once per second the numbers 1..10
+ $tween = $timeline->tween_int(
+ on => sub { say shift },
+ t => 10_000,
+ range => [1, 10],
+ );
+
+The value in your code is only updated when the integer tweened value changes,
+not on every tick.
+
+If the tween arg C<bounce> is true then the tweened value will be rounded into
+an integer, otherwise it will be floored.
+
+=item tween_float
+
+Tween a 1D floating point value over a range.
+
+ # Call scale() method every tick from its current value
+ # to 2.5 over 1 second
+ $tween = $timeline->tween_float(
+ on => {scale => $shape},
+ t => 1_000,
+ to => 2.5,
+ );
+
+=item tween_path
+
+Tween a 2D integer position along a path through the plane.
+
+ # move $enemy around in a circle
+ # xy() will be called with array ref of 2 integers
+ # when ticks cause position to change
+ $tween = $timeline->tween_path(
+ on => {xy => $enemy},
+ t => 2_000,
+ path => [circular => {
+ center => [320,240],
+ radius => 140,
+ from => 0,
+ to => 2*pi,
+ }],
+ );
+
+There are other paths available besides C<circular>. See L</PATHS> for the full
+list.
+
+=item tween_spawn
+
+Useful when you want to spawn waves of creeps, bullets from a machine gun,
+and generally call GOB constructors over time. Requires C<waves> constructor
+arg, providing how many waves to spawn. Does not work with C<direct proxy>, only
+with code calling proxies.
+
+Unlike other tweens, your code gets called with I<two> args. Besides the
+tweened value as 1st parameter (in this case the wave number, starting from 1),
+you also get the ideal spawn time for the GOBs you are about to spawn. This is
+useful if they themselves are animated, see L</ACCURACY> for more info.
+
+ # float 60 balloons at rate of 2 balloons/sec from the $balloons array
+ $spawner = $tweener->tween_spawn(
+ t => 30_000,
+ waves => 60,
+ on => sub {
+ my ($balloon_num, $start_t) = @_;
+ $balloons[ $balloon_num - 1 ]->float_to_sky($start_t);
+ },
+ );
+
+=item tween_fade
+
+Tween the opacity of an SDL color over a range. Provide the starting color in
+the C<from> key (Uint32 color), and the final opacity (Uint8) in the C<to> key.
+
+ # fade away a red curtain to reveal what is behind it
+ $tween = $tweener->tween_fade(
+ t => 2_000,
+ from => 0xFF0000FF,
+ to => 0x00,
+ on => \&set_curtain_color,
+ );
+
+=item tween_rgba
+
+Tween a 32bit RGBA value over a range. Th color given in the C<from> key, will be
+blended into the C<to> color.
+
+ # slowly transform a blue circle into a semi-transparent green one
+ $tween = $tweener->tween_rgba(
+ t => 10_000,
+ from => 0x0000FFFF,
+ to => 0x00FF0099,
+ on => {set_color => $circle},
+ );
+
+=item tween_seek
+
+The seeker is a simple behavior for making one GOB follow another moving GOB.
+Useful for homing missiles following a moving target at a constant velocity.
+It is more limited than other tween types in that there is no cycle control or
+easing (see below for info on these tween features), but you gain the ability
+to tween towards a dynamic, rather than static, target.
+
+ # the circle will follow the cursor at a constant velocity
+ # of 50 pixels/sec
+ # you can change the $cursor position in a mouse move event handler,
+ # and the circle will seek the new value until it reaches the cursor
+
+ $circle = {xy => [ 0, 0]}; # starts at 0, 0, set by tween
+ $cursor = {xy => [100,100]}; # starts at 100,100, set by mouse event handler
+ $seeker = $tweener->tween_seek(
+ on => $circle->{xy},
+ to => $cursor->{xy},
+ speed => 100 / 1_000,
+ );
+
+=back
+
+
+=head2 CYCLE CONTROL
+
+A tween has a duration and a cycle start time. These define its cycle. Several
+tween constructor arguments help to control the tween cycle:
+
+=over 4
+
+=item t
+
+C<integer> Duration of the tween from start to stop in msec
+
+=item forever
+
+C<boolean> Repeat the cycle forever, restarting on each cycle completion.
+
+=item repeat
+
+C<integer> Repeat the cycle C<n> times, then stop.
+
+=item reverse
+
+C<bool> Should the tween start reversed.
+
+=item bounce
+
+C<bool> If the cycle is repeating, on each cycle completion reverse the
+tween direction, I<bouncing> the tween between its edge points.
+
+=item done
+
+C<CODE> or C<HASH> ref of method name and object. Code or method to be called
+when tween cycle completes.
+
+=back
+
+Cycle control methods:
+
+=over 4
+
+=item start/stop/pause/resume
+
+A C<start()/stop()> sequence will reset the tween. A C<pause()/resume()>
+sequence will resume it from its last position before the C<pause()>. These all
+take an optional ideal event time in SDL msec since game start, see
+L</ACCURACY> for more info.
+
+=item is_active
+
+true if tween is started.
+
+=item is_paused
+
+true for paused tweens.
+
+=item get_cycle_start_time
+
+Returns the tween cycle start time, in SDL style msec since game start.
+
+=item get/set_duration
+
+Get/set the tween duration, in msec. This lets you slow/haste a tween as
+it is animating.
+
+=back
+
+
+=head2 PROXIES
+
+The tween computes its tweened value on each tick, and uses the proxy to
+deposit it inside your code. You can use a proxy to call a method, call a
+callback, or directly set a Perl value. The proxy is set using the C<on> key of
+the tween constructor. There are several proxy types:
+
+=over 4
+
+=item method proxy
+
+Create by setting C<on> to a hash with one key- method name, and one value-
+some Perl object.
+
+ # as part of the tween constructor arg hash
+ on => {method_name => $game_object},
+
+The tween value will be set by calling the given method on the given object.
+
+Some tweens require a range (e.g. C<tween_path> with a linear path). If none is
+supplied, the method defined for the proxy is used to I<get> the initial tween
+value. In this case the proxy method is expected to support get and set. This
+is mere syntax sugar for not specifying the initial value in the range. You can
+always provide a C<from> key explicitly in constructor, or use the C<range> key
+for setting C<from> and C<to> at once.
+
+=item callback proxy
+
+If the C<on> key points at a code ref, then it will be called with the tweened
+value on each tick.
+
+ # as part of the tween constructor arg hash
+ on => sub { my $v = shift; say "tweened value=$v" },
+
+=item direct proxy
+
+If the tween constructor arg C<on> is a scalar ref on a number, or a 2D numeric
+array ref (for path tweens), then the tween will use the direct proxy:
+
+ $color = 0xFF0000FF;
+ ...
+ # as part of the tween constructor arg hash
+ on => \$color,
+
+The numeric color value will be updated on each tick. This is very fast, but
+you lose any semblance of encapsulation.
+
+=back
+
+
+=head2 EASING
+
+The default tween changes in constant speed because it uses the linear easing
+function. The time used by the path to compute position of the tween value,
+advances in a linear rate.
+
+By setting the C<ease> arg in the tween constructor you can make time advance
+according to a non-linear curve. For example to make the tween go slow at
+first, then go fast:
+
+ # as part of the tween constructor arg hash
+ ease => 'p2_in',
+
+This will cause time to advance in a quadratic curve. At normalized time
+C<$t> where C< $t=$elapsed/$duration > and $t is between 0 and 1, the C<p2_in>
+tween will be where a linear tween would be at time C<$t**2>.
+
+All easing functions except linear ease have 3 variants: C<_in>, C<_out>, and
+C<_in_out>. C<_out> is reverse of C<_in>. C<_in_out> suffix variant is C<_in>
+followed by C<_out>. E.g. C<exponential_in> starts slow then speeds up,
+C<exponential_out> starts fast and slows down, and C<exponential_in_out> starts
+slow, speeds up, then slows down.
+
+These are the available easing functions. See C<eg/04-easing.pl> in the
+distribution for a visual explanation. See
+L<https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c> for a math
+explanation. The tweening functions originate from
+L<http://robertpenner.com/easing/penner_chapter7_tweening.pdf>.
+
+=over 4
+
+=item *
+
+linear
+
+=item *
+
+p2
+
+=item *
+
+p3
+
+=item *
+
+p4
+
+=item *
+
+p5
+
+=item *
+
+sine
+
+=item *
+
+circular
+
+=item *
+
+exponential
+
+=item *
+
+elastic
+
+=item *
+
+back
+
+=item *
+
+bounce
+
+=back
+
+
+=head2 PATHS
+
+Simple tweens follow a linear path, and this is the only option when tweening a
+1D value.
+
+When building a tween of type C<tween_path>, you can customize the path the
+tween takes through the plane. The path is given in the C<path> arg of the
+tween constructor hash. It is given as an array ref of, whose 1st value is the
+path name, and the other array values are path args to specify the path
+construction.
+
+=over 4
+
+=item linear
+
+Requires one of 2 constructor args: C<range> or C<from + to>. If no C<range>
+and no C<from> are given then the value is taken from the tween target using
+the proxy. Thus you can tween a GOB from its current position to another
+without specifying the current position twice. Here are the 3 options for
+using the default linear path:
+
+ # option 1: construct a tween only with "to", from is taken from the target
+ to => [320, 200]
+
+ # option 2: provide "from" + "to"
+ from => [ 0, 0]
+ to => [320, 200]
+
+ # option 3: provide "range"
+ range => [[0, 0], [320, 200]]
+
+Linear path, being the default and the simplest of the paths, needs no
+C<path> key. Just make sure the tween has a way to get C<from> and C<to>.
+
+=item circular
+
+Tweens a value along a circle with a given radius and center, between 2 angles.
+
+ path => [circular => {
+ center => [320, 200],
+ radius => 100,
+ from => 0,
+ to => 2*pi,
+ }],
+
+=item polyline
+
+Tweens a value along an array of segments, specified by the xy coordinates of
+the waypoints. The tween will start at the 1st waypoint and continue until the
+last following a linear path between them.
+
+ path => [polyline => [
+ [200, 200],
+ [600, 200],
+ [200, 400],
+ [600, 400],
+ [200, 200],
+ ]],
+
+=back
+
+
+=head2 MEMORY MANAGEMENT
+
+There are two issues with tween memory management: how do you keep a ref to the
+tween in game objects, and how does the tween keep ref to the game elements it
+changes.
+
+The C<SDLx::Betweener> only keeps weak refs to active tweens. This means you
+must keep a strong ref to the tween somewhere, usually in the game object. When
+the game object goes out of the scope, the tween will stop, be destroyed, and
+cleaned out of the tweener automatically.
+
+The tween only keeps weak refs to the game elements (objects or array refs) it
+changes. Usually other game object will have strong refs to them, as part of
+the game scene graph. When the game object that is the target of the tween
+goes out of scope, you must stop the tween, and never use it again.
+
+
+=head2 MULTIPLE TWEENERS
+
+A tween tick can trigger user code, e.g. a C<done> handler could call a user method.
+This code could destroy tweens, e.g. a missile hitting a target. In this case the
+two tweens should be created using two different C<SDLx::Betweener> objects.
+
+B<TODO> fix and delete this section.
+
+
+=head2 ACCURACY
+
+C<SDLx::Betweener> takes into account rounding errors, the inaccuracy of the
+C<SDLx::Controller> C<move_handler>, and the inaccuracy of time/distance limits
+on behaviors. Used correctly, 2 tweens on the same path, one with duration 1
+sec and the other 2 sec, will always meet every 2 cycles, even 100 years later.
+
+To get this absolute accuracy with no errors growing over time, you need to set
+ideal C< start/pause/resume> times when controlling tween cycles.
+
+Here is an example of starting 2 tweens which is I<NOT> accurate:
+
+ # dont do this!
+ $t1 = $tweener->tween_int(...);
+ $t1->start;
+ $t2 = $tweener->tween_int(...);
+ $t2->start;
+
+
+C<$t1> and C<$t2> will not have the same C<cycle_start_time>, and this applies
+to all cycle control methods.
+
+If accuracy is needed, use the optional ideal time argument of the cycle
+control methods:
+
+ # or this
+ $start_time = SDL::get_ticks;
+ $t1 = $tweener->tween_int(...);
+ $t1->start($start_time);
+ $t2 = $tweener->tween_int(...);
+ $t2->start($start_time);
+
+
+When chaining tweens, the 2nd tween ideal start time should be set as the 1st
+tween start time + the tween duration. Tween completion handlers (the C<done>
+arg) are given the tween ideal stop time so you don't need to compute this:
+
+ $tween = $tweener->tween_int(
+ ...
+ # start time for next tween is this tween cycle complete time
+ done => sub { $next_tween->start(shift) },
+
+When spawning tweens the second parameter in the spawn handler is the ideal
+spawn time. Use this for the animation start time on the spawned GOB.
+
+B<TODO> fix and delete this section.
+
+
+=head1 WHY
+
+Writing Perl SDL game move handlers is hard. Consider a missile with 3 states:
+
+=over 4
+
+=item *
+
+firing - some sprite animation
+
+=item *
+
+flying towards enemy - need to update its position until it hits enemy
+
+=item *
+
+exploding - another sprite animation
+
+=back
+
+The move handler for this game object (GOB) is hard to write, because it needs to:
+
+=over 4
+
+=item *
+
+update GOB properties
+
+=item *
+
+you must take into account acceleration and paths in the computation of these
+values
+
+=item *
+
+you need to set limits of the values, wait for the limits
+
+=item *
+
+GOBs need to act differently according to their state, so you need to manage
+that as well
+
+=item *
+
+it all must be very accurate, or animations will miss each other
+
+=item *
+
+it has to be fast- this code is run per each GOB per each update
+
+=back
+
+As a game becomes more wonderful, the GOB move handlers become more hellish.
+Brave souls have done it, but even they could not do it in a way us mortals
+can reuse or even understand.
+
+C<SDLx::Betweener> solves the missile requirements. Instead of writing a move
+handler, declare tweens on your GOBs. C<SDLx::Betweener> will take care of the move
+handler for you.
+
+Instead of writing a move handler which updates the position of $my_gob
+from its current position to x=100 in 1 second, you can go:
+
+ $tween = $timline->tween(on => [x => $my_gob], to =>100, t => 1_000);
+
+C<SDLx::Betweener> will setup the correct move handler.
+
+According to L<http://en.wikipedia.org/wiki/Tweening>:
+
+ "In the inbetweening workflow of traditional hand-drawn animation, the
+ senior or key artist would draw the keyframes ... and then would hand over
+ the scene to his or her assistant the inbetweener who does the rest."
+
+Let SDLx-Betweener be your inbetweener.
+
+
+=head1 FEATURES
+
+Perl SDL move handlers are rarely a simple linear progression. An ideal
+tweening library should feature:
+
+=over 4
+
+=item *
+
+tween any method, e.g. a Moose get/set accessor, or directly on an array
+
+=item *
+
+tween a property with several dimensions, e.g. xy position, some 4D color space
+
+=item *
+
+tween xy position not on a line, but on some curve
+
+=item *
+
+round the tween values, and pass only values when they change
+
+=item *
+
+smooth the motion with acceleration/deceleration using easing functions
+
+=item *
+
+make the tween bounce, reverse, and repeat for N cycles or forever
+
+=item *
+
+pause/resume tweens
+
+=item *
+
+hasten/slow a tween, for example when creeps are suddenly given a speed bonus
+
+=item *
+
+follow a moving target, e.g. a homing missile with constant acceleration
+
+=item *
+
+chain tweens, parallelize tween, e.g. start explode tween after reaching target
+
+=item *
+
+tween sprite frames, color/opacity/brightness/saturation/hue, volume/pitch,
+spawning, rotation, size, camera position
+
+=item *
+
+delay before/after tweens
+
+=item *
+
+rewind/ffw/reverse/seek tweens, and generally play with elastic time for making
+the game faster or slower
+
+=back
+
+C<SDLx::Betweener> doesn't do everything yet. See the C<TODO> file in the
+distribution for planned features, and the docs above for supported features.
+
+
+=head1 EXAMPLES
+
+Tweening examples in the distribution dir C< eg/>:
+
+=over 4
+
+=item C<01-circle.pl>
+
+the hello world of tweening, a growing circle
+
+=item C<02-starfield.pl>
+
+many concurrent path tweens
+
+=item C<03-polyline.pl>
+
+polyline path demo
+
+=item C<04-easing.pl>
+
+demo of all easing functions available
+
+=item C<05-colors.pl>
+
+demo of color transitions
+
+=item C<06-chaining.pl>
+
+how to chain tweens
+
+=item C<07-seeker.pl>
+
+demo of many seekers following cursor
+
+=back
+
+
+=head1 SEE ALSO
+
+Development is at L<https://github.com/PerlGameDev/SDLx-Betweener>.
+
+Interesting implementations of the tweening idea:
+
+=over 4
+
+=item *
+
+http://www.greensock.com/tweenlite/
+
+=item *
+
+http://drawlogic.com/2010/04/11/itween-tweening-and-easing-animation-library-for-unity-3d/
+
+=item *
+
+http://www.leebyron.com/else/shapetween/
+
+=back
+
+
+=head1 BUGS
+
+Very little safety in XS code. Lose your ref to the tween target (object or
+ref being updated) and horrible things will happen on next tick. See C<TODO>
+file in distribution for more issues.
+
+
+=head1 DESIGN
+
+Timeline has a std::set of Tween objects. It broadcasts tick(Uint32 now)
+to them.
+
+The Tween tick method normalizes the time given using now/tween_duration,
+so that it is between 0 and 1.
+
+Then the time is passed through the easing function, which maps it to some
+eased time value, useful for non-linear speed animations.
+
+The tween then calls tick(Uint32 now) on its ITweenForm. The tween form
+translates the eased time into some domain value and pushes it into the
+tween target using the tween proxy.
+
+LinearTweenForm interpolates between 2 values ("from" and "to") in a linear
+path. The values tweened are Vector<typename T, int DIM>.
+
+PathTweenForm is more general. It lets you tween a Vector<int,2> along a 2D
+path, given in construction. LinearPath makes the form behave like a
+LinearTweenForm. CircularPath tweens along a circle or a pie slice from it.
+PolylinePath tweens along a set of linear segments.
+
+A tween form uses an IProxy for pushing the value into Perl. There are proxies
+for setting Perl values (scalar for 1D tween, array ref for 2D) directly,
+for calling a callback with the tweened value, and for calling a method.
+
+A tween uses a CycleControl object for controlling cycle repeat and cycle
+reverse. A tween can be made to run forever, to reverse on cycle completion
+(bounce), to start reversed, and to repeat N times.
+
+Tween start/stop registers/unregisters the tween on a timeline.
+
+
+=head1 AUTHOR
+
+eilara <ran.eilam@gmail.com>
+
+Big thanks to:
+
+ Sam Hocevar, from 14 rue de Plaisance, 75014 Paris, France
+ https://raw.github.com/warrenm
+
+For his excellent AHEasing lib which C<SDLx-Betweener> uses for easing
+functions: L<https://github.com/warrenm/AHEasing>. Check that page for some
+great info about easing functions.
+
+Huge thanks to Zohar Kelrich <lumimies@gmail.com> for patient listening and
+advice.
+
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2011 by Ran Eilam
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.10.1 or,
+at your option, any later version of Perl 5 you may have available.
+
+
+=cut
+
View
1  src/cpp/PathTweenForm.h
@@ -3,7 +3,6 @@
#define PATHTWEENFORM_H
#include <stdlib.h>
-#include <iostream>
#include "Vector.h"
#include "IProxy.h"
#include "IPath.h"
View
4 src/cpp/Timeline.cpp
@@ -10,7 +10,7 @@ using namespace std;
typedef LinearTweenForm<int ,1,false> LinearIntForm;
typedef LinearTweenForm<int ,1,true> LinearIntFormFloored;
typedef LinearTweenForm<float,1,false> LinearFloatForm;
-typedef LinearTweenForm<int ,4,false> LinearRgbaForm;
+typedef LinearTweenForm<int ,4,false> LinearRgbaForm;
Timeline::Timeline() : tickers() {
}
@@ -31,6 +31,8 @@ void Timeline::unregister_ticker(ITicker *ticker) {
tickers.erase(ticker);
}
+// this loop implies tween ticks and tween complete handlers should not
+// unregister or destroy other tweens in the same timeline
void Timeline::tick(Uint32 now) {
for (set<ITicker*>::iterator it = tickers.begin(); it != tickers.end();) {
set<ITicker*>::iterator it2 = it;
View
12 src/cpp/Tween.cpp
@@ -71,18 +71,20 @@ void Tween::set_duration(Uint32 new_duration, Uint32 now) {
}
void Tween::on_tick(Uint32 now) {
- bool is_complete = 0;
- Uint32 elapsed = now - cycle_start_time - total_pause_time;
+ bool is_complete = 0;
+ Uint32 elapsed = now - cycle_start_time - total_pause_time;
if (elapsed >= duration) {
is_complete = 1;
- elapsed = duration;
+ elapsed = duration;
}
float t_normal = (float) elapsed / duration;
float eased = ease_func(t_normal);
+
if (control->is_reversed()) eased = 1 - eased;
form->tick(eased);
+ // check is_active because tween tick could have stopped the tween
if (!is_active() || !is_complete) { return; }
control->cycle_complete();
@@ -94,7 +96,7 @@ void Tween::on_tick(Uint32 now) {
}
// begin repeat cycle
- cycle_start_time += elapsed;
- last_cycle_complete_time = 0;
+ cycle_start_time += elapsed;
+ last_cycle_complete_time = 0;
}
View
4 src/cpp/Vector.h
@@ -2,6 +2,10 @@
#ifndef VECTOR_H
#define VECTOR_H
+// namespace collisions
+#undef write
+#undef read
+
#include <math.h>
#include <stdlib.h>
#include <algorithm>
Please sign in to comment.
Something went wrong with that request. Please try again.