Clicking an object beneath another object (SOLVED)

Started by Matti, Tue 30/06/2009 15:53:28

Previous topic - Next topic

Matti

I have two objects one on another and I want to make both be clickable at the same time. The sprite of the one in the back sticks out so there shouldn't be a problem with clicking it. But though I've turned perfect-pixel detection on I just can click the one in the front. Both sprites have an alpha-channel, could that cause the problem? Or doesn't the click detection refer to objects?

Of course I could make a GUI pop up and let the player decide which object he wants to click but it would be much nicer without a GUI.

Here they are:


GuyAwesome

It works perfectly for me, with pixel-perfect detection on. Obviously, I have to click the sleeves of the chainmail t-shirt object but there doesn't seem to be a problem distinguishing between the objects, with or without the alpha-channel. With PPD switched OFF, only the vest is clickable - and includes the 'blank' area around it. (PPD refers to Objects and Characters. GUI Buttons are the only exemption, AFAIK.)

This might not be much use to you though, sorry. At least it proves the IDEA is valid... Is there anything else that might be interfering with the clicks? (Walkbehind, character, a 3rd object.) What happens if you add a few lines to show where you're clicking? (Get object at mouse coords, display object name/ID.) Or try cropping the sprites to just the important bits?

Matti

Quote from: GuyAwesome on Tue 30/06/2009 16:27:16
GUI Buttons are the only exemption, AFAIK.)

Ah, damn. Well, I forgot that they are indeed buttons since they're part of a character sheet-GUI. They aren't inventory items, that's why I have to use them as buttons. I guess then there's no way around that pop-up GUI... too bad.

Khris

Why don't you just shrink the vest button to the cropped sprite's dimensions?
I suppose the equipment is gonna change during the game, but resizing the buttons to Game.SpriteWidth[]/Height[] is trivial. And you can store the button coordinates in an array or similar.
Then change the position and size whenever the equipment changes.

GuyAwesome

Couldn't you get the transparency of the 'top' button (the vest, I'd imagine), and if it's opaque do that button's code, otherwise do the lower button's stuff, something like
Code: ags

function bVest_OnClick(GUIControl *control, MouseButton button)
{
  DynamicSprite *TempDS = DynamicSprite.CreateFromExistingSprite(7, true); // Or 'bVest.Graphic', for convenience
  DrawingSurface *DSTrans = TempDS.GetDrawingSurface();
  if (DSTrans.GetPixel(mouse.x, mouse.y) != -1) Display("Vest"); // Or whatever
  else Display("Shirt"); // Or something less pointless... (like call bShirt_OnClick)
  DSTrans.Release();
}


NOTE: My buttons are on gStatusline, positioned right at 0,0. You'll probably need to play around with DSTrans.GetPixel(mouse.x, mouse.y) to get the right position...

Matti

Thank you both. I'll try out what you suggested, GuiAwesome, and let you know if it worked (or if I could get it to work).

Matti

#6
Somehow it doesn't work. This is what I have in the global sript now. I needed that variable "a" for the different slots of the different armors.

I still can only click the above button (Ruest22).

Code: ags

function Ruest12_OnClick(GUIControl *control, MouseButton button) // mail armor
{
  // do some stuff
}

function Ruest22_OnClick(GUIControl *control, MouseButton button) // leather armor / brigantine
{
  int a;
  if(Armor2[gegnernummer]==1) a=203;
  else if(Armor2[gegnernummer]==2) a=204;  
  else if(Armor2[gegnernummer]==3) a=195;
  else if(Armor2[gegnernummer]==4) a=202;
  
  DynamicSprite *TempDS = DynamicSprite.CreateFromExistingSprite(a, true); 
  DrawingSurface *DSTrans = TempDS.GetDrawingSurface();

  if (DSTrans.GetPixel(mouse.x, mouse.y) != -1) {  
    // do some stuff 
  }  
  else {
    DSTrans.Release();
    Ruest12_OnClick(Ruest12, eModeInteract);
  }
}

GarageGothic

#7
Well, GuyAwesome's code assumes that the button is placed at screen coordinate (0,0). You need to calculate offsets for its actual location, otherwise the DrawingSurface stuff will be using the wrong coordinates.

If the button is named btnVest, the GetPixel code should be:

Code: ags
DSTrans.GetPixel((mouse.x - btnVest.X)-btnVest.OwningGUI.X, (mouse.y - btnVest.Y)-btnVest.OwningGUI.Y)


A couple of years ago, before the GetPixel function was implemented, I came up with a different workaround for pixel perfect button clicks. It uses a dummy character to check transparent areas. You can see the code here.

Matti

#8
Damn, he deliberately mentioned that and I just ignore it. D'oh!

Thanks, I'll try that out soon and I'll also take a look at your other code.


EDIT:

Cool, works like a charm. Thanks again, guys.

GuyAwesome

#9
Sorry, I was down the pub 'til just now. Thanks for picking that up for me, GarageGothic. I figured that'd be where things'd go wrong - I just couldn't be bothered working out the right code, sorry ;).

Glad the idea was sound, anyway.

EDIT:
GG, your code was actually the inspiration for my suggestion. I'd just forgotten where I read it, and was able to use newer functions to trim it down a bit. So, double thanks to you, I guess...

SMF spam blocked by CleanTalk