Take the 2-minute tour ×

There are a couple of problems i'm having with this - the first is how to work out how to find where the tip of each sine curve is (ie the frequency) and the second is to work out how to rotate each object so that it slides sideways along the sine wave

(note file is 800 x 600)

here's my code: CarouselTest.as:

    import com.greensock.easing.Sine;
    import com.greensock.TweenMax;
    import com.components.CarouselItem;
    import com.theflashblog.fp10.SimpleZSorter;
    import flash.display.Sprite;
    import flash.events.Event;
    import uk.co.thereceptacle.utils.Trig;

    public class CarouselTest extends Sprite 
        public static const SPACING : int = 20;
        public static const XSPACING: int = SPACING * 5;
        public static const SPEED   : Number = .05;
        public static const XSPEED  : Number = 800 / 360 * 2;
        public static const RADIUS  : int = 400;

        private var _items:Array;
        private var _container:Sprite;
        private var _movePerItem:Number;
        private var _noOfItems:int;

        public function CarouselTest() 
            _items = new Array();
            _noOfItems = 200;
            _movePerItem = 360 / _noOfItems; // my attempt at finding how much each item must move in order to bring it to the front

            _container = new Sprite();
            _container.x = 400;
            _container.y = 300;
            _container.z = 200;

            var item:CarouselItem = new CarouselItem();
            for (var i:int = 0; i < _noOfItems; i++)
                item = new CarouselItem();
                item.radius = RADIUS;
                item.angle = (i * SPACING) % 360;
                item.x = i * XSPACING - 300;
                item.speed = SPEED;

            moveItems(-1 * _movePerItem);

        private function moveItems(direction:int):void
            TweenMax.allTo(_items, 5, { angle:direction.toString(), x:(direction * XSPACING).toString(), ease:Sine.easeInOut } );
            TweenMax.to(this, 5, { onUpdate:SimpleZSorter.sortClips, onUpdateParams:[_container] } );


package com.components 
    import flash.display.Sprite;
    import flash.text.TextField;
    import uk.co.thereceptacle.components.HTMLTextField;
    import uk.co.thereceptacle.utils.Trig;

    public class CarouselItem extends Sprite
        private var _angle  : Number;
        private var _prevX  : Number;
        private var _prevZ  : Number;

        public var speed    : int;
        public var radius   : Number;

        public function CarouselItem() 
            graphics.drawRect( -100, -150, 200, 300);

            var tf:TextField = new HTMLTextField();
            tf.embedFonts = false;
            tf.wordWrap = false;
            tf.htmlText = "<p>THIS IS A TEST</p>";
            tf.x = -100;
            tf.y = -tf.textHeight / 2;

        public function get angle():Number { return _angle; }
        public function set angle(value:Number):void 
            _angle = value;

            z = Math.sin(angle) * radius;

            var deltaX:Number = x - _prevX;
            var deltaZ:Number = z - _prevZ;
            var rotate:Number = Trig.radiansToDegrees(Math.atan2(deltaZ, deltaX));
            rotationY = rotate; <strike>// this is getting close but always rotates the item away from the center and i need it to rotate towards the center on the positive side of the sine wave</strike>
// edit: i've updated this as it's much closer but still flaky - it feels like i haven't done it right


        override public function set x(value:Number):void 
            _prevX = x;
            super.x = value;

        override public function set z(value:Number):void 
            _prevZ = z;
            super.z = value;

hope you can help obie

share|improve this question
hi guys - i've worked out the problem about the freqency (ie, the tips of the sine wave). If a single revolution is 2*PI then as long as i always use a fraction of PI, i'm golden, so now all i really need help with is working out the angle of the line –  obie May 27 '11 at 15:10
A sine is at maximum for pi/2 or 90 degrees depending on your units. I can't run your code, but it's clear you need to figure out at what point the rotation should be 0 and at what point it should be 90 degrees (or whatever you want). this tutorial explains how atan2 works –  Peter May 27 '11 at 15:28
Can you explain a little more what you want to achieve? At what point to you want the sprite to be rotated by how many degrees? –  Peter May 27 '11 at 15:35
i'd like the object to be rotated to 90 degrees of the path it's following (as if it's sliding along it, basically) during the course of it's journey (so i'll put it into the angle mutator and update the angle with the tween) –  obie May 27 '11 at 15:40
i think i've found something on wikipedia which may be the answer - now all i have to do is work out what it's saying –  obie May 27 '11 at 15:59
add comment

1 Answer

up vote 0 down vote accepted

I assume you want to animate something like a skateboard on a rolling hill (or boat on seas, or something with similar motion).

All of the trig/calculus you need to know for this problem: The line sitting on a curve in the way you want is the tangent line. It is described by the derivative of the curve. The derivative of the sine curve is the cosine. Calculus magic: if your curve is a*sin(b*x), the tangent is a*b*cos(b*x). That gives you (rise/run). If you want this expressed as an angle, you will want the atan (or atan2) of that. Note, you will need to be consistent with your angle units. Most likely atan gives you radians and you want degrees.

share|improve this answer
thanks for your help guys :) I tried to use Trig.radiansToDegrees(Math.atan2(deltaY, deltaZ)) but i found it quite flickery and if the objects hadn't moved the previous frame (due to being at the end of a tween for instance) they would end up with deltaX/deltaZ of 0 and snap flat. If this is the right way to go then i'll see if i can try to account for this. –  obie May 27 '11 at 23:50
add comment

Your Answer


