Home Tutorials Download Beta Store Forum Documentation KnowledgeBase Wiki Blog

ShiVa3D

Return to Game programming

Animations transitions issue ?  [SOLVED]

All about the StoneScript

Animations transitions issue ?

Postby etXtra » 26 Jun 2012, 23:39

Hi, I don't understand how to use "animation.setPlaybackLevel" and any of animation functions: all I did is a "hack" with the simple animation sample provided... Finally I can play the animation clip I want: that's OK....
BUT, I can't get smooth transitions betweenn 2 consecutive different animations. I guess I have to blend animations together .... ???

So here is my "hack": (see attachement)

use the arrowkeys to change animation.
open the main IA : "main"

Code: Select all
function main.onEnterFrame (  )
--------------------------------------------------------------------------------
   
   --
   -- Write your code here, using 'this' as current AI instance.
   -- This handler is called every frame.
    hOtherObject = application.getCurrentUserSceneTaggedObject ( "moi" )
    object.matchTranslation ( application.getCurrentUserActiveCamera ( ), hOtherObject, object.kGlobalSpace )
    object.setRotation ( application.getCurrentUserActiveCamera ( ), 0.0, 0.8, 0.0, object.kLocalSpace )
    object.setTranslation ( application.getCurrentUserActiveCamera ( ), 0.0, 2.0, 7.0, object.kLocalSpace )
   
    --animation.setPlaybackLevel ( hOtherObject, 0, 1 )
    --animation.setPlaybackLevel ( hOtherObject, 0, 1 - 0.01 )
    --animation.setPlaybackLevel ( hOtherObject, 1,     0.01 )
   
    if ( this.anim ( ) == 0 )
    then
        animation.setCurrentClip ( hOtherObject, 0, 0 )
    end
   --
   if ( this.anim ( ) == 1 )
    then
        animation.setCurrentClip ( hOtherObject, 0, 1 )
    end
   --
    if ( this.anim ( ) == 2 )
    then
        animation.setCurrentClip ( hOtherObject, 0, 2 )
    end
   --
    if ( this.anim ( ) == 3 )
    then
        animation.setCurrentClip ( hOtherObject, 0, 3 )
    end
   --

   
    if ( object.hasController ( hOtherObject, object.kControllerTypeAnimation ) )
    then
        local cur = this.nCurFactor ( )
        local dst = this.nDstFactor ( )
       
        if ( cur ~= dst )
        then
            local dt = application.getLastFrameTime ( )
           
            if ( dst > cur )
            then cur = math.min ( cur + dt, 1 )
            else cur = math.max ( cur - dt, 0 )
            end
           
            this.nCurFactor ( cur )
           
            animation.setPlaybackLevel ( hOtherObject, 0, 1 - cur )
            animation.setPlaybackLevel ( hOtherObject, 1,     cur )
        end
    end
--------------------------------------------------------------------------------
end
--------------------------------------------------------------------------------


and:

Code: Select all
--------------------------------------------------------------------------------
function main.onKeyboardKeyUp ( kKeyCode )
--------------------------------------------------------------------------------
   
   --
   -- Write your code here, using 'this' as current AI instance.
   -- This handler is called when a keyboard key is released.
    if ( kKeyCode == input.kKeyUp )
    then
        if ( this.anim ( ) == 1 )
        then
            this.nDstFactor ( 0 )
        else
            -- this.nDstFactor ( 1 )
        end
        --
        this.anim ( 0.0 )
    end
   --
    --
   if ( kKeyCode == input.kKeyRight )
    then
        if ( this.anim ( ) == 0 )
        then
            this.nDstFactor ( 1 )
        else
            --this.nDstFactor ( 0 )
        end
        --
        this.anim ( 1 )
        --this.nDstFactor ( 1 )
    end
    --
   if ( kKeyCode == input.kKeyDown )
    then
        this.anim ( 2 )
        --this.nDstFactor ( 2 )
    end
   --
    --
   if ( kKeyCode == input.kKeyLeft )
    then
        this.anim ( 3 )
        --this.nDstFactor ( 3 )
    end
--------------------------------------------------------------------------------
end
--------------------------------------------------------------------------------

Please help me,
- Regards -
etXtra
Junior Boarder
Junior Boarder
 
Posts: 39

Re: Animations transitions issue ?

Postby broozar » 27 Jun 2012, 10:09

every animation you want to blend should be on its own blend layer. right now, you are assigning all animations to blend layer 0.

but, to make the "hack" work, you are limited to blend layers 0 and 1. you should dynamically assign the new clip you want to blend into to the currently unused blend layer (0 if 1 is in use, 1 if 0 is in use).
User avatar
broozar
Platinum Boarder
Platinum Boarder
 
Posts: 3337
Location: Berlin - Germany

Re: Animations transitions issue ?

Postby etXtra » 27 Jun 2012, 13:19

Hi, I've tried to understand the function without success,

