Rotating an Image with Specified "Forward" Directi

LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
mokogobo
Posts: 37
Joined: Wed Jun 18, 2008 6:27 pm
Contact:

Rotating an Image with Specified "Forward" Directi

Post by mokogobo » Sun Jul 27, 2008 5:45 pm

Hello. I'm working on a project where I need to rotate an image object with a specified "facing" direction (since an image doesn't always have contents facing a certain direction) so that it will always face the correct direction when moving along a curve specified by a set of points.

I can move an image along a curve, and I'm setting the "facing" direction with a custom property, but I'm having some difficulty coming up with a way to rotate the image. I'm interested in any pointers or examples. Any help will be appreciated.

Thanks!

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4027
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Post by bn » Sun Jul 27, 2008 10:29 pm

Hi mokogobo,

look at angle

you can set the angle of an image

create an image
call it "i1"
set the border to false in the inspector
fill the image with a color, lets say with the bucket tool

create a slider
in the inspector set the start value to 0
set the end value to 360

set the script of the slider to:

-----------
on scrollbarDrag pScrollValue
set the angle of image "i1" to pScrollValue
end scrollbarDrag
-----------

now you can rotate the image

I dont quite understand how you want to change the angle of an image while moving.
If I get you right you could calculate the angle between every two points of your pointlist and move from point to point after adjusting the angle of the image between moves


regards

Bernd

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4027
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Post by bn » Sun Jul 27, 2008 11:38 pm

OK, mokobogo

try this and see if it is what you want:

you can use the stack from my previous post or make a new one

it has an image that is called "i1"

make a freehand polygon graphic with not too many points to begin with and call it "g1"

now make a button

set the script to the button to:

------------------
on mouseUp pMouseBtnNo
put the points of graphic "g1" into thePoints
MoveAndRotate thePoints
end mouseUp


on MoveAndRotate theList
repeat with i = 1 to the number of lines of theList-1
put line i of theList into aPoint1
put line i + 1 of theList into aPoint2
put theAngle (aPoint1, aPoint2) into tThatAngle
set the angle of image "i1" to tThatAngle
move image "i1" from aPoint1 to aPoint2
end repeat

end MoveAndRotate

function theAngle tPoint1, tPoint2

put item 1 of tPoint1 into x1
put item 2 of tPoint1 into y1
put item 1 of tPoint2 into x2
put item 2 of tPoint2 into y2

put x1-x2 into oppositeLeg
put y1-y2 into adjacentLeg
return round (abs(atan2(adjacentLeg,oppositeleg)*180/pi-180))
end theAngle
-----------------------

this lets the image 'walk' along the path of graphic "g1" and the angle of the image is adjusted to the angle between every two points.

By the way you could make graphic "g1" invisible and the image would still follow the path.

Now depending on the number of points the movement may look a little jerky.

Malte is an expert in animation, he wrote the animation engine and he probably has a lot of ideas how to make the movement smother. He might comment on this.
But this is what I can offer and I hope it gives you some ideas. there is plenty of room for improvement.
Please note that I 'lifted' the code for the angle somwhere, I don't know anything about atan2 :)

regards

Bernd

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4027
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Post by bn » Mon Jul 28, 2008 8:05 pm

Hi,

maybe mokogobo is up to something else but I post this anyway if anybody is interested in a nonblocking version of the move and rotate thing
Additionally I rotate the image now a lot more smoothly with controllable degrees of the rotational steps, looks much better now. Moving speed is also controllable.

Again:
Make a new stack
make a freehand or freehand polygon graphic you call "g1"
make an image you call "i1"
make a button that you call "MoveAndRotate"
set the script of this button to the following script mind the linewraps

script of btn
-----------------------------------------
local tOldAngle, thePoints, tSoOften, tRelAngle, tMaxMoves

on mouseUp pMouseBtnNo
put empty into tOldAngle
put 0 into tSoOften

-- to control how fast the moves are
-- Rev's default is 200,
set the movespeed to 200

put the points of graphic "g1" into thePoints
-- look for the number of moves to make
put the number of lines of thePoints - 1 into tMaxMoves
MoveAndRotate
end mouseUp

on MoveAndRotate
add 1 to tSoOften

if tSoOften > tMaxMoves then
set the angle of image "i1" to 0
exit MoveAndRotate
end if

put tSoOften into i

put line i of thePoints into aPoint1
put line i + 1 of thePoints into aPoint2

put theAngle (aPoint1, aPoint2) into tThatAngle

