Center a dropped object on a grid

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

rumplestiltskin
Posts: 222
Joined: Wed Jun 21, 2006 7:33 pm
Location: West of the Pecos
Contact:

Center a dropped object on a grid

Post by rumplestiltskin » Sun Mar 11, 2018 10:41 pm

I have a grid of squares (all graphic objects) aligned on their edges in an 11x11 grid. Here's a 4x4 portion of that grid:
Labeled Grid.png
Labeled Grid.png (31.49 KiB) Viewed 7845 times
I've labeled each grid square for convenience (for this discussion).

The round "X" object is a button. I'm using a mouseStillDown handler to move it around the grid until I release the button. Then the button stops moving. What I need to have happen is for the button to center itself within the grid. So, in this example, I've dropped the button so its location is somewhere within square A2; therefore, there needs to be a mouseUp handler in the button that sets the loc of the button to the loc of square A2. But, during runtime, I don't know which square the button will be dropped on so I need to have a means of testing which square the button's loc is within.

There's probably a very simple method but I'm thinking along the lines of a Case structure where I have to test if the loc of the button is within the rect of each square (121 tests) and then, in each test, set the loc of the button to the loc of the square (if true).

Suggestions?

Thanks very much!

Regards,
Barry

SparkOut
Posts: 2852
Joined: Sun Sep 23, 2007 4:58 pm

Re: Center a dropped object on a grid

Post by SparkOut » Sun Mar 11, 2018 11:22 pm

This is a perfect use case for behaviors.
If you set the behavior of each grid element to the same script, you can use "the loc of me" and each instance will identify the "of me" to its own individual self. No testing or calculating necessary.

rumplestiltskin
Posts: 222
Joined: Wed Jun 21, 2006 7:33 pm
Location: West of the Pecos
Contact:

Re: Center a dropped object on a grid

Post by rumplestiltskin » Mon Mar 12, 2018 12:01 am

I'm afraid I'm not following you. I referred to the dictionary's entry for "behavior" but I'm not seeing how this would help me. I know the loc of the button when I drop it. How do I know which square is under the loc of the button at that moment? Perhaps you might post a snippet of code to help explain your answer. Thanks.

I've thought about the 121 tests and I can see how I might reduce that number to 37 at most. If I divide the grid into four quadrants, then the largest quadrant would have 36 square so I test first for which quadrant the button is in, then test only the squares in that quadrant. Sort of a quaternary search algorithm.

Ideas welcome.

Thanks,
Barry

MaxV
Posts: 1579
Joined: Tue May 28, 2013 2:20 pm
Location: Italy
Contact:

Re: Center a dropped object on a grid

Post by MaxV » Mon Mar 12, 2018 2:21 am

How about something like this?

Code: Select all

on MouseDown
 grab me
end MouseDown

On MouseUp
   put the loc of me into temp
   if item 1 of temp > 25 then
      put 50 into t1
   else 
      put 0 into t1
   end if
   if item 2 of temp > 25 then
      put 50 into t2
   else 
      put 0 into t2
   end if
   set the loc of me to  (t1,t2)
end MouseUP
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

rumplestiltskin
Posts: 222
Joined: Wed Jun 21, 2006 7:33 pm
Location: West of the Pecos
Contact:

Re: Center a dropped object on a grid

Post by rumplestiltskin » Mon Mar 12, 2018 3:20 am

That's fine if I have only one possible grid location onto which I may drop the dragged object but the trick here is to find that correct location in a grid of 121 possibilities
MaxV wrote:
Mon Mar 12, 2018 2:21 am
How about something like this?

Code: Select all

on MouseDown
 grab me
end MouseDown

On MouseUp
   put the loc of me into temp
   if item 1 of temp > 25 then
      put 50 into t1
   else 
      put 0 into t1
   end if
   if item 2 of temp > 25 then
      put 50 into t2
   else 
      put 0 into t2
   end if
   set the loc of me to  (t1,t2)
end MouseUP

rumplestiltskin
Posts: 222
Joined: Wed Jun 21, 2006 7:33 pm
Location: West of the Pecos
Contact:

Re: Center a dropped object on a grid

Post by rumplestiltskin » Mon Mar 12, 2018 3:40 am

I think I may have found an answer but I had to re-wrap my head about events.

I used this in the dragged object's script:

Code: Select all

on mouseUp
   global inScript
   put true into inScript
   lock screen
   hide me
   click at the loc of me
   show me
   put false into inScript
end mouseUp
There's a reason for the inScript flag and that's in the script that shared by all 121 objects:

