Two button mouse interface scripting question (solved)

Started by KBlaney, Wed 27/02/2013 04:04:15

Previous topic - Next topic

KBlaney

I've finally fulfilled a promise to myself to learn AGS (made so many years ago after playing 5 Days a Stranger). While learning the various ins and outs of the editor, I happened upon Vince Twelve's 'Why Your Game is Broken' entry on the wiki about how the player interacts with the game. Specifically, he notes that most interactions and verbs are fairly useless because most clickable areas have only a small selection of useful options. That is, there are very few items that you can both "use" and "talk to". He makes a pretty compelling argument for a two button interface. That is, left button walks/interacts and the right button looks (similar to what has been done in any number of games like The Blackwell Legacy or Resonance)

I went ahead and managed to implement something that is 60% of the way there with this in the on_mouse_click function of the global script:
Code: AGS
if (button == eMouseLeft) { 
   ProcessClick(mouse.x, mouse.y, eModeWalkto);
 } else if (button == eMouseRight){
   ProcessClick(mouse.x, mouse.y, eModeLookat);
 }


The obvious problem is that with this set up the player will walk to places and look at things, but it lacks the ability to interact. Changing "eModeWalkto" in the ProcessClick to "eModeInteract" fixes the ability to interact, but breaks the ability for the player to arbitrarily walk in the walkable areas. I can think of certain workarounds (for instance, making a hotspot out of the walkable areas and then adding a "player.Walk(mouse.X, mouse.Y)") but they all seem rather inefficient, time consuming, prone to errors or otherwise just the "wrong way" to do things.

Is there a better way I should be handling this to get the effect I'm intending?

Snarky

Yes.  :)

The function you're looking for is GetLocationType(), which tells you what sort of thing the cursor is pointing to. Then if it's an object, character or hotspot, you interact, otherwise you walk. Here's part of my on_mouse_click() method, which also has code to support using inventory items:

Code: AGS
  else if (button == eMouseLeft)  // Left click
  {
    if(GetLocationType(mouse.x, mouse.y) == eLocationNothing) // If not over anything clickable, walk
    {
      ProcessClick(mouse.x, mouse.y, eModeWalkto);
    }
    else
    {
      if(mouse.Mode == eModeUseinv)
      {
        ProcessClick(mouse.x, mouse.y, eModeUseinv);  // Use inventory item
      }
      else
      {
        ProcessClick(mouse.x,mouse.y, eModeInteract); // Interact with object/char/hotspot
      }
    }
  }
  else if (button == eMouseRight) // right-click, so look or cancel inv. item
  {
    if(mouse.Mode == eModeUseinv)
    {
      mouse.Mode = eModeInteract;
    }
    else
    {
      ProcessClick(mouse.x,mouse.y, eModeLookat);
    }
  }

KBlaney

Brilliant. That's even easier than I expected. Thank you very much.

Tramponline

Maybe someone would correct me and tell me if my logic is faulty (...or if there's some ninja way of solving this, in case it isn't)

I studied Snarky's script and played around with it (great help by the way!).

If I understand properly, then there are certain scenarios where this two button interface would cause some problems.
Basically every time a hotspot area is overlapping a walkable area?

Made a quick mock-up, to demonstrate what I mean.
[imgzoom]http://img35.imageshack.us/img35/4426/sidealleytrek.png[/imgzoom]
If I wanted a player character to walk up and down the stairs (selfcontroled, without the use of regions), I'd have
some problems, wouldn't I? Since the 2-button interface would only register Hotspot 2 in most cases?

I do apologize in advance in case that I'm just being a bit slow and not seeing the obvious?!

