Center a dropped object on a grid
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
-
- Posts: 222
- Joined: Wed Jun 21, 2006 7:33 pm
- Location: West of the Pecos
- Contact:
Center a dropped object on a grid
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:
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
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
Re: Center a dropped object on a grid
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.
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.
-
- Posts: 222
- Joined: Wed Jun 21, 2006 7:33 pm
- Location: West of the Pecos
- Contact:
Re: Center a dropped object on a grid
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
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
Re: Center a dropped object on a grid
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
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w
-
- Posts: 222
- Joined: Wed Jun 21, 2006 7:33 pm
- Location: West of the Pecos
- Contact:
Re: Center a dropped object on a grid
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 amHow 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
-
- Posts: 222
- Joined: Wed Jun 21, 2006 7:33 pm
- Location: West of the Pecos
- Contact:
Re: Center a dropped object on a grid
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:
There's a reason for the inScript flag and that's in the script that shared by all 121 objects:
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
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
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
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
-
- 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
Yet another proposal:
Script your X-Object with the following, nothing else needed.
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
Re: Center a dropped object on a grid
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#####
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
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w
Re: Center a dropped object on a grid
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)
(Sampler made with LC 9.0 dp 11)
- Attachments
-
- DropSnap.zip
- (1.28 KiB) Downloaded 178 times
-
- Posts: 222
- Joined: Wed Jun 21, 2006 7:33 pm
- Location: West of the Pecos
- Contact:
Re: Center a dropped object on a grid
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.
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 190 times
-
- VIP Livecode Opensource Backer
- Posts: 7235
- Joined: Sat Apr 08, 2006 8:31 pm
- Location: Minneapolis MN
- Contact:
Re: Center a dropped object on a grid
Here's a way that doesn't require changing or hiding anything. It goes into the draggable button:
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.
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
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com
HyperActive Software | http://www.hyperactivesw.com
Re: Center a dropped object on a grid
That is pretty neat, I think I'll steal it... erm, I mean, file it away for later use, yah, thats what I meant...
-
- Posts: 222
- Joined: Wed Jun 21, 2006 7:33 pm
- Location: West of the Pecos
- Contact:
Re: Center a dropped object on a grid
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.
...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
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
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
-
- 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
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)...
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
-
- VIP Livecode Opensource Backer
- Posts: 7235
- Joined: Sat Apr 08, 2006 8:31 pm
- Location: Minneapolis MN
- Contact:
Re: Center a dropped object on a grid
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
HyperActive Software | http://www.hyperactivesw.com