Pressing UP on the keyboard to interact with something. (SOLVED)

Started by Ekeko, Mon 10/10/2011 15:03:38

Previous topic - Next topic

Ekeko

Hey guys! I would like to know how to do something like in Art of Theft or 1213 where you interact with something pressing the UP key.  This is what i tried:

Code: ags
 
function region2_Standing()
{
 if (keycode == eKeyUpArrow) player.Say ("Something");
}


In that part there is a PC and you step on in front of it (Region 2) and i want the character to make a comment about the PC when UP is pressed (When I say UP, I mean the up arrow), but when i try to run it, it says:

Failed to save room room4.crm; details below
room4.asc(17): Error (line 17): undefined symbol 'keycode'

Could anyone out there help me?  ???

NickyNyce

I'm just guessing here, but try to make the (K) capital in keycode.....(Keycode)

if Keycode is the proper terminology when your typing it, Keycode should pop up after you type in the first three letters...

EDIT: And that's why I don't like to guess.

Khris

keycode is a local variable used by the on_key_press function.

Find it in the global script, then add this inside:

Code: ags
  if (keycode == eKeyUpArrow) {
    Region*rr = Region.GetAtRoomXY(player.x, player.y);

    if (rr.ID > 0) {
 
      // handling code, we'll fill this in later, see below

    }
  }


Now you need a way to assign the regions to hotspots and objects. Unfortunately, regions don't have custom properties, so we need to loop through objects and hotspots.

Put this function in the global script, above on_key_press:

Code: ags
int GetIDForRegion(int id) {

  int i;
  while (i < Room.ObjectCount) {
    if (object[i].GetProperty("region") == id) return -i;
    i++;
  }
  
  i = 1;
  while (i < AGS_MAX_HOTSPOTS) {
    if (hotspot[i].GetProperty("region") == id) return i;
    i++;
  }
}


Now open the Properties of the PC hotspot, click Edit Schema and add a new property by right-clicking in the empty window. Add a property of type "Number", name "region", default value "0". Use any description you want, maybe "region number". Mark only hotspots and objects, then click ok and close the schema editor.
Back at the PC's custom properties, set the region to 2.

Now we need the handling code.
Code: ags
      int p = GetIDForRegion(rr.ID);
      if (p > 0) hotspot[p].RunInteraction(eModeInteract);
      else object[-p].RunInteraction(eModeInteract);


So what happens is if you press up while standing on a region, AGS checks the region property of all hotspots and objects in the current room and if it's the one you're standing on, AGS runs the event "Interact with ...".

So that's where you'd put code specific to interacting with the PC for example.


--------

(There is another way; you could use IsKeyPressed() and handle the interaction directly, the only problem is that holding the button even for a short time will trigger the event multiple times.)

Ekeko

Edit: Forget it, I corrected it!
Thanks guys for the help!

KodiakBehr

Did this code work for you without modification, Ekeko?
I'm doing something similar and not having any luck.

Ekeko

Quote from: KodiakBehr on Mon 10/10/2011 19:59:55
Did this code work for you without modification, Ekeko?
I'm doing something similar and not having any luck.

Yes it worked although I had a hard time making it work, I didn't had to change anything...  :-\ What problem are you getting?

KodiakBehr

rr.ID never goes above zero.

Does the second bit of code that's intended to be above on_key_press need to be within a specific function?

Ekeko

Quote from: KodiakBehr on Mon 10/10/2011 20:21:47
rr.ID never goes above zero.

Does the second bit of code that's intended to be above on_key_press need to be within a specific function?

Hmmm... I didn't got that error... :-\ I pasted that code below the closing brace of the function
repeatedly_execute_always. Where did you paste it? Maybe there's the prob...

EDIT: Wait, have you modified the property of the hotspot?

KodiakBehr

I put it in the same place.  The hotspot has a property known as "region" that is set to 2, as per the instructions.

The only difference was that the variables "i" and "p" were already in use and were substituted for unused two-character variables.  I did this twice just to make sure there wasn't an "i" or a "p" missed.  It's very frustrating when somebody holds your hand through the code like this and you still can't pull it together.

Ekeko

Quote from: KodiakBehr on Mon 10/10/2011 20:41:06
I put it in the same place.  The hotspot has a property known as "region" that is set to 2, as per the instructions.

The only difference was that the variables "i" and "p" were already in use and were substituted for unused two-character variables.  I did this twice just to make sure there wasn't an "i" or a "p" missed.  It's very frustrating when somebody holds your hand through the code like this and you still can't pull it together.

