Link character movement [SOLVED]

Started by glurex, Sat 11/02/2023 22:47:29

Previous topic - Next topic

glurex

I was wondering if there's a way to link the character movement, for example, to the properties of a GUI (like its transparency). So while a character (the player) walks in X axis coordinates a GUI could slowly became visible (from 100 to 0 transparency). Or even a Music could slowly became more loud.

Maybe with a while condition?

Code: ags
While (player.moving? player.x >Screen.Width / 2?)
{
GUI.transparency--;?
}

But i'm sure I'm not understanding how while works.

Thanks!


Matti

This depends on how you want it to work exactly. Should the GUI only become more visible while the player walks and should it immediately become invisible again if the player stops?

You could link the transparency directly to room coordinates, like this for example:

Code: ags
if (player.x > 200)
{
  GUI.Transparency = 100 - (player.x - 200)
  if (GUI.Transparency < 0) GUI.Transparency = 0;
}

Khris

while is used to create a loop, and it will block everything else while the condition is true. AGS also doesn't advance to the next frame while the execution is stuck inside the loop running the lines over and over again (at maximum execution speed), so anything you change about the game doesn't become visible until the loop exits (because the screen never gets redrawn).

If it's ok that the while loop is blocking everything else, you can add Wait(1); inside the loop, this will advance the engine one frame and redraw the screen.
A use-case for that is a blocking cutscene where the camera pans across a room.

To run code in a loop without blocking the rest of the game, AGS has the three repeatedly_execute functions. Rooms use a separate event instead of the regular function, so if you want code to run continuously only in a specific room, you use the room event and put your code in the event's function instead.

Code: ags
function Room_RepExec() {
  int tr = 400 - player.x; // invisible below 300, fully visible at 400
  if (tr < 0) tr = 0; // clamp value to allowed range
  if (tr > 100) tr = 100;
  gSomeGUI.Transparency = tr;
}

glurex

#3
Quote from: Matti on Sun 12/02/2023 12:43:25This depends on how you want it to work exactly. Should the GUI only become more visible while the player walks and should it immediately become invisible again if the player stops?

You could link the transparency directly to room coordinates, like this for example:

Thanks for the reply, Matti! Surprisingly your code is very similar to my first try, but for some reason as my code doesn't work I go for other stranger paths.

Quote from: Khris on Sun 12/02/2023 13:57:42while is used to create a loop (...)

Thanks for the explanation, Khris!

Quote from: Khris on Sun 12/02/2023 13:57:42A use-case for that is a blocking cutscene where the camera pans across a room.

Yes, I used it (instinctively, but without fully understanding it) when I need to pan the camera across the room at Intro.

Quote from: Khris on Sun 12/02/2023 13:57:42AGS has the three repeatedly_execute functions

Yes, I knew that  :-D  But, for some reason, I was confused about what exactly while does.

Well, I undestand what your code does, but I realise I didn't explain myself well. What I want to do is that the GUI appears slowly as my character walks from A to B, being A gDark.Transparency=100; and B gDark.Transparency=0;. But in the middle of the path from A to B, gDark should has a range of transparency (99, 98 ... 1, 0). So the effect is that the gDark appears very slowly while the character walks up to the B point (a region that trigger an event).   

glurex

I was thinking on define the starting point (A) and the ending point (B) of my character's walk and assume that A is at (x1) and B is at (x2). And later write a script that will "read" my character moving from A to B and adjust the transparency of gDark along the way.

For example, something like:

Code: ags
 int x1 = 100;
 int x2 = 200;
 
 int steps = 100;
 
 int dx = (x2 - x1) / steps;
 
 for (int i = 0; i < steps; i++)
{
  if (player.Moving && x1 + i * dx)
  
  {
     gDark.Transparency = 100 - i;
  }
}

But, of course, that doesn't work neither  :-D

glurex

#5
Well, I found a kind of workarround...

I create a Variable: int movement=100.

and in Room_RepExec:

Code: ags
if (player.Moving)
{
  Wait(10);
  movem--;
  }

 int tr = movem; // Khris code :-)
  if (tr < 0) tr = 0;
  gDark.Transparency = tr;

Not exactly what I had in mind, but close enough I guess.

Snarky

Why couldn't you just use Khris's code?

The only issue I can see with it is that depending on your animation speed, it could get jerky, since it will only update when the character changes position.

glurex

Quote from: Snarky on Mon 13/02/2023 05:59:57The only issue I can see with it is that depending on your animation speed

That's the key. With Khris code as is, the GUI becomes solid very fast. With my workaround (that involves Khris code) the GUI becomes solid more slowly, which produces a more dramatic effect.


Snarky

Quote from: glurex on Mon 13/02/2023 06:10:09With Khris code as is, the GUI becomes solid very fast.

Well, that's probably because the distance you want the GUI to fade in over is more than 100 pixels. You would need to scale it depending on the actual coordinates in your game, like you started to do in one of your earlier examples. That's just a simple tweak.

In general, if something doesn't work, please don't just say "it doesn't work," but explain what it does and how that differs from what you want to happen.

Where do you put the code in your workaround, BTW? Putting a Wait() in a repeatedly_execute function is a bad idea.

glurex

#9
Quote from: Snarky on Mon 13/02/2023 06:18:21"it doesn't work,

First of all: I never said Khris code doesn't work wich would be disrespectful. I only use the phrase doesn't work with my own code (I have the right to be disrepectful with myself  :-D). And later in my first reply I have done just that: explain what it does and how it differs from what I want to happen.

Yes, I know put a Wait on rep exec function isn't the best idea, that's why I call this a workaround and not a proper solution.