But I did some little progress/changes :
Code: Select all
--------------------------------------------------------------------------------
function main.onKeyboardKeyUp ( kKeyCode )
--------------------------------------------------------------------------------
   
   --
   -- Write your code here, using 'this' as current AI instance.
   -- This handler is called when a keyboard key is released.
    hObject = application.getCurrentUserSceneTaggedObject ( "moi" )
   
    if ( kKeyCode == input.kKeyUp )
    then
        if ( this.anim ( ) == 1 )
        then
            this.nDstFactor ( 0 )
            animation.setCurrentClip ( hObject, 0, 0 )
        end
        --
        if ( this.anim ( ) == 2 )
        then
            this.nDstFactor ( 0 )
            animation.setCurrentClip ( hObject, 0, 0 )
        end
        --
        this.anim ( 0 )
    end
--
    --
   if ( kKeyCode == input.kKeyRight )
    then
        if ( this.anim ( ) == 0 )
        then
            this.nDstFactor ( 1 )
            animation.setCurrentClip ( hObject, 1, 2 )
        end
        --
        this.anim ( 1 )
    end
    --
   if ( kKeyCode == input.kKeyDown )
    then
        if ( this.anim ( ) == 0 )
        then
            this.nDstFactor ( 2 )
            animation.setCurrentClip ( hObject, 1, 3 )
        end
        --
        if ( this.anim ( ) == 1 )
        then
            this.nDstFactor ( 2 )
-- ****************** HERE IS THE PROBLEM: WHAT SHOULD I WRITE TO GET TRANSITION WORKING HERE (below) ??? ******************
            animation.setCurrentClip ( hObject, 1, 2 )
            animation.setCurrentClip ( hObject, 1, 3 )
-- ********** INFORTUNATELY THE ABOVE DOESN'T WORKS, NEED HELP... ***********
        end
        this.anim ( 2 )
    end
   --
    --
   if ( kKeyCode == input.kKeyLeft )
    then
        --this.anim ( 3 )
        --this.nDstFactor ( 3 )
    end
--------------------------------------------------------------------------------
end
--------------------------------------------------------------------------------


So to explain: I've 3 AnimClips : A, B , C
starts with A.
transition from A to B and from B to A works ok, now
transition from A to C and "vice-versa" works ok...

BUT transition from B to C don't work nor C to B !!!!
I believe I've tried anything I could !!!
PLease where is the solution ??? please help me !!!

- Regards -
etXtra
Junior Boarder
Junior Boarder
 
Posts: 39

Re: Animations transitions issue ?  [SOLVED]

Postby DoctorPepper » 28 Jun 2012, 20:27

Actually, it will take a bit more than 1 functions to write this.
I suggest rewriting everything from ground up. Not only will it give you full control of your code, animation is one of those basics that you have to master to write games.

So, lets start thinking rationally. If you just use 1 bled layer (you can call it animation channel), it will be like making a cartoon with each time a completely different drawing. What we want to draw, is a series of drawings with a smooth transition, each time having a slight iteration of the image going towards a different drawing. Also note that a human eye requires at least 23 drawings every second, to make it seem like a 1 fluent motion.

You will need 3 global variables.
1. memory for increasing nLevel (indexLevel)
2. index of the new clip (indexClip)
3. Current Layer index (indexLayer)
But its not efficient to make those ahead of time. What you want is to add globals when you actually need them

Lets imagine that you are making a football game. And some function will start working when a player receives the ball. Let call it onReceive. So its probably a good time to switch the animation to "Receive_Ball" which is also known in the animation bank as a Clip with index 99.
Good time to create an AI for handling animations. Lets name it AI_Animation. Assign it to the player. There, create a handle onSwitchAnimation. Its only logical that this function receives the index of the new animation, so add a parameter: para_animation

Go back to onReceive and write object.sendEvent( playerObject,"AI_Animation", "onSwitchAnimation", 99 ) . 99 because we know that its the index of Receive_Ball animation clip.

Back to onSwitchAnimation. We know that at some point it will receive a parameter para_animation. in our case it will be index 99. This is a good point to review animation.setPlaybackLevel ( hObject, nBlendLayer, nLevel ). Object is your playerObject, blend layer (or animation channel) is 0 or 1 and your nLevel will be between 0 and 1 (from 0% to 100%). What we want to do now is to detect what layer is running atm and then assign the new animation to the other one and raise nLevel from 0% to 100% at least 23 times.

But you probably want to keep it simple at first. I assume that there is some init function that will be playing initial "stand" animation with clip index 1 on the 0 layer, 100%. So those line were already ran somewhere:
animation.setCurrentClip ( playerObject, layer=0, clip=1 )
animation.setPlaybackLevel ( playerObject, layer=0, nLevel=1)

If onSwitchAnimation was ran only 1 time, we know that current layer is 0 running at 100% so we can write.

animation.setCurrentClip ( playerObject, layer=1, clip=para_animation )
animation.setPlaybackLevel ( playerObject, layer=1, nLevel= 0 )

