Best method of assigning clickable areas?

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

User avatar
Gizmog
Metal King Slime
Posts: 2622
Joined: Tue Feb 19, 2008 5:41 am

Post by Gizmog »

Oooh, this is a fun command! In answer to your first question, it returns a value. This value is 0 if there is no slice or if some other thing went wrong. On the other hand, if it's true it returns the handle of the slice in question. Let's take it argument by argument.

find colliding slice (parent, slice, number, check descendants)

Parent is a slice. Preferably a slice with a lot of children. FindColliding Slice is going to go through all those children and see if any of the slices are colliding with Slice which is naturally also a slice.

Number is an optional argument, meaning you don't have to put it in if you don't want. It's possible that multiple slices are colliding with slice, and that you might want to specify which one. According to the dictionary, FindCollidingSlice will return 0 (or false) of Number is higher than the actual number of children who Slice is colliding with. You can also put GetCount for number, and it will tell you how many children of Parent are collidng with Slice.

CheckDescendants is also an optional argument. It tells whether or not the script should check only Parent's immediate children, or if it should check the children of those children too. Its default value is true, so it will check the Children, Grand-Children, Great-Grandchildren etc. of Parent. If it's false, it will only check the direct children of Parent.

So how does it work?

Let's say I'm making a shooting game. I've got a container slice of enemies and a bullet.

Code: Select all

Enemies 01
 Dog 02
 Dog 03 
 Dog 04 
 Hydra 05
  Head 06
  Head 07
  Head 08
 Dog 09

Bullet 10
The names represent slices, and the numbers represent their handles.

I could do...

Code: Select all

variable (SomebodyShot?)
setvariable (SomebodyShot?,FindCollidingSlice (Enemies,Bullet,0,False))
ShowValue (SomebodyShot?)
That script would see if the bullet was colliding with enemies, and would display a number on screen representing the handle of that slice. If it were colliding with the Hydra, for instance, I'd see 05 in the lower left corner of the screen.

Note that it would never display 06, 07, or 08 because those slices are *NOT* direct descendants of Enemy: They're children of Hydra. To be able to target the heads, you'd switch False to True. You might still hit the body of the Hydra first, which is why you'd want GetCount and changing the 0 to different values to choose which colliding slice to deal with. There's clever ways to cycle through that and hit ALL of the slices you're colliding with.
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Here is how I am assigning clickable areas in my game

I have a slice collection that holds a screenful of buttons. Each button has its own slice lookup code

<img src="https://i.imgur.com/VzJRzu4.png">

In this example we will be looking at the button named "keep playing button"

In my main loop for this screen, I have some code that looks like this:

Code: Select all

    if&#40;click button&#40;sli&#58;keep playing button, col&#41;&#41; then&#40;
      break
    &#41;
col is the slice handle that holds the collection, which I loaded earlier with:

Code: Select all

col &#58;= load slice collection&#40;15&#41;
The click button script looks like this:

Code: Select all

script, click button, button code, holder, begin
  # Returns true if button was clicked
  variable&#40;button&#41;
  button &#58;= lookup slice&#40;button code, holder&#41;
  if&#40;button&#41; then&#40;
    if&#40;slice collide point&#40;button, mouse pixel x, mouse pixel y&#41;&#41; then&#40;
      if&#40;mouse click&#40;left button&#41;&#41; then&#40;
        exit returning&#40;true&#41;
      &#41;
    &#41;
  &#41;
  exit returning&#40;false&#41;
end

I can re-use this one "click button" script everywhere for all of my buttons, just by calling:

Code: Select all

if&#40;click button&#40;sli&#58;lookup code of any button, parent or grandparent handle of the button&#41;&#41; then&#40;
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

Okay I am totally ripping off that mouse click code when I get home from work. I already have some ideas on how I'd like objects to be organized in the .hss
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

I made some small changes to the documentation for those commands. The reason it was vague is because those commands can return either a slice handle or false or a count of slices.

By the way, about that screenshot you posted in the other thread:
Image
Realise that all the slice collision commands consider a slice to be a solid rectangle defined by its width and height, even if it's an ellipse or a sprite.
Last edited by TMC on Sat Jun 13, 2015 3:48 am, edited 1 time in total.
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

Oh dang, that sucks. Guess I'll just make them rectangles then.
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

I have recognition of HUD slices working so far using James's script with some modifications. Moving forward, I'd really like to avoid a horrifying mess of frontloading all the different "mouse clicked (button, holder)" possibilities -- of which there will be dozens and dozens of -- into the autorun script. Ideally I'd like to organize all the possible clickable stuff into:

* A HUD button category
* An inventory item category
* A spellbook item category
* A save/restore/quit menu category
* A scene/background clickables category

Could anyone suggest a method of having the initial mouse click checking script to return the parent/holder and then go to a separate script, e.g. a script checking only HUD buttons after the HUD parent handle was returned, and further narrow down what was clicked? Should I just take James's "mouse clicked (button, holder)" script, cut out the 'button' argument for the initial script, then cut out the 'holder' argument for the narrowed down script?
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

Is there a way to have a wildcard/anything argument when checking a script? If I could just check for "whatever/HUD" then that'd be pretty easy.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1243
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

