animating mutliple things at the same time

Started by daniel, Mon 15/05/2017 19:32:48

Previous topic - Next topic

daniel

hi,

i'm trying to animate my 2-part logo on the title screen.

what i'd like to do is:
1. fade in the BG from black. (i'm using a black object and fade it to 100% transparency because i couldn't get the FadeIn and FadeOut to work without the BG flashing on the screen for a second at the start)
2. fade in the main logo
3. once the main logo is at 50% transparency start fading in the second part of the logo while it's moving down into position along Y

when i put this code into function room_RepExec() it just executes one command after the another:

Code: ags
int BlackoutTrans = oBlackout.Transparency;
int LogoTrans = oLogo.Transparency;
int LogoExtraTrans = oLogoExtra.Transparency;

  while (BlackoutTrans < 100){
    BlackoutTrans++;
    oBlackout.Transparency = BlackoutTrans;
    Wait(1);
  }
    
  while ((BlackoutTrans == 100)&&(LogoTrans > 0)){
    LogoTrans--;
    oLogo.Transparency = LogoTrans;
    Wait(1);
  }
  
  while ((LogoTrans < 50)&&(LogoExtraTrans > 0)){
    LogoExtraTrans--;
    oLogoExtra.Transparency = LogoExtraTrans;
    Wait(1);
  }
  
  while ((LogoTrans < 50)&&(oLogoExtra.Y < 30)){
    oLogoExtra.Y++;
    Wait(1);
  }


how can i execute all of these at the same time without them blocking each other?
when i use "if" instead of "when" the script stops after the blackout is at 100% transparency.
so, once again my noob skills have failed me...

cheers

dayowlron

Basically what you need to do is have one loop with conditions to determine at what part of the animation your at.
I am not sure of what you wanting specifically but I can code something up for you if you like. You also don't need variables to contain the transparency as that is a property of the object anyways.
For instance:
Code: ags

int BlackoutTrans=oBlackout.Transparency;
BlackoutTrans++;
oBlackout.Transparency = BlackoutTrans;

is the same as
Code: ags

oBlackout.Transparency ++;
Pro is the opposite of Con                       Kids of today are so much different
This fact can clearly be seen,                  Don't you know?
If progress means to move forward         Just ask them where they are from
Then what does congress mean?             And they tell you where you can go.  --Nipsey Russell

dayowlron

Try this:
Code: ags

    while (oLogoExtra.Transparency>0) {
        if (oBlackout.Transparency<100) oBlackout.Transparency++;
        if (oLogo.Transparency>0) oLogo.Transparency--;
        if (oLogo.Transparency<50) {
            oLogoExtra.Transparency--;
            if (oLogoExtra.Y<30) oLogoExtra.Y ++;
        }
        wait(1);
    }
Pro is the opposite of Con                       Kids of today are so much different
This fact can clearly be seen,                  Don't you know?
If progress means to move forward         Just ask them where they are from
Then what does congress mean?             And they tell you where you can go.  --Nipsey Russell

abstauber

Also for this kind of stuff, try the Tween Module. It makes your life considerably easier and also handles transparency transitions.

Khris

IIRC, changing the transparency directly wasn't reliable for some reason; the preferred method is to change a variable, then set the transparency to that.

With that out of the way, the idea is to basically plan a timeline.
Frames
0-------------------100---------150---------200-----------250--------->
|<- fade out black ->|
                     |<- fade in LogoTrans ->|
                                  | <- fade in LogoExtra ->|
We end up with this:

Code: ags
int clamp(int a) {
  if (a < 0) return 0;
  if (a > 100) return 100;
  return a;
}

int frames = 0;
function room_RepExec() {
  oBlackout.Transparency = clamp(frames); // 0 -> 100, starting @ frame 0
  oLogo.Transparency = clamp(200 - frames); // 100 -> 0, starting @ frame 100
  oLogoExtra.Transparency = clamp(250 - frames); // 100 -> 0, starting @ frame 150
  if (frames < 400) frames++;
}

Snarky

Quote from: abstauber on Mon 15/05/2017 20:45:36
Also for this kind of stuff, try the Tween Module. It makes your life considerably easier and also handles transparency transitions.

So much this!

Code: ags
function room_AfterFadein()
{
  oBlackout.TweenFadeOut(2.5);  // Fade to transparent over 2.5 seconds = 100 cycles

  oLogo.TweenFadeIn(2.5, eEaseLinearTween, eNoBlockTween);          // Non-blocking, so run the next tween in parallel
  oLogoExtraTweenFadeIn(2.5, eEaseLinearTween, eBlockTween, 1.25);  // Delay start of tween by 1.25 seconds = 50 cycles
}

