sutoL
sutoL

Reputation: 1767

rotating object to face another object

currently i have a function in which my object fish will move to a food i am having trouble getting it to rotate nicely to the food currently my function is as below.if the food is above the fish my fish rotation is 0 which is facing up, if the food is below my fish i will give it a rotation of 180 which will make it face down , however the rotation is too sudden it does not give a nice and realistic effect of rotating to the food.

how can i make it when rotating to move some distance and at the same time rotate? because it cant rotate to the food in the same spot as it would not be realistic.

public function moveToFood():void
        {   
            var foodTarget:Food = fishArray[fishArray.length - 1];
            trace("Popped food with position" + foodTarget.x + " " +foodTarget.y);
            var dx:Number = x - foodTarget.x;
            var dy:Number = y - foodTarget.y;
            if (foodTarget.y > this.y)
            {
                trace("Food below fish")
                rotation = 180;
                this.x -= dx / 15;
                this.y -= dy / 15;
            }else if (foodTarget.y < this.y)
            {
                trace("Food above fish")
                rotation = 0;
                this.x -= dx / 15;
                this.y -= dy / 15;
            }

        //removing food when both hit boxes hit
        if (hit.hitTestObject(foodTarget.hit))
            {
                foodIsDropped = false;
                foodTarget.removeSelf();
            }
        }

Upvotes: 2

Views: 1126

Answers (5)

noncom
noncom

Reputation: 4992

btw there is also a simpler way. you can make "sensors" for you fish. just place them like this:

     \  o
>--fish--)
     /  o

there where you see the o signs. then count distance from each of them to the target. if left distance is smaller, turn left, if the right one is smaller - turn right. very simple, i have used this in my childhood. however, because of using two dists for a single object, it is quite slower than the other "iffed" method.. and do not forget to include a condition on when difference between the two distances is less than DELTA, you do not turn the fish, but align it with target (angle = atan2(difx, dify))...

Upvotes: 0

noncom
noncom

Reputation: 4992

... i have just bruteforced the formula for every possible kind of situation. the bunch of if above mean just that:

 if there is need to turn
    if we are now in + arc
        if target in - arc
            if target is lefter
                if difference is more than turnrate
                    turn left
                else
                    align
                end
            else //target is righter
                if difference is more than turnrate
                    turn right
                else
                    align
                end
            end
        else //target is in + arc
            if target is lefter or opposite
                if difference is more than turnrate
                    turn left
                else
                    align
                end
            else //target is righter
                if difference is more than turnrate
                    turn right
                else
                    align
                end
            end
        end
    else //same thing as above but for us being in - arc
    ...

Upvotes: 1

noncom
noncom

Reputation: 4992

I have used the code below for my Java app. The atan2(y,x) function here returns an angle between -PI and PI. Please note that it is likely that the function takes Y as its first argument and only then X. The X and Y for the args are the difference between target and object positions, which in your case are the food and the fish respectively. Plain math. Only worth noticing that the 0 angle is to the right, the + angle goes up and left, and the - angle goes down and left, look at this image: http://iepro.files.wordpress.com/2009/12/atan2.jpg?w=280&h=283 or this http://www.mathworks.com/help/techdoc/ref/math_a20.gif (the forum wont allow me post images yet)

float heading;
float targetHeading = atan2(target.y - this.y, target.x - this.x);

...

