How do I add speed for blink frames to this script? **SOLVED**

Started by Knox, Mon 13/09/2010 01:28:23

Previous topic - Next topic

Knox

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:
Code: ags
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... :-[)

Code: ags

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);
}
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

In rep_ex_always, Portrait_BlinkTimer is decreased by one every loop unless it is 0.

In DoFrame, look at these lines:

Code: ags
    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:
Code: ags
    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;
    }

Knox

#2
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?)
Code: ags

  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?
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

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.

Knox

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!  :-[
--All that is necessary for evil to triumph is for good men to do nothing.

Khris

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.

Knox

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! :)
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

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):

Code: ags

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--;
}

--All that is necessary for evil to triumph is for good men to do nothing.

Khris

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:

Code: ags
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
}

Knox

--All that is necessary for evil to triumph is for good men to do nothing.

SMF spam blocked by CleanTalk