daniel

#6
thanks guys,

@dayowlron
i tried your solution and the result is similar to what i get if i just used "if" statements...the BG fades in and then nothing more happens

@Khris
your solution works, however it's still missing the downward movement for "oLogoExtra" from 0 to 30 along the Y axis...also it seems to me it's very tricky to adjust animation speed for each element using this method?

@abstauber
thanks for the recommendation. i'm gonna take a look at that module...it sounds pretty neat.

EDIT:
got it. thanks for the code snarky.
i just added this to tween the logoExtra along the Y...also had to set the fadeIn to noBlock
Code: ags
oLogoExtra.TweenY(2.5, 30, eEaseInOutSineTween, eNoBlockTween, 1.25);

daniel

hey guys,

i've hit another snag and this question is kind of related so i'll just post it here and hope somebody will find it:D

anyway i have multiple animations in a background that i would like to tween (TweenImage) in order to make them look smoother.
however since these are endless loops i tried placing them in "function room_RepExec()" like this:

Code: ags

  oGlitter.TweenImage(oGlitterEmpty, 0.5, 377, eEaseLinearTween, eBlockTween); 
  oGlitter.TweenImage(oGlitterEmpty, 0.5, 378, eEaseLinearTween, eBlockTween);
  oGlitter.TweenImage(oGlitterEmpty, 0.5, 379, eEaseLinearTween, eBlockTween);
  oGlitter.TweenImage(oGlitterEmpty, 0.5, 376, eEaseLinearTween, eBlockTween);

  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 383, eEaseLinearTween, eBlockTween);
  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 384, eEaseLinearTween, eBlockTween);
  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 385, eEaseLinearTween, eBlockTween);
  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 386, eEaseLinearTween, eBlockTween);
  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 387, eEaseLinearTween, eBlockTween);
  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 388, eEaseLinearTween, eBlockTween);
  oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 382, eEaseLinearTween, eBlockTween);


which of course doesn't work since one animation is blocking the other and they run in sequence instead of simultaneously.
i tried using "eNoBlockTween" with delays set for each tween and somehow setting a variable to check if a tween is playing but failed completely.
i also tried setting it up outside of "function room_RepExec()" using tween delays and a timer...couldn't get that to work either:(

any ideas?

Cassiebsg

I'm not familiar with the tween module this much, but have you tried to set all tweens but the last to NoBlock? Usually works for normal animations, so maybe it'll work with the tween too?
There are those who believe that life here began out there...

daniel

Quote from: Cassiebsg on Wed 17/05/2017 18:29:19
I'm not familiar with the tween module this much, but have you tried to set all tweens but the last to NoBlock? Usually works for normal animations, so maybe it'll work with the tween too?

thanks cassiebsg,

yes i've tried that and it doesn't work unfortunately. i'm a total noob myself but i think the problem is that, if there is no block or some kind of variable that switches the tweens on and off the RepExec just keeps spawning new tweens every frame. so basically you don't see anything happening because none of the tweens (other than the ones with the block set) are ever executed before the next one gets thrown on top.
also the game then crashes because it's exceeding the 64 tweens limit...

Cassiebsg

Are you running these inside an if?
You need to, to avoid them being run from the start every loop.  :-\

You need to tell AGS to only run the code IF it's not running, otherwise ignore it.
There are those who believe that life here began out there...

Khris

#11
You need to keep track of the game state (here: your objects' sprites) using variables. Then you need to think about how and when to advance the state.
And you cannot use a blocking command for background animations, ever.

The idea here is to either set timers or count frames, then advance the object(s) to the next sprite.

Code: ags
int glitterFrame = 0, smokeFrame = 0;

function room_RepExec() {
  if (IsTimerExpired(1)) {
    glitterFrame = (glitterFrame + 1) % 4; // 0 - 3
    smokeFrame = (smokeFrame + 1) % 7; // 0 - 6
    oGlitter.TweenImage(oGlitterEmpty, 0.5, 376 + glitterFrame, eEaseLinearTween, eNoBlockTween); 
    oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 382 + smokeFrame, eEaseLinearTween, eNoBlockTween);
    SetTimer(1, GetGameSpeed() / 2); // half a second to next frame
  }
}


Start the animations by calling SetTimer(1, 1); in after fadein.

