Multiple random idle views linked together

Started by WatchDaToast, Mon 13/07/2020 11:59:46

Previous topic - Next topic

WatchDaToast

Hey everyone, I really hope some of you helpful people can somewhat solve this issue for me!  :-D
I wonder how I could go about displaying random idle animations ingame.

So far, as soon as the player stands on a spot, a standard idle animation always plays in which he blinks with his eyes for a short amount of time. After that, I want to randomly let the game pick
one of 5 idle animations, in which the main character does random things. After that, I want the character to go back to his normal blinking frame, so the process can start over.
Like this:

[Blinking Animation] --> [Random Idle]  --> [Blinking Animation] --> [Random Idle] etc...

My scripting skills are make-do for the most part and I am not sure how to properly get this thing done. I had this hacky idea here, placed in repeatedly_execute_always:
Code: ags
if ((cEgo.loop == 64) && (cEgo.frame == 6)) {  ////Normal blinking view which got assigned to the main character at the game start. frame 6 is the last frame

  int RandomIdle = (Random(5));
  if (RandomIdle == 0) {
  cEgo.SetIdleView(70, 2);  ///random idle 1
  }
  else if (RandomIdle == 1) {
  cEgo.SetIdleView(71, 2);  ///random idle 2
  }
  else if (RandomIdle == 2) {
  cEgo.SetIdleView(72, 2);  ///random idle 3
  }
  else if (RandomIdle == 3) {
  cEgo.SetIdleView(73, 2);  ///random idle 4
  }
  else if (RandomIdle == 4) {
  cEgo.SetIdleView(74, 2);   ///random idle 5
  }
  else if (RandomIdle == 5) {
  cEgo.SetIdleView(75, 2);  ///random idle 6 
  }
  
}


After this code, I would have added more scripts that checks the last frame of each random idle animation, so the idle view for the character can be reset to the normal blinking view.
Of course this is a pretty bad solution, and so far this script presented here did not even work (nothing happened).

I hope someone here can help me with that... (laugh)

Khris

For one, you can replace lines 3-21 with
Code: ags
  cEgo.SetIdleView(70 + Random(5), 2);


Try adding a Display() to make sure the code is actually called.

Matti

Because your view numbers are consecutive (which is good), you can shorten the script significantly [edit: beaten by Khris]:

Code: ags

if ((cEgo.loop == 64) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(70 + Random(5), 2);
}


I wouldn't change the idle view though and just animate the player normally. This way, after any of the random animations the player will automatically return to the idle view. I don't have the time to test it, but this might work:

Code: ags
if ((cEgo.loop == 64) && (cEgo.frame == 6)) {
  player.LockView(70 + random(5));
  player.Animate(player.Loop, 2, eOnce, eNoBlock);
  player.UnlockView();
}

WatchDaToast

#3
@Khris @Matti
Thanks a lot! Gonna change these lines then!  :)

I still have this problem that AGS won`t check the idle views frames though. (I made a mistake by the way, it is supposed to be (cEgo.view == 64) instead of (cEgo.loop == 64)).
So far it seems that AGS only checks the "normal" views a character can have, not the idle views. Even when the main character is clearly on frame 2 of his idle view, AGS takes no notice.
Only when I assign the view by script via Ego.ChangeView(64), AGS notices it.

Looks like I need to call the idle animations like Matti did in the latter script then...
Or play them with a script that checks when the player stands still.

Edit: Wait a second, I found the reason why AGS won`t check. I need to write .View instead of .view. Oops.

eri0o

ChangeView modifies the normal view. This is probably not what you want - you want to either change the idle view or lock/unlock a view.

What do you mean about the lower case view, did the compiler not catch you wrote it wrong and threw an error?

It looks like you want a different behavior than the regular idle view, may be easier to script your own idle handling. Otherwise, check if the character has just become not idle and then change the idle view so next time he has a different one.

WatchDaToast

