Prevent player from "automatically" walking off cliffs

Started by Intangible, Tue 03/01/2012 23:54:06

Previous topic - Next topic

Intangible

I have a room with a cliff and some objects. When you interact with the object, the player walks up to the object and says something. My problem is that, if you put the cliff between yourself and the object and then interact with it, the player will walk right over the cliff and die (because player.Walk uses the most direct route from where you started).

Some technical information: The cliff’s “drop zone” is defined by a region; when you walk onto that region the “fall off cliff” logic runs. My walkable area overlaps the region a little bit, because otherwise the player would never be able to reach the cliff and die.

Basically, I don’t want the player to get themselves killed because their character automatically walked off the cliff. I don’t want their character automatically walking off cliffs at all. I can think of a two possible solutions to my current issue:
1) If the player isn’t close enough to the object, don’t do the interaction: tell them to walk closer to the object istead, thus eliminating the possibility of putting the cliff between yourself and the object when the interaction happens. If I do this, I’ll need to whip up some formula to calculate distance between the player and the object.
2) Make the ground right next to the “death region” a separate walkable area. Remove it before the player starts walking toward the object and restore it immediately after, so that the “death walkable area” won’t be used during the automatic walking. I tried this already; the problem is that unless the “death region” and “death walkable area” line up perfectly, you can end up with little areas where you’re on the “death walkable area” but not the “death region”, and in that case your player would be immobile when you removed it prior to walking. It’s a little too exacting for my taste.

However, I would imagine that someone’s faced this sort of issue before, so before I spend a lot of time changing a lot of rooms, I was hoping for some feedback on approaches that have worked well for other people. Any advice would be appreciated.

Khris

I gotta admit, I don't really get your game logic.
If you don't want the player to automatically walk off the cliff, what's the point of allowing them to at all?
The player basically has to deliberately choose to walk off and die, defeating the point of having to carefully maneuver walkable areas.

Unless of course you simply want to distinguish between walk clicks and interact clicks, with the latter being blocking. So crossing the screen by clicking with the walk cursor on an empty area is a different thing in terms of being able to die on the way than crossing the screen to interact with an object (which doesn't really make sense either).

If you still want to implement this, just check for a blocking walk:

Code: ags
// in walks onto region event

  if (!IsInterfaceEnabled()) return; // don't kill the player during a blocking walk

  // die

Intangible

#2
Quote from: Khris on Wed 04/01/2012 00:25:25
I gotta admit, I don't really get your game logic.
If you don't want the player to automatically walk off the cliff, what's the point of allowing them to at all?
The player basically has to deliberately choose to walk off and die, defeating the point of having to carefully maneuver walkable areas.

You know, I never really thought about it that way. I just figured, a cliff feels a lot more menacing and "real" when you know that it could actually kill you if you got too close (as opposed to being merely scenic). But none of the cliffs in my game are intended to be part of the challenge or game mechanics; they just happen to mark natural boundaries of the room or world. Let me think about this.

Intangible

Okay, what you're saying makes sense. Cliffs are either dangerous or they're not. So, if the player can walk off one deliberately, they should also be able to fall off one if they're careless with issuing interaction commands that cause automatic walking. Having said that, I now have a different problem (I wasn't worried about it before, because it's a side-effect of the scenario I originally wanted to prevent... now that I'm not trying to prevent that scenario, it's a problem).

Back to the original case where we position the cliff in between the player and the object: if the player tries to interact with the object, they will walk over the cliff to reach the object, but they don't fall right away. Instead, they finish walking up to the object, say their little line, and then they fall & die from where they're currently standing (which isn't even the cliff anymore). Obviously, this behavior is absurd-looking... if they enter the "death region", they need to fall & die right away... we can't wait for the interact command stuff to finish executing first (nor do we even want the rest of the interaction command stuff to execute, because the player is now dead).

So... how do I do this? Can the region's code for falling and dying somehow "interrupt" what the interact command was doing?

Khris

There are two ways to handle this:

1) In repeatedly_execute_always (which is called even during blocking events), check for Region.GetAtRoomXY(player.x, player.y).
This is the only workaround for region events not being processed until after a blocking function has finished.

2) A much better way: use my GotThere module. It allows for non-blocking walks that are still followed by interactions if they aren't interrupted.


Intangible

Wow, that is a seriously useful module! Now the player plunges to his death when he's supposed to, and better yet, the user can interrupt his walk if they realize they're heading for trouble. Thanks! I'd be happy to credit you in my game if you want.

Khris

Thanks, and yeah, I wouldn't mind being credited :)

Intangible

Okay, another question... I've started implementing GotThere in other places in my game, and I've encountered one case where it doesn't complete for me:

