[{"data":1,"prerenderedAt":10},["ShallowReactive",2],{"2-making-simple-auto-follow-camera":3},{"title":4,"preview":5,"createdDate":6,"updatedDate":6,"slug":7,"description":8,"content":9},"Making simple auto follow camera","","2026-02-02T13:00:02.000Z","2-making-simple-auto-follow-camera","A guide to make a simple auto follow marbles camera","\u003Cp>In this tutorial, we will create a simple system that make camera automatically follow a group of marbles in Algodoo.\u003C/p>\u003Ch2>Create the controller\u003C/h2>\u003Cp>Create a box and name it &quot;Auto Camera&quot;. This box will act as the camera controller, it stores the marbles list and controls the camera.\u003C/p>\u003Cimg alt=\"AutoCameraBox.png\" src=\"/assets/blog/2-making-simple-auto-follow-camera/b3qw6iuaflbptvibhkfd.webp\">\u003Cp>We make global reference to this controller and create a function to add marble to list. Paste this into console in script menu:\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">_marbles := [];\r\n_count := 0;\r\n\r\npostStep = (e) =&gt; {\r\n    scene.temp.autoCamera = e.this;\r\n    postStep = (e) =&gt; {}\r\n};\r\n\r\n_addMarble := (marble) =&gt; {\r\n    _marbles = _marbles ++ [marble];\r\n    _count = _count + 1\r\n};\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Cimg alt=\"Console\" src=\"/assets/blog/2-making-simple-auto-follow-camera/rhtg39ksjn6ic3lwfx4x.webp\">\u003Ch2>Marble Script\u003C/h2>\u003Cp>Each marble must register itself to the controller.\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">postStep = (e) =&gt; {\r\n    sim.tick &gt; 1 ? {\r\n        scene.temp.autoCamera._addMarble(e.this);\r\n        postStep = (e)=&gt;{}\r\n    } : {}\r\n}\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Ch2>Camera Script\u003C/h2>\u003Cp>To control the camera, we need to know where to center it and how much to zoom. We do this by calculating a bounding box around all marbles.\u003C/p>\u003Cimg alt=\"BoundingBox\" src=\"/assets/blog/2-making-simple-auto-follow-camera/qoaoconcpjljn7lmv9sv.webp\">\u003Cp>Back in the &quot;Auto Camera&quot; box, define an update camera function.\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">_updateCamera := (dt) =&gt; {\r\n    _calculateBound;\r\n    _move(dt);\r\n    _zoom(dt)\r\n};\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Cp>Now add calculate bounding box function. This finds the outer edges, width and height.\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">_left := 0;\r\n_right := 0;\r\n_top := 0;\r\n_bot := 0;\r\n_w := 0;\r\n_h := 0;\r\n\r\n_calculateBound := {\r\n    _right = -inf;\r\n    _left = +inf;\r\n    _top = -inf;\r\n    _bot = +inf;\r\n\r\n    for(_count, (i) =&gt; {\r\n        marble := _marbles(i);\r\n        marble.pos(0) &gt; _right? { _right = marble.pos(0) } : {};\r\n        marble.pos(0) &lt; _left? { _left = marble.pos(0) } : {};\r\n        marble.pos(1) &gt; _top? { _top = marble.pos(1) } : {};\r\n        marble.pos(1) &lt; _bot? { _bot = marble.pos(1) } : {}\r\n    });\r\n    \r\n    _w = _right - _left;\r\n    _h = _top - _bot\r\n};\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Cp>Once we have the bouding box, we can calculate the center point and use lerp to smoothly move the camera toward that point.\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">_moveSpeed := 2;\r\n\r\n_move := (dt) =&gt; {\r\n    center := [(_left + _right) * 0.5, (_top + _bot) * 0.5];\r\n    scene.camera.pan = math.lerp(scene.camera.pan, center, _moveSpeed* dt)\r\n};\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Cp>Next, we want to keep marbles in view. We will find the greatest distance by compare width and height of bouding box and use lerp to adjust zoom smoothly.\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">_zoomSpeed := 2;\r\n_zoomLimit := [40, 100];\r\n_distanceLimit := 20;\r\n\r\n_zoom := (dt) =&gt; {\r\n    dist := math.max(_w, _h);\r\n    zoom := math.lerp(_zoomLimit(1), _zoomLimit(0), dist / _distanceLimit);\r\n    zoom = math.clamp(zoom, _zoomLimit(0), _zoomLimit(1));\r\n    scene.camera.zoom = math.lerp(scene.camera.zoom, zoom, _zoomSpeed * dt)\r\n}\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Cp>Finally, update postStep to call _updateCamera:\u003C/p>\u003Cdiv class=\"code-block\">\u003Cpre>\u003Ccode class=\"language-plain\">postStep = (e) =&gt; {\r\n    scene.temp.AutoCamera = e.this;\r\n    postStep = (e) =&gt; {\r\n        _updateCamera(e.dt);\r\n    }\r\n};\r\n\u003C/code>\u003C/pre>\u003C/div>\u003Cp>Adjust _moveSpeed, _zoomSpeed, _zoomLimit and _distanceLimit to fit your need.\u003C/p>\u003Ch2>Result\u003C/h2>\u003Cvideo controls=\"\">\u003Csource src=\"/assets/blog/2-making-simple-auto-follow-camera/sfnywv1paqjtzqd9ehdt.webm\" type=\"video/mp4\">\u003C/video>\u003Cp>\u003Ca href=\"https://drive.google.com/uc?export=download&amp;id=1PwCVJr2QtSeFcTnLnIX32PzU-1uieUPF\" rel=\"noopener noreferrer\" target=\"_blank\">Download scene here\u003C/a>\u003C/p>",1772447366060]