It's also possible to change this code to use a specific view loop; that way you can simply set the sprites in the view editor without having to worry about the number of frames or their sequence.

daniel

thanks chris,

i'll give this a try as soon as i get the time...

i hate to be a bother but could you explain to me briefly what the "%" remainder does in the code?
i looked in the AGS help but didn't find anything...

Snarky

#13
% is the modulo operator, which gives you the remainder of an integer division: the part of the first number that can't be divided by the second number. So 7 % 3 = 1, because 7/3 = 2 (in integer division â€" meaning you can only fit 3 two times in seven), with a remainder of 1 (because 2*3 = 6 and 7-6 = 1).

Another way to think about it is that the remainder is the fractional part of the division. So if the integer division 7/3=2 gives you the integer part of the answer, 7%3=1 gives you the fractional part: put them together, and you get 7/3 = 2 + 1/3.

The cool thing about the modulo is that taking a number % N leaves you with a remainder that is guaranteed to be between 0 and N-1. For example, consider modulo 10:

0 % 10 = 0 (0 / 10 = 0 with a remainder of 0)
1 % 10 = 1 (1 / 10 = 0 with a remainder of 1)
...
9 % 10 = 9
10 % 10 = 0 (because 10/10 = 1 with no remainder)
11 % 10 = 1
...
19 % 10 = 9
20 % 10 = 0
21 % 10 = 1
...

A number modulo 10, then, is just the last digit of that number, cycling 0-9 for ever. Similarly, taking the number sequence modulo 8 will give you a repeating 0-7 cycle. This is a very useful property for making loops.

daniel

thanks snarky!
i'm not 100% sure i understood the maths behind it but at least now i know what it does:)

Snarky

#15
OK, let's put it like this: Let's say you have 23 comic books that you want to give away to four cousins. They can't share, and if they don't all get exactly the same number they'll fight.

Q1: How many comics does each cousin get?
This is integer division, and the answer is five. (You have enough to give each cousin five comics each, but not enough to give them each six.)
23/4 = 5

Q2: How many comics are you left with?
This is the remainder, and in this case the answer is three, because if you give four cousins five comics each, you've given away 20 and are left with 3.
23%4 = 3

The number of comics you're left with will always be between 0 and 3, because if you were left with 4 comics or more you could just give them each another one.

Make sense?

Khris

You can also visualize it using a table. Here's the table for % 4:
 0  1  2  3
 4  5  6  7
 8  9 10 11
12 13 14 15
16 17 18 19
20 21 ...
Pick any number x, and x % 4 results in the first row's number of the same column.

daniel

thanks guys, i think i got it now
i've always been more of a "right hemisphere of the brain" kind of guy:D

Snarky

Khris's table also leads to another way to think of it: if you have a wheel with N number of spaces (e.g. wheel of fortune, roulette, combination safe), which we'll label sequentially from 0 to N-1, and you spin it X spaces, what space do you land on? For example, if the wheel has 9 spaces and you spin it 47 spaces (starting from 0), where do you land? That's the remainder or modulo, X%N. (47%9 = 2)

It's equivalent because what remains of 47 spaces after you've taken away all the full revolutions of the wheel that put you back where you started (multiples of 9, with the largest multiple being 5*9=45) is 2.

daniel

#19
hey guys,

so i just put in the code and thought i'd report back with the results.

it works fine but for some reason only in "repeatedly_execute_always()"...? when i put it in "room_RepExec()" nothing happened.
i also had to adjust the timer setting. it seems there's some weirdness going on with the tweenImage timing...when it's set to 0.5 it actually takes a second to complete the tween.
maybe the timing is on a "per image" basis? which doesn't really make sense since both images tween at the same time...oh well:D

anyway here's what i'm using now and it looks nice

Code: ags
unction repeatedly_execute_always()
{  
  if (IsTimerExpired(GlitterTimer)){
    glitterFrame = (glitterFrame + 1) % 4;
    oGlitter.TweenImage(oGlitterEmpty, 0.25, 376 + glitterFrame, eEaseLinearTween, eNoBlockTween);
    SetTimer(GlitterTimer, GetGameSpeed()/2);
  }
  if (IsTimerExpired(SmokeTimer)){
    smokeFrame = (smokeFrame + 1) % 7;
    oChimneySmoke.TweenImage(oSmokeEmpty, 0.5, 382 + smokeFrame, eEaseLinearTween, eNoBlockTween);
    SetTimer(SmokeTimer, GetGameSpeed());
  }
}


thanks again for your help!

SMF spam blocked by CleanTalk