<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Núria</title>
    <description>The latest articles on Forem by Núria (@pincfloit).</description>
    <link>https://forem.com/pincfloit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F207838%2F530a25d7-9ef4-47e5-b2ec-c7a2654d968f.jpg</url>
      <title>Forem: Núria</title>
      <link>https://forem.com/pincfloit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pincfloit"/>
    <language>en</language>
    <item>
      <title>Fighting impostor syndrome in four easy steps</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Mon, 13 Jul 2020 08:16:37 +0000</pubDate>
      <link>https://forem.com/codegram/fighting-impostor-syndrome-in-four-easy-steps-4doe</link>
      <guid>https://forem.com/codegram/fighting-impostor-syndrome-in-four-easy-steps-4doe</guid>
      <description>&lt;p&gt;If you are anything like me, you have experienced impostor syndrome at some point in your life. If you are really like me, you have to deal with it pretty often. And we both know that sucks. So, for this week's lunch talks, let's try and get rid of it once and for all! *&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* Ok, let's be honest. It probably won't work 100%. But if we can reduce it a teeny-weeny bit, we'll have succeeded&lt;/em&gt; 🙌&lt;/p&gt;

&lt;h3&gt;
  
  
  What makes a developer? | Ivana McConnell &lt;em&gt;(29:33 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;First, repeat with me: "I &lt;strong&gt;am&lt;/strong&gt; a developer". No matter where your background is, no matter what languages you know. Ivana McConnell insists on that, and puts focus on consciously pull away from perceptions that devaluate certain languages or paths into development. It's not you, it's them. You &lt;strong&gt;are&lt;/strong&gt; a developer.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LB-DvtCHOgE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Attitude Determines Altitude: Engineering Yourself &amp;amp; Your Teams | Randy Shoup &lt;em&gt;(43:02 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Ok, you now believe you are a developer. Great! But, I know, it's not easy to keep the confidence up. Randy Shoup focuses on the psychological aspects of how our mind works and talks about getting into a growth mindset and gaining trust and confidence.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/y1SpwCiRoPY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Mejorando como desarrolladores | Belén Albeza &lt;em&gt;(42:24 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Hopefully confidence is building up on you, and you want to keep improving as a developer. But, what to learn next? Many new shiny things come up every day, and it's hard to know what to focus on. Belén Albeza gives us concrete advice (in Spanish) on what to do to keep learning effectively, and how we can make our teammates better as well.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/AHVnR0oLk6Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you should make useless things | Simone Giertz &lt;em&gt;(11:58 min)&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Yay! You are a confident developer and you know how to keep improving. What's next? It's likely your career will be bumpy, and you will fail a lot, but that's ok because you will succeed on other things too. You don't need to build a rocket and save the human race by terraforming Mars to be a great developer. Simone Giertz talks about the importance of making useless things, how it will relieve you from pressure and how it can lead to unexpectedly awesome results. Plus, she is wearing a googly eyes t-shirt.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/c0bsKc4tiuY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>motivation</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Stop (ab)using z-index</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Thu, 25 Jun 2020 09:00:00 +0000</pubDate>
      <link>https://forem.com/codegram/stop-ab-using-z-index-14kk</link>
      <guid>https://forem.com/codegram/stop-ab-using-z-index-14kk</guid>
      <description>&lt;p&gt;&lt;code&gt;z-index: 2147483647&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I once saw this in a codebase. The number seemed so random that I thought it couldn't be that random, so I googled it. Turns out it's the highest value that the &lt;code&gt;z-index&lt;/code&gt; property supports!&lt;/p&gt;

&lt;p&gt;That developer must have been really desperate, but it's very common to see things like &lt;code&gt;z-index: 9999&lt;/code&gt;, and if that doesn't work, let's keep adding &lt;code&gt;9&lt;/code&gt;s until it does. You can guess what happens when you try to position something above that.&lt;/p&gt;

&lt;p&gt;There are good solutions like &lt;a href="https://gist.github.com/toadkicker/fc290e84d7bd861e3e73"&gt;creating a z-index scale&lt;/a&gt;, which puts a bit sanity into the z-index nonsense, and we use this solution here at Codegram. But most of the time we don't even use the property at all, and when we use it we only use a couple of values. If you find yourself using more, either you have an extremely complex design that is very different from most sites in the internet (not likely), or you are using it wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---BRJd8Im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/stop-ab-using-z-index/design.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---BRJd8Im--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.codegram.com/blog/stop-ab-using-z-index/design.png" alt="Did you know you can code overlapping elements without using z-index at all?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How z-index works
&lt;/h3&gt;

&lt;p&gt;When working with CSS, we usually deal with two dimensions. However, when elements overlap and we need to adjust their order, we have to deal with a third dimension, the Z axis that the property &lt;code&gt;z-index&lt;/code&gt; controls.&lt;/p&gt;

&lt;h4&gt;
  
  
  Positioning and order
&lt;/h4&gt;

&lt;p&gt;Let's go over the basics: the &lt;code&gt;z-index&lt;/code&gt; is a property related to positioning. By default, all elements have a &lt;code&gt;static&lt;/code&gt; position. In order for &lt;code&gt;z-index&lt;/code&gt; to have any effect at all, it needs to be applied to a positioned element, that means, an element with position &lt;code&gt;relative&lt;/code&gt;, &lt;code&gt;absolute&lt;/code&gt;, &lt;code&gt;fixed&lt;/code&gt;, or &lt;code&gt;sticky&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you don't apply a &lt;code&gt;z-index&lt;/code&gt;, the elements will be stacked in the order they are written in the HTML. Check this example:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nuria-fl/embed/NWxpEPV?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The text is not positioned, so it's behind everything. The other elements stack above each other in the order they are written in the HTML.&lt;/p&gt;

&lt;p&gt;If we want this to match the design, we could add a &lt;code&gt;z-index: 1&lt;/code&gt; to the illustration, and &lt;code&gt;position: relative&lt;/code&gt; and &lt;code&gt;z-index: 2&lt;/code&gt; to the &lt;code&gt;.hero__title&lt;/code&gt; element. It's a good idea to always start with the lowest &lt;code&gt;z-index&lt;/code&gt; value you can, to keep things simple.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nuria-fl/embed/pogeqVa?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;But when working with CSS, it's always best if we can rely on the natural order of the elements and avoid altering the flow ourselves, to keep our code simple and scalable. As long as it makes sense, we could adjust the order of the items in the HTML, placing the text as the last element, and by applying &lt;code&gt;position: relative&lt;/code&gt; to it, it wouldn't be necessary to use &lt;code&gt;z-index&lt;/code&gt; at all:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nuria-fl/embed/ZEQemWW?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Of course, this approach has certain limitations, sometimes it is not possible to change the HTML, and changing the order arbitrarily should only be done to elements that don't have meaning, so we don't alter the experience of users who use screen-readers.&lt;/p&gt;

&lt;p&gt;You can read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index"&gt;stacking without the z-index property&lt;/a&gt; at the MDN web docs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stacking contexts
&lt;/h4&gt;

&lt;p&gt;Following the previous example, let's imagine that it's part of an external library and we do not have control over the code, we cannot alter its HTML or CSS and, to make things worse, the &lt;code&gt;.hero__title&lt;/code&gt; element has a &lt;code&gt;z-index: 9999&lt;/code&gt;. Now, let's say we need to add a modal to the same page. Which &lt;code&gt;z-index&lt;/code&gt; value do you think the modal should have?&lt;/p&gt;

&lt;p&gt;Your first reaction might be: oh dear, I should increase that modal &lt;code&gt;z-index&lt;/code&gt; to &lt;code&gt;99999&lt;/code&gt;, otherwise it will fall below the title, and here they come, the bad practises we wanted to avoid in the first place. But we can avoid this: &lt;code&gt;z-index&lt;/code&gt; only competes with sibling elements within the same &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context"&gt;stacking context&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even if the &lt;code&gt;.hero__title&lt;/code&gt; has a &lt;code&gt;z-index: 9999&lt;/code&gt;, we can place it inside a container with &lt;code&gt;position: relative&lt;/code&gt; and &lt;code&gt;z-index: 1&lt;/code&gt;, creating a new stacking context. Each stacking context is completely independent of its siblings: the descendants from each context will not interfere with elements outside. This way, we can position the modal above the hero just by adding a &lt;code&gt;z-index: 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nuria-fl/embed/wvMJQPV?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Take-aways
&lt;/h3&gt;

&lt;p&gt;To sum up, always keep in mind these tips when positioning elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand how stacking works, and use the rules to your advantage to avoid using &lt;code&gt;z-index&lt;/code&gt;, as long as it makes sense.&lt;/li&gt;
&lt;li&gt;Keep &lt;code&gt;z-index&lt;/code&gt; values low: you'll rarely need more than &lt;code&gt;z-index: 1&lt;/code&gt; (or less than &lt;code&gt;z-index: -1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Create stacking contexts to keep things boxed and prevent them from interfering with each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Further reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index"&gt;Understanding CSS z-index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position"&gt;CSS position docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/z-index"&gt;CSS z-index docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>JamstackConf: A virtual conference experience</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Mon, 08 Jun 2020 08:03:00 +0000</pubDate>
      <link>https://forem.com/codegram/jamstackconf-a-virtual-conference-experience-26de</link>
      <guid>https://forem.com/codegram/jamstackconf-a-virtual-conference-experience-26de</guid>
      <description>&lt;p&gt;Last week, &lt;a href="https://www.codegram.com/blog/author/anna-collins/"&gt;Anna&lt;/a&gt;, &lt;a href="https://www.codegram.com/blog/author/aitor-porro/"&gt;Aitor&lt;/a&gt; and &lt;a href="https://www.codegram.com/blog/author/nuria-soriano/"&gt;I&lt;/a&gt; got the chance to attend the &lt;a href="https://jamstackconf.com/virtual/"&gt;Jamstack Conf&lt;/a&gt;. It was originally planned to happen in London, and at the beginning of the year we had planned to attend other conferences, like &lt;a href="https://nordicjs.com/"&gt;NordicJS&lt;/a&gt; and &lt;a href="https://jsheroes.io/"&gt;JS Heroes&lt;/a&gt;. Due to the COVID-19 situation, those were cancelled, and we were sad at the prospect of not attending any conference this year.&lt;/p&gt;

&lt;p&gt;Luckily for us, the Jamstack Conf organizers decided not only to go forward with the conference, moving it to a virtual setting, but they also made it free for everyone! So we took the chance to experience a virtual conference for the first time.&lt;/p&gt;

&lt;p&gt;I must admit, I was not thrilled by the idea. For me, a conference is much more than the talks. I'd even say that the talks are the least important thing, as they are usually recorded and made public. What I enjoy the most is the opportunity to bond with my colleagues, meet new people, and of course, get free stickers. So, how does a remote conference compare to the real-life experience? Let's see!&lt;/p&gt;

&lt;h2&gt;
  
  
  The talks
&lt;/h2&gt;

&lt;p&gt;For some reason, I find it very hard to focus when watching a video. I guess I'm one of those old people who prefers reading to following a video course. Because I know how my mind works, I took extra preparation to be able to follow this conference as closely as I would have if I had attended physically. I marked the day as busy in my calendar, and did not plan to do any work (I consider attending conferences and learning part of my work, but you know what I mean). I turned off my notifications, put the video on full screen, moved away from the keyboard and took notes in a real notebook. From time to time I checked Slack to chat about the conference with my colleagues (that is also part of attending a conference right?), but other than that I tried to stay away from the keyboard as much as possible. It helped, although it was still harder for me to focus than in a real-life conference, I think it went pretty well. By no means would I have been able to follow if I just had the talks on my other screen while doing client-related work.&lt;/p&gt;

&lt;p&gt;But enough about me, let's talk about the talks! They were all pre-recorded, which at first I thought this was a bit strange, but quickly saw the value: more relaxed speakers, no demo effect, and the speaker was available on the chat to answer questions while the talk was playing. I found the chat to be very chaotic (there were like 6000 people in the room so you can imagine), and maybe it would have benefited from a bit more moderation — not because of any Code of Conduct violation, but simply noise. Still, it's an interesting tool. To be noted, in-between the talks they had live Q&amp;amp;A sessions which worked great.&lt;/p&gt;

&lt;p&gt;In terms of content, I especially enjoyed Christian Nwamba's talk about &lt;a href="https://www.youtube.com/watch?v=cvHYOtkQl7w&amp;amp;list=PL58Wk5g77lF8jzqp_1cViDf-WilJsAvqT&amp;amp;index=8"&gt;Jamstack for Emerging Markets&lt;/a&gt;, and Erin Kissane's about &lt;a href="https://www.youtube.com/watch?v=ryngYoHXNfQ&amp;amp;list=PL58Wk5g77lF8jzqp_1cViDf-WilJsAvqT&amp;amp;index=3&amp;amp;t=0s"&gt;The COVID Tracking Project.&lt;/a&gt; It's refreshing to see a technology we love be put to use to make a positive impact on people's lives, and talk about performance in those terms instead of just being about more visits and making more money.&lt;/p&gt;

&lt;p&gt;There were many other interesting talks, and they are &lt;a href="https://www.youtube.com/playlist?list=PL58Wk5g77lF8jzqp_1cViDf-WilJsAvqT"&gt;already online&lt;/a&gt; so make sure to check them out!&lt;/p&gt;

&lt;h2&gt;
  
  
  The hallway experience
&lt;/h2&gt;

&lt;p&gt;I was really amazed by the tool the conference used, &lt;a href="https://hopin.to/"&gt;Hopin&lt;/a&gt;. They really put an effort into making the virtual conference experience as close to reality as possible, and I'm sure it will be a killer app in the conference space.&lt;/p&gt;

&lt;p&gt;As I said previously, it has a chat and there were live Q&amp;amp;A sessions, but that's not all. Sponsor booths were also virtual rooms with a live video feed. I think this suffered in comparison to the real-life experience, as usually when you approach a sponsor booth they always come to you and start talking about their product (which can be a bit annoying, but you are able to fully understand what they do). In these virtual booths, since you might join at any point, it's hard to follow the conversation if you don't know about the product beforehand, and I didn't find it very engaging.&lt;/p&gt;

&lt;p&gt;To complete the hallway experience of a conference, one cannot forget the most important part. Networking! I'm a shy person, but I like to meet new people (yes, it's not as contradictory as it sounds). I often find it hard to talk to other attendees in real-life conferences, especially when groups start forming in the hallway and you are there all alone holding your cup of coffee as your only friend. Hopin offers the perfect tool for people like me. There is this chatroulette-like feature where they pair you up with a random attendee and you have a video chat for 5 minutes. No more standing alone trying to find the right angle to approach a group, all you need to do is click a button! Plus, being time-framed, you don't reach that awkward point where the conversation is over and you don't know how to say goodbye. I probably spoke to more people in this conference than any other before.&lt;/p&gt;

&lt;p&gt;It's clear that they made an extra effort to match the experience of a real-life conference, so much that they might have missed opportunities to improve on it. For example, to visit the sponsors booths you need to leave the main &lt;em&gt;stage&lt;/em&gt; video, which of course makes sense when you cannot be in two places at once in real-life, but in a virtual setting it would be cool to minimize and mute a video so you can check something else, but without losing all context. It would also be cool to have a log of the people you've interacted with, in case you want to connect with them later. Still, for being a platform in early access, it has offered a great experience!&lt;/p&gt;

&lt;h2&gt;
  
  
  Are virtual conferences here to stay?
&lt;/h2&gt;

&lt;p&gt;I must say, I still prefer the real-life experience in many ways, especially for team-building. But, while I thought that virtual conferences (for me) were just a temporary thing while we are dealing with the COVID-19 situation, I'm now sure that I will be attending more of them. We need to keep in mind that virtual conferences are more accessible to everyone (or should be — Hopin doesn't support captions at the moment), and also more environmentally friendly, something that is essential to fight climate change (we talked about that in the &lt;a href="https://buttondown.email/codegram/archive/climate-change-what-can-we-do-as-developers/"&gt;first issue of our newsletter&lt;/a&gt;). Having more virtual conferences is in everyone's best interest, so if you were skeptical like me, I really recommend you try it!&lt;/p&gt;

