[SUGGESTION] Preventing walk navigation from running while multiple clicking

Started by Ryan Timothy B, Sun 04/07/2010 01:50:14

Previous topic - Next topic

Ryan Timothy B

With any AGS game, if you multiple click in the same spot on the screen, the character stops walking, it calculates the navigation area, then starts walking again.

I understand that if the mouse is clicking in a different spot each time that it should still run the navigation algorithm, but why does it need to run it while the mouse is in the same spot and the character is still heading in that direction?  It's kinda redundant.

Basically, if using ProcessClick(mouse.x,mouse.y, eModeWalkto) happens to be the same as the previous click, it shouldn't need to run it again if the character is still moving and heading in that direction.


Ryan Timothy B

Is it?  How do I know the destination of the character?
What would happen if the character walks into region which has it automatically walk somewhere else?

I don't know.  I haven't played around with it much, mostly because it's all hard coded, I just know it's very annoying.

And yes, I have no idea why I like to multiple click sometimes.  I usually do it because I start getting impatient and then start multiple clicking, even though I know it does the exact opposite and just slow it down.

GarageGothic

Well, before calling ProcessClick you could check player.Moving. If false, store the mouse.x, mouse.y as ints and run ProcessClick. If true, check the stored ints - if they are identical to current mouse.x, mouse.y, don't call ProcessClick, else store the new coordinates and run ProcessClick.

Edit: Of course if it's a scrolling screen you need to use GetViewportX, GetViewportY to offset the coordinates you store/compare

Ryan Timothy B

Yes, this is very possible.  There are issues that could prevent the player from walking again until the mouse moves once it click again, or until the player stops walking, but the likelihood of the mouse being in the same spot during these, are pretty slim.


Honestly though, I'm not actually suggesting this for a game of my own. I want it for all future AGS games.  I have no idea why I like to multiple click while getting impatient; especially when I know doing so will slow down the character, not speed it up.  I think it has something to do with my beta testing necessity and me knowing it should be a simple fix for AGS, yet it still exists -- as if I'm the only one who does this.

The Electrician

I am not entirely sure that what Ryan proposed is a good idea. On one hand, you will notice that the very action of pressing a mouse button tends to move the mouse ever so slightly: so in fact you will have quasi-unpredicatable behaviour when you click again: did the mouse move or not? This could confuse the player, rather than teach them not to multiple-click. You could also check for proximity, say no more than 2 pixels away from the first click, if you really want to do this.

This leads me to another question: when are walkpaths calculated and recalculated? It seems that on a walk-to click the game engine constructs a list of waypoints, and the character moves in straight lines, checking off the waypoints one by one (the AddWaypoint() method suggests this is how its done). HOWEVER: as the character moves, the environment may change. Now I am not 100% certain as I can't test this right now, but it seems the following things happen:
1) If another character gets in the way (and both are blocking==true), then I guess the old path is dropped, and a new path is recalulated to the same previous destination and our first character keeps walking. (However, I sometimes get the impression that two blocking charactes walk through each other, but it's hard to tell).
2) I had a situation where a square room is all walkable, but has a thin walkable area
though its middle. If the player steps on certain stones (regions), an iron grid falls across the middle of the room, blocking passage between the two sides. At that point, I RemoveWalkableArea() the middle area, so that the grid becomes solid. However, if cEgo is at one end of the room and the player clicks (only once) to walk to the other end of the room, then, if while walking cEgo triggers the required region, the grid will drop but cEgo will still happily walk through the grid and to the other end of the room. [A workaround to this problem was not hard, but it got me thinking.]

So, in conclusion, should not the walk path be recalculated:
a) whenever a character OR object with blocking==true changes coordinates (moves),
b) whenever RemoveWalkableArea() or RestoreWalkableArea() is called?

I guess this can all be scripted as needed, though having it embedded in the engine would be nice. I appreciate that pathfinding can be computationally expensive (AGS uses A* on 3x3 squares, I think), but do you really want your characters to walk through stuff they shouldn't? I guess IRL we recalculate our paths all the time when walking down a crowded street [or don't, and then bump into people].

Thoughts?

Calin Leafshade

McCarthy 2 actually has a lot of little hacks like this and I certainly think they help.. Things like characters only turning via the front, custom pathfinding to avoid that nasty hiccup in movement around hard corners in the movement area etc etc.

but yea these are relatively easy to script I suppose.. but I do think the engine could do with a little updating when it comes to things like this.

Ryan Timothy B