you could assign random(1,10) to a variable and use that.
My pronouns are they/them
Ps. I love my wife
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

I'm not sure if that would work. To clarify I was wanting to know if you could do something like


Code: Select all

if &#40;mouseclicked&#40;*,sli&#58;hudcontainer&#41;&#41; then &#40;
       ......
To where you could fulfill the requirement of actually putting down a script argument but not HAVE to have it be anything in particular for an if statement to be true or not.
Last edited by Foxley on Sun Jun 14, 2015 12:23 am, edited 1 time in total.
User avatar
Gizmog
Metal King Slime
Posts: 2622
Joined: Tue Feb 19, 2008 5:41 am

Post by Gizmog »

I'm not sure I understand the question. What's the wildcard in

Code: Select all

if &#40;mouseclicked&#40;*,sli&#58;hudcontainer&#41;&#41;
supposed to stand for? If it stands for which mouse-button you clicked with, IE: You want to be able to left OR right click anything and have it do the same thing, you'd have to get fancy and do something like...

Code: Select all

variable &#40;SomethingNeedsDone&#41;

if &#40;MouseClick &#40;RightButton&#41;,or,MouseClick &#40;LeftButton&#41;&#41;
then &#40;SomethingNeedsDone &#58;= 1&#41;


if &#40;SomethingNeedsDone&#41;
then &#40;
        #WhereTheHellsTheCursorAndWhatShouldIDoAboutIt
        &#41;

SomethingNeedsDone &#58;= 0
If it means like... if you clicked on any slice in the HudContainer you want something to happen in addition to the normal effects, you could record what slice had been clicked on and then check its parentage? Like...

Code: Select all

variable &#40;SliceThatGotClicked&#41;

#Whenever you click on a slice, record what slice that is to SliceThatGotClicked. Be sure to clear it later too!

if &#40;CheckParentage &#40;SliceThatGotClicked,sli&#58;HudContainer&#41;&#41;
then &#40;#DoSomethingWildAndWonderful&#41;
Not sure which you mean. Also, the fun thing about If is that left to its own devices, any non-zero value means true. So for instance...

Code: Select all

variable &#40;DontHitZero&#41;
DontHitZero &#58;= random &#40;0,10&#41;
ShowValue &#40;DontHitZero&#41;
if &#40;DontHitZero&#41;
then &#40;
        #You didn't hit zero! 1,2,3,4,5,6,7,8,9 maybe even 10!
        TryItAgain
       &#41;
else &#40;
        #I told you not to hit zero! You hit Zero! WTF man!
        GameOver
       &#41;

#This is the best game I've written in 20 years
EDIT: I guess what I mean to ask is: What do you want to happen, what's happening instead and what have you tried so far?
Last edited by Gizmog on Sun Jun 14, 2015 3:48 am, edited 1 time in total.
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Everything in this thread starting with the word "frontloading" is completely confusing to me. I have no idea what is going on :)
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

To put it simply, I don't want to have every single contingency in the game's script to be shoved in a gigantic wall of text right beneath the mouse cursor loop. I'd rather have the code look at least somewhat clean and readable. So, to that end, I was hoping I could have simple concepts like "did mouse click return a slice that's part of the HUD? OK, go to another script that narrows down what HUD button got clicked and run an appropriate script from there." and then eventually get to really specific things like "did you click on the potion bottle ...while USE was selected ...and then click on the cauldron?" deeper into the .HSS.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

There's a very easy way to do that. Just split your wall-of-if-tests into separate scripts, and call them all:

Code: Select all

plotscript, the on key press script, begin
  check hud clickables
  check inventory clickables
  ...
end
But then there's a problem if any of the clickables overlap, such as if you pop up a message box with buttons. Here's one solution, which is basically what you asked for. Create one container for each category such as the HUD, one for the inventory, etc. Each container should be sized to the rectangle of the screen they cover. In this scheme, if they overlap then you won't be able to click-through to something in the category underneath even if there's just empty space in the top one.

Give each of these category container slices a lookup code. Then you can treat them as huge buttons. If you click inside one of these big invisible rectangle, then you just call the script that handles that category and checks what was clicked inside it:

Code: Select all

if &#40;click button&#40;sli&#58; hud container&#41;&#41; then &#40;
    check hud clickables
&#41; else if &#40;click button&#40;sli&#58; inventory container&#41;&#41; then &#40;
    check inventory clickables
&#41; else if &#40;
...
Note that when you have overlapping clickables you should test them for clicks in order from topmost to bottommost.

(Aside: You could also use the findcollidingslice and sliceatpixel commands. There's a quirk in them. They return the bottom-most colliding slice, whereas for clicking you want the top-most slice. I'm currently adding a new argument to these commands to specify that you want the top-most slice instead.)
Last edited by TMC on Sun Jun 14, 2015 11:38 am, edited 2 times in total.
User avatar
Foxley
Metal Slime
Posts: 832
Joined: Sat Nov 09, 2013 5:54 pm

Post by Foxley »

Wow... derp. I have no idea why I didn't think of that before. No need to determine what type of object got clicked if you can just run checks through everything and let it find the thing it needs to find, right? Thanks TMC.

The only overlap to consider would be inventory, spellbook and game menu objects taking up the same screen space, which is a slice problem that I mentioned in another thread.
Post Reply