Changing character position while walking

Started by Honza, Sun 14/11/2010 13:15:03

Previous topic - Next topic

Honza

Hello everyone,

I'm not sure if this belongs here or in the Technical forums, but since this is my first post here, I'll assume I must be a beginner :).

What I need to do is adjust my character's position in every frame of his walking animation. It's a way to avoid gliding (the "anti-glide" and "adjust speed according to scale" do help, but they don't work correctly for me). So what I need the script to do is this:

- change the character's position and frame as usual, according to AGS's pathfinding engine.
- notice that the character's position and frame have changed
- change his x and y values depending both on the previous and on the new position
- display the character in his new position

What the script does instead is this:

- change the character's position and frame as usual
- display the character in his new position
- notice that the character's position and frame have changed
- change his x and y values depending both on the previous and on the new position
- display the character in his new position *again*

The result is that the character is constantly shaking - my script for adjusting position works, but not before the character is displayed for a split second in his original position dictated by the AGS engine. Is there a way to make changes to coordinates take place before the game draws the character onscreen?

Thanks for any reply!

mode7

I'm not sure if I understand it right but if I get it correctly:

You are trying to use the standart walking function and while the function is running you try to offset the character on a per frame basis.

I'm pretty sure this will result in shake because as far as i understand is the standart walking function does nothing other than changing the x and y coordinates. So it's like two script will simultaneously change the coordinates which results in shaking.

There are two solutions for this I could come up with:
1. Writing your own walking function.
2. Put the offset you need inside the animation by just offseting the original frame the amount of pixel you need

Honza

Thanks for the input!

You understand correctly. The idea is to use the core walking script for counting "rough" coordinates (basically to define in which direction should the character proceed at any given frame) and then adjust these coordinates with my own script. Creating my own walking script altogether seems too complicated, at least with my current level of AGS knowledge.

I can't offset individual frames because the change to the frame is always a little different depending on angle, speed, scale, etc. When I tried this, the animation looked okay when walking on straight lines, but it became completely disjointed and shaky with different angles / scales.

Even if I allow the character to walk only in the standard 8 directions (so he'd basically walk in octagons, not in circles), it'd still come apart when the character is scaled.

Khris

You could have an invisible character do the actual walking and use their data to manually change the character's loop, frame and coordinates.

Although it seems to me all you need to do is adjust the frames of the walk-cycle. If the walk animation is drawn right, sliding can be almost completely eliminated. Sure, diagonal walking will always look a bit off, scaling on the other hand should work fine though since the walk speed is scaled along with the sprite.

I'd really like to see your walk-cycle, btw :)

Honza

Thanks for the tip with the invisible character, I'll definitely try that.

Here's an example of my walking cycle, not colored yet. It should be adjusted for speed 7, i.e. the foot moves 14 pixels with each frame:



Apparently, the scaling feature doesn't change the speed proportionally. If the character moves 14 pixels (= speed 7) per frame as mine does, and it's scaled to 120%, it won't move 17 or 18 pixels per frame. Instead, it'll still move 14 pixels per frame, and on every fifth frame it will suddenly jump 28 pixels ahead to compensate.

Khris

Each character has an option "AdjustSpeedWithScaling", you have to set that to "true".

While even straight walking gets slightly out of sync unfortunately with scaling the character, I couldn't replicate what you described last. Although the feet on the ground didn't remain completely still, the character moved smootly and evenly (at ~120-130% zoom).


Honza

#6
I have it set to "true", as well as "MovementLinkedToAnimation". This is what it does at scale 70: http://hvavra.sweb.cz/AGS/walk_70.html
Notice the "difference from last x" value - the character proceeds at normal speed for 3 frames and then it plays every fourth frame without actually moving. It slows the character to 75% speed, so the AdjustSpeedWithScaling option "works", but it makes the animation shaky.

This is scale 120, with the 28 pixel jumps as I described: http://hvavra.sweb.cz/AGS/walk_120.html

Maybe I have some other option checked that causes this... ?

Honza

#7
So I used an invisible character and tried to move the visible dummy character around it. But the core walking script outsmarted me :). Basically, I did this (I'll try to sum it up instead of posting the whole script):

- I calculated my own adjusted speed in every game loop: my speed = (original speed/100)*scale
- Every time the player's x value changed, I adjusted the difference: new x = old x + ((new x - old x)/original speed)*my speed
- Then I just changed the dummy character's coordinates, loop and frame to the values of the invisible player character.

So far so good - the character was showing properly, it stopped shaking, but it still seemed to glide just as before. So I tracked it's movement after each frame and I found out that the core walking script is reacting to my meddling. The more I tried to slow it down, for example, the bigger steps it would make after every frame. If the basic speed was 15 pixels/frame and mine was 10, he'd make a 15-pixel step first (I'd adjust it to 10), then a 20-pixel step (I'd adjust it to (20/15)*10 = 13), then a 22-pixel step. My script would adjust the 22 pixels to 15, which is the original speed - from now on, the original script will keep making 22-pixel steps.

It seems that the AGS script counts the coordinates of individual steps in advance and then sticks to them even if the current coordinates change. I guess I'll just have to get used to my character gliding, at least for now - this is getting too complicated :).

Khris

Just to exclude this as error source, you have to be careful when doing operations like this with ints.
E.g. you wrote that (20/15)*10 = 13; however, the result of this calculation will be 10 since 20/15 is rounded down to 1 first.
Most of the time, changing the order is accurate enough; in this case doing (20*10)/15 will result in 13.

To get back to your code, if those are actual lines:
Quotemy speed = (original speed/100)*scale
new x = old x + ((new x - old x)/original speed)*my speed

my speed will end up being 0, thus new x will be old x every time.

Honza

#9
Those are not actual lines of code, just a rough summary to give you an idea what the code does. The code itself is kinda messy and most of the variable names are in czech, but in case you want to see it anyway, here it is:

Code: ags

function repeatedly_execute() {

if (player.Moving == true) {
    
    rozdil_x = player.x-s1; 
    rozdil_y = player.y-s2;
    newframe = player.Frame;
    
 if (rozdil_x!=0 || rozdil_y!=0 || newframe-oldframe!=0) {moved = true;} else moved = false;
    
    oldframe = player.Frame;
    
    if (moved == true) {
      rozdil_x_pomer = (IntToFloat(rozdil_x)/(IntToFloat(player.WalkSpeedX)*2.0))*IntToFloat(rychlost_moje_x);
      player.x = s1 + FloatToInt(rozdil_x_pomer, eRoundNearest);
      if (info_display == true) Display("rozdil_x_pomer = (rozdil_x (%d) / 2*player.WalkSpeedX (%d))*rychlost_moje_x (%d) = %f = %d[[s1: %d x: %d", rozdil_x,  2*player.WalkSpeedX,  rychlost_moje_x, rozdil_x_pomer,  FloatToInt(rozdil_x_pomer, eRoundNearest),  s1,  player.x);
      cLisa.x = player.x;
      cLisa.y = player.y;
      cLisa.Loop = player.Loop;
      cLisa.Frame = player.Frame;
      rychlost_moje_x = FloatToInt(0.14*IntToFloat(player.Scaling), eRoundNearest);
      
    }
    s1=player.x;
    s2=player.y;
    
 }
  
  
  if (player.Moving == false) {
  
  rychlost_moje_x = FloatToInt(0.14*IntToFloat(player.Scaling), eRoundNearest);
  cLisa.x = player.x;
  cLisa.y = player.y;
  cLisa.Loop = player.Loop;
  cLisa.Frame = player.Frame;
  }
}


The integers are first transfered to floats, and only the final result is rounded, so it really does result in 13 ;).

My speed is also calculated right - I let the script display key values on every new frame, so I can check for this type of mistakes. There probably are some discrepancies in my code, but I'm pretty sure anything like that is not the (main) problem.

Do you have any idea why the "AdjustSpeedWithScaling" option is behaving as my screenshots show? You said that you couldn't replicate it, and if it was how it's supposed to work, I think more people would complain about it. So I'm guessing it must be something specific for my game, but I have no idea what.

SMF spam blocked by CleanTalk