Maybe I'm about to say something that might be wrong...  But I think that two-character variables can't be used... Why don't you try numbers, for example? And have you already used ALL letters? (I don't really know if numbers can be used, because I have never made great use of variables, actually)

EDIT: So yeah, I was wrong.

pcj

Quote from: Ekeko on Mon 10/10/2011 20:57:24Maybe I'm about to say something that might be wrong...  But I think that two-character variables can't be used

Nope.  It just sounds like the hotspots aren't set up correctly.
Space Quest: Vohaul Strikes Back is now available to download!

Khris

Did you create global variables i & p? That's a bad idea; always use longer, descriptive names for global variables.

Just to make sure, it's supposed to look like this:

Global script:
Code: ags
...
...

int GetIDForRegion(int id) {

  int i;
  while (i < Room.ObjectCount) {
    if (object[i].GetProperty("region") == id) return -i;
    i++;
  }
  
  i = 1;
  while (i < AGS_MAX_HOTSPOTS) {
    if (hotspot[i].GetProperty("region") == id) return i;
    i++;
  }
}

function on_key_press(eKeyCode keycode) {

  if (keycode == eKeyUpArrow) {
    Region*rr = Region.GetAtRoomXY(player.x, player.y);

    if (rr.ID > 0) {
      int p = GetIDForRegion(rr.ID);
      if (p > 0) hotspot[p].RunInteraction(eModeInteract);
      else object[-p].RunInteraction(eModeInteract); 
    }
  }

  ...
  // rest of on_key_press code
  ...
}

...


If rr.ID keeps being 0, make sure that what you have drawn is actually regions, not walkbehinds or hotspots.
Also make sure that the player can actually step on them; they aren't a replacement for hotspots, they are meant to mark the part of the walkable area in front of the hotspot/object.

Variable names can have lots of characters, they obviously can't be numbers though.

KodiakBehr

That did it.  I was using hotspots instead of regions.  Silly me -- I didn't understand that both are necessary.

Thanks to all.

Ekeko

I suppose I can mark the thread as SOLVED since we're all happy now! ;)

Khris

It didn't occur to me until now but you don't really need to draw hotspots. It's enough to name them and set up the interaction(s) and region number.

Thinking about this further, that means it makes more sense to use regions only for objects and draw the hotspots not over the background object but the floor area.

That way one can use region 1 for object 1, region 2 for object 2, etc. while the game also checks for hotspots at the player's feet.
So no need for all the custom property business.

On the other hand, seeing all areas where pressing UP triggers something at once isn't such a bad thing either.

Ekeko

Quote from: LeKhris on Mon 10/10/2011 22:03:57
It didn't occur to me until now but you don't really need to draw hotspots. It's enough to name them and set up the interaction(s) and region number.

Thinking about this further, that means it makes more sense to use regions only for objects and draw the hotspots not over the background object but the floor area.

That way one can use region 1 for object 1, region 2 for object 2, etc. while the game also checks for hotspots at the player's feet.
So no need for all the custom property business.

On the other hand, seeing all areas where pressing UP triggers something at once isn't such a bad thing either.


Wow... You... Simply... ROCK, MAN!

Khris

In case you want to switch, here'd be code:

Code: ags
// in on_key_press

  if (keycode == eKeyUpArrow) {
    int x = player.x - GetViewportX(), y = player.y - GetViewportY();
    Hotspot*h = Hotspot.GetAtScreenXY(x, y);
    if (h.ID > 0) h.RunInteraction(eModeInteract);
    else {
      Region rr = Region.GetAtRoomXY(player.x, player.y);
      if (rr.ID > 0) object[rr.ID].RunInteraction(eModeInteract);
    }
  }


So no extra function and no properties necessary.

Ekeko

Quote from: LeKhris on Tue 11/10/2011 00:02:29
In case you want to switch, here'd be code:

Code: ags
// in on_key_press

  if (keycode == eKeyUpArrow) {
    int x = player.x - GetViewportX(), y = player.y - GetViewportY();
    Hotspot*h = Hotspot.GetAtScreenXY(x, y);
    if (h.ID > 0) h.RunInteraction(eModeInteract);
    else {
      Region rr = Region.GetAtRoomXY(player.x, player.y);
      if (rr.ID > 0) object[rr.ID].RunInteraction(eModeInteract);
    }
  }


So no extra function and no properties necessary.

Thanks! :D You are AWESOME!!  :D

SMF spam blocked by CleanTalk