if(this.heading != this.targetHeading){
    if(this.heading <=0){ //heading in minus
        if(this.targetHeading > -PI && this.targetHeading <=0){ //target in minus
            if(this.targetHeading < this.heading){  // both in minus and target is lefter
                if(this.heading - this.targetHeading > this.mManeuverSpeed){
                    this.turnLeft();
        //          System.out.println("SHIP: A");
                }else{
                    this.resetHeading();
                }
            }else{                                  // both in minus and target is righter
                if(this.targetHeading - this.heading > this.mManeuverSpeed){
                    this.turnRight();
        //          System.out.println("SHIP: B");
                }else{
                    this.resetHeading();
                }
            }
        }else{                                                  //target in plus
            if(this.heading + PI <= this.targetHeading){            //target in plus and is lefter or opposite
                if(PI + this.heading + (PI - this.targetHeading) > this.mManeuverSpeed){
                    this.turnLeft();
        //          System.out.println("SHIP: C "  + this.heading + " > " + this.targetHeading);
                }else{
                    this.resetHeading();
                }
            }else{                                              //target in plus and is righter
                if(this.targetHeading - this.heading > this.mManeuverSpeed){
                    this.turnRight();
        //          System.out.println("SHIP: D");
                }else{
                    this.resetHeading();
                }
            }
        }
    }else{                                  //heading in plus
        if(this.targetHeading > -PI && this.targetHeading <=0){ //target in minus
            if(this.heading - this.targetHeading < PI){     //if target is in minus and lefter
                if(this.heading - this.targetHeading > this.mManeuverSpeed){
                    this.turnLeft();
        //          System.out.println("SHIP: E");
                }else{
                    this.resetHeading();
                }
            }else{
                if(PI + this.targetHeading + (PI - this.heading) > this.mManeuverSpeed){
                    this.turnRight();
        //          System.out.println("SHIP: F");
                }else{
                    this.resetHeading();
                }
            }
        }else{                                              //if target in plus
            if(this.heading <= this.targetHeading){
                if(this.targetHeading - this.heading > this.mManeuverSpeed){
                    this.turnRight();
        //          System.out.println("SHIP: G " + this.heading + " < " + this.targetHeading);
                }else{
                    this.resetHeading();
                }
            }else{
                if(this.heading - this.targetHeading > this.mManeuverSpeed){
                    this.turnLeft();
        //          System.out.println("SHIP: H " + this.heading);
                }else{
                    this.resetHeading();
                }
            }
        }
    }
}//heading != targetHeading

void turnLeft(){
    this.heading -= this.mManeuverSpeed;
}

void turnRight(){
    this.heading += this.mManeuverSpeed;
}

void resetHeading(){
    this.heading = this.targetHeading;
}

Upvotes: 0

Michael Antipin
Michael Antipin

Reputation: 3532

While the previous answer (about Tweener) is a possible solution, I think it's a bit of an overkill.

You already have a method which is triggered to move your fish. And you are doing a -= operation with x and y there. So why not do the same thing with rotation instead of changing it instantly?

public function moveToFood():void
{   
    var foodTarget:Food = fishArray[fishArray.length - 1];
    trace("Popped food with position" + foodTarget.x + " " +foodTarget.y);

    var targetRotation:Number = 0;
    if (foodTarget.y > y)
    {
        trace("Food below fish")
        targetRotation = 180;
    } else if (foodTarget.y < y)
    {
        trace("Food above fish")
        targetRotation = 0;
    }

    var dx:Number = x - foodTarget.x;
    var dy:Number = y - foodTarget.y;
    x -= dx / 15;
    y -= dy / 15;

    // *** update rotation ***
    rotation += (targetRotation-rotation)*.2;

    //removing food when both hit boxes hit
    if (hit.hitTestObject(foodTarget.hit))
        {
            foodIsDropped = false;
            foodTarget.removeSelf();
        }
    }
}

Upvotes: 1

Chunky Chunk
Chunky Chunk

Reputation: 17217

you can use a tweening engine.

i would recommend you use Tweener instead of the standard Flash Tween class. the fl.transitions.Tween class is kind of ridiculous compared to Tweener and you may not even have access to it if you're not using Flash Professional IDE. there are several other tweening engines you can look around for, but some of them can carry licensing fees (IE: TweenLite)

so, if you were using Tweener, you would simply import some of the classes:

import caurina.transitions.Equations;
import caurina.transitions.Tweener;

then then tween the rotation like this:

trace("Food below fish")
Tweener.addTween(this, {time: 0.25, transition: Equations.easeInOutCubic, rotation: 180});

read thru the Tweener documentation (it's really short). you'll probably end up using it a lot if you haven't heard about it before.

Upvotes: 0

Related Questions