&lt;p&gt;Oh, and the stickers? &lt;a href="https://redwoodjs.com/"&gt;RedwoodJS&lt;/a&gt; mentioned that they would email them to any attendee that wanted them. Here we go, the conference experience is complete.&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>conferences</category>
      <category>remote</category>
    </item>
    <item>
      <title>​Kill the back-end: Bring user-generated content to Jamstack with GitHub Actions</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Tue, 12 May 2020 12:09:00 +0000</pubDate>
      <link>https://forem.com/codegram/kill-the-back-end-bring-user-generated-content-to-jamstack-with-github-actions-1524</link>
      <guid>https://forem.com/codegram/kill-the-back-end-bring-user-generated-content-to-jamstack-with-github-actions-1524</guid>
      <description>&lt;p&gt;Static sites have been making a comeback these last few years. Deploying to a CDN is easy and cheap (or even free!), and nothing beats a static site with SEO, security, performance, and scalability. Of course, dealing with a lot of static pages used to be a nightmare, but not after the Jamstack approach arrived. It's not about specific languages or frameworks, according to Mathias Biilmann (CEO &amp;amp; Co-founder of Netlify), it's &lt;em&gt;"a modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup"&lt;/em&gt;. Using a static site generator like &lt;a href="https://gridsome.org/"&gt;Gridsome&lt;/a&gt; or &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt;, we can statically generate sites with lots of content, like a blog, and deploy them in a matter of minutes. You can read more about Jamstack it in this &lt;a href="https://www.codegram.com/blog/a-jamstack-journey-headless-content-management-with-vue-react/"&gt;excellent post by Josep Jaume&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here at Codegram we love the Jamstack, but we are aware that it comes with its limitations. One of them is that you need to be in control of the content. In the case of the blog, a common scenario is committing the content in your repository as markdown or JSON files. This is the approach we follow for this very same site where you are reading this. After all, most of the team is familiar enough with technology to write a markdown file, commit and create a pull request on GitHub.&lt;/p&gt;