put 3 into tStepSize -- increase to speed up rotation, decrease to make rotation smoother
if tOldAngle <> "" then

put abs (tRelangle) mod tStepSize into tTheRest

if tRelAngle > 0 then
repeat with a = 1 to (tRelangle - tTheRest) step tStepSize
set the angle of image "i1" to (tOldAngle + a)
wait 1 milliseconds with messages
end repeat
set the angle of image "i1" to the angle of image "i1" + tTheRest
end if

if tRelAngle < 0 then
repeat with a = 1 to ((abs(tRelangle)) - tTheRest) step tStepSize
set the angle of image "i1" to (tOldAngle - a)
wait 1 milliseconds with messages
end repeat
set the angle of image "i1" to the angle of image "i1" - tTheRest
end if
else
set the angle of image "i1" to tThatAngle
end if

move image "i1" from aPoint1 to aPoint2 without waiting
put tThatAngle into tOldAngle
end MoveAndRotate


function theAngle tPoint1, tPoint2
-- find absolute angle
put item 1 of tPoint1 into x1
put item 2 of tPoint1 into y1
put item 1 of tPoint2 into x2
put item 2 of tPoint2 into y2
put x1-x2 into oppositeLeg
put y1-y2 into adjacentLeg
put round (abs(atan2(adjacentLeg,oppositeleg)*180/pi-180)) into tNewAbsoluteAngle

-- find relative angle from old absolute angle and new absolute angle
-- with the relative angle you can rotate the image smoother because you
-- just rotate the difference between old and new angle
-- there must be a smarter way to calculate this...
if tSoOften > 1 then -- start in the second round
if tOldAngle ≠ "" then -- no old angle if it is the first round
if not (oppositeLeg = 0 and adjacentLeg = 0) then -- keine bewegung

put tOldAngle into tAngle1
put tNewAbsoluteAngle into tAngle2

if tAngle2 ≥ tAngle1 then
put 180 - (tAngle2 - tAngle1) into tChangeOfDirection
end if

if tAngle2 < tAngle1 then
put ((tAngle1 - tAngle2) - 180) into tChangeOfDirection
end if

if tChangeOfDirection < 0 then
put ( abs (tChangeOfDirection)) - 180 into tChangeOfDirection
else
put (180 - tChangeOfDirection) into tChangeOfDirection
end if

end if -- oppositeLeg = 0 and adjacentLeg = 0
end if -- tOldAngle ≠ "" then
end if -- tSoOften > 1

put tChangeOfDirection into tRelAngle
return tNewAbsoluteAngle
end theAngle
----------------------
end of button script

now you make a card script

card script
---------------------
on moveStopped
send "moveAndRotate" to btn "MoveAndRotate" in 1 milliseconds
end moveStopped

on arrowKey whichKey
put the movespeed into tSpeed
if whichKey is down then
if tSpeed > 20 then set the movespeed to round((tspeed -(tSpeed * .2)))
end if
if whichKey is up then
if tSpeed < 2000 then set the movespeed to round((tspeed +(tSpeed * .2)))
end if
end arrowKey
--------------------------------
end card script

If you feel like it you can add a button to stop the move, call it what you want
script of that button
-----------------------------
on mouseUp pMouseBtnNo
stop moving image "i1"
end mouseUp
-----------------------------

and a button to restart the movement, call it what you want
script of that button
----------------------------
on mouseUp pMouseBtnNo
send "moveAndrotate" to btn "moveandRotate"
end mouseUp
----------------------------

because of the card script you can controll the speed of the movement with the arrowkey up (faster) and down (slower)

In making the code non-blocking (not all code executed before Rev idles again) you have the opportunity to tweak parameters while the image is moving, like speed or stopping and restarting and more.

probably not the shortest posting :)
but I like it when I find working code and this should work.

If you just want to move objects around without rotating them everything is a lot easier.
You probably could adjust this code for more than one object, but that adds considerably to the complexity of this.

alright, got this off of my mind

regards
bernd

mokogobo
Posts: 37
Joined: Wed Jun 18, 2008 6:27 pm
Contact:

Post by mokogobo » Tue Jul 29, 2008 2:50 am

Awesome. Thank you all for your help! :-)

mokogobo
Posts: 37
Joined: Wed Jun 18, 2008 6:27 pm
Contact:

Post by mokogobo » Wed Jul 30, 2008 7:14 am

mokogobo wrote:Awesome. Thank you all for your help! :-)
And of course by "you all" I mean "bn". ;-) I appreciate it.

Post Reply

Return to “Getting Started with LiveCode - Experienced Developers”