That's being said... I have been adapting the number of Khris code to my coordinates. But I couldn't get the desired effect. Many thanks anyway, Snarky!

Snarky

#10
Quote from: glurex on Mon 13/02/2023 06:28:00First of all: I never said Khris code doesn't work wich would be disrespectful.

I'm sure that's appreciated, but the reason I asked you to explain how something doesn't work is for effective communication, not respect. And you implied that his code didn't do what you wanted it to, without explaining how it differed:

Quote from: glurex on Sun 12/02/2023 21:14:53Well, I undestand what your code does, but I realise I didn't explain myself well. What I want to do is that the GUI appears slowly as my character walks from A to B, being A gDark.Transparency=100; and B gDark.Transparency=0;. But in the middle of the path from A to B, gDark should has a range of transparency (99, 98 ... 1, 0). So the effect is that the gDark appears very slowly while the character walks up to the B point (a region that trigger an event).   

... Because what you describe is exactly what Khris's code ought to do, so without you describing how his code fails to match what you want, it's hard to offer any further help.

Here's a slightly modified version where you just need to enter the X coordinates of Point A and Point B:

Code: ags
function Room_RepExec() {
  int startX = 123; // Change to the X coordinate where you want the fade-in to begin
  int endX = 321;   // ... and where you want it to complete
  int tr = 100*(endX - player.x)/(endX-startX); 
  if (tr < 0) tr = 0; // clamp value to allowed range
  if (tr > 100) tr = 100;
  gSomeGUI.Transparency = tr;
}

Note that we don't use player.Moving or any kind of loop: the transparency is directly tied to the character position, so it will automatically update as the character moves. And therefore we don't need any Waits or anything like that: the mapping of the position to transparency ensures that it fades in to reach full opacity only when the character arrives at the target X.

glurex

Yeah, we can agree on that. But as English isn't my first language sometimes i'm afraid of sound rude when isn't, always, my intention.
 
Quote from: Snarky on Mon 13/02/2023 06:51:59Note that we don't use player.Moving or any kind of loop: the transparency is directly tied to the character position, so it will automatically update as the character moves. And therefore we don't need any Waits or anything like that: the mapping of the position to transparency ensures that it fades in to reach full opacity only when the character arrives at the target X.

Wow, Snarky that's exactly what I wanted to do. Many thanks!

Snarky

#12
So that code worked for you? Great!

There is another small improvement we can make in case a particular problem arises:

If the character movement is linked to animation (often called "anti-glide"), and the character movement speed (the distance it moves per animation frame) is large, and the animation delay is significant, then the fade-in effect could appear "jerky," with sudden jumps in transparency.

Specifically, this could become noticeable if AnimationDelay > 2, and 100*MovementSpeed/(endX-startX) >= 2 (but especially if it is some higher number like 4 or 5).

If this is not the case, we don't need to worry about it, but if it does arise, we can achieve a smoother fade this way:

Code: ags
function Room_RepExec() {
  int startX = 123; // Change to the X coordinate where you want the fade-in to begin
  int endX = 321;   // ... and where you want it to complete
  int tr = 100*(endX - player.x)/(endX-startX); 
  if (tr < 0) tr = 0; // clamp value to allowed range
  if (tr > 100) tr = 100;

  if(gSomeGUI.Transparency < tr) gSomeGUI.Transparency = gSomeGUI.Transparency + 1;
  if(gSomeGUI.Transparency > tr) gSomeGUI.Transparency = gSomeGUI.Transparency - 1;
}

glurex

Quote from: Snarky on Mon 13/02/2023 07:29:17There is another small improvement we can make in case a particular problem arises:

If the character movement is linked to animation (often called "anti-glide"), and the character movement speed (the distance it moves per animation frame) is large, and the animation delay is significant, then the fade-in effect could appear "jerky," with sudden jumps in transparency.

Specifically, this could become noticeable if AnimationDelay > 2, and 100*MovementSpeed/(endX-startX) >= 2 (but especially if it is some higher number like 4 or 5).

Thanks, Snarky! Since my character's movement speed is 8 and AnimationDelay is 4 (and that without counting that the character can run if user double click/ hold shift) the improvement is very welcomed.



Snarky

Well, it also depends on the distance over which the fade happens. If the distance is 800 pixels, then each 8-pixel step is only 1% of that anyway, so we can't get any more smoothness. But if the distance is, say, 200 pixels, then each step is a 4% change in transparency, and it makes sense to smooth it out.

This approach does introduce an absolute limit to the speed at which the fade can happen (1% per game loop, so 2.5 seconds to complete the whole fade), and therefore if your character can run across the distance much faster than that, we might have to add another condition to speed it up in that case, so the player doesn't have to wait for the fade to catch up at the end. For example:

Code: ags
function Room_RepExec() {
  int startX = 123; // Change to the X coordinate where you want the fade-in to begin
  int endX = 321;   // ... and where you want it to complete
  int tr = 100*(endX - player.x)/(endX-startX); 
  if (tr < 0) tr = 0; // clamp value to allowed range
  if (tr > 100) tr = 100;

  if(gSomeGUI.Transparency + 6 < tr) gSomeGUI.Transparency = gSomeGUI.Transparency + 2;
  else if(gSomeGUI.Transparency < tr) gSomeGUI.Transparency = gSomeGUI.Transparency + 1;
  else if(gSomeGUI.Transparency - 6 > tr) gSomeGUI.Transparency = gSomeGUI.Transparency - 2;
  else if(gSomeGUI.Transparency > tr) gSomeGUI.Transparency = gSomeGUI.Transparency - 1;
}

(This makes it fade twice as quickly if the actual transparency differs by more than 6 percentage points from what it should be at this position.)

SMF spam blocked by CleanTalk