About Monkey 2 › Forums › Monkey 2 Programming Help › Trying to pan and zoom
This topic contains 2 replies, has 2 voices, and was last updated by
cocon 1 year, 3 months ago.
Viewing 3 posts - 1 through 3 (of 3 total)
-
AuthorPosts
-
January 8, 2018 at 11:45 am #12756
I would be interested to find a way to pan and zoom from the center of the screen or the cursor position.
January 8, 2018 at 4:26 pm #12757You can use inverted matrix to reverse the transformation. As for the camera in the center, I pasted a Canvas extension I often use to watch the world “by viewpoint at the center of the screen” so SetCameraByCenter(New Vec2f(0,0)) will place things drawn at 0,0 on the center of the screen. you can even rotate now!
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123#Import "<std>"#Import "<mojo>"Using std..Using mojo..Global gMyWindow:MyWindowClass MyWindow Extends WindowField pan : Vec2fField zoom:Float = 1.0Method New()Super.New("", 800, 600)Stuff.Create()pan=New Vec2f (Width/2,Height/2) 'now set as center to beginEndMethod OnRender(canvas:Canvas) OverrideApp.RequestRender()If Keyboard.KeyDown(Key.Raw|Key.R)zoom = 1.0pan = New Vec2f (Width/2,Height/2)EndIf Keyboard.KeyDown(Key.Raw|Key.Q)zoom -= 0.01EndIf Keyboard.KeyDown(Key.Raw|Key.E)zoom += 0.01EndIf Keyboard.KeyDown(Key.Raw|Key.A) Then pan.X -= 1*zoom 'it's nice to use Key.Raw for non qwerty keyboards..If Keyboard.KeyDown(Key.Raw|Key.D) Then pan.X += 1*zoomIf Keyboard.KeyDown(Key.Raw|Key.W) Then pan.Y += 1*zoomIf Keyboard.KeyDown(Key.Raw|Key.S) Then pan.Y -= 1*zoomcanvas.SetCameraByCenter(pan,zoom) 'no need to push and pop matrix if it's the only tranform of the OnRender() CallStuff.Draw(canvas)If Mouse.ButtonPressed(MouseButton.Left)Local mouseWorldCoord:=-canvas.Matrix*Mouse.Location '- inverts the matrix (to reverse the transformation)'* applies the transformation to the vector (multiplies the vector by the matrix)Stuff.Hit(mouseWorldCoord)EndEndEndClass Stuff AbstractGlobal Items:Vec2f[]Global Hits:Bool[]Function Create()Items = New Vec2f[100]Hits = New Bool[100]For Local i := 0 Until Items.LengthItems[i] = New Vec2f(i * 20, Rnd(-100, 100))Hits[i] = FalseNextEndFunction Hit(p:Vec2f)For Local i := 0 Until Items.LengthLocal x := Items[i].XLocal y := Items[i].YIf Contains(x - 5, x + 5, y - 5, y + 5, p.x, p.y)Hits[i] = TruePrint("Hit Success: " + i)ExitEndNextEndFunction Contains:Bool(minx:Float, maxx:Float, miny:Float, maxy:Float, x:Float, y:Float)Return x>=minx And x<maxx And y>=miny And y<maxyEndFunction Draw(canvas:Canvas)For Local i := 0 Until Items.LengthIf Not Hits[i]canvas.Color = Color.WhiteElsecanvas.Color = Color.RedEndcanvas.DrawRect(Items[i].X - 5, Items[i].Y - 5, 10, 10)NextEndEndClass Canvas ExtensionMethod SetCameraByCenter(point_x:Float,point_y:Float,zoom:Float=1.0,rotation:Float=0.0)Translate(Viewport.Width/2,Viewport.Height/2) 'Modify this line to change to something else than centerScale(zoom,zoom)Rotate(rotation)Translate(-point_x,-point_y)EndMethod SetCameraByCenter(point:Vec2f,zoom:Float=1.0,rotation:Float=0)Translate(Viewport.Width/2,Viewport.Height/2) 'Modify this line to change to something else than centerScale(zoom,zoom)Rotate(rotation)Translate(-point)EndEndFunction Main()New AppInstancegMyWindow = New MyWindowApp.Run()EndJanuary 8, 2018 at 10:03 pm #12761Awesome!
After doing some tests and trying to figure out how to add rotations I resulted to this one.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181#Import "<std>"#Import "<mojo>"Using std..Using mojo..Global gMyWindow:MyWindowClass MyWindow Extends WindowField pan : Vec2f ' to hold the panningField zoom : Float = 1.0 ' to hold the zoomingField rot : Float = 0.0 ' to hold the rotationField viewSpeed : Float = 2.0 ' the speed of panningField canvasView: AffineMat3f ' to keep a copy of the view matrixField messages : String[] ' to render some text on the screenMethod New()Super.New("", 800, 600)Stuff.Create()pan = New Vec2f(Width / 2, Height / 2)messages = New String[3]EndMethod OnRender(canvas:Canvas) OverrideApp.RequestRender()' USER INPUT FOR VIEW' user input for controlling the view valuesIf True' rotation and zoom won't have any problem' but panning will have to be based on trigonometry calculationsIf Keyboard.KeyHit(Key.Raw | Key.R)pan = New Vec2f(Width / 2, Height / 2)zoom = 1.0rot = 0.0EndIf Keyboard.KeyDown(Key.Raw | Key.Q) Then zoom -= 0.01If Keyboard.KeyDown(Key.Raw | Key.E) Then zoom += 0.01If Keyboard.KeyDown(Key.Raw | Key.A)Local speed := viewSpeed * zoompan.X -= Cos(rot) * speedpan.Y -= Sin(rot) * speedEndIf Keyboard.KeyDown(Key.Raw | Key.D)Local speed := viewSpeed * zoompan.X += Cos(rot) * speedpan.Y += Sin(rot) * speedEndIf Keyboard.KeyDown(Key.Raw | Key.W)Local speed := viewSpeed * zoompan.X += Cos(rot - MathHelper.DegreesToRadians(90)) * speedpan.Y += Sin(rot - MathHelper.DegreesToRadians(90)) * speedEndIf Keyboard.KeyDown(Key.Raw | Key.S)Local speed := viewSpeed * zoompan.X -= Cos(rot - MathHelper.DegreesToRadians(90)) * speedpan.Y -= Sin(rot - MathHelper.DegreesToRadians(90)) * speedEndIf Keyboard.KeyDown(Key.Raw | Key.Z) Then rot -= 0.01 * zoomIf Keyboard.KeyDown(Key.Raw | Key.C) Then rot += 0.01 * zoomEnd' SCREEN TO WORLD HIT TEST' demonstrate how convert the screen coords to world coordsIf TrueIf Mouse.ButtonPressed(MouseButton.Left)Local mouseWorldCoord := -canvasView * Mouse.LocationPrint("Mouse: " + Mouse.Location)Print("Transformed: " + mouseWorldCoord)Stuff.Hit(mouseWorldCoord)EndEnd' DRAW THE WORLDIf True' I can do PushMatrix so after this' operation is done it can be restored' to the window based coordinate systemcanvas.PushMatrix()canvas.Translate(Width/2, Height/2)canvas.Rotate(rot)canvas.Scale(zoom, zoom)canvas.Translate(-pan)Stuff.Draw(canvas)' I will have to keep a copy of the current transform' in order to use it for the hit testcanvasView = canvas.Matrixcanvas.PopMatrix()End' DRAW VARIOUS GUI STUFFIf Truecanvas.Color = Color.Blackmessages[0] = "Pan: " + panmessages[1] = "Rotation: " + MathHelper.RadiansToDegrees(rot)messages[2] = "Zoom: " + zoomFor Local i := 0 Until messages.Lengthcanvas.DrawText(messages[i], 10, 10 + (i*12))NextEndEndMethod DrawLastHitOnGUI(canvas:Canvas)If Stuff.LastHit <> -1Local p := Stuff.Items[Stuff.LastHit]canvas.DrawCircle(p.X-5, p.Y-5, 10)EndEndEndClass Stuff AbstractGlobal Items:Vec2f[]Global Hits:Bool[]Global LastHit:IntFunction Create()Items = New Vec2f[100]Hits = New Bool[100]For Local i := 0 Until Items.Length' these coordinates are world based, nothing to do with monitorItems[i] = New Vec2f(i * 20, Rnd(0, 500))Hits[i] = FalseNextLastHit = -1EndFunction Hit(p:Vec2f)For Local i := 0 Until Items.LengthLocal x := Items[i].XLocal y := Items[i].Y' no problem to use rect collision since it happens in the world spaceIf Contains(x - 10, x + 10, y - 10, y + 10, p.x, p.y)Hits[i] = TrueLastHit = iPrint("Hit Index: " + i + ", Position: " + Items[i])ExitEndNextLastHit = -1EndFunction Contains:Bool(minx:Float, maxx:Float, miny:Float, maxy:Float, x:Float, y:Float)Return x >= minx And x < maxx And y >= miny And y < maxyEndFunction Draw(canvas:Canvas)For Local i := 0 Until Items.LengthIf Not Hits[i]canvas.Color = Color.WhiteElsecanvas.Color = Color.RedEndcanvas.DrawRect(Items[i].X - 10, Items[i].Y - 10, 20, 20)NextEndEndFunction Main()New AppInstancegMyWindow = New MyWindowApp.Run()EndClass MathHelper AbstractFunction DegreesToRadians:Double(degrees:Double)Return degrees * (Pi / 180.0)EndFunction RadiansToDegrees:Double(radians:Double)Return radians * (180.0 / Pi)EndEnd -
AuthorPosts
Viewing 3 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic.