About Monkey 2 › Forums › Monkey 2 Programming Help › How to rotate an image like in graphic apps
This topic contains 6 replies, has 3 voices, and was last updated by
Ratchet 1 year, 8 months ago.
-
AuthorPosts
-
August 5, 2017 at 5:10 pm #9734
I got kind of a graphical app where the user can add images and can place it on the screen with drag and drop anywhere. Simple stuff, guess I don’t have to explain, how it works.
Now I want let the user to rotate the image like you can so in most graphical apps. See the attached GIF/MP4, please.First problem: I can’t select the image anymore just by checking if the mouse position inside the image’s rect. Now the rect might be rotated and is more like an polygon. Ok, I know how to check the if a point inside a polygon, BUT
Second problem: How to rotate a polygon?
Then more you think about it, then more problems are coming out.
Does anyone got a good idea how to do this rotation stuff?
August 5, 2017 at 5:32 pm #9737The most common way to do this is to use matrix transform. It’s what mojo uses. There is an affineMat3 class wich is usable for rotate/size/translate transforms. Matrices are your friends, this is the most usefull Math stuff you can have for video games after trigonometry..
August 6, 2017 at 6:57 am #9745here’s a little example of a transformable poly that can be enhanced to get what you need, you can add size too..
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100Namespace myapp#Import "<std>"#Import "<mojo>"Using std..Using mojo..Struct TransformablePoly 'I'll assume here that center of polys are [0,0] so I'll wrap arround origin while creating themField transfoMat:AffineMat3fPrivateField _nbVertices:intField _vertices:Vec2f[]PublicMethod New(verts:Vec2f[])_vertices=verts_nbVertices=_vertices.GetSize(0) 'getting the number of vec2f in the arraytransfoMat=New AffineMat3f()EndMethod GetTransformedXYArray:Float[]() 'to be used with DrawPoly (it does not accepts vec2f!)Local outputArray:=New Float[_nbVertices*2]Local TranformedVec2:=GetTransformedVec2fPoly() 'getting the tranformed poly in a Vec2f arrayFor Local i:=0 Until _nbVerticesoutputArray[2*i]=TranformedVec2[i].xoutputArray[2*i+1]=TranformedVec2[i].yNextReturn outputArray 'ouputing transformed poly in a x/y Float array (for drawpoly)EndMethod GetTransformedVec2fPoly:Vec2f[]() 'Transforms all the vertices with the AffineMat3Local outputArray:=New Vec2f[_nbVertices]For Local i:=0 Until _nbVerticesoutputArray[i]=transfoMat.Transform(_vertices[i])NextReturn outputArrayEndEndClass MyWindow Extends WindowField poly1:TransformablePolyMethod New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )Super.New( title,width,height,flags )' The polys are initialised with (0,0) as their (rotation and scale) center, it the easiest way to "view" with matrixpoly1=New TransformablePoly(New Vec2f[](New Vec2f(-10.0,-10.0),New Vec2f(10.0,-10.0),New Vec2f(10.0,10.0),New Vec2f(-10.0,10.0))) 'a square in polygon format (center at 0,0)' Here is the interresting stuff !!!' The order of the transforms has it's importance!' It looks like we first translate then rotate BUT NOT!!!!!!!!' Think it as a stack: Last in = First out'' Having the rotation as the first transform is more intuitive because' the center of the poly will have the corresponding translate positionpoly1.transfoMat=poly1.transfoMat.Translate(100,100) 'second transformpoly1.transfoMat=poly1.transfoMat.Rotate(Pi/4) 'rotation arrond (0,0)! , first transform' this should be implemented into the struct to have something like "poly1.Translate(100,100)"' and voilà! you have a transformable poly...EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()canvas.DrawPoly(poly1.GetTransformedXYArray())EndEndFunction Main()New AppInstanceNew MyWindowApp.Run()Endyou can extract translate,rotate and size from a AffineMat3 too if you need. see http://monkeycoder.co.nz/forums/topic/matrix-scale/
August 8, 2017 at 6:24 am #9765Here is a much more intuitive form of Tpoly.. It’s using position, angle and scale fields instead of affineMat3. But is of course internally using an affineMat3 to transform the original poly (centered at the origin, you could add a center/handle field too and make one more translation to center it to the origin before rotating/scaling).
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105Namespace myapp#Import "<std>"#Import "<mojo>"Using std..Using mojo..Struct TransformablePoly 'I'll assume here that center of polys are [0,0] so I'll wrap arround origin while creating themField position:=New Vec2f()Field scale:=1.0Field angle:=0.0PrivateField _nbVertices:intField _vertices:Vec2f[]PublicMethod New(verts:Vec2f[])_vertices=verts_nbVertices=_vertices.GetSize(0) 'getting the number of vec2f in the arrayEndMethod GetTransformedVec2fPoly:Vec2f[]() 'Transforms all the vertices with AffineMat3' creating a transformation matrixLocal transfo:=New AffineMat3f()transfo=transfo.Translate(position) 'third transformtransfo=transfo.Scale(scale,scale) 'around (0,0) , second transformtransfo=transfo.Rotate(angle) 'rotation arrond (0,0)! , first transform'transforming the verticesLocal outputArray:=New Vec2f[_nbVertices]For Local i:=0 Until _nbVerticesoutputArray[i]=transfo.Transform(_vertices[i])NextReturn outputArrayEndMethod GetTransformedXYPoly:Float[]() 'to be used with DrawPoly (it does not accepts vec2f!)Local outputArray:=New Float[_nbVertices*2]Local TranformedVec2:=GetTransformedVec2fPoly() 'getting the tranformed poly in a Vec2f arrayFor Local i:=0 Until _nbVerticesoutputArray[2*i]=TranformedVec2[i].xoutputArray[2*i+1]=TranformedVec2[i].yNextReturn outputArray 'ouputing transformed poly in a x/y Float array (for drawpoly)EndEndClass MyWindow Extends WindowField poly1:TransformablePolyField count:=0Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )Super.New( title,width,height,flags )poly1=New TransformablePoly(New Vec2f[](New Vec2f(-10.0,-10.0),New Vec2f(10.0,-10.0),New Vec2f(10.0,10.0),New Vec2f(-10.0,10.0))) 'a square in polygon format (center at 0,0)EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()count+=1If count>400 Then count=10poly1.angle=count/100.0poly1.position=New Vec2f(count,count)poly1.scale=1.5-Sin(count/60.0)canvas.DrawPoly(poly1.GetTransformedXYPoly())EndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndAugust 9, 2017 at 2:47 am #9770You can rotate images by canvas.DrawImage( image:Image,tx:Float,ty:Float,rz:Float ) where rz is rotation angle.
Also you need to use image.Handle property to setup rotation anchor for image.
For detection images by click you can use polygon / rect function like that or even chipmunk physics collider (I want to use it for complex shapes, but didn’t try yet).
August 9, 2017 at 7:45 am #9772Now the rect might be rotated and is more like an polygon. Ok, I know how to check the if a point inside a polygon, BUT
Second problem: How to rotate a polygon?
If you only want rotated rects then nerobot’s solution is probably better (more monkeyish)
August 9, 2017 at 7:46 am #9773Great, thank you so much. That will do it.
I thought about Chipmunk, too. But I guess it’s way oversized for that “simple” stuff I need it for.
-
AuthorPosts
You must be logged in to reply to this topic.