Quote from: Calin Leafshade on Sun 04/07/2010 08:06:03
custom pathfinding to avoid that nasty hiccup in movement around hard corners in the movement area
How'd you manage that?


Anyway, the whole navigation seems to run quite slowly compared to other games.  For instance, sending whole squadrons of men in star craft to the very far corner of a map, they start walking the very instance you click.

Even multiple clicking while they're walking only helps them get a straighter path, it doesn't slow them down and make them stutter.

The straight line walking in AGS is even laggy.


Ultimately it would be cool if the character wouldn't stop walking while it runs the pathfinding, then it alters course without a hiccup.

Calin Leafshade

Quote from: Ryan Timothy on Sun 04/07/2010 13:42:11
Quote from: Calin Leafshade on Sun 04/07/2010 08:06:03
custom pathfinding to avoid that nasty hiccup in movement around hard corners in the movement area
How'd you manage that?

Well its not finished yet but basically its just A* pathfinding with a little smoothing and custom walk code.
I have no idea why the code built into the engine is so slow but over such short distances it's really not that cpu intensive.

originally I wanted to make a system similar to wintermute so that each frame of a walk cycle can move the character a different distance.
This would solve the gliding problem without having to resort to the 'sticking feet, stretchy legs' animation style.

GarageGothic

Instead of checking for the clicked coordinates, you could also check the destination coordinates (use an invisible character who travels to the clicked destination - or as near he can get - immediately to get the end coordinates) and not re-issue the walk command if they're identical.

The reason I keep suggesting workarounds is that I can't fully foresee the scope of the consequences of the suggested functionality change, not that I don't agree that the current behavior is slightly annoying. Overall though, my approach to AGS is that it has a bunch of flaws, but many of them can be worked around and even if a lot of things that *ought* to work out-of-the-box don't quite, I'd rather have CJ implement functionality that's currently out of reach than fix every little annoyance with the default setup.

Shane 'ProgZmax' Stevens

I understand what you're getting at, Ryan, and I empathize.  It's strange to watch a character do the two-frame shuffle when repeat clicking on a spot that you are frustratingly ordering them to, but GarageGothic's solution could easily be turned into a simple script module that you could toss into all your games and use for the basic controls so that they move directly to a location, ignoring future left clicks until they are:

A.  At the mouse coords you originally clicked on

and

B.  Are no longer moving (Moving==false)

That will satisfy all conditions for proving they did as ordered.  One thing that I would recommend adding to this, though, is a right-click cancel so you can cancel them out of this behavior and make them stop wherever they are, and that would just take a simple stopmoving call and some adjustments to the code to notify it that future processclicks for the left mouse will be read.  In this way you won't be forced to stay on course for a stray mouse click, but at the same time, you'll be able to click away at a target and they'll continue to move where the first click was registered. 

Now, if you wanted them to seamlessly move towards your click regardless then you're facing a more complicated solution that will involve writing your own animation, walk, and pathing functions that instead of stopping the character to check as the current ones do the character will continue walking and gradually adjust himself towards the right course.  I think the main reason the path logic has the character stop briefly is to avoid him sliding into a non-walkable zone while re-calculating, so you'd probably have to be aware of that as well. 

Or just try not to let it bother you :).

Khris

Quick test:

Code: ags
// header

import void iWalk(this Character*, int x, int y);


Code: ags
// module script

#define tolerance 2

int ox = -1, oy = -1;

void iWalk(this Character*, int x, int y) {
  
  int d = (ox-x)*(ox-x)+(oy-y)*(oy-y);
  ox = x;
  oy = y;
  if (d <= tolerance*tolerance) return;
  
  // new walk
  this.Walk(x, y);
}


Now catch walkto clicks:

Code: ags
// on_mouse_click, eMouseLeft

    if (mouse.Mode == eModeWalkto) player.iWalk(x+GetViewportX(), y+GetViewportY());
    else ProcessClick(mouse.x, mouse.y, mouse.Mode);


All this does is ignore subsequent walkto clicks within tolerance pixels.

Pumaman

The calculated path could change, if walkable areas have been enabled/disabled or other blocking characters have moved around since the initial calculation.

Quote1) If another character gets in the way (and both are blocking==true), then I guess the old path is dropped, and a new path is recalulated to the same previous destination and our first character keeps walking. (However, I sometimes get the impression that two blocking charactes walk through each other, but it's hard to tell).

When the path is initially calculated, AGS will treat other blocking characters as non-walkable, and calculate a path around them. If two moving characters collide mid-move, one of them will stop temporarily and wait for the other one to get out of the way.

SMF spam blocked by CleanTalk