&lt;p&gt;But when working with clients, we often find that the people writing the content is not very technical and they prefer to work with a UI. In these cases, like &lt;a href="https://www.codegram.com/our-work/davis-cup-finals/"&gt;Davis Cup Finals&lt;/a&gt; website, we usually rely on a headless CMS service like &lt;a href="https://prismic.io/"&gt;Prismic&lt;/a&gt; or &lt;a href="https://www.contentful.com/"&gt;Contentful&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you need more flexibility and features than these services provide, like letting users submit their own content and publishing it, you can always write your own backend, if you have the time, knowledge and budget. But wouldn't it be nice to keep things simple and avoid having to worry about servers?&lt;/p&gt;

&lt;p&gt;Imagine we are organizing a conference and want to have call for papers. We want users to be able to fill a form with their proposal, and then we as organizers review the proposals and display the accepted ones on the website. Maybe even list the ones that are pending review, if we want to keep the process really open. But how on earth are we going to handle user submissions without a server or a database!? Well, you can &lt;a href="http://jamstack-cfp.netlify.app"&gt;check the final site&lt;/a&gt;, and read on to know more about how it works… 🍿&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Let's take a small break and introduce &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;. You have probably heard about them already, but if not, they are simply a way to automate software workflows. Think CircleCI or Travis but completely integrated with GitHub. Running tests and linting when a PR is opened, and building and deploying when pushing to master are the most typical flows that will probably come to mind, but you can run any piece of code you want, and there are &lt;a href="https://help.github.com/en/actions/reference/events-that-trigger-workflows"&gt;many ways to trigger a workflow&lt;/a&gt;. We have this repository of &lt;a href="https://github.com/codegram/useful-github-workflows"&gt;useful workflows&lt;/a&gt; if you want to take a look.&lt;/p&gt;

&lt;p&gt;As you can imagine, the ability to run any script opens a new world of possibilities for Jamstack sites. So in this post we'll see how we can turn GitHub into our own Content Management System that will receive user submissions from the client-side application, validate them and publish them, all without any backend server involved! 🤯&lt;/p&gt;

