Rotating an Image with Specified "Forward" Directi
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
Rotating an Image with Specified "Forward" Directi
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!
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!
-
- VIP Livecode Opensource Backer
- Posts: 4027
- Joined: Sun Jan 07, 2007 9:12 pm
- Location: Bochum, Germany
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
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
-
- VIP Livecode Opensource Backer
- Posts: 4027
- Joined: Sun Jan 07, 2007 9:12 pm
- Location: Bochum, Germany
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
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
-
- VIP Livecode Opensource Backer
- Posts: 4027
- Joined: Sun Jan 07, 2007 9:12 pm
- Location: Bochum, Germany
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
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