#5
@eri0o
I was checking the IdleView`s last frame in my script, but it only did that after I changed "If (cEgo.view)" to "If (cEgo.View)". Kind of weird though.
Before I found this out, I assumed AGS did not check if the player was currently playing an Idle View or something. I haven`t scripted in a few months, so that may explain why i wrote view in lowercase. Mistake on my end.  :-D


So far it all works perfectly! First the players blinking view plays, and then another idle animation gets picked randomly.
To go back to the blinking view after one random Idle View has played, I made this horrible mess of a spaghetti code.
It looks for the last frame of each random Idle animation and brings back the blinking idle, which repeats the whole process.

Code: ags
 

 /////Randomly picked Idle animations

   ///looks around 1 Idle
    if ((cEgo.View == 513) && (cEgo.loop == 0) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 513) && (cEgo.loop == 1) && (cEgo.frame == 10)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 513) && (cEgo.loop == 2) && (cEgo.frame == 10)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 513) && (cEgo.loop == 3) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(64, 2);
    }
    
    ///looks around 2 Idle
    if ((cEgo.View == 514) && (cEgo.loop == 0) && (cEgo.frame == 10)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 514) && (cEgo.loop == 1) && (cEgo.frame == 8)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 514) && (cEgo.loop == 2) && (cEgo.frame == 8)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 514) && (cEgo.loop == 3) && (cEgo.frame == 12)) {
  cEgo.SetIdleView(64, 2);
    }
    
    ///wiggles ears Idle
    if ((cEgo.View == 515) && (cEgo.loop == 0) && (cEgo.frame == 24)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 515) && (cEgo.loop == 1) && (cEgo.frame == 25)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 515) && (cEgo.loop == 2) && (cEgo.frame == 25)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 515) && (cEgo.loop == 3) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(64, 2);
    }
    
    ///anxious shudder Idle
    if ((cEgo.View == 516) && (cEgo.loop == 0) && (cEgo.frame == 31)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 516) && (cEgo.loop == 1) && (cEgo.frame == 33)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 516) && (cEgo.loop == 2) && (cEgo.frame == 33)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 516) && (cEgo.loop == 3) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(64, 2);
    }
    
    ///freezes and shakes Idle
    if ((cEgo.View == 517) && (cEgo.loop == 0) && (cEgo.frame == 38)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 517) && (cEgo.loop == 1) && (cEgo.frame == 38)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 517) && (cEgo.loop == 2) && (cEgo.frame == 38)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 517) && (cEgo.loop == 3) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(64, 2);
    }
    
    ///bounces around Idle
    if ((cEgo.View == 518) && (cEgo.loop == 0) && (cEgo.frame == 6)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 518) && (cEgo.loop == 1) && (cEgo.frame == 34)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 518) && (cEgo.loop == 2) && (cEgo.frame == 34)) {
  cEgo.SetIdleView(64, 2);
    }
    else if ((cEgo.View == 518) && (cEgo.loop == 3) && (cEgo.frame == 12)) {
  cEgo.SetIdleView(64, 2);
    }


I have this on repeatedly_execute_always in my global script. It works, but I imagine it could take quite some toll on the poor AGS engine, which has to check this mess every tic?  :-D

Crimson Wizard

#6
Quote from: WatchDaToast on Mon 13/07/2020 14:44:29
I have this on repeatedly_execute_always in my global script. It works, but I imagine it could take quite some toll on the poor AGS engine, which has to check this mess every tic?  :-D

Above script is not even close to put a pressure on the engine.

It may make sense to optimize the code for the sake of the writer though, if you find it difficult to work with :)

For instance, you could make extra condition nesting and only test for the View once:
Code: ags

if (cEgo.View == 513)
{
    if (cEgo.Loop == ... && cEgo.Frame == ...)
    else if ...
}
else if (cEgo.View == 514)
{
    ...
}

Khris

The last frame of the current loop is  Game.GetFrameCountForLoop(player.View, player.Loop) - 1 

SMF spam blocked by CleanTalk