&lt;h2&gt;
  
  
  Jamstack with user-generated content
&lt;/h2&gt;

&lt;p&gt;So let's get on it and build our CFP application. We will be using Gridsome because we love Vue, and we will be deploying to Netlify. Users will be presented with a form to submit their talk. On submit, we trigger a GitHub workflow that generates a pull request that adds a JSON file to the repository. Once this PR is merged, &lt;a href="https://gridsome.org/"&gt;Gridsome&lt;/a&gt; generates the site statically listing all the accepted submissions, and it gets deployed to &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;. The result is a &lt;a href="https://jamstack-cfp.netlify.app/"&gt;100% static site that is able to handle user-generated content&lt;/a&gt;! Feel free to &lt;a href="https://github.com/codegram/jamstack-cfp"&gt;check out the repository&lt;/a&gt;, but if you want to understand how it works, let's review the submission process in a bit more detail:&lt;/p&gt;

&lt;h3&gt;
  
  
  Trigger a workflow from your client-side app
&lt;/h3&gt;

&lt;p&gt;So a user visits our client-side application and wants to submit a talk. To make it easier to set up and play with, we will not be adding any authentication method, but you could connect the app with a GitHub OAuth app or similar to prevent abuse. So for now, the users will just fill in the details and submit the form. We want this form to open a pull request in the repository with the talk information. As we've seen before, we can use GitHub Actions to create a PR. But how can a form trigger a GitHub Actions workflow? There's a way to trigger a workflow externally, using the &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#external-events-repository_dispatch"&gt;&lt;code&gt;repository_dispatch&lt;/code&gt; event&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;codegram&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jamstack-cfp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://api.github.com/repos/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/dispatches`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/vnd.github.everest-preview+json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`token &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GH_TOKEN_PERSONAL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handle-submission&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;client_payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok, I must admit, I lied. This process should not be done completely from the client-side. To trigger a &lt;code&gt;repository_dispatch&lt;/code&gt; event you need to use a token with &lt;code&gt;repo&lt;/code&gt; scope of a user that has write access to the GitHub repository (you can &lt;a href="https://github.com/settings/tokens"&gt;generate the token in your GitHub settings&lt;/a&gt;). Doing this on the client-side means that everyone could see the token, and that's no good! We will be handling this bit of logic in a serverless function. Luckily, with &lt;a href="https://docs.netlify.com/functions/overview/"&gt;Netlify functions&lt;/a&gt; writing and deploying a serverless function is super easy. You can &lt;a href="https://github.com/codegram/jamstack-cfp/blob/master/functions/submit.js"&gt;check the full function code&lt;/a&gt; in the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a pull request
&lt;/h3&gt;

&lt;p&gt;When the form is submitted and the Netlify function has done its job, the workflow is triggered on our &lt;code&gt;jamstack-cfp&lt;/code&gt; repo. This workflow creates a &lt;code&gt;JSON&lt;/code&gt; file with the talk details, then opens a new pull request to add this new file to the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Handle&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Submission"&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repository_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handle-submission&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;create-pr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create PR&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@master&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ env.NODE_VERSION }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.NODE_VERSION }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create json file&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;node actions/process-input.js&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create Pull Request&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peter-evans/create-pull-request@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_TOKEN_PERSONAL }}&lt;/span&gt;
          &lt;span class="na"&gt;branch-suffix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;random&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;feat(submission):&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;github.event.client_payload.name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;github.event.client_payload.title&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;# ${{ github.event.client_payload.title }}&lt;/span&gt;
            &lt;span class="s"&gt;## by ${{ github.event.client_payload.name }}&lt;/span&gt;
            &lt;span class="s"&gt;&amp;gt; ${{ github.event.client_payload.description }}&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;submission&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As we said before, when running GitHub Actions we can run any bit of arbitrary code, and that's what we are doing on the &lt;code&gt;Process input&lt;/code&gt; step, adding the logic to create the &lt;code&gt;JSON&lt;/code&gt; file with the payload we received from the &lt;code&gt;repository_dispatch&lt;/code&gt; event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client_payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_EVENT_PATH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;`submissions/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;client_payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;client_payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client_payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this, we have the main functionality of our app ready! You can try and see this in action by &lt;a href="https://jamstack-cfp.netlify.app/"&gt;submitting the form&lt;/a&gt; and then checking the &lt;a href="https://github.com/codegram/jamstack-cfp/actions?query=workflow%3A%22Handle+Submission%22https://github.com/codegram/jamstack-cfp/actions?query=workflow%3A%22Handle+Submission%22"&gt;running workflows&lt;/a&gt;. Once the workflow finishes, you will be able to &lt;a href="https://github.com/codegram/jamstack-cfp/pulls?q=is%3Aopen+is%3Apr+label%3Asubmission"&gt;see the open PR&lt;/a&gt; with your submission. Once PRs are merged, the application will list them in the &lt;a href="https://jamstack-cfp.netlify.app/submissions"&gt;accepted submissions section&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On next posts we will be seeing how to list the &lt;a href="https://jamstack-cfp.netlify.app/pending"&gt;pending submissions&lt;/a&gt; by integrating the GitHub GraphQL API to Gridsome, and how to add another GitHub workflow that automatically validates and merges or closes the PRs. There's still a lot of potential to take this further!&lt;/p&gt;

&lt;h2&gt;
  
  
  Have we really killed the back-end?
&lt;/h2&gt;