Code: Select all

on mouseUp
   global inScript
   if inScript is true then set the loc of button "A1" to the loc of me
end mouseUp
Rather then having to determine which grid location (which is a graphic square) into which I dropped the button, I'm letting the button figure it out for itself by sending a mouseClick to the square directly under it. The "inScript" variable, normally false, prevents a manual click on any square from actually doing anything, whereas the click that's sent by my script hits that square because I hid the button just for the time I needed to send that click to the underlying square and inScript is true momentarily.

Maybe SparkOut's "behavior" would be of use here. I would imagine I would need to programmatically do this although a short handler in each of the 121 squares to direct the mouseUp from the square to a common handler in the stack might be just as easy. Hmm...I'd then probably have to send the loc of the clicked square to the handler in the stack script for each of the 121 squares.

What do you think? Getting closer?

Barry

[-hh]
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2262
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: Center a dropped object on a grid

Post by [-hh] » Mon Mar 12, 2018 1:06 pm

Yet another proposal:
Script your X-Object with the following, nothing else needed.

Code: Select all

on mouseUp
  put 41 into zh -- the horiz distance between the locs
  put 41 into zv -- the vert. distance between the locs
  put the top of grc "A1" into t0 -- assuming grc "A1" is at topleft
  put the left of grc "A1" into l0
  put 1+((the mouseH-l0) div zh) into x -- this is the grid column
  put 1+((the mouseV-t0) div zv) into y -- this is the grid row
  if x > 11 or y > 11 then set loc of me to (520,60) -- a baseloc
  else
    put (char x of "ABCDEFGHIJK")&y into g
    set loc of me to the loc of grc g -- e.g. C2 is column C, row 2
  end if
end mouseUp

on mouseDown
  grab me
end mouseDown
shiftLock happens

MaxV
Posts: 1579
Joined: Tue May 28, 2013 2:20 pm
Location: Italy
Contact:

Re: Center a dropped object on a grid

Post by MaxV » Mon Mar 12, 2018 2:03 pm

Let's see in a livecode point of view.
Create 121 buttons, put it the roccrect positions and name them "pos1" to "pos121". Now make them invisibles.
Now just use this code:

########CODE to copy and paste with you mouse#######
on MouseDown
grab me
end MouseDown

on MouseUp
lock screen
put 2 * (the height of this card) into tMin
repeat with i=1 to 121
put the top of button ("pos" & i) into temp
if (abs(the top of me - temp )) < (abs(the top of me - tMin)) then
put temp into tMin
end if
put the top of me,temp,abs(the top of me - temp ),tMin & return after tutto
end repeat
set the top of me to tMin
put 2 * (the width of this card) into tMin
repeat with i=1 to 121
put the left of button ("pos" & i) into temp
if (abs(the left of me - temp )) < (abs(the left of me - tMin)) then
put temp into tMin
end if
put the left of me,temp,abs(the left of me - temp ),tMin & return after tutto
end repeat
set the left of me to tMin
unlock screen
end MouseUp
#####END OF CODE generated by this livecode app: http://tinyurl.com/j8xf3xq with livecode 9.0.0-dp-11#####
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

SparkOut
Posts: 2852
Joined: Sun Sep 23, 2007 4:58 pm

Re: Center a dropped object on a grid

Post by SparkOut » Mon Mar 12, 2018 6:39 pm

This is what I meant by using behaviors. There is a little bit of fiddling to make the check get despatched to the right grid square, by hiding the button as it's dropped and using the mouseControl to be the target grid square for the check, then showing the button again, all under lock screen.

(Sampler made with LC 9.0 dp 11)
Attachments
DropSnap.zip
(1.28 KiB) Downloaded 176 times

rumplestiltskin
Posts: 222
Joined: Wed Jun 21, 2006 7:33 pm
Location: West of the Pecos
Contact:

Re: Center a dropped object on a grid

Post by rumplestiltskin » Mon Mar 12, 2018 8:19 pm

I've attached a stack (zip'd) with only four of the 121 squares present just so you can see what I ended up doing. I decided against the "grab me" command because, during the move, the location of the object doesn't seem match up to the loc of the mouse; instead, I used "set the loc of me to the mouseLoc" as it seems to maintain accuracy during the drag and subsequent drop.

I added a couple of custom properties to the button (what is dragged) and the graphic squares (where the buttons are dropped). I am keeping track of where the buttons began their move, where they end up, and a "home" property so I may return the buttons to some sort of starting point (for each button). In addition, the graphic squares are keeping track (programmatically) whether their space is occupied by a button or not.

