Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Knox on Mon 13/09/2010 01:28:23

Title: How do I add speed for blink frames to this script? **SOLVED**
Post by: Knox on Mon 13/09/2010 01:28:23
Hi,

I modified the guiPortrait module a bit and I was wondering if someone had an idea on how to add the speed for blink frames...right now this is ignored, so if I place a delay of 40 on a certain blink frame, the animation ignores it completly. SSH is currently too busy to help me out with this so Ive been trying on my own for a while now...and well...I suck! heheh

I think I have to do something with the ".Speed" command, but Im not too sure how to implement it. To test, if I remove the "Portrait_vf.Speed" part in these lines: Portrait_Counter = (Portrait_AnimSpeed + Portrait_vf.Speed + 1);, the script no longer takes into account  the delays in the speech views either, so I believe somehow I need to do something like that, but for the blinking (which I really dont know how to proceed, Ive been trying all night... :-[)


function Portrait_DoFrame()
{
 Portrait_vf = Game.GetViewFrame(Portrait_View, Portrait_Loop, Portrait_Frame);
 bool flip = Portrait_vf.Flipped;
 // Something like:
 if (Portrait_AutoFlip && Portrait_AtRight) flip =! flip;
 Portrait_Mod = DynamicSprite.CreateFromExistingSprite(Portrait_vf.Graphic, true);
 if (Portrait_BlinkTimer == 0)
 {
   DrawingSurface *mod = Portrait_Mod.GetDrawingSurface();
   Portrait_bvf = Game.GetViewFrame(Portrait_BlinkView, Portrait_BlinkLoop, Portrait_BlinkFrame);
     
   mod.DrawImage(0, 0, Portrait_bvf.Graphic);
   mod.Release();

   Portrait_BlinkFrame++;
   if (Portrait_BlinkFrame == Game.GetFrameCountForLoop(Portrait_BlinkView, Portrait_BlinkLoop))
   {
     Portrait_BlinkTimer = Portrait_BlinkInterval;
     Portrait_BlinkFrame = 0;
   }
 }
 // Flip AFTER blink, if required
 if (flip) Portrait_Mod.Flip(eFlipLeftToRight);
 Portrait_GUI.BackgroundGraphic = Portrait_Mod.Graphic;
}

function repeatedly_execute_always()
{
 if (Portrait_Counter == 0)
 {
   Portrait_Frame++;
   if (Portrait_Frame == Game.GetFrameCountForLoop(Portrait_View, Portrait_Loop)) Portrait_Frame = 0;
   Portrait_DoFrame();
   Portrait_Counter = (Portrait_AnimSpeed + Portrait_vf.Speed + 1);
 }
 else if (Portrait_Counter >= 0) Portrait_Counter--;
 if (Portrait_BlinkTimer > 0) Portrait_BlinkTimer--;  
}

// TBD: Animate
// Check for flipped frames
// Blinking: goes on top of speech view
 
function GSay(this Character*, String what, int view, int loop)
{
 if (view < 1) view = this.SpeechView;
 Portrait_Frame = 0;
 Portrait_Loop = loop;
 Portrait_View = view;
 Portrait_AnimSpeed = this.SpeechAnimationDelay;
 int positioning = GetGameOption(OPT_PORTRAITPOSITION);
 int x;
 //Left
 if (positioning == 0) Portrait_AtRight = false;
 //Right
 else if (positioning == 1) Portrait_AtRight = true;
//Alternate
 else if (positioning == 2)
 {
   if (this != Portrait_Last_Talker) Portrait_AtRight =! Portrait_AtRight;
 }
 // Based on Character Position Relation to the Main Player
 else
 {
   if (this == player)
   {
     player.SetupCharacterPortrait(playerFaceAnim, playerClothes, playerProp);
     if (BasePortrait_BASE.BackgroundGraphic != 372) BasePortrait_BASE.BackgroundGraphic = 372;      
     if (this.x <= partner.x) Portrait_AtRight = false;
     else if (this.x > partner.x) Portrait_AtRight = true;
   }
   else if (this == partner)
   {
     //Display("Partner's Clothes being st to: %d", partnerClothes);
     partner.SetupCharacterPortrait(partnerFaceAnim, partnerClothes, partnerProp);
     if (partner == cDispatcherA) BasePortrait_BASE.BackgroundGraphic = 1105;
     else if (BasePortrait_BASE.BackgroundGraphic != 372) BasePortrait_BASE.BackgroundGraphic = 372;
     
     if (this.x >= player.x) Portrait_AtRight = true;
     else if (this.x < player.x)Portrait_AtRight = false;
   }  
 }
 Portrait_DoFrame();
 if (Portrait_AtRight == true)
 {
   x = (System.ViewportWidth - Game.SpriteWidth[Portrait_vf.Graphic] - Portrait_Right_Indent);
   BasePortrait_FRAME.X = x;
   if (this == player)
   {
     BasePortrait_PLAYERCLOTHES.X = x;
     BasePortrait_PLAYERPROPS.X = x;
   }
   else if (this == partner)
   {
     BasePortrait_PARTNERCLOTHES.X = x;
     BasePortrait_PARTNERPROPS.X = x;      
   }
 }
 else if (Portrait_AtRight == false)
 {
   x = Portrait_Left_Indent;
   BasePortrait_FRAME.X = Portrait_Left_Indent;
   if (this == player)
   {
     BasePortrait_PLAYERCLOTHES.X = Portrait_Left_Indent;
     BasePortrait_PLAYERPROPS.X = Portrait_Left_Indent;
   }
   else if (this == partner)
   {
     BasePortrait_PARTNERCLOTHES.X = Portrait_Left_Indent;
     BasePortrait_PARTNERPROPS.X = Portrait_Left_Indent;      
   }
 }

 Portrait_GUI.X = x;
 Portrait_GUI.Y = Portrait_Sierra_Y;
 BasePortrait_BASE.X = x; //ACL MODIFICATIONS
 BasePortrait_BASE.Y = Portrait_Sierra_Y; //ACL MODIFICATIONS
 SetGameOption(OPT_PORTRAITPOSITION, Portrait_AtRight);
 BasePortrait_BASE.Visible = true;
 if(BasePortrait_BASE.BackgroundGraphic == 1105 )
 {
   BasePortrait_BASE.LockView(19);
   BasePortrait_BASE.Animate(0, 5, eRepeat, eNoBlock);
 }
 else BasePortrait_BASE.UnlockView(false);
 BasePortrait_FRAME.Visible = true;
 if (this == player)
 {
   BasePortrait_PLAYERCLOTHES.Visible = true;
   BasePortrait_PLAYERPROPS.Visible = true;
 }
 else if (this == partner)
 {
   BasePortrait_PARTNERCLOTHES.Visible = true;
   BasePortrait_PARTNERPROPS.Visible = true;    
 }
 Portrait_GUI.Visible = true;
 Portrait_Counter = (Portrait_AnimSpeed + Portrait_vf.Speed + 1);
 if (this.BlinkView > 0)
 {
   Portrait_BlinkTimer = this.BlinkInterval;
   Portrait_BlinkInterval = this.BlinkInterval;
   Portrait_BlinkView = this.BlinkView;
   Portrait_BlinkLoop = 0;
   Portrait_BlinkFrame = 0;
 }
 else Portrait_BlinkTimer = -1;
 this.Say(what);
 BasePortrait_BASE.Visible = false;
 BasePortrait_FRAME.Visible = false;
 if (this == player)
 {
   BasePortrait_PLAYERCLOTHES.Visible = false;
   BasePortrait_PLAYERPROPS.Visible = false;
 }
 else if (this == partner)
 {
   BasePortrait_PARTNERCLOTHES.Visible = false;
   BasePortrait_PARTNERPROPS.Visible = false;    
 }
 Portrait_GUI.Visible = false;
 SetGameOption(OPT_PORTRAITPOSITION, positioning);
 Portrait_Counter = -1;
 Portrait_BlinkTimer = -1;
 player.SetupCharacterPortrait(playerFaceAnim, playerClothes, playerProp);
}
Title: Re: How do I add speed for blink frames to this script?
Post by: Khris on Mon 13/09/2010 09:43:56
In rep_ex_always, Portrait_BlinkTimer is decreased by one every loop unless it is 0.

In DoFrame, look at these lines:

    Portrait_BlinkFrame++;
    if (Portrait_BlinkFrame == Game.GetFrameCountForLoop(Portrait_BlinkView, Portrait_BlinkLoop))
    {
      Portrait_BlinkTimer = Portrait_BlinkInterval;
      Portrait_BlinkFrame = 0;
    }


So what's done here is every time a new frame of the speech animation is drawn, IF BlinkTimer has already reached 0 by then, the blinking animation is advanced a frame. The blinking timer is then reset to Portrait_BlinkInterval IF the animation has reached its last frame, which is frame 1 of a total of 2, I guess the module assumes.

Try this:
    Portrait_BlinkFrame++;
    if (Portrait_BlinkFrame == Game.GetFrameCountForLoop(Portrait_BlinkView, Portrait_BlinkLoop))
    {
      Portrait_BlinkTimer = Portrait_BlinkInterval;
      Portrait_BlinkFrame = 0;
    }
    else {
      ViewFrame*v = Game.GetViewFrame(Portrait_BlinkView, Portrait_BlinkLoop, Portrait_BlinkFrame);
      Portrait_BlinkTimer = v.Speed;
    }
Title: Re: How do I add speed for blink frames to this script?
Post by: Knox on Mon 13/09/2010 18:14:26
Hey Khris!

Ok, well I tried that and it works, but partially (but I most prob did something wrong somewhere).

It now seems to take into account the delays, but it also seems to "reset" the loop after a few frames only  depending on what the character says...it seems that the full loop doesnt have time to display itself fully...so instead of getting 14 frames of animation in loop 0, it seems only the first few frames get animated. They have delays of 40 frames each, approx.

Does it have something to do with modifying these lines in the function GSay to get it to work (Portrait_BlinkTimer here should contain the .Speed too?)

 if (this.BlinkView > 0)
 {
   Portrait_BlinkTimer = this.BlinkInterval;
   Portrait_BlinkInterval = this.BlinkInterval;  
   Portrait_BlinkView = this.BlinkView;
   Portrait_BlinkLoop = 0;
   Portrait_BlinkFrame = 0;
 }
 else Portrait_BlinkTimer = -1;



Quoteanimation has reached its last frame, which is frame 1 of a total of 2, I guess the module assumes.

--can we add a script where it wont assume 2 frames, but gets the real number of frames the blink loop actually contains?
Title: Re: How do I add speed for blink frames to this script?
Post by: Khris on Mon 13/09/2010 22:40:18
Well, the original script did that (get the actual number of frames), it just skipped the rest of the frames because it left BlinkTimer having a value of 0.
My small change is supposed to change that so that the complete loop is shown.

I don't see with that code how the length of the text would influence how much of the blink loop is displayed (except when the text is very short, of course).

The only thing I can think of is you assumed a base speed although I didn't implement one and left some frame speeds set to 0.
Title: Re: How do I add speed for blink frames to this script?
Post by: Knox on Tue 14/09/2010 00:30:29
crap I retested with the added code and 1 frame with a delay of 120 (to debug) and it doesnt take into account that delay.

So, crap...sorry, actually it doesnt fix the prob!  :-[
Title: Re: How do I add speed for blink frames to this script?
Post by: Khris on Tue 14/09/2010 01:00:29
The least complicated way to solve this is to simply separate the talk animation completely from the blinking animation. This requires rewriting Portrait_DoFrame() and repeatedly_execute_always() a bit.
I guess it's best to put the eye part of the sprite on a button as big as the GUI to avoid messing about with composing DynamicSprites.
You basically just need to duplicate the code for the speech animation but use the blinking view and the button instead of the talking view and the GUI background.

I might give this a shot tomorrow, but it shouldn't be too hard to do yourself.
Title: Re: How do I add speed for blink frames to this script?
Post by: Knox on Tue 14/09/2010 01:36:22
Hmm, creative idea. Ok Ill try that tonight to see what I can do...if I fail miserably Ill post about how much I suck tomorrow morning! :)
Title: Re: How do I add speed for blink frames to this script?
Post by: Knox on Tue 14/09/2010 04:09:37
Ok so I made a button the same size as the portrait gui (btn_BlinkView). I got the blinkview now drawn onto it, the only thing is, the blink frame stays drawn on the button "forever"...doesnt get "cleared" so we dont see the blink turn off. This is what I got so far (from your suggestion):


function Portrait_DoFrame()
{
  Portrait_vf = Game.GetViewFrame(Portrait_View, Portrait_Loop, Portrait_Frame);
  bool flip = Portrait_vf.Flipped;
  // Something like:
  if (Portrait_AutoFlip && Portrait_AtRight) flip =! flip;
  Portrait_Mod = DynamicSprite.CreateFromExistingSprite(Portrait_vf.Graphic, true);

  // Flip AFTER blink, if required
  if (flip) Portrait_Mod.Flip(eFlipLeftToRight);
  Portrait_GUI.BackgroundGraphic = Portrait_Mod.Graphic;
}

function Portrait_DoBlinkFrame()
{
  Portrait_bvf = Game.GetViewFrame(Portrait_BlinkView, Portrait_BlinkLoop, Portrait_BlinkFrame);
  bool flip = Portrait_bvf.Flipped;
  // Something like:
  if (Portrait_AutoFlip && Portrait_AtRight) flip =! flip;

  // Flip AFTER blink, if required
  if (flip) Portrait_bMod.Flip(eFlipLeftToRight);
  btn_BlinkView.NormalGraphic = Portrait_bvf.Graphic;
}
 
function repeatedly_execute_always()
{
  if (Portrait_Counter == 0)
  {
    Portrait_Frame++;
    if (Portrait_Frame == Game.GetFrameCountForLoop(Portrait_View, Portrait_Loop)) Portrait_Frame = 0;
    Portrait_DoFrame();
    Portrait_Counter = (Portrait_AnimSpeed + Portrait_vf.Speed + 1);
  }
  else if (Portrait_Counter >= 0) Portrait_Counter--;

  if (Portrait_BlinkTimer == 0)
  {
    Portrait_BlinkFrame++;
    if (Portrait_BlinkFrame == Game.GetFrameCountForLoop(Portrait_BlinkView, Portrait_BlinkLoop)) Portrait_BlinkFrame = 0;
    Portrait_DoBlinkFrame();
    Portrait_BlinkTimer = (Portrait_AnimSpeed + Portrait_bvf.Speed + 1);
  }
  else if (Portrait_BlinkTimer >= 0) Portrait_BlinkTimer--;
}

Title: Re: How do I add speed for blink frames to this script?
Post by: Khris on Tue 14/09/2010 10:01:00
Quote from: general_knox on Tue 14/09/2010 04:09:37
Ok so I made a button the same size as the portrait gui (btn_BlinkView). I got the blinkview now drawn onto it, the only thing is, the blink frame stays drawn on the button "forever"...doesnt get "cleared" so we dont see the blink turn off.

You aren't using the DynamicSprite.

This should work:

function Portrait_DoBlinkFrame()
{
  Portrait_bvf = Game.GetViewFrame(Portrait_BlinkView, Portrait_BlinkLoop, Portrait_BlinkFrame);
  bool flip = Portrait_bvf.Flipped;
  // Something like:
  if (Portrait_AutoFlip && Portrait_AtRight) flip =! flip;
  Portrait_bMod = DynamicSprite.CreateFromExistingSprite(Portrait_bvf.Graphic, true);      //  <-- this line was missing

  // Flip AFTER blink, if required
  if (flip) Portrait_bMod.Flip(eFlipLeftToRight);
  btn_BlinkView.NormalGraphic = Portrait_bMod.Graphic;      // <-- DynSprite is put on button, not original frame
}
Title: Re: How do I add speed for blink frames to this script?
Post by: Knox on Thu 16/09/2010 17:17:51
Perfect, thanks for all your help Khris!