Here is your first problem. layer 0 is at 100% layer 1 is at 0%. We want nLevel of layer 0 to decrease and layer 1 increase at least 23 times a second, 46 times/sec total. So we need something that will ran for a few second, increasing some variable from 0,00 to 1,00. This value should probably be stored as a global variable, lets name it "indexLevel" with type integer. Initial value 0. You want to make sure that its value is always 0 when you switch an animation so write this.indexLevel(0); Also create a global variable indexClip to save your clip parameter (ours is 99). just as indexLevel add it to onSwitchAnimation as: this.indexClip(para_animation). It might be also a good idea to save the index of the new layer. Make a global variable indexLayer. Back in the function give it value 1, as 0 was the old one.

Personally i prefer states doing a job overtime, instead of onEachFrame, as they dont need to run when you are dont with the loop. so make an idle initial state and a state "state_SwitchAnimation". Lets keep it simple, and just increase this.nLevel 100 times from 0 to 1.

this.indexLevel(this.indexLevel + 0.01)
if this.indexlevel is 1 then go back to the idle state

Fairly simple up till now. But now we actually want to increase nLevel or layer 1 (indexLayer)

animation.setPlaybackLevel ( playerObject, layer=indexLayer, nLevel=indexLevel)

so as decrease the nLevel of layer one. A logical trick to write the oposite of the indexLayer would math.abs(indexLayer - 1). ( 0-1=-1 absolute value is 1; 1-1=0 absolute value is 0)

animation.setPlaybackLevel ( playerObject, layer=math.abs(indexLayer - 1), nLevel=1-indexLevel)

1-indexLevel because we actually want to count down from 100% to 0

back to onSwitchAnimation. You probably want to run the switch state. Also replace the code where it says layer=1 by the opposite of the current level before switching to a new one.
In your switch state. add frametime dt to make the transition frame independent.

Sorry for not writing out the full code, but this should give you a good idea of the basic thought process.
User avatar
DoctorPepper
Platinum Boarder
Platinum Boarder
 
Posts: 469
Location: Belgium

SOLVED !!: Animations transitions issue ?

Postby etXtra » 29 Jun 2012, 23:17

Your message really helped me !!!

I did as you said (though I had to create some additional variables that you 'forgot')

not only it Works perfectly and easily but the best is that I understand this functionality, now !!

thank you so much !! animations blends correctly now !!!

- Cheers - :D
etXtra
Junior Boarder
Junior Boarder
 
Posts: 39

Re: Animations transitions issue ?

Postby DoctorPepper » 30 Jun 2012, 00:45

Great man. Was a bit afraid thats its too vague. But im glad that i could help out. Shivas biggest problem is lack of documentation. Would be neat if ppl could fill the gaps
User avatar
DoctorPepper
Platinum Boarder
Platinum Boarder
 
Posts: 469
Location: Belgium

Re: Animations transitions issue ?

Postby DoctorPepper » 17 Jul 2012, 13:56

Alrighty, recently wrote one of those myself. Variable naming are a bit different from above described.

Variables:
Code: Select all
   indexClip
   indexDuration
   indexLayer
   indexLevel


states:
idle (empty)
switchAni - onLoop()
Code: Select all
    local L = this.indexLevel ( )
    local o = this.getObject ( )
    local dT = application.getLastFrameTime ( )
    local dur = this.indexDuration ( )
    local layer = this.indexLayer ( )
    local BGlayer = math.abs ( layer - 1 )
   
    L = L + dT/dur
    this.indexLevel ( L )
   
    log.message ( L)
    animation.setPlaybackLevel ( o, BGlayer, L)
    if(L > 1)
    then
        this.idle ( )
    end


Handlers:

onInit()
Code: Select all
    -- Animations:
    -- 0. Stand
    -- 1. Walk
    -- 2. Jump
    local o = this.getObject ( )
    animation.setCurrentClip ( o, 0, 0 )
    animation.setPlaybackLevel ( o, 0, 1 )
    animation.setPlaybackMode ( o, 0, animation.kPlaybackModeLoop )
    animation.setPlaybackIgnoreIfCursorOutOfRange ( o, 0, false )


onChangeAnimation (clip,duration,loop)
Parameters:
clip = index of the animation
duration = duration of the animation transition
loop = boolean check for looping animation
Code: Select all
    local o = this.getObject ( )
    local l = math.abs ( this.indexLayer ( ) - 1 )
   
    animation.setCurrentClip ( o,l,clip )
    animation.setPlaybackLevel ( o,l,0 )
    animation.setPlaybackIgnoreIfCursorOutOfRange ( o, l, loop )
   
    this.indexLevel ( 0 )
    this.switchAni ( )
    this.indexDuration ( duration )


in my case, i can switch animations (lets say walking animation) by simply calling
Code: Select all
object.sendEvent ( this.getObject(),"AI_CharAnimation","onChangeAnimation",1,0.3,true )
User avatar
DoctorPepper
Platinum Boarder
Platinum Boarder
 
Posts: 469
Location: Belgium

Re: Animations transitions issue ?

Postby etXtra » 05 Aug 2012, 15:34

ok, thank you so much !! now I think I understand better. I will update my script with your example.
etXtra
Junior Boarder
Junior Boarder
 
Posts: 39


Return to Game programming