(also if this is hijacking the thread, I'll create a new topic, but I thought since these topics are closely related?)   

zabnat

Remember that you don't need to click on walkable area to make the character walk somewhere. In your mock-up you can just click on the right corner of the screen and the character will walk as close to clicked point as possible within the walkable area.

Snarky

I'd say that if you need to be able to have characters interactively walk around some walkable area, it's not a great idea to have that walkable area almost completely obscured behind some other object, regardless of what flavor of point-and-click you're using. Even if you can technically do it when you have separate walk-to and interact modes, it's confusing to click on a foreground object in order to walk to something far behind it, in a different walkable area. In a two-button interface I think it should definitely be avoided.

That said, I don't think it's all that difficult to deal with the situation in your mock-up as a player, because as zabnat says you can click outside the walkable area, and the character will try to move towards that point. So as long as you click in the lower-right corner of the screen, the character will walk down the stairs.

Finally, going back to my initial point, is the situation you describe really all that realistic? In a background like this, the stairs would almost certainly just function as an exit anyway (or as a hotspot that could trigger cut-scenes in e.g. a hide-and-seek scenario), so it wouldn't really come up. Just designate a region around the top of the stairs as the "click here to go down" hotspot, and you're sorted. I'm having a hard time imagining a scenario where it's crucially important that you directly control the walking up/down the stairs, but where it makes sense to have them hidden behind another object.

Tramponline

Thanks a lot, guys. I definitely didn't take into account that you've the x/y and the eModeWalkto command. Also I seemingly do suck at producing mock-ups :tongue:
The real scenario I'm experimenting with in AGS is a corner shop in 2-point perspective with a back alley next to it. You can't actually see the back alley (only
the gap between buildings) and the storefront itself is one big hotspot covering pretty much every space where the player would click in order to enter
the back alley.
Anyway, it is merely a hypothetical scenario, to be able to get to know the limitations of a pure 2-button interface. But your are perfectly right Snarky, if I'd
design a room from scratch, I'd definitely not go about it in the way of the mock-up or the back alley for that matter. Thanks again.
     
 

selmiak

in your case I'd place a big hotspot on the ground in front of the alley (and on the alley) and when the player hovers the mouse over it make a big arrow appear on the ground pointing into the alley. Would this work in your setup? Of course when clicked the player enters.

Tramponline

That would work perfectly, selmiak, cheers.
Though for this particular experiment I gave myself some self-imposed restrictions. Using a 2-button interface and letting the player navigate the scene as 'intuitively' as possible, without too much use of regions, hotspots (and other 'gimmicks') for navigation purposes. My major focus was for the player not to feel as if he was 'led' by the game, but navigates where he wants to go. At the same time keeping it as simple and as intuitve as possible, though (if possible) without 'compromising' vantage points and/or the graphical representation of scenes.
Basically, just playing around, making it more difficult than necessary and learning a lot on the way. :wink: ...and cursing a lot too! :tongue:       

KBlaney

Best community on the internet... but I suppose you all knew that already.  ;-D

Just as a quick follow up the possible returns for GetLocationType(x,y) are only eLocationNothing, eLocationObject, eLocationCharacter or eLocationHotspot. At least, that is all I am seeing with autocomplete in the editor. Are there any other possibilities like for regions or walkbehinds (I'll probably end up modifying your code a bit).

Also, I assume that GetLocationType(x,y) will return eLocationCharacter based on either a simple rectangle or pixel perfect representation of the character as opposed to based on cCharacter.x and cCharacter.y (thus making it nearly impossible to actually click on a character).

Khris

You can look for specific things using the AtXY commands:

Code: ags
Region.GetAtRoomXY(mouse.x + GetViewportX(), mouse.y + GetViewportY())  // in a scrolling room, turn mouse coords to room coords
Character.GetAtScreenXY(mouse.x, mouse.y)   // also Hotspot, Object, GUI, InventoryItem
GetWalkableAreaAt(mouse.x,mouse.y)


GetLocationType is pixel-based.

cCharacter.X/Y is the character's position; not really suitable to detect clicks on the character. You could in theory get the character's current frame, calculate the sprite's pixel based on mouse and character position and look whether that pixel is not transparent. But Character.GetAtScreenXY() already does exactly that.

san.daniele

I've been teaching myself AGS for some weeks now and since I'm eager to find out everything myself before asking stupid questions in the forum. I'm happy I finally have a good reason to make my first post:

Thanks a lot Snarky! Your script helped me out a lot! (as my scripting skills aren't high class pro …yet). Works like a charm and was easy enough to customize to my needs.

SMF spam blocked by CleanTalk