function hTapestry1_Interact()
{
  if (!GotThere())
  {
    GoFace(172, 261, eUp);
  }
  else
  {
    player.Say("hi");  // we never get here
    //hTapestry_Interact(172, 261);
  }
}

When I interact with the tapestry in the game, the player will walk up to it but never perform the "else" part of the logic (you can see that there used to be another function call in the "else", but while I'm trying diagnosing the issue I just put a "Say" command there for simplicity). I can't see anything different from the interaction where it was working; does it matter if the hotspot is on a wall (and therefore not overlapping the walkable coordinates I'm providing in "GoFace()"?)

Khris

If you press Ctrl+D, you can check the player's coordinates.

Maybe they are a pixel off? Are you positive that 172,261 is within a walkable area?
If the player won't walk to the specified coordinates, it might be necessary to change the GotThere script so it allows for the coordinates to be slightly off.

Intangible

I didn't know about Ctrl+D; that's pretty useful. I used it, and it looks like the player was stopping at 172,260. When I changed the command to use these coordinates, it started working.

The funny thing is, not only are both coordinates within the walkable area, but172,260 is actually further away from the player's starting point than 172,261... so I'm still a little unclear on why that particular location wasn't working. Still, at least if this comes up again, I can hopefully use Ctrl+D to see where the player would "prefer" to stop. Thanks again!

Intangible

Okay, I noticed the pattern... whenever the x or y coordinate is an odd number, the player stops just short of that number. Fortunately, even numbers always work.

The simple and obvious workaround is to use even numbers for the coordinates, but now I'm curious. Do you have any ideas as to why this would be happening? I didn't see anything in GotThere that would suggest what might be causing this...

Gilbert

I have not read any part of this long thread, but if you're talking about a character stopping by only some of the pixels on-screen and skipping the others, this is related to the character's walking speed and how movement is implemented.

Typically the faster the character walks there're more chance in him appearing only at certain coordinates periodically. That's also why walkable areas should be at least a few pixels wide.

Khris

I think this is related to the resolution; if you aren't suing 320x2X0, AGS still does internal stuff using these coordinates, then upscales it to the actual resolution.
With older versions of AGS, one could place objects only on even coordinates in the room editor when editing a high res game.
I didn't know that current versions still have this "feature". Or are you using an older version?

Intangible

I'm using AGS version 3.2.1. My game is 640x480 resolution, so I can see how this would happen if it's doing calculations based on 320x240. Actually, when I realized this was an "odd numbers" problem, my first thought was to look for integer division in GotThere... but based on what you're saying, it's probably coming from the engine itself.

No biggie, though. I can't imagine a situation where my game would absolutely need to use an odd-numbered pixel, as opposed to an even-numbered pixel right next to it. As long as I'm aware of the issue, I can work around it.

Sslaxx

Walk areas are like that, certainly. I think walk-behinds, regions and hotspots also are low-res.
Stuart "Sslaxx" Moore.

Intangible

It seems that, the first time any GotThere clause completes (that is, the character reaches the destination specified by GoFace and the interaction logic in the "else" is executed), character events start double-firing. For example, if the player is supposed to say "hi" when you talk to a character, they will now say "hi" twice in a row.

This doesn't happen for hotspot events, just character events. And like I said, it doesn't start happening until the first time the player reaches the location specified by a GoFace command. Any idea what could be happening here?

Khris

I can't replicate this; could you post the character's interaction code?
Also, characters aren't processed any differently than objects or hotspots. So technically, it should either work for everything or not at all.

Intangible

Okay, in the process of getting a simple code sample together, I figured out how to fix it.

Basically, the double-event firing only happens when my player is standing at the target x/y coordinates of the previous GoFace command, and an interaction is triggered which doesn't employee the GotThere/GoFace command. I haven't the faintest idea why this would matter (perhaps something to do with ClaimEvent() or ProcessClick()?), but I solved it by setting GotThere's target x/y coordinates to -1 immediately after __arrived is set to true in repeatedly_execute(), so that the player's x/y no longer matches GotThere's target x/y once the GoFace command completes.

As to why this was only happening with characters... characters are the only interactions in my game which aren't using GotThere at the moment, simply because I haven't got around to it yet. Please let me know if you have any questions (or concerns) about the solution I used.

monkey0506

Without looking at the GotThere source, is there any reason the code would rely on using 320x200/320x240 (low-resolution) coordinates? Newer versions of the engine do support native coordinates for high-resolution games (there's a setting in the editor which sets this, then there's Game.UsesHighResCoordinates to check for it (or something like that)).

Off the top of my head I'm not sure that there's a reason you would have used low-res coordinates in writing the module, but it could be relevant if you did.

SMF spam blocked by CleanTalk