"Smart" cursor hotspots - seeking a reasonably automatic solution

Started by Intangible, Sat 11/06/2011 21:36:36

Previous topic - Next topic

Intangible

I really want my game's cursors for walking, looking, interacting and talking to highlight when they're over an area that will do something for that cursor. Of course, the "Animate", "AnimateOnlyOnHotspots" and "View" properties for the cursors got me 90% of the way there with very little effort, but there are a couple of gaps:

1) I only want the cursor to highlight if there is actual code behind the event that will produced by clicking the object with that particular cursor. For example, a tree should make the cursor highlight if it's "look at" or "interact", but not "talk to". Likewise, an unreachable object shouldn't highlight the cursor if it's "walk to", but it if it's "look at" that would be fine.
2) The screen edges don't count as hotspots, and so the "Walk To" cursor won't highlight if the mouse goes near it (even if walking over the edge would make you change rooms). Again, I'd like this to be automatic... I would only want the "Walk To" cursor to highlight if there was actual code behind the "Leave" event for that specific edge.

Of course, both 1) and 2) could be achieved by manually writing lots of code for every room, but what I'm hoping to find is a solution that is fairly dynamic/automatic and smart. This solution will pervade the whole game, so I don't want to use an approach that will be difficult to maintain or needlessly tedious to code.

Babar

One solution is to use custom properties. You can create bool properties for all hotspots, characters, objects, etc., such as "Walk" "Use" "Look" "Talk" (you could probably condense it all into 1 int property with some clever scripting IF you wanted), and then accordingly, in your repeatedly_execute (or wherever you are handling your cursor highlighting), depending on which mode you are in, you can have it highlighted or not.

This WOULD require you to go through each and every hotspot and character and object, etc. and set it's various properties, but I'm assuming it'd be less work than having to code it all manually.
The ultimate Professional Amateur

Now, with his very own game: Alien Time Zone

Khris

Part of 1) can be done using IsInteractionAvailable(). This checks if there's a linked function or if the game is going to try to run unhandled_event().

2) can be done using regions or hotspots as exits instead of screen edges. A custom property flag would marks them as exits.

Intangible

Thanks for the suggestions! I'll give them a try in my game.

Intangible

So far, it's working excellently! Here's what I have so far:

function room_RepExec()
{
  // Walk to (TODO: enhance this logic with an additional cursor image for screen change regions)
  if (GetWalkableAreaAt(mouse.x, mouse.y) != 0)
  {
    mouse.ChangeModeGraphic(eModeWalkto, 171);
  }
  else
  {
    mouse.ChangeModeGraphic(eModeWalkto, 2054);
  }
 
  // Look at, Interact and Talk to
  if (IsInteractionAvailable(mouse.x, mouse.y, mouse.Mode))
  {
    mouse.ChangeModeGraphic(eModeLookat, 183);
    mouse.ChangeModeGraphic(eModeInteract, 184);
    mouse.ChangeModeGraphic(eModeTalkto, 185);
  }
  else
  {
    mouse.ChangeModeGraphic(eModeLookat, 2056);
    mouse.ChangeModeGraphic(eModeInteract, 2057);
    mouse.ChangeModeGraphic(eModeTalkto, 2058);
  }
}

That covers off almost all of my requirements, although I was wondering if there's anything I could do with my "use inventory" cursor. Each inventory item has its own cursor image, so it seems like I'd need a big "if" statement that covers each possible inventory item and its corresponding "interaction/no interaction" cursors. I was thinking, I could put the "if" statement in a global method so that at least I only need to write it once (and maintain it in one place). Any thoughts? If anything I've mentioned is going to cause me trouble, I'd love to know about it now. :)

Khris

You can use the sprite slots for that; when you import the items, make sure that for every item, the highlighted cursor image is the normal image+1. You can change the numbers after importing a sprite, too.

Then use something like this:

Code: ags
  // Look at, Interact and Talk to
  if (IsInteractionAvailable(mouse.x, mouse.y, mouse.Mode))
  {
    mouse.ChangeModeGraphic(eModeLookat, 183);
    mouse.ChangeModeGraphic(eModeInteract, 184);
    mouse.ChangeModeGraphic(eModeTalkto, 185);
    if (player.ActiveInventory != null) player.ActiveInventory.CursorGraphic = player.ActiveInventory.Graphic + 1;
  }
  else
  {
    mouse.ChangeModeGraphic(eModeLookat, 2056);
    mouse.ChangeModeGraphic(eModeInteract, 2057);
    mouse.ChangeModeGraphic(eModeTalkto, 2058);
    if (player.ActiveInventory != null) player.ActiveInventory.CursorGraphic = player.ActiveInventory.Graphic;
  }

Intangible

That worked like a charm! At first, I was a little uneasy about directly manipulating sprite id's, but I like this solution because it doesn't require me to add extra code to the method every time I add a new inventory item. I just have to make sure that the sprite id's follow the pattern.

SMF spam blocked by CleanTalk