{"id":404,"date":"2025-07-08T16:43:33","date_gmt":"2025-07-08T06:43:33","guid":{"rendered":"https:\/\/nonlinearexperience.com\/?p=404"},"modified":"2025-07-15T15:21:57","modified_gmt":"2025-07-15T05:21:57","slug":"camera","status":"publish","type":"post","link":"https:\/\/nonlinearexperience.com\/index.php\/2025\/07\/08\/camera\/","title":{"rendered":"Camera"},"content":{"rendered":"<h1 class=\"wp-block-post-title\">Camera<\/h1>\n\n\n<p>See also:<\/p>\n\n\n\n<p>System:<\/p>\n\n\n\n<p>&#8216;Camera Manipulations&#8217;<\/p>\n\n\n\n<p>Camera methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n\n\n\n<p>needs to know:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>target\n<ul class=\"wp-block-list\">\n<li>player<\/li>\n\n\n\n<li>npc<\/li>\n\n\n\n<li>item<\/li>\n\n\n\n<li>nothing (tracks the &#8216;ground&#8217;)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>viewport x and y\n<ul class=\"wp-block-list\">\n<li>this is the dimensions of what the camera &#8216;sees&#8217;<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>bounds x and y\n<ul class=\"wp-block-list\">\n<li>these are the levels edges<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>What is the view point &#8211; how does the camera interact (or not) with the player<\/p>\n\n\n\n<p>Most common is: locks onto player &#8211; stops at level edges<\/p>\n\n\n\n<p>Centre on player &#8211; player is static (apart from animations etc.) and bg scrolls &#8211; tops at level edges<\/p>\n\n\n\n<p>Camera box &#8211; player moves around screen until they hit a margin\/border, then bg scrolls<\/p>\n\n\n\n<p>Factors: where the player is &#8211; what happens to the background &#8211; what happens at teh edge of the map<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Options<\/p>\n\n\n\n<p>Locks to player<\/p>\n\n\n\n<p>Can have it lock to NPCs<\/p>\n\n\n\n<p>Can have it lock to Map<\/p>\n\n\n\n<p>Can have it change mid<\/p>\n\n\n\n<p>Easing &#8211; refer to an easing lookup &#8211; (see <a href=\"https:\/\/docs.google.com\/document\/d\/1-F5AUCgCMoi2p-x4N3mE8R-R8_VvGjWPZEpikCZUDdw\/edit#heading=h.7yk983vzrdib\">Easing<\/a>)<\/p>\n\n\n\n<p>Can do any of the following, including one then the other:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Follow<\/li>\n\n\n\n<li>Track to<\/li>\n\n\n\n<li>Static<\/li>\n<\/ul>\n\n\n\n<p>If tracking, what to do at map or map section edge &#8211; know the map size and where we are in 9t &#8211; calculate the bounds and gutter ahead of time<\/p>\n\n\n\n<p>The camera has an offset, based upon the viewport being 22 x 16px cells wide and&nbsp;<\/p>\n\n\n\n<p>10.5 offset x<\/p>\n\n\n\n<p>6 offset y<\/p>\n\n\n\n<p>22 &#8211; viewportCells<\/p>\n\n\n\n<p>so, the calculation is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>total # of cells width &#8211; 1 (for camera position) \/ 2<\/li>\n\n\n\n<li>w &#8211; 1 \/ 2 = offset<\/li>\n\n\n\n<li>viewportCells &#8211; 1 \/ 2 = 10.5<\/li>\n<\/ul>\n\n\n\n<p>In &#8216;<strong>overworld.js<\/strong>&#8216;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/ Establish the camera person\nconst cameraPerson = this.map.gameObjects.hero;\n<\/pre><\/div>\n\n\n<p>Or a fixed position:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconst cameraPerson = {x: utils.withGrid(7), y: utils.withGrid(6)};\n<\/pre><\/div>\n\n\n<h6 class=\"wp-block-heading\"><strong>Camera &#8211; changing camera person<\/strong><\/h6>\n\n\n\n<p>**** NOTE **** We can change who the camera person is for a cut scene, or other thing if we want, just by changing this value\u2026<\/p>\n\n\n\n<p>Also, might want to consider locking the input controls temporarily while this happens\u2026<\/p>\n\n\n\n<p><strong>Lock input<\/strong><\/p>\n\n\n\n<p>Look into how the cut scene locks out the input &#8211; see: <strong>isCutScenePlaying <\/strong>and <strong>checkForActionCutscene<\/strong> in <strong>OverworldMap.js<\/strong><\/p>\n\n\n\n<p>Can also use this &#8211; will pause <strong>everything <\/strong>else tho\u2026<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nthis.map.isPaused = true;\n<\/pre><\/div>\n\n\n<p>Then sent to the draw map layers and game objects thing:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/ Draw Lower layer\nthis.map.drawLowerImage(this.ctx, cameraPerson);\n<\/pre><\/div>\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/ Draw Upper layer\nthis.map.drawUpperImage(this.ctx, cameraPerson);\n<\/pre><\/div>\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nobject.sprite.draw(this.ctx, cameraPerson);\n<\/pre><\/div>\n\n\n<p>in &#8216;<strong>OverworldMap.js<\/strong>&#8216;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\ndrawLowerImage(ctx, cameraPerson) {\n\u00a0\u00a0\u00a0\u00a0ctx.drawImage(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.lowerImage,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0utils.withGrid(10.5) - cameraPerson.x,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0utils.withGrid(6) - cameraPerson.y)\n}\n\ndrawUpperImage(ctx, cameraPerson){\n\u00a0\u00a0\u00a0\u00a0ctx.drawImage(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.upperImage,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0utils.withGrid(10.5) - cameraPerson.x,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0utils.withGrid(6) - cameraPerson.y)\n}\n<\/pre><\/div>\n\n\n<p>then in the &#8216;<strong>sprite.js<\/strong>&#8216;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconst x = this.gameObject.x -8 + utils.withGrid(10.5) - cameraPerson.x;\nconst y = this.gameObject.y -18 + utils.withGrid(6) - cameraPerson.y;\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>That&#8217;s it!!<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h6 class=\"wp-block-heading\"><strong>Camera person flag<\/strong><\/h6>\n\n\n\n<p>Set the camera person flag in <strong>OverworldMap.js<\/strong><\/p>\n\n\n\n<p>Add this to the constructor:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nthis.camera = config.camera;\nthis.cameraOffset = config.cameraOffset;\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>The data<\/p>\n\n\n\n<p>This will be fixed to a static location on the map &#8211; useful for smaller, internal places such as houses etc.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\ncamera: &quot;map&quot;, \/\/ FIXED POSITION\ncameraOffset: {x: utils.withGrid(6), y: utils.withGrid(6)},\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Dynamic camera, follows hero (or who ever is added there)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\ncamera: &quot;hero&quot;,\n\u00a0\u00a0\u00a0\u00a0\u00a0cameraOffset: {},\n<\/pre><\/div>\n\n\n<p>And, the code to do it &#8211; currently there is no internal camera boundary\/buffer &#8211; that&#8217;s next!<\/p>\n\n\n\n<p>In <strong>Overworld.js<\/strong><\/p>\n\n\n\n<p>In <strong>gameStepWork<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet cameraPerson = this.map.camera;\nlet cameraPersonOffset = this.map.cameraOffset;\nif(cameraPerson === &quot;hero&quot;) {\n\u00a0\u00a0\u00a0cameraPerson = this.map.gameObjects.hero;\n}\nif(cameraPerson === &quot;map&quot;){\n\u00a0\u00a0\u00a0cameraPerson = cameraPersonOffset;\n}\n<\/pre><\/div>\n\n\n<p>half canvas &#8211; 99<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<p>how to make an RPG &#8211; p68<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>See also: System: &#8216;Camera Manipulations&#8217; Camera methods: needs to know: What is the view point &#8211; how does the camera interact (or not) with the player Most common is: locks onto player &#8211; stops at level edges Centre on player &#8211; player is static (apart from animations etc.) and bg scrolls &#8211; tops at level [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"wp-custom-template-nlx-the-knowledge-page","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-404","post","type-post","status-publish","format-standard","hentry","category-the-knowledge"],"_links":{"self":[{"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/posts\/404","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/comments?post=404"}],"version-history":[{"count":9,"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/posts\/404\/revisions"}],"predecessor-version":[{"id":519,"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/posts\/404\/revisions\/519"}],"wp:attachment":[{"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/media?parent=404"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/categories?post=404"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nonlinearexperience.com\/index.php\/wp-json\/wp\/v2\/tags?post=404"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}