This all seems to work well and the code is, well, more novice-friendly and straightforward than what others have suggested. I am not judging the veracity and efficiency of others' code, just how easy it is to understand for me and the novices I work with.

I see SparkOut is hiding the button momentarily and (great minds think alike) that was my solution, as well. Why not let Livecode make the determination of location directly (with that extra mouseClick) rather than having to parse through the squares (either all 121 or 37 using a quantenary algorithm)?

The next step is to add a few more squares—maybe 6x6—and add some additional code.
To do:
- Is a square occupied? Then I can't drop a button there so put it back where it came from.
- Must "jump" an adjacent button into an empty square. (Move the jumped button off-screen.)
- Can't move to an adjacent square without a jump.
- If I pick up and drop a button in the same square, a "move" hasn't occurred.

Once that all works, I'll duplicate the squares into the 11x11 grid and duplicate buttons ("pegs") until I have 120 (leaving a free space in the middle of the grid). Each of the "pegs" will be given a "home" property so I may reset them to their respective starting points.

If this seems familiar, it's the old "jump the pegs" game that many of you have seen in family restaurants (or maybe owned as a kid - I did) using a wooden board with golf tees. The object is to jump a peg over another into an open space (removing the jumped peg) and repeating until there is only one peg remaining (preferably in the middle of the board).

This is a Livecode development exercise I'll be using as a school project for a class I teach. We'll use a smaller grid for the class but this 11x11 version is large enough to provide many different approaches of solving it at runtime.
Attachments
Peg Game.livecode.zip
(1.74 KiB) Downloaded 189 times

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7228
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Center a dropped object on a grid

Post by jacque » Mon Mar 12, 2018 10:32 pm

Here's a way that doesn't require changing or hiding anything. It goes into the draggable button:

Code: Select all

local sDragging

on mouseDown
  put true into sDragging
end mouseDown

on mouseUp
  put false into sDragging
end mouseUp

on mouseMove x,y
  if not sDragging then exit mouseMove
  set the loc of me to x,y
  put getTarget(the loc of me) into tControl
  put tControl -- do something with it, a script local maybe
end mouseMove

function getTarget pLoc
  repeat with x = 1 to the num of controls
    if the id of control x = the id of me then next repeat
    if within(control x, pLoc) then return the short name of control x
  end repeat
  return empty
end getTarget
You can scan dozens of controls almost instantly so speed shouldn't be an issue. If there are controls you don't want to bother with, group the grid controls and only scan those.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bogs
Posts: 5435
Joined: Sat Feb 25, 2017 10:45 pm

Re: Center a dropped object on a grid

Post by bogs » Mon Mar 12, 2018 11:10 pm

That is pretty neat, I think I'll steal it... erm, I mean, file it away for later use, yah, thats what I meant... :mrgreen:
Image

rumplestiltskin
Posts: 222
Joined: Wed Jun 21, 2006 7:33 pm
Location: West of the Pecos
Contact:

Re: Center a dropped object on a grid

Post by rumplestiltskin » Tue Mar 13, 2018 12:27 am

Jacque,

Very nice! It took me a few false starts with it but I think it may do the trick. I had to make tControl a local variable in order to make it work when used in the mouseUp handler.

Code: Select all

set the loc of me to the loc of graphic tControl
...centered the button in the drop zone.

Now we'll see if the other code I need can be shoehorned in at the appropriate places.

Thanks! (And thanks to all who suggested solutions!)

Barry

[-hh]
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2262
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: Center a dropped object on a grid

Post by [-hh] » Tue Mar 13, 2018 4:56 am

One remark.

Sadly there remains always the same old problem: What does this solution report if controls partially overlap? Or if there is only *one* control (e.g. one polygon graphic that displays the "grid")?

A computed solution needs two divisions only to get the grid "cell" of a given point.
And it works always, even if the "grid" is not a control but a variable only (think of a jigsaw puzzle)...
shiftLock happens

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7228
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Center a dropped object on a grid

Post by jacque » Tue Mar 13, 2018 6:28 am

[-hh] wrote:
Tue Mar 13, 2018 4:56 am
A computed solution needs two divisions only to get the grid "cell" of a given point.
And it works always, even if the "grid" is not a control but a variable only (think of a jigsaw puzzle)...
Very true . I usually like to customize my approach for a problem but you're right it isn't a universal solution. In this case it seemed like the simplest though.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

Post Reply

Return to “Talking LiveCode”