&lt;p&gt;Obviously, this approach has some limitations, so all back-end devs out there, don't worry, you still get to keep your jobs! So, when to use this approach? The submission process can take a few minutes, so if you need immediate feedback it's probably not a good option. Same if the amount of submissions you need to handle in a short period is very high. There's also a privacy issue: if your repository is public you shouldn't store any sensitive data (I'm not sure if storing it in a private repository has any legal issues). As a rule of thumb, this is a good use-case for a proof of concept, MVP, or small application. We've successfully used this approach in production, reaching around 700 submissions, and we were very happy with the result!&lt;/p&gt;

&lt;p&gt;If I've convinced you of giving it a try, &lt;a href="https://github.com/codegram/jamstack-cfp"&gt;fork the repo&lt;/a&gt;, and let us know your experience! You can &lt;a href="https://twitter.com/codegram"&gt;reach us on Twitter&lt;/a&gt;, we will be very glad to hear it!&lt;/p&gt;




&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@etienneblg"&gt;Etienne Boulanger&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>jamstack</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Promisifying Phaser</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Sat, 09 May 2020 10:58:41 +0000</pubDate>
      <link>https://forem.com/pincfloit/promisifying-phaser-2oak</link>
      <guid>https://forem.com/pincfloit/promisifying-phaser-2oak</guid>
      <description>&lt;p&gt;Working on web development, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;promises&lt;/a&gt; are a basic tool I use every day, and I feel that the old days when everybody used callbacks are long gone. Except when I'm working with Phaser!&lt;/p&gt;

&lt;p&gt;For example, at the start of the game, I want to move the camera around so the player gets a sense of their surroundings, and then start playing the game. Phaser cameras have a &lt;code&gt;pan&lt;/code&gt; method to do that, and this method receives a callback which is called on every update. In order to wait and call another method once the effect has finished, you need to check if the &lt;code&gt;progress&lt;/code&gt; has reached &lt;code&gt;1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Linear&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startFollow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This approach might be useful if I want to do something while the pan is running, but most of the time I want to wait until it's done, and it's a bit tedious to keep writing the callback, not to mention if you want to chain multiple effects: you easily run into &lt;a href="http://callbackhell.com/"&gt;callback hell&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, I decided to turn this kind of Phaser methods into promises:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cameraPan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Linear&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This way, thanks to async/await, the previous code looks much simpler and easier to understand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameraPan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startFollow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The improvement is even more obvious when you are using several camera effects, tweens, and other methods that would require callbacks. Imagine how this code would look without &lt;code&gt;await&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;endScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stopFollow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameraFade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fadeIn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameraPan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;How strange to see northern lights so far down south.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameraPan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;survivor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cameraFade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fadeOut&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can still use the original Phaser method at certain points when you need more control over the progress, but I've found this is a quick and easy way to make your Phaser games a bit more readable. Hope it helped!&lt;/p&gt;

</description>
      <category>phaser</category>
      <category>gamedev</category>
      <category>devdiary</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Using BEM in components</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Wed, 29 Apr 2020 13:49:00 +0000</pubDate>
      <link>https://forem.com/codegram/using-bem-in-components-10h4</link>
      <guid>https://forem.com/codegram/using-bem-in-components-10h4</guid>
      <description>&lt;p&gt;Front-end development has changed a lot in the last 10 years. The most common scenario back then was to have all your site CSS in global styles. On a big site, the number of CSS classes could become unmanageable: it was hard to keep them ordered, you run into class name collision easily, and using &lt;code&gt;!important&lt;/code&gt; as a quick fix (that stayed in your codebase forever) was quite common. BEM and similar methodologies (OOCSS, SMACSS, Atomic CSS…) were created to help mitigate those issues. And it worked, if you applied them well.&lt;/p&gt;

&lt;p&gt;In case you haven't heard about it, I recommend checking out the &lt;a href="http://getbem.com/introduction/"&gt;documentation&lt;/a&gt;. To sum up, BEM is a naming convention for your classes, it stands for Block Element Modifier, and it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Block */
.card { }

/* Elements */
.card__header { }
.card__button { }

/* Modifiers */
.card__button--disabled { }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Having a strict convention to write class names makes the front-end code more explicit and easier to work with. It also avoids class name collisions, making the code more robust and improving scalability. But of course, using BEM has its drawbacks: class names tend to be very long, which makes your HTML harder to read. For a long time the pros outweighed the cons, but is it still true?&lt;/p&gt;

&lt;h3&gt;
  
  
  Using BEM today
&lt;/h3&gt;

&lt;p&gt;Nowadays, when &lt;a href="https://css-tricks.com/styling-a-web-component/"&gt;styling web components&lt;/a&gt;, we can make use of Shadow DOM to make the styles encapsulated in that component, preventing them from affecting outer elements. Similar approaches exist in &lt;a href="https://angular.io/guide/component-styles"&gt;Angular&lt;/a&gt;, &lt;a href="https://vue-loader.vuejs.org/guide/scoped-css.html"&gt;Vue&lt;/a&gt; or &lt;a href="https://cssinjs.org/"&gt;React&lt;/a&gt;, either using Shadow DOM as well or appending unique attributes to the class names, to ensure that the styles are scoped to that component.&lt;/p&gt;

&lt;p&gt;Since class collision between components is not a problem anymore, a lot of devs consider now BEM obsolete. But I believe that BEM offers more than that, and at Codegram we still use it in our projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  A component is not a Block
&lt;/h3&gt;

&lt;p&gt;If you check the first sentence in the &lt;a href="http://getbem.com/"&gt;official site&lt;/a&gt;, it says "BEM — Block Element Modifier is a methodology that helps you to create &lt;strong&gt;reusable components&lt;/strong&gt;". But now we already have the reusable component part solved! Imagine a &lt;code&gt;Product&lt;/code&gt; component. With the traditional approach, we would think of the product as the Block, and end up with classes like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.product {}
.product__header {}
.product__header-title {}
.product__header-subtitle {}
.product__image {}
.product__image-description {}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's not bad, but is it really necessary to specify in each class that it applies to &lt;code&gt;product&lt;/code&gt;? We are already in the product component, and styles will not be applied anywhere else. If a component doesn't necessarily translate to a single Block element, we can use several Blocks inside a single component. We do not need to worry about class collision, so we can keep class names short but meaningful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.product {}
.header {}
.header__title {}
.header__subtitle {}
.image {}
.image__description {}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now the responsibility of each class is much clearer just by looking at it, it's easier to split the component later if needed, and overall it's much easier to read.&lt;/p&gt;

&lt;h3&gt;
  
  
  A convention
&lt;/h3&gt;

&lt;p&gt;You might think that, based on the previous example, you could just skip BEM altogether, and classes would still be short, meaningful and manageable. And you would be right. But still, I find BEM is useful in providing a convention for our class names. In JavaScript (or any language of your choice), it's common to have a convention for the names of the variables. It does not matter which convention you choose, as long as the team agrees on following it. So why should CSS be any different? It's still a language, it's a crucial part of frontend development, and if we forget to apply best practices to it, that's when it becomes cumbersome to work with. Just because the styles don't leak out to all your site anymore, it doesn't mean you should hide all the mess inside your components. So use BEM, or skip it, but make it a conscious decision and &lt;strong&gt;put effort and thought when writing CSS&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@calebeangel?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Caleb Angel&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Phaser: Loading assets in a saner way</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Sun, 19 Apr 2020 08:46:35 +0000</pubDate>
      <link>https://forem.com/pincfloit/game-development-diary-viii-loading-assets-in-a-saner-way-1pf0</link>
      <guid>https://forem.com/pincfloit/game-development-diary-viii-loading-assets-in-a-saner-way-1pf0</guid>
      <description>&lt;p&gt;It's been some time since I talked about the code of the game, so I thought I'd share some of the changes I've made to make my life easier, in the shape of short posts. Today's turn is…&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading Assets
&lt;/h2&gt;

&lt;p&gt;As you may know, to add an asset to a Phaser scene, you need to call a load function with a &lt;code&gt;key&lt;/code&gt; and the asset path as parameters. If the asset is a sprite, you also need to pass the frame width and height.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spritesheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enemy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/enemy.png`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can imagine, when you have a lot of sprites, the preloading of all the assets becomes very verbose, and if you use the same sprite in different scenes, having the width and height hardcoded is tiresome and a potential source of bugs (if you change the size of the sprite, it's likely you forget to update it everywhere).&lt;/p&gt;

&lt;p&gt;So the first step to improve this is to move all this hardcoded data to a &lt;code&gt;constants.ts&lt;/code&gt; file. We've solved an issue but it's still quite verbose. This is how a scene preload function looked like at a certain point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FIRE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/sound/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FIRE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STATIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/sound/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STATIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/sound/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BANG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/sound/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BANG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_BG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_BG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_BG_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_BG_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FLOOR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FLOOR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LADDER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LADDER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BOXES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BOXES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WOOD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WOOD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOTH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOTH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ROCK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ROCK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;METALBOX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;METALBOX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spritesheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANTENNA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANTENNA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spritesheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FIREPIT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FIREPIT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I have a &lt;code&gt;BaseScene&lt;/code&gt; with some common methods that all scenes inherit, to I created a &lt;code&gt;loadAudio&lt;/code&gt;, &lt;code&gt;loadImage&lt;/code&gt; and &lt;code&gt;loadSprite&lt;/code&gt; functions there that receive the sprite constant as a parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SpriteAsset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spritesheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SPRITE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;frameWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SPRITE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;frameHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SPRITE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HEIGHT&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So the preload function ended up looking like this. It's actually loading more assets than before, but it's way easier to read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Preload audio&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadAudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FIRE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadAudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STATIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadAudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadAudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AUDIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BANG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Preload images&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_BG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_BG_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_NIGHT_BG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUILDING_NIGHT_BG_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FLOOR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WOOD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLOTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DROP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IMAGES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ROCK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Preload sprites&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;METALBOX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LADDER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BOXES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANTENNA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FIREPIT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUGGY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SPRITES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRANGER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There's still room for improvement, for example I could have all the audio, images and sprites a scene needs in a constant, and load them all in a single call. But for now it's more than enough to make the code a bit more readable!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
      <category>phaser</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Visiting Radio Liberty</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Sun, 19 Apr 2020 08:41:56 +0000</pubDate>
      <link>https://forem.com/pincfloit/game-development-diary-vii-visiting-radio-liberty-297j</link>
      <guid>https://forem.com/pincfloit/game-development-diary-vii-visiting-radio-liberty-297j</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://medium.com/@pincfloit/game-development-diary-vii-adafec37fa4a" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; on Jul 21, 2019&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, this post has not much to do with the development of the game but… I visited Radio Liberty! Or what’s left of it, anyway.&lt;/p&gt;

&lt;p&gt;It may be a bit sad to have it all just go to waste like that, but for my game it couldn’t be more perfect, it has the exact post apocalyptic vibe I’m looking for. It’s a shame that the game will be quite small and that I’m not a great pixel artist, because those scenarios would shine. Hope you all like the game and some big studio wants to fund me to do a remaster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwhvi1zyalrpuhsaskohe.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwhvi1zyalrpuhsaskohe.jpeg" alt="Radio Liberty exterior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdwownyajq9c80zngnn5v.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdwownyajq9c80zngnn5v.jpeg" alt="Staircase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fegwetexc7q08hstbrdy0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fegwetexc7q08hstbrdy0.jpeg" alt="Europe map with lights"&gt;&lt;/a&gt;&lt;br&gt;
This is begging to become a game puzzle&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1e5dva7ddha22eaidtg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1e5dva7ddha22eaidtg3.png" alt="Collage of images"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzostyskh7rffwen7d1pm.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzostyskh7rffwen7d1pm.jpeg" alt="A door with a "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No, the game won’t have any zombies in it but this is priceless&lt;/p&gt;

&lt;p&gt;Please note! As a police officer kindly reminded me of, Radio Liberty is still private property so you shouldn’t go there. I won’t do it again, promise.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>A DevRel in a digital product agency</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Wed, 08 Apr 2020 17:00:00 +0000</pubDate>
      <link>https://forem.com/codegram/a-devrel-in-a-digital-product-agency-2h2a</link>
      <guid>https://forem.com/codegram/a-devrel-in-a-digital-product-agency-2h2a</guid>
      <description>&lt;p&gt;You've probably heard about Developer Relations or Developer Advocacy before. You probably know someone with that job title, or maybe you are one. But, what does a DevRel exactly do? A quick search will give you answers along these lines: "Developer Relations is best defined as building relationships with the developer community" (from &lt;a href="https://influitive.com/introduction-developer-relations/"&gt;Introduction to Developer Relations&lt;/a&gt;), or "the interface between 3rd party developers and the engineering and product teams building the underlying platforms" (from &lt;a href="https://medium.com/google-developers/the-core-competencies-of-developer-relations-f3e1c04c0f5b"&gt;The Core Competencies of Developer Relations&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Codegram is a digital product agency, we build products for clients (&lt;a href="https://www.codegram.com/our-work"&gt;check out our case studies&lt;/a&gt; if you are curious), but rarely for other developers. So, at first glance it doesn't look like the type of company that needs to have a Developer Relations role. But we respectfully disagree!&lt;/p&gt;

&lt;h3&gt;
  
  
  Give back
&lt;/h3&gt;

&lt;p&gt;We use a lot of open source to make money, so it seems only fair to give back to the community. The most obvious action is contributing to open source, but it's not the only thing. We like to explore new technologies and we learn a lot in each project we make. It's a shame to keep this to ourselves, so sharing knowledge is important for us. We've been doing so in &lt;a href="https://www.codegram.com/blog/"&gt;our blog&lt;/a&gt;, but also speaking at conferences, organizing &lt;a href="https://2019.fullstackfest.com/"&gt;Full Stack Fest&lt;/a&gt;, the &lt;a href="https://2019.fullstackfest.com/podcast"&gt;Full Stack Cast&lt;/a&gt;, and more to come (stay tuned!).&lt;/p&gt;

&lt;h3&gt;
  
  
  A shared responsibility
&lt;/h3&gt;

&lt;p&gt;Our industry has issues, and it's everyone's responsibility to solve them. Not only to make the industry a better place for everyone, but also to improve the products we build. Creating accessible websites and apps is very important and often neglected. Respect for the users' privacy is forgotten in favor of getting the maximum profit out of their data. A single developer can only do so much, but companies have a lot of power to change that.&lt;/p&gt;

&lt;p&gt;We believe in our values, and we think it would be positive if more companies worked like us. We've worked hard on &lt;a href="https://www.codegram.com/blog/shaping-a-diverse-and-inclusive-culture-at-codegram"&gt;making our team more diverse&lt;/a&gt;, and we want to communicate that there is a different way to do things. Not only would this help solve the problems mentioned before, but it's also more profitable for the company: we have a very low employee turnover rate, and in this industry that's very rare.&lt;/p&gt;

&lt;h3&gt;
  
  
  A DevRel's job
&lt;/h3&gt;

&lt;p&gt;Everyone at Codegram is aligned with these values, but combining our work for client's projects with contributing to open source, writing blog posts, speaking at conferences, etc. is hard, and not everyone's cup of tea. So a DevRel's job is to coordinate these efforts and ensure this keeps happening and we contribute in a meaningful way. And of course, be a public face for the company, so say hi on twitter if you want to chat, you can find me on my &lt;a href="https://twitter.com/pincfloit"&gt;personal account&lt;/a&gt;, or &lt;a href="https://twitter.com/codegram"&gt;Codegram's&lt;/a&gt; as always 👋&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>community</category>
    </item>
    <item>
      <title>Phaser meets Vue</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Sat, 22 Feb 2020 09:39:04 +0000</pubDate>
      <link>https://forem.com/pincfloit/game-development-diary-vi-phaser-meets-vue-37l9</link>
      <guid>https://forem.com/pincfloit/game-development-diary-vi-phaser-meets-vue-37l9</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://medium.com/@pincfloit/game-development-diary-vi-ba0f7af76a10"&gt;Medium&lt;/a&gt; on Jul 6, 2019&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you may or may not know, before I started working on Radio Liberty I made a couple of videogames using Vue, a JavaScript framework (and &lt;a href="https://www.youtube.com/watch?v=K13DFYOCaC4"&gt;talked&lt;/a&gt; about that at WTM Barcelona — talk is in spanish). Obviously it has some limitations when it comes to the complex interaction you usually need for a videogame, but, being a framework for web applications, it also makes UI things much more simpler. If you have some CSS knowledge, you will see the pain that it represents &lt;a href="https://labs.phaser.io/edit.html?src=src%5Cdisplay%5Calign%5Cin%20right%20center.js"&gt;aligning something&lt;/a&gt; with Phaser, compared to using flexbox, absolute positioning, or even floats.&lt;/p&gt;

&lt;p&gt;I started working on an inventory UI for Radio Liberty, sort of a grid to list all the items, possibly with the need to scroll or paginate if you have too many items to fit in the screen.&lt;/p&gt;

&lt;p&gt;Obviously I couldn’t stop thinking how much easier would it be for me to do it in CSS. And then I thought… wait, Phaser is JavaScript, it’s running on a website, what’s stopping me from using Vue?&lt;/p&gt;

&lt;p&gt;I created a new project with &lt;a href="https://cli.vuejs.org/"&gt;Vue CLI&lt;/a&gt;, moved my phaser files into &lt;code&gt;src&lt;/code&gt;, copied the old webpack config into &lt;code&gt;vue.config.js&lt;/code&gt; (that’s my favourite part about the Vue CLI: no need to eject to provide full webpack configuration!), added an extra &lt;code&gt;div&lt;/code&gt; to the &lt;code&gt;index.html&lt;/code&gt; file, and &lt;strong&gt;that’s it&lt;/strong&gt;. It was that easy.&lt;/p&gt;

&lt;p&gt;Now I can display the inventory easily and I can reuse the water, food and health stats component that I had done for a &lt;a href="https://nuria-live.netlify.com/"&gt;previous Vue game&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Obviously, the Vue app and the Phaser game need to communicate between them. The player picks up an object on the Phaser game (handled with a collision), the Vue inventory needs to update. If any of the stats reach 0, player must die and Phaser game must respond accordingly. But hey, it’s all JavaScript! They can communicate easily via Events.&lt;/p&gt;

&lt;p&gt;Right now there are a bunch of events sent and received through many files, but in the future I’ll probably create a service to manage those, and all (or most) of the game state will be centralized in the Vue store, managed with &lt;a href="https://vuex.vuejs.org/"&gt;Vuex&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here you can check the current status of the game, with stats and inventory: &lt;a href="https://www.youtube.com/watch?v=mbqEcUb4k0Y"&gt;https://www.youtube.com/watch?v=mbqEcUb4k0Y&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the inventoy and the stats solved, I have all the basic pieces to build the game. Now, it’s time to focus on doing a lot of pixel art (oh no), sound, and build the remaining scene to finish &lt;strong&gt;Chapter 1&lt;/strong&gt;!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
      <category>phaser</category>
      <category>vue</category>
    </item>
    <item>
      <title>Phaser: Moving to TypeScript</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Tue, 11 Feb 2020 16:46:47 +0000</pubDate>
      <link>https://forem.com/pincfloit/game-development-diary-v-moving-to-typescript-5a4k</link>
      <guid>https://forem.com/pincfloit/game-development-diary-v-moving-to-typescript-5a4k</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://medium.com/@pincfloit/game-development-diary-v-61521b8df4ef"&gt;Medium&lt;/a&gt; on Apr 17, 2019&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’m not a fan of TypeScript. Anyone that has worked with me, follows me on &lt;a href="http://twitter.com/pincfloit"&gt;Twitter&lt;/a&gt; or been &lt;em&gt;near&lt;/em&gt; me has probably heard my rants. It’s not that I’m against statically typed languages, but I feel that TypeScript tries to fix something that is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; broken. Yes, I strongly believe that JavaScript is not broken. Most people that keep complaining about JavaScript has not taken the time to understand the language.&lt;/p&gt;

&lt;p&gt;But yeah, TypeScript. It’s supposed to make your code more robust, avoid bugs, &lt;em&gt;blah blah blah&lt;/em&gt;. I’m a bit skeptical about all those blanket statements. And I’m not alone on that, as Eric Elliott mentions on &lt;a href="https://medium.com/javascript-scene/the-typescript-tax-132ff4cb175b"&gt;The TypeScript Tax&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Type safety doesn’t seem to make a big difference. TypeScript proponents frequently talk about the benefits of type safety, but there is little evidence that type safety makes a big difference in production bug density.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By now you might be thinking &lt;em&gt;“but wait, wasn’t this post titled &lt;strong&gt;Moving to Typescript&lt;/strong&gt;?”&lt;/em&gt;. Yeah, despite all this ranting I moved the game code to TypeScript, and I don’t regret it.&lt;/p&gt;

&lt;p&gt;The reason I switched to TypeScript, the main benefit I see over JavaScript and the one I see least mentioned when people say nice things about TypeScript, is &lt;strong&gt;&lt;em&gt;developer experience&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You see, Phaser 3 doesn’t have the best &lt;a href="https://photonstorm.github.io/phaser3-docs/index.html"&gt;documentation&lt;/a&gt;. It’s quite cumbersome to find something there, and most of the time I find it really hard to see how everything is connected. Plus, Phaser itself does not make things too easy for the developer(like functions with a lot of parameters, instead of using an object with keys which makes the code much clearer).&lt;/p&gt;

&lt;p&gt;TypeScript really helps making this way easier and reducing trips to the docs dramatically. I can see what kind of parameter a function expects, in which order, and what is returned. Which are the available properties of a Sprite, or a Scene. It’s true that you &lt;a href="https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html"&gt;can have type checking with JavaScript&lt;/a&gt; without actually having to use TypeScript in your files, but if you are doing this I think it’s worth to go all the way and use TypeScript at its fullest.&lt;/p&gt;

&lt;p&gt;It’s not all nice and good, the truth is that Phaser and TypeScript don’t work that well together, there is even less documentation, and at the time there are no Phaser types in &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped"&gt;DefinitelyTyped&lt;/a&gt; (so you need to &lt;a href="https://github.com/photonstorm/phaser3-docs/tree/master/typescript"&gt;manually add them&lt;/a&gt; to your project, and remember to update them if you upgrade the Phaser version). But overall, it’s totally worth it.&lt;/p&gt;

&lt;p&gt;Does this mean I want to use TypeScript in all my projects now? Hell no. If you are using a simpler framework with good documentation, I don’t think it adds as much. But for Phaser, TypeScript has saved my sanity.&lt;/p&gt;




&lt;p&gt;I haven’t been posting on the development diary lately, but this doesn’t mean I haven’t been working on the game! If you are curious about the progress, that’s how it looks so far:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=i5tFT-5p_0U"&gt;https://www.youtube.com/watch?v=i5tFT-5p_0U&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Graphics and animations are not final, but they give a guideline about how it’s going to look. I’m pretty happy!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
      <category>typescript</category>
      <category>phaser</category>
    </item>
    <item>
      <title>Pixel art and the art of doing nothing</title>
      <dc:creator>Núria</dc:creator>
      <pubDate>Mon, 10 Feb 2020 16:37:18 +0000</pubDate>
      <link>https://forem.com/pincfloit/game-development-diary-iv-pixel-art-and-the-art-of-doing-nothing-20op</link>
      <guid>https://forem.com/pincfloit/game-development-diary-iv-pixel-art-and-the-art-of-doing-nothing-20op</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://medium.com/@pincfloit/game-development-diary-iv-919030878389" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; on Sep 23, 2018&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, summer has just ended. I’ve hardly felt like staying home and work on the game these past months. I don’t feel too bad, I’m doing this for fun if something else sounds more fun, well, so be it. Also, if I’m being completely honest, I’ve been dreading a bit the next step I had planned: start working on the art. It’s funny, because I actually have a design background, and I’ve always liked to draw.&lt;/p&gt;

&lt;p&gt;As I mentioned in previous posts, I had planned for the game to be pixel art, for a few reasons. One, I like it, and two, I thought it would be easier. Right? WRONG. I really haven’t done any pixel art before, unless you count my first game for Ludum Dare. And one would think that pixel art is just any other art, just drawn in a smaller space. Oh boy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tools
&lt;/h2&gt;

&lt;p&gt;So, pixel art. It’s just big pixels. You basically only need pen and eraser. Without softening, good old sharp edges. Layers would be a plus. Any program should allow you to do this in a super easy way, right.&lt;/p&gt;

&lt;p&gt;I’ve always used Photoshop for graphic editing, but it’s not an option for me anymore, because I really dislike the subscription approach Adobe is using, and I don’t want to download it illegally when there are so many alternatives. I’m just going to skip the rant about Gimp and the sad times I spent searching for alternatives. Just buy &lt;a href="https://www.aseprite.org/" rel="noopener noreferrer"&gt;Aseprite&lt;/a&gt;, it’s great.&lt;/p&gt;

&lt;h2&gt;
  
  
  The art
&lt;/h2&gt;

&lt;p&gt;Did I mention it’s basically my first time doing pixel art?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F558lhy40swnkr7og4vxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F558lhy40swnkr7og4vxu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, after realizing I don’t know shit about pixel art, I started gathering a few resources to learn, like &lt;a href="https://www.retronator.com/" rel="noopener noreferrer"&gt;Retronator&lt;/a&gt; and &lt;a href="https://www.youtube.com/playlist?list=PLLf03i3vdC4xBVVjCFtUrxH1m1vLNEdpR" rel="noopener noreferrer"&gt;Pixel Art Academy 101&lt;/a&gt;, &lt;a href="http://blog.studiominiboss.com/pixelart" rel="noopener noreferrer"&gt;MiniBoss Pixel Art Tutorials&lt;/a&gt;, &lt;a href="https://raymond-schlitter.squarespace.com/blog/" rel="noopener noreferrer"&gt;Slynyrd’s blog&lt;/a&gt; and of course, kept staring at &lt;a href="https://twitter.com/Pixel_Dailies" rel="noopener noreferrer"&gt;Pixel Dailies&lt;/a&gt; and &lt;a href="https://www.pixelshuh.com/" rel="noopener noreferrer"&gt;Pixels Huh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And then back to work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F49h5o9mvnjslqfmpk5cv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F49h5o9mvnjslqfmpk5cv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
That’s a little bit better&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu2eq36zbhk29n5xjyzlu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu2eq36zbhk29n5xjyzlu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m having a hard time with backgrounds and colors, so I also did some gray scale backgrounds to practice&lt;/p&gt;

&lt;h2&gt;
  
  
  The doing nothing
&lt;/h2&gt;

&lt;p&gt;But really, these past weeks I’ve been mostly doing nothing. It kinda breaks your motivation, when you are stuck doing something that you don’t particularly enjoy and you keep not seeing any good results. I feel it’s the point where most projects just get abandoned. I’ve felt like ditching this a few times. But I also found a few ways to keep the spirits up.&lt;/p&gt;

&lt;p&gt;One is sharing with people what you are doing, the ideas you have. It’s a good way to remember why you started the project, plus when people know you are working on something, there’s a small pressure there — the good kind of pressure, I think — that keeps you going.&lt;/p&gt;

&lt;p&gt;Another is to switch tasks and do something else that is less frustrating. Sure, it’s good to have a plan and actually finish tasks, but it’s no good if you are so stuck you want to throw everything away. In the moments when I really didn’t feel like doing pixel art I’ve been working on the story, and it’s been great because I’ve gotten really excited about certain scenes or characters, and that brought back the will to l̶i̶v̶e̶ draw.&lt;/p&gt;




&lt;p&gt;So, still a lot of artwork to do but summer has ended and I’ve managed to get some of my motivation back, so I’m hoping to start working on the game more often now.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
      <category>pixelart</category>
    </item>
  </channel>
</rss>
