<?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>DEV Community: Abhishek</title>
    <description>The latest articles on DEV Community by Abhishek (@lilshake).</description>
    <link>https://dev.to/lilshake</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%2F1104537%2Fc592bd43-9b09-4af2-803b-9dcfb6c8a7e9.jpg</url>
      <title>DEV Community: Abhishek</title>
      <link>https://dev.to/lilshake</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lilshake"/>
    <language>en</language>
    <item>
      <title>If you could use notion to build an app/startup , what would you make?</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sun, 09 Jun 2024 11:04:47 +0000</pubDate>
      <link>https://dev.to/lilshake/if-you-could-use-notion-to-build-an-appstartup-what-would-you-make-5fgg</link>
      <guid>https://dev.to/lilshake/if-you-could-use-notion-to-build-an-appstartup-what-would-you-make-5fgg</guid>
      <description>&lt;p&gt;I've been working hard on a framework that converts notion pages to usable apps. I wanted to know what use cases would be most popular.&lt;/p&gt;

&lt;p&gt;This would be a purely &lt;strong&gt;no code solution&lt;/strong&gt; (maximum code would be a simple DSL) and the focus is on actually getting an app out there that you've just built in notion.&lt;/p&gt;

&lt;p&gt;If anyone is interested in trying out the framework please let me know!! Thank youu&lt;/p&gt;

&lt;p&gt;Assume the following integrations are available&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign in with Google, phone number etc&lt;/li&gt;
&lt;li&gt;Payments from your end users and subscriptions&lt;/li&gt;
&lt;li&gt;Normal notion pages or content can be used as UI&lt;/li&gt;
&lt;li&gt;Notion databases are used to model any data with forms and views etc etc&lt;/li&gt;
&lt;li&gt;Chat between any user in your app&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;or anything else you want.. just tell me any app idea you have. The technical side would be sorted.&lt;/p&gt;

</description>
      <category>nocode</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>startup</category>
    </item>
    <item>
      <title>I made a simple Room-based Low Code Multiplayer Framework for Gamemaker🚀</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sat, 11 Nov 2023 11:46:31 +0000</pubDate>
      <link>https://dev.to/lilshake/i-made-a-simple-room-based-low-code-multiplayer-framework-for-gamemaker-49mc</link>
      <guid>https://dev.to/lilshake/i-made-a-simple-room-based-low-code-multiplayer-framework-for-gamemaker-49mc</guid>
      <description>&lt;p&gt;Hello, fellow game developers! 🎮&lt;/p&gt;

&lt;p&gt;I'm thrilled to introduce you to Rocket Networking, a powerful networking engine designed specifically for GameMaker. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://rocketnetworking.net/" rel="noopener noreferrer"&gt;Rocket Networking&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever gone into multiplayer game development, you know the challenges of implementing even a networking system. For beginners or game developers who are more on the artistic side, this can get very difficult and time consuming.&lt;/p&gt;

&lt;p&gt;That's where Rocket Networking comes in, simplifying your journey and accelerating your project's success.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Rocket Networking? And why particularly Gamemaker?
&lt;/h1&gt;

&lt;p&gt;When I started this game development journey, all I knew was that I wanted to create my own .io game. (I finally did btw, check out my last post ;)&lt;/p&gt;

&lt;p&gt;Gamemaker is the best starting point if you want to get into game development. Many would argue it is Unity, but the difference in learning curves is HUGE. And it really doesn't make sense to use Unity for 2D games, it's overcomplicating things a lot. Gamemaker has an easy to use IDE, easy to learn Script and is just overall more welcoming. &lt;/p&gt;

&lt;h2&gt;
  
  
  Need for a dedicated server
&lt;/h2&gt;

&lt;p&gt;Unity does have a popular framework for making multiplayer games, Photon Unity Networking (PUN) and it's very famous. In gamemaker you had to start from the vanilla functionality provided and that isn't bad but it is very time consuming. The problem is you can't really build a scalable multiplayer game that anyone can play anytime around the world. For that, you need some kind of a &lt;strong&gt;dedicated server that is always on&lt;/strong&gt;. Otherwise you're stuck with local multiplayer. You can see this starts to get messy. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;I have to go to a cloud provider? Rent a VM? Write a script in some backend framework like Node.js? And then make it communicate with gamemaker?...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Even after that you have to learn how to use Buffers (which are infamously hard) to communicate, which is definitely not for the beginner.&lt;br&gt;
However this isn't that bad because it's only a one time thing. Once you learn how to use buffers, you just have to repeat that code.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Rocket Networking Solves this Problem
&lt;/h2&gt;

&lt;p&gt;Rocket Networking will host and manage the backend server for you. So you don't have to touch any backend code or go to another cloud provider. All you have to do is make an account with us, and there you go.&lt;br&gt;
Our Client side Gamemaker extension is designed so that communication is dumbed down to just 1 line of code to share data with the server.&lt;/p&gt;

&lt;h1&gt;
  
  
  Room Based Multiplayer
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Rooms (Auto State Sharing)
&lt;/h2&gt;

&lt;p&gt;Making multiplayer games is broken down in RNet to rooms. A client can choose their room like "public" or "lobby" and they automatically share data with other clients in that room.&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%2Fuploads%2Farticles%2Fedk7qe6cig3zo3103277.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%2Fuploads%2Farticles%2Fedk7qe6cig3zo3103277.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So if you are in the "lobby" and you are sharing your "name", then other clients are automatically created for you and you can see all their names. &lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Player Creation and Destruction
&lt;/h2&gt;

&lt;p&gt;You don't have to worry about creating a new player everytime someone joins the room or destroying that player everytime they leave. All that is auto managed. You just have to outline the general stuff. Like print the "name" on top of the player.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entity System
&lt;/h2&gt;

&lt;p&gt;Some elements in multiplayer game development are not just limited to a client. This can be NPCs, bullets etc.. For those things, we have an entity system. So if you create an entity, it is created for everyone else until you destroy it. You can see this perfectly fits the application of a bullet that you shoot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Private Messaging System
&lt;/h2&gt;

&lt;p&gt;This is independent of the pre existing state sharing system, so you may or may not pair it with that. Sometimes state based sharing of data can be heavy... And in turn based games it's not the optimal solution. What if we could just send an individual packet of data from one client to the other? That is the Private Messaging System, built separately and very easy to use&lt;br&gt;
&lt;strong&gt;Example usage. Your bullet hits another player, you have to tell that player to reduce their health by 10.&lt;/strong&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%2Fuploads%2Farticles%2Fuxbjxcuuegq5uex4fttf.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%2Fuploads%2Farticles%2Fuxbjxcuuegq5uex4fttf.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  User Reviews and Games
&lt;/h1&gt;

&lt;p&gt;To be completely honest the customer base is still very small but we've got some wonderful feedback from those who have used it!&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%2Fuploads%2Farticles%2Fs7fsrp6ylrkkid4cregn.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%2Fuploads%2Farticles%2Fs7fsrp6ylrkkid4cregn.png" alt="Image description"&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%2Fuploads%2Farticles%2Ftre095vqztq0ok06deii.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%2Fuploads%2Farticles%2Ftre095vqztq0ok06deii.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also have some sample projects you can try out...&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%2Fuploads%2Farticles%2Fbk6x7o3afr25ka8y1j5r.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%2Fuploads%2Farticles%2Fbk6x7o3afr25ka8y1j5r.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lil-shake-code.github.io/lilshake-io/" rel="noopener noreferrer"&gt;Open this&lt;/a&gt; with your friend or even in 2 tabs or 2 people from anywhere in the world. All this code is available on github so you can get started easily.&lt;/p&gt;

&lt;p&gt;On the Website I have all these guides.&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%2Fuploads%2Farticles%2Fg9hgk1rtjxgydne845in.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%2Fuploads%2Farticles%2Fg9hgk1rtjxgydne845in.png" alt="Image description"&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%2Fuploads%2Farticles%2Fd4os569nic5co0tmg0lf.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%2Fuploads%2Farticles%2Fd4os569nic5co0tmg0lf.png" alt="Image description"&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%2Fuploads%2Farticles%2Fml8xplvc5zya6x4sgcma.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%2Fuploads%2Farticles%2Fml8xplvc5zya6x4sgcma.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you so much for the time to read this post!💝. I appreciate it a lot, and I hope I'll see you soon :)&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>career</category>
      <category>showdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>Made an .io game in 10 days✈️</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Tue, 31 Oct 2023 15:05:49 +0000</pubDate>
      <link>https://dev.to/lilshake/made-an-io-game-in-10-days-48fi</link>
      <guid>https://dev.to/lilshake/made-an-io-game-in-10-days-48fi</guid>
      <description>&lt;p&gt;Hello Everyone!&lt;br&gt;
Let's talk gamedev, better yet fast addictive .io games. And how I made&lt;br&gt;
&lt;a href="https://stellarclash.io" rel="noopener noreferrer"&gt;StellarClash.io✈️&lt;/a&gt; in 10 days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is a real .io game!! You can open 2 tabs on your browser and see 2 planes!!&lt;/strong&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%2Fuploads%2Farticles%2Fy19gqt4cra6re3gtirl4.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%2Fuploads%2Farticles%2Fy19gqt4cra6re3gtirl4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the source &lt;a href="https://github.com/lil-shake-code/aerospace-io" rel="noopener noreferrer"&gt;GitHub🐈&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Basic Structure of an .io Game
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Frontend - Gamemaker
&lt;/h2&gt;

&lt;p&gt;You have to choose a frontend which is compatible with the HTML5 Canvas. You can directly use the canvas API if you like vanilla JS code but I used Gamemaker and it's really easy! &lt;br&gt;
Because the frontend stuff is mostly just&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Drawing planes and Moving the Camera there&lt;/li&gt;
&lt;li&gt;Drawing bullets &lt;/li&gt;
&lt;li&gt;Showing what is happening on the server&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Backend Nodejs Server
&lt;/h2&gt;

&lt;p&gt;This is where all the game logic actually works.&lt;br&gt;
And there is always websocket communication between client and server.&lt;/p&gt;
&lt;h3&gt;
  
  
  Players
&lt;/h3&gt;

&lt;p&gt;Every player is treated like a point particle and is spawned at a relatively low density area of the game. All players are saved to a players array&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%2Fuploads%2Farticles%2F6m2y73zi239zrqd9imj5.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%2Fuploads%2Farticles%2F6m2y73zi239zrqd9imj5.png" alt="Image description"&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%2Fuploads%2Farticles%2Fud7q3r76cxe85rsz6t92.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%2Fuploads%2Farticles%2Fud7q3r76cxe85rsz6t92.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Bullets
&lt;/h3&gt;

&lt;p&gt;Shooting is important and based on your level you shoot a specific number of bullets, bullets of specific damage. And on the client side the damage of the bullet appears as its size, so you have an idea how much you'll be hurt.&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%2Fuploads%2Farticles%2Ffbuy57g2sz3cncow6j2u.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%2Fuploads%2Farticles%2Ffbuy57g2sz3cncow6j2u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Food ie Selenium
&lt;/h3&gt;

&lt;p&gt;Some metal... these are like the slither io orbs. The gamemaker particle effects make it look a lot like that.&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%2Fuploads%2Farticles%2Fst8mq5cwjxaqipprsfnx.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%2Fuploads%2Farticles%2Fst8mq5cwjxaqipprsfnx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Levelling system
&lt;/h1&gt;

&lt;p&gt;The levelling system uses a formula.... This formula will need to be updated as the game gets better but here it is&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%2Fuploads%2Farticles%2F1zsetjr5gkcgp1yivppe.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%2Fuploads%2Farticles%2F1zsetjr5gkcgp1yivppe.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The Game Loop in Nodejs
&lt;/h1&gt;

&lt;p&gt;Here,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All the players are propelled forward according to their speed and direction&lt;/li&gt;
&lt;/ol&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%2Fuploads%2Farticles%2Flvcj0fvq1n671gi6bqt0.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%2Fuploads%2Farticles%2Flvcj0fvq1n671gi6bqt0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All the bullets are propelled forward according to their speed and direction. If a bullet is hitting another player, the bullet is destroyed and health and kills of victim and killer are updated.&lt;/li&gt;
&lt;/ol&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%2Fuploads%2Farticles%2Fk7uxiici5llw2romta4k.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%2Fuploads%2Farticles%2Fk7uxiici5llw2romta4k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If players are close to the food, it is destroyed and added to their score.&lt;/li&gt;
&lt;li&gt;Other behaviors like bots ...&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  Bot Creation
&lt;/h1&gt;

&lt;p&gt;So bots are created when there are less players and they are made to behave very similar to normal players.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createBots&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//go through the players and count how many are bots&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;botCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;realPlayerCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;botCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;health&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;realPlayerCount&lt;/span&gt;&lt;span class="o"&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;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;botCount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_BOTS&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;realPlayerCount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_BOTS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;creating a new bot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;spawnPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bestSpawnPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spawnPoints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;//for the name of the bot, 30% chance use the name from the list, 70% chance use empty string&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;botName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;botName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;botNames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentBotName&lt;/span&gt;&lt;span class="o"&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;currentBotName&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;botNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentBotName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;spawnPoint&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="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;spawnPoint&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="na"&gt;A&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="na"&gt;N&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="na"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;health&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;maxHealth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;kills&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;///BOTS WILL ONLY EXIST in public room&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;botName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;recoil&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="na"&gt;lifetime&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="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;skin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;//0-6&lt;/span&gt;
      &lt;span class="na"&gt;lastHitTime&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="na"&gt;recoil&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="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getShootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kills&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thrustSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxHealth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxHealth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//tell other players we created this guy&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sendThis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_player&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&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="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&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="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;skin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;skin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;otherPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

      &lt;span class="c1"&gt;//check if same room&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;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&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;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//if ws is not null&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;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sendThis&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;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createBots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Bot Behavior
&lt;/h1&gt;

&lt;p&gt;Inside the game Loop, bots are made to follow the closest player to them and once they are close enough start shooting. Note that there is some randomness allowed here to make it feel real.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lifetime&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//recoil&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;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoil&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoil&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;//bot logic&lt;/span&gt;
      &lt;span class="c1"&gt;//try to chase the player closest to this bot and once you are close enough, shoot&lt;/span&gt;

      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;closestPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;closestDistance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;otherPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="c1"&gt;//if roomId is different, skip this player&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;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;//if health is 0, skip this player&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;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;health&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&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;otherPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&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;player&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;otherPlayer&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;otherPlayer&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;closestDistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;closestDistance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;closestPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;otherPlayer&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;closestPlayer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//chase this player&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;closestPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;player&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;dy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;closestPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;player&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="c1"&gt;//if the player is close enough, shoot&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;closestDistance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kills&lt;/span&gt;&lt;span class="p"&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;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoil&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//rotate the bot to face the player&lt;/span&gt;
            &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;///repeat x times&lt;/span&gt;

            &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bullet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&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="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&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="na"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bulletSpeed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;damage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;damage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;firedBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;lifetime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;};&lt;/span&gt;
              &lt;span class="nx"&gt;bullets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;bulletId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bullet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;//recoil&lt;/span&gt;
            &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoilTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shootingCharacteristics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recoilTime&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;//just make the bot move in the direction of the player 5 pixels&lt;/span&gt;
          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fakeN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kills&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;closestDistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;fakeN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dy&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;closestDistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;fakeN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

          &lt;span class="c1"&gt;//rotate the bot to face the player&lt;/span&gt;
          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="c1"&gt;//lerp player.A to newA&lt;/span&gt;
          &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;newA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;//check if player is out of bounds&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;correctedPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;outOfBounds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&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;player&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;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;correctedPosition&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;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;correctedPosition&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="k"&gt;continue&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;h1&gt;
  
  
  Deployment and public facing.
&lt;/h1&gt;

&lt;p&gt;The nodejs websocket server is deployed on heroku for just 7$ a month!!! That is my game server, only 7$🤑🤑🤑💵💵&lt;/p&gt;

&lt;p&gt;It is hosted in US so players like me from India can face some lag. But because of extreme lerping, it's smooth lag which kind of does not feel as bad.&lt;/p&gt;

&lt;p&gt;The actual game is hosted with Firebase hosting. I bought the domain on Namecheap for like 42$ and then deployed using the firebase CLI.&lt;/p&gt;

&lt;h1&gt;
  
  
  Future Plans
&lt;/h1&gt;

&lt;p&gt;The next step would be to &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Improve the game - Adding more SFX and VFX to make it look better, and improve the levelling up and evolution&lt;/li&gt;
&lt;li&gt;Develop a following for constant feedback. &lt;a href="//iogames.forum"&gt;iogames.forum &lt;/a&gt; is the best place imo and then there are other io game sites. &lt;/li&gt;
&lt;li&gt;Iterate 1 and 2 so that players are funnelled to my twitter and iogames.forum where they get updates on the games and can interact with me and that will make the game better&lt;/li&gt;
&lt;li&gt;Ads by Google - I was magically approved as a google H5 Games ad associate but I don't have the basic adsense approval on my site yet😶... so I have to figure some stuff out but hopefully I'll be able to earn a little from this!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thank you for reading this post! Follow me on &lt;br&gt;
&lt;a href="https://twitter.com/lilshake139" rel="noopener noreferrer"&gt;Twitter🐦&lt;/a&gt; for more updates!!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>javascript</category>
      <category>node</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GPT Mental Health Chatbot💛 and Google Calendar API📆</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Fri, 25 Aug 2023 20:09:38 +0000</pubDate>
      <link>https://dev.to/lilshake/gpt-mental-health-chatbot-and-google-calendar-api-3d94</link>
      <guid>https://dev.to/lilshake/gpt-mental-health-chatbot-and-google-calendar-api-3d94</guid>
      <description>&lt;p&gt;Hi Everyone!&lt;br&gt;
I have been working on a GPT Chatbot that...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Talks to you for a while and understands your feelings&lt;/li&gt;
&lt;li&gt;Asks you 10 questions to plan your day&lt;/li&gt;
&lt;li&gt;Uses Google Calendar API to Build a schedule for you.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Motivation to do this
&lt;/h1&gt;

&lt;p&gt;When I was in high school and preparing for a college entrance I achieved high level consistency and my Google Calendar Reflected it. It was more like a diary.&lt;/p&gt;

&lt;p&gt;It looked like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rLSOCuaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asvh1mbsjmxzynx8wpat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rLSOCuaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asvh1mbsjmxzynx8wpat.png" alt="Image description" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This honestly made me happy because I had some sort of a plan for my life and &lt;strong&gt;I could visually see how it turned out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The color scheme was also predefined. Light blue and yellow was work, pink was sleep, orange was neutral events and dark blue was R&amp;amp;R.&lt;/p&gt;

&lt;p&gt;I want to share this amazing system that made me happy, made me more productive, and in general a much smarter person.&lt;/p&gt;

&lt;p&gt;Also, at the moment &lt;em&gt;I'm taking BZDs&lt;/em&gt;. &lt;strong&gt;Medications that make you feel "tranquillity"&lt;/strong&gt;. I want people to have that feeling without them meds.&lt;/p&gt;

&lt;h2&gt;
  
  
  React app + Firebase Functions Express Endpoint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--39p8xMLA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovqhkqwkbmqpk0goat0d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--39p8xMLA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovqhkqwkbmqpk0goat0d.png" alt="Image description" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where all the chats are combined and we get a response from the openAI api.&lt;/p&gt;

&lt;p&gt;It is trained to go like a therapy session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Calendar API
&lt;/h2&gt;

&lt;p&gt;Okay getting the whole OAuth thing working was difficult and even now, my app is still in testing! But the GPT API can call functions and I made some sort of a function to add events to someone's calendar&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample Chat response to Calendar
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--65GoYUqi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gljuxz5bdxzd5wqz9bvy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--65GoYUqi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gljuxz5bdxzd5wqz9bvy.png" alt="Image description" width="800" height="861"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T0zKWkua--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/syvdv1o553wlae2lzyfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T0zKWkua--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/syvdv1o553wlae2lzyfk.png" alt="Image description" width="246" height="1302"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Please ignore the light time zone mismatch.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So lets talk about testers💛&lt;/p&gt;

&lt;h1&gt;
  
  
  Looking for Testers! Try tranqility out now!
&lt;/h1&gt;

&lt;p&gt;As of now if you go to &lt;a href="https://tranqility-ai.web.app/"&gt;https://tranqility-ai.web.app/&lt;/a&gt;  I don't think you'll be able to use it unless you are registered by me as a test user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But with another account it did work without all this test user stuff, so just try it out, it'll barely take 20 seconds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, if anyone is interested in a light therapy session followed by day planning, &lt;strong&gt;comment your email address and I'll invite you&lt;/strong&gt;!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mentalhealth</category>
      <category>firebase</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Babylon.js + Google Blockly = No Code FPS, TPS🔥</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sun, 06 Aug 2023 16:24:08 +0000</pubDate>
      <link>https://dev.to/helicity/babylonjs-google-blockly-no-code-fps-tps-3bld</link>
      <guid>https://dev.to/helicity/babylonjs-google-blockly-no-code-fps-tps-3bld</guid>
      <description>&lt;p&gt;As I was normally going about developing &lt;a href="https://helicity.ai"&gt;helicity.ai&lt;/a&gt; I realised that a lot of functionality can be added.&lt;/p&gt;

&lt;h1&gt;
  
  
  Problems with current Game Engines IMO
&lt;/h1&gt;

&lt;p&gt;I always thought about Babylon.js like something I can never understand, one of the late realisations of life I guess.&lt;/p&gt;

&lt;p&gt;I've tried Unity, I've tried GMS and pure H5 Canvas API.&lt;/p&gt;

&lt;p&gt;The problem with &lt;strong&gt;Unity&lt;/strong&gt; was the steep learning curve that never seemed to resolve(it finally did but just saying)..🥲&lt;br&gt;
&lt;strong&gt;GMS&lt;/strong&gt; was good but its paid and you can pretty much do nothing without paying. Also its H5 Development is too buggy. Its only good for PCs&lt;br&gt;
The &lt;strong&gt;canvas API&lt;/strong&gt; was cute and not really a game engine 😅...&lt;/p&gt;

&lt;h1&gt;
  
  
  The REAL TRUTH about Game Engines
&lt;/h1&gt;

&lt;p&gt;I really dont wan't to hate on any Game Engine, because the truth is and honestly this is with any tech stack...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The best Game Engine is not the one with the most features, its the one which allows you to be the most productive.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Large studios will love Unity and Unreal. &lt;br&gt;
But I'm a web developer..&lt;br&gt;
I live and breathe JavaScript&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not use the same codebase?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The packages and feature version mismatches of Unity are enough for me to not like it. H5 games are too slow to even build and test and my PC burns man..&lt;/p&gt;

&lt;h2&gt;
  
  
  Making multiplayer games sucks on normal Game Engines
&lt;/h2&gt;

&lt;p&gt;And my biggest point!! Networking API in any major game engine is so poor! I love making multiplayer games and the best way to do that for me has always been &lt;strong&gt;make the damn server in Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I'd do stuff like use GMS for the Game Client and Node+ websockets for the backend, but it was always like 2 people speaking different languages trying to make a relationship work💔&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Babylon.js🧡
&lt;/h1&gt;

&lt;p&gt;I made more progress in Babylon in 1 hour than I did in days with Unity or GMS.(GMS is still a very easy one)&lt;br&gt;
The JS code was so readable and easy to understand and &lt;strong&gt;felt intuitive&lt;/strong&gt;&lt;br&gt;
I did not have to worry about adding new features and using more JS libraries because they're all independent.&lt;br&gt;
In babylon it actually feels like you understand the full picture behind your code and between you and your code execution there isnt much of a wall.&lt;br&gt;
Babylon js is made so beautifully you can built so much in it with low code. Talk about the &lt;strong&gt;built in physics engine&lt;/strong&gt; for a JS library!&lt;br&gt;
&lt;strong&gt;The Graphical performance&lt;/strong&gt; is way too good. It even works on low end devices and is the best for H5 games. Make realistic games, host online, anyone with a browser can play.. this is too good to be true.&lt;/p&gt;

&lt;p&gt;Also as a web developer its very easy to export your game and host it because you learn so much about deployment specifically.&lt;/p&gt;

&lt;h1&gt;
  
  
  Connecting with Helicity.ai
&lt;/h1&gt;

&lt;p&gt;I had made a basic 2D engine and it was a good learning experience but even a &lt;strong&gt;basic game in 3D is more fun than a complex game in 2D&lt;/strong&gt; for the average guy.&lt;/p&gt;

&lt;p&gt;Now that I understood babylon, I wanted to integrate it with Google's Blockly,  to provide a &lt;strong&gt;NO CODE EXPERIENCE in Game Development.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The end result looks something like this. Its a No code editor made in React&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--53TRv_xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3dcbkwt0sq8nhbnckw9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--53TRv_xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3dcbkwt0sq8nhbnckw9g.png" alt="Image description" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its purely a work in progress but Helicity is going 3D. You'll soon be able to create an FPS with a few blocks. It'll still take time but anyone can make it now.&lt;/p&gt;

&lt;p&gt;Join this journey on &lt;a href="https://twitter.com/helicityai"&gt;twitter or x or whatever theyre calling it now&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>GPT3.5 Turbo Game Engine✨ - You can make money from H5 Games now</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Mon, 31 Jul 2023 20:36:48 +0000</pubDate>
      <link>https://dev.to/lilshake/gpt35-turbo-game-engine-you-can-make-money-from-h5-games-now-405j</link>
      <guid>https://dev.to/lilshake/gpt35-turbo-game-engine-you-can-make-money-from-h5-games-now-405j</guid>
      <description>&lt;p&gt;It's been a while since I've posted on DEV, and I have been consistently working on &lt;a href="https://helicity.ai"&gt;helicity.ai&lt;/a&gt;. ✨💙&lt;/p&gt;

&lt;p&gt;The cool part is that helicity is finally in good shape! Here are some interface and functionality highlights. And then we'll talk about &lt;strong&gt;Google Ad Money🫰💵&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects Page
&lt;/h2&gt;

&lt;p&gt;This is a Route in React (/projects) and uses &lt;strong&gt;firebase RTDB&lt;/strong&gt; to look into your pojects and list them out. Might be moving to Firestore soon&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lBPGM11b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yeitubofecsywe8todwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lBPGM11b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yeitubofecsywe8todwl.png" alt="Image description" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  IDE Code Editor
&lt;/h2&gt;

&lt;p&gt;This is the /ide route in react and consists of the &lt;strong&gt;monaco code editor component&lt;/strong&gt; to make it look like VSCode. Also the code is autosynced to the firebase RTDB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CtkguoM1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p06kzfc2kq5r23h7lwv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CtkguoM1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p06kzfc2kq5r23h7lwv5.png" alt="Image description" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is how the autosave works. Just a little sneak peak into the backend in express.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p5_n-iJp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0spddafzwenrzex7fyqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p5_n-iJp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0spddafzwenrzex7fyqh.png" alt="Image description" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Game Maker
&lt;/h2&gt;

&lt;p&gt;The part which makes helicity what it is. What I did was teach GPT3.5 my game engine and then make it write code in that.&lt;/p&gt;

&lt;p&gt;A game description is taken from you, and those parameters decide what kind of code the AI writes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind that AI is just an add on and this is a fully functioning game engine on its own!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Publish your Game and Get a Shareable link in 12 seconds
&lt;/h1&gt;

&lt;p&gt;After you have coded your game, when you press the play button it opens up a new tab on &lt;em&gt;&lt;strong&gt;app.helicity.ai/games/some-id&lt;/strong&gt;&lt;/em&gt; and you can share this link with all your friends!&lt;br&gt;
Here is a slither io like snake movement prototype. Bones randomly spawn on the screen as black blocks and then arrange themselves into a snake of red rings. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This code is a template on our site and you can tweak the snake length and size!&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;NODE_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="c1"&gt;// The size of each bone in pixels&lt;/span&gt;
&lt;span class="c1"&gt;//you can change the snake bone to anything ex "lookup: elon musk face"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NODE_IMAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lookup: red circle png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="c1"&gt;// The image source of each node&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TENDON_LENGTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="c1"&gt;// The maximum distance between two nodes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LENGTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// The initial number of nodes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4sLAv5_E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tv5tginoaie1xwpe1sow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4sLAv5_E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tv5tginoaie1xwpe1sow.png" alt="Image description" width="800" height="858"&gt;&lt;/a&gt;&lt;br&gt;
Here is the game link.&lt;br&gt;
&lt;a href="https://app.helicity.ai/games/42aef1d4-51a6-4f31-87a4-53b3c2c3f2aa.html"&gt;Snakey&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Game Monetisation - The AI Money Minting Engine
&lt;/h1&gt;

&lt;p&gt;A few days back I just realised that the Google H5 beta Ads can be used because this is a pure HTML5 Game engine so that's what I'm working on now!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X-eC7xJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m991iedvjppy78mr8g52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X-eC7xJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m991iedvjppy78mr8g52.png" alt="Image description" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With a function to call Display ads and Rewarded ads so any developer can plug them, and after 1000 plays on a game or 1000 ad views, you can earn some $!&lt;br&gt;
Payouts would be managed by stripe and automated by cloud functions that keep track of how much your game has been played.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading!&lt;/strong&gt; I know this was a short post but I realllyy wanted to share what I've been working on. If you have any feedback please join &lt;a href="https://discord.com/invite/RkH98RgVDr"&gt;our discord server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also recently made a &lt;a href="https://twitter.com/helicityai"&gt;🐦twitter or x or whatever account&lt;/a&gt; specifically for helicity, and I drop in my progress everyday.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pdAgwEGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh6bf9ibaribyv8cofly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pdAgwEGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh6bf9ibaribyv8cofly.png" alt="Image description" width="800" height="881"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>ai</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Create a HTML5 Game with a Single Prompt💙 [GPT3.5]</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sun, 16 Jul 2023 21:47:20 +0000</pubDate>
      <link>https://dev.to/lilshake/create-a-html5-game-with-a-single-prompt-gpt35-3mhc</link>
      <guid>https://dev.to/lilshake/create-a-html5-game-with-a-single-prompt-gpt35-3mhc</guid>
      <description>&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%2Fuploads%2Farticles%2Fsc4g27knn3svv9l86idz.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%2Fuploads%2Farticles%2Fsc4g27knn3svv9l86idz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey guys! Did you know that GPT3.5 is amazing? Seriously, its performance to price ratio is amazing. That has allowed me to create a Code Generator for my game engine.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;taught GPT3.5&lt;/strong&gt; how to use &lt;strong&gt;my game engine&lt;/strong&gt; in the first part of the prompt and in the 2nd part I provided the &lt;strong&gt;Game Description&lt;/strong&gt; we want.&lt;/p&gt;

&lt;p&gt;You can try it out for free at &lt;a href="https://app.helicity.ai" rel="noopener noreferrer"&gt;Helicity.ai✨&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is my &lt;a href="https://github.com/lil-shake-code/helicity.ai" rel="noopener noreferrer"&gt;Game Engine - Full Open Source Code on GitHub😺&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Result
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GameObject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Gameobject.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Input.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Physics&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Physics.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Renderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Renderer.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Engine.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Set the background image&lt;/span&gt;
&lt;span class="nx"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBackground&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lookup: flappy bird background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create the player object&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;GameObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&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;width&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="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageSrc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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;width&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="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageSrc&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;velocityY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;gravity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Apply gravity&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;velocityY&lt;/span&gt; &lt;span class="o"&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;gravity&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;y&lt;/span&gt; &lt;span class="o"&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;velocityY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Jump when space is pressed&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;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;space&lt;/span&gt;&lt;span class="dl"&gt;"&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;velocityY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Check collision with pipes&lt;/span&gt;
    &lt;span class="k"&gt;for &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;pipe&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gameObjects&lt;/span&gt;&lt;span class="p"&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;pipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Physics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkCollision&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;pipe&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Game Over!&lt;/span&gt;&lt;span class="dl"&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Create the pipe object&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pipe&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;GameObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&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;width&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="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageSrc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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;width&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="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageSrc&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;velocityX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;update&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;x&lt;/span&gt; &lt;span class="o"&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;velocityX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Remove the pipe when it goes off the screen&lt;/span&gt;
    &lt;span class="k"&gt;if &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;x&lt;/span&gt; &lt;span class="o"&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;width&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gameObjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gameObjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&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="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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Spawn pipes every 2 seconds&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pipeHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&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;pipeGap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&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;topPipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pipeHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lookup: green pipe mario png&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;bottomPipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&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="nx"&gt;pipeHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;pipeGap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pipeHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;pipeGap&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lookup: green pipe mario png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gameObjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;topPipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bottomPipe&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// Create the game objects&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&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="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;player&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lookup: flappy bird png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add the game objects to the game loop&lt;/span&gt;
&lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gameObjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Start the game loop&lt;/span&gt;
&lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Play it here
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://storage.googleapis.com/ai-game-maker.appspot.com/public/zdfRs9zO3PW6LRPZ0yLlFLcQ3eA3.html" rel="noopener noreferrer"&gt;Game&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Better prompts =&amp;gt; Better Results
&lt;/h2&gt;

&lt;p&gt;Notice that a simple prompt like "Make flappy bird" would probably not have resulted in a working version of the game. The best game descriptions are those that talk about&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input&lt;/strong&gt; - What keys pressed do what&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Good Image Descriptions&lt;/strong&gt; - Tell the engine what images you want to use for what. And what kind of a background you want to have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collisions&lt;/strong&gt;- When "elon" collides with "mark" do this ...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specific Behavior&lt;/strong&gt;  - When the bird is falling rotate it so it looks more realistic and feels good on the player.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;On the discord server I am making a list of good Prompts so anyone can understand and develop better games.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you want to support this project, please join the &lt;a href="https://discord.com/invite/RkH98RgVDr" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt; and drop your feedback! Thank you so much&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Send a 'Welcome' Email after someone signs in to your Firebase🔥 App with Brevo</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Fri, 14 Jul 2023 13:54:30 +0000</pubDate>
      <link>https://dev.to/lilshake/send-a-welcome-email-after-someone-signs-in-to-your-firebase-app-with-brevo-md0</link>
      <guid>https://dev.to/lilshake/send-a-welcome-email-after-someone-signs-in-to-your-firebase-app-with-brevo-md0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Today, I will show you how to automate the process of sending a welcome email to a new user upon sign-up with Firebase Authentication, using Firebase Functions and Brevo's email service. It's very easy...  &lt;/p&gt;

&lt;p&gt;Firebase is definitely the best backend provider in my opinion and you can create a full Web App with the &lt;strong&gt;FERN stack - Firebase Express React Node&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Brevo is a very easy to use &lt;strong&gt;'Email Builder'&lt;/strong&gt;, because the content in the email is rich...and you can also make customer lists here. However a simple way to make a welcome mail is to just make one and Store it as a template. And then send to everyone.&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%2Fuploads%2Farticles%2Fpfj9e00jgysxyvajyily.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%2Fuploads%2Farticles%2Fpfj9e00jgysxyvajyily.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My Project is &lt;a href="https://helicity.ai" rel="noopener noreferrer"&gt;Helicity.ai&lt;/a&gt; , an AI powered JS Game Engine still in the works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Firebase Authentication
&lt;/h2&gt;

&lt;p&gt;First, you need to set up Firebase Authentication on your platform. Firebase provides a simple, secure, and free system for this purpose. &lt;/p&gt;

&lt;p&gt;You can use a library like &lt;a href="https://github.com/firebase/firebaseui-web-react" rel="noopener noreferrer"&gt;firebaseui-web-react&lt;/a&gt; to make your &lt;strong&gt;Sign in with Google&lt;/strong&gt; Button.&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%2Fuploads%2Farticles%2Feypj83aec8o3b1scqgm2.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%2Fuploads%2Farticles%2Feypj83aec8o3b1scqgm2.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Firebase will handle everything else for you and when you go to your project page you can see everyone and their UUID which uniquely identifies them. Even if they use Email sign in or Phone or all the other ones firebase offers.&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%2Fuploads%2Farticles%2Fx88embcpnpph8azh94cu.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%2Fuploads%2Farticles%2Fx88embcpnpph8azh94cu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a Firebase Function
&lt;/h2&gt;

&lt;p&gt;We will create a Firebase Function that triggers whenever a new user signs up. Firebase Functions are essentially small pieces of backend code that can be executed in response to various events.&lt;/p&gt;

&lt;p&gt;Here is the code for our function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions&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;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUserSignUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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="c1"&gt;// User signed up&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uid&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Write to RTDB&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;database&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;uid&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="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;credits&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;//How many prompts this guy can use today&lt;/span&gt;
    &lt;span class="c1"&gt;// Add any other fields you want to save&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendBrevoEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&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;In the function &lt;code&gt;onUserSignUp&lt;/code&gt;, Firebase passes a UserRecord object representing the newly created user to our function. The function then writes the user's information to Firebase's Realtime Database (RTDB) and attempts to send a welcome email through Brevo. The RTDB record looks like this&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%2Fuploads%2Farticles%2Fpx6az9tibvws9bur6udu.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%2Fuploads%2Farticles%2Fpx6az9tibvws9bur6udu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending an email through Brevo with an API request
&lt;/h2&gt;

&lt;p&gt;To send the email, we are going to use Brevo's API. We will create a function called &lt;code&gt;sendBrevoEmail&lt;/code&gt; that takes an email address and a template ID as parameters:&lt;/p&gt;

&lt;p&gt;Most of this is boilerplate so don't bother much. What's important is who you send the email to and the template ID. You can go to your brevo project and see all the templates and IDs.&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%2Fuploads%2Farticles%2Fop818vu5ahic4h0m6pir.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%2Fuploads%2Farticles%2Fop818vu5ahic4h0m6pir.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;SibApiV3Sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;sib-api-v3-sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendBrevoEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;templateId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;defaultClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SibApiV3Sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ApiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authentications&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api-key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xkeyDONTSTEALMINEPLEASE7QvM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;apiInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SibApiV3Sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TransactionalEmailsApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sendSmtpEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SibApiV3Sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SendSmtpEmail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;sendSmtpEmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;templateId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;templateId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 6 is google , 5 is early access&lt;/span&gt;
  &lt;span class="nx"&gt;sendSmtpEmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Helicity.ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lilshake@helicity.ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;sendSmtpEmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}];&lt;/span&gt;

  &lt;span class="nx"&gt;apiInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransacEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sendSmtpEmail&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;function &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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;API called successfully.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;h2&gt;
  
  
  Extras - Using Formspark✨ to also send an email when someone signs up for Early Access
&lt;/h2&gt;

&lt;p&gt;Formspark is another UI widget manager that looks like this once you set it up. It has a list of the people who signed up and can POST this information to our ENDPOINT.&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%2Fuploads%2Farticles%2F1jzp0viy5mv55e9hnv9l.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%2Fuploads%2Farticles%2F1jzp0viy5mv55e9hnv9l.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  A new firebase Function
&lt;/h1&gt;

&lt;p&gt;Okay so the previous one was for google sign ins. This is for people who have provided their Email for a Newsletter/Early Access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendBrevoEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bad request, expecting POST&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="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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Extract the email from the Formspark request&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendBrevoEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email sent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to send email&lt;/span&gt;&lt;span class="dl"&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;Firebase will give you an endpoint which you will need to set as the webhook URL in Formspark&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%2Fuploads%2Farticles%2F57qyv224ribwllimsczn.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%2Fuploads%2Farticles%2F57qyv224ribwllimsczn.png" alt="Image description"&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%2Fuploads%2Farticles%2F9b3h9111yu2no21jp8ir.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%2Fuploads%2Farticles%2F9b3h9111yu2no21jp8ir.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you can see, sending an email upon user sign-up is a breeze with Firebase Functions and Brevo's API. With this method, you can ensure that every new user gets a warm welcome without any manual intervention. Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can try this out right now! Make an account on helicity.ai and you will receive an email.&lt;/strong&gt;&lt;br&gt;
If you like this and are interested in the development, do consider joining the &lt;a href="https://discord.com/invite/RkH98RgVDr" rel="noopener noreferrer"&gt;discord&lt;/a&gt; server!&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://github.com/lil-shake-code/helicity.ai" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Helicity.ai Team 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>firebase</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I made over 9000$ on Fiverr and Freelancing</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sun, 09 Jul 2023 16:16:55 +0000</pubDate>
      <link>https://dev.to/lilshake/how-i-made-over-9000-on-fiverr-and-freelancing-3d7g</link>
      <guid>https://dev.to/lilshake/how-i-made-over-9000-on-fiverr-and-freelancing-3d7g</guid>
      <description>&lt;p&gt;Hello there,! I'm a Physics + CS undergrad at BITS Goa, a freelancer, a game developer, a web developer, and a co-lead in the TCG at Solana Sneks. I've been on an incredible journey of self-discovery, and today, I wanted to share a little bit about my experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting out
&lt;/h2&gt;

&lt;p&gt;I remember when I first started at University. I had made a game &lt;a href="//gatdamn.io"&gt;gatdamn.io&lt;/a&gt;, a simple io game.&lt;/p&gt;

&lt;p&gt;I wasn't doing anything much then but I did have a dead fiverr profile and 1 gig &lt;br&gt;
&lt;em&gt;&lt;strong&gt;I will make a game in GMS2&lt;/strong&gt;&lt;/em&gt;. One day randomly, out of nowhere I got an order for 30$. This was huge for me back in the day and I was extremely excited. I did not expect Gamemaker to be big enough for a guy to contact me to help him.. So I did and it wasn't even a lot of work, but I made 30$💸&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking Freelance Seriously
&lt;/h2&gt;

&lt;p&gt;During the summer of my first year, I decided to go all in to this freelance thing. I was a complete novice and I didn't even know web development, &lt;strong&gt;barely how to use nodejs&lt;/strong&gt;. And guess what? It worked out. I feel like fiverr is a very friendly platform to start out. It takes time to grow and may not make money at first because you will have to show people some reviews but after a few orders people really start trusting you.🤝&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9-4E925m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yrapeqrg04nw5rtzfc5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9-4E925m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yrapeqrg04nw5rtzfc5d.png" alt="Image description" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made a new gig for this no code tool called &lt;strong&gt;Thunkable&lt;/strong&gt; and turns out many schools and colleges use it...So at first I was just doing their homework for money lol but it led to my biggest client. &lt;/p&gt;

&lt;p&gt;It was a company from AU trying to run a SaaS and they used &lt;strong&gt;Thunkable for the frontend and AWS for the backend&lt;/strong&gt;. This was also my first time getting familiar with &lt;strong&gt;building APIs and Lambda functions and I guess just overall using a cloud service.&lt;/strong&gt; So I learned backend development properly as I kept working from them and mastered &lt;strong&gt;Firebase🔥&lt;/strong&gt;. I love firebase, you can literally make anything with it.&lt;/p&gt;

&lt;p&gt;I would put in a lot of hours every day for this client and started making a few hundred $ every week. I was extremely happy and kinda felt secure... I was paying my tuition and I bought a new laptop.💻&lt;/p&gt;

&lt;p&gt;One day, I was approached by the good guys at &lt;strong&gt;Solana Sneks&lt;/strong&gt;. I didn't realize it at the time, but this was going to be &lt;strong&gt;THE BEST THING THAT EVER HAPPENED TO ME✨&lt;/strong&gt;. My experience with them has been nothing short of extraordinary. We started building (and still are) a trading card game in &lt;strong&gt;Gamemaker&lt;/strong&gt;. I used my Firebase skills to build our whole application and we are in fact close to launch now, I mean like in July 2023.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IBo4RThD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zy4j7e5v1ywqwumsaxif.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IBo4RThD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zy4j7e5v1ywqwumsaxif.gif" alt="Image description" width="400" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Depression
&lt;/h2&gt;

&lt;p&gt;In my second year, I got to really dive deep into the enigmatic world of Physics. Quantum mechanics. Lagrangian mechanics. It was truly enlightening, to say the least.&lt;/p&gt;

&lt;p&gt;But then a horrible depression hit me out of personal problems. I had to start taking antidepressants which caused horrible fatigue and demotivation, in the middle I stopped making money for a while. In his period of my life I was just too sick to feel anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rocket Networking
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--No0XIFuW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vj4nd8i4oosciwnohj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--No0XIFuW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vj4nd8i4oosciwnohj5.png" alt="Image description" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As my experience in game development grew, I felt a calling to transform my freelancing ventures into something more structured. This led me to create &lt;strong&gt;Rocket Networking&lt;/strong&gt;, a multiplayer game development framework designed to streamline the process of building games. I paused freelance to do this. I learned &lt;strong&gt;basic React.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was my first time building a SaaS from scratch so I made a lot of mistakes. The worst one being doing a linear launch. One day to launch without building an audience. Looking back this is stupid because when I would tell people about the product they really liked using it. It was basically a managed VPS for you. I made and still do make some money off this but its not at all close to what I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meltdown
&lt;/h2&gt;

&lt;p&gt;Then it happened...all my problems blew up in my face and I had a huge episode followed by months of trauma-related stress. I was not freelancing. Rocket Networking mostly had free users. I was doing bad in University....everything got fucked up on Feb 14 2023. And no this isn't because of dating, the date is just coincidental.&lt;/p&gt;

&lt;p&gt;It took me weeks to just get my emotions back and start feeling things. One week I went manic (oMg My lIfE Is a mOvIe)&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to freelance
&lt;/h2&gt;

&lt;p&gt;As I was recovering from that whole incident I realised that maybe I do need some security. Not a startup. I went back to fiverr and there were like 60 unread messages. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e0fWEFRZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r89oh29v4x49pcudg5oj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e0fWEFRZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r89oh29v4x49pcudg5oj.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started working on this again. "Yes, I'm so sorry for replying so late, If there is anything I can do please let me know". I got some really cool projects around this time.&lt;br&gt;
I learned to control the &lt;strong&gt;HTML5 Canvas with Canvas API&lt;/strong&gt; and a little bit of Pure H5 Game development. We were building an io game with Canvas API and Socket.io.🖼️&lt;br&gt;
Another really cool project was from the University of Cincinnati where I built a Game, UI based Game Control system in *&lt;em&gt;Google Cloud *&lt;/em&gt; for them. It was kind of related to biology🦇 and I really liked it.&lt;/p&gt;

&lt;p&gt;Similarly, other projects came too and made a couple 1000$ after a huge period of not making money. One of the worst things I experienced a lot was sleepwalking so I bought this Health Ring💍 similar to oura but a lot cheaper which could monitor my sleep and tell me if I'm walking or whatever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pausing freelance for another startup
&lt;/h2&gt;

&lt;p&gt;Maybe this is me being stupid🤦‍♂️ but this summer I slowed down freelance again to focus on developing a project which could lead to a SaaS soon. Its &lt;a href="https://helicity.ai"&gt;helicity.ai&lt;/a&gt; , an AI based JS Game engine that you can use right in your browser. It feels like every project I did previously, I learned something from. And I'm using that somehow in helicity.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Canvas API - Core of the game engine&lt;/li&gt;
&lt;li&gt;Google Cloud to handle our whole backend&lt;/li&gt;
&lt;li&gt;Firebase(which is really like a cute nonscary version of GCLOUD) - Identity management, Database and a ton of Functions, APIs&lt;/li&gt;
&lt;li&gt;React and Next.js - Building the Interface&lt;/li&gt;
&lt;li&gt;Gamemaker - Learning what a game engine really needs
And many more...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--utLObVHa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39w9co90roselehyabfh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--utLObVHa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39w9co90roselehyabfh.png" alt="Image description" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today even now, I am investing my time in creating Helicity.ai, Feel free to check it out!&lt;/p&gt;

&lt;p&gt;Where am I headed next? Well, honestly, I'm not quite sure. But one thing I've learned from my journey is that the joy isn't just in the destination but in the journey itself. I believe it's this appreciation for the journey that keeps me motivated and excited for what's next.&lt;/p&gt;

&lt;p&gt;Freelancing has been a stepping stone for me, allowing me to connect my love for physics with game development, and create a unique space for myself in this vast tech universe. It gave me the flexibility to explore different fields, learn on the go, and build something meaningful along the way. If you're considering a similar path, I hope my story serves as a beacon of possibility. &lt;/p&gt;

&lt;p&gt;Here's to the winding road ahead!&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/lilshake/"&gt;linkedin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>learning</category>
      <category>startup</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Adding Rotation and Scaling🕹️🌟 to my Game Engine - Part 4</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sun, 09 Jul 2023 13:59:22 +0000</pubDate>
      <link>https://dev.to/lilshake/adding-rotation-and-scaling-to-my-game-engine-4pim</link>
      <guid>https://dev.to/lilshake/adding-rotation-and-scaling-to-my-game-engine-4pim</guid>
      <description>&lt;p&gt;Hello, developers! 👋💖 &lt;/p&gt;

&lt;p&gt;I'm back with some news! I added &lt;strong&gt;rotation and image scaling&lt;/strong&gt; to our game objects. There are many approaches to doing this and this is what I have done.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/lilshake/making-flappy-bird-in-my-game-engine-how-hard-can-it-be-4m61"&gt;previous post&lt;/a&gt; I tried making a flappy bird game in my engine  &lt;a href="https://helicity.ai"&gt;Helicity.ai&lt;/a&gt; and it was clear that we needed Rotation and Scaling for a normal and usable Experience.&lt;/p&gt;

&lt;p&gt;I find this sequence of events particularly interesting because *&lt;em&gt;it is like taking a pencil and moving it to where we want to draw something , rotating the page and then drawing and then rotating back the page and bringing the pencil back to where it was. *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://github.com/lil-shake-code/helicity.ai"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H-ePYWjX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdcopg2re5og74rlz1hd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H-ePYWjX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdcopg2re5og74rlz1hd.png" alt="Image description" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Changes to how a Game Object is Rendered
&lt;/h1&gt;

&lt;p&gt;Take a peek at the GameObject class. We're calling the 'render' method every frame after clearing the canvas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// GameObject.js
render() {
  if (this.image.loaded) {
    Renderer.drawImage(
      this.image,
      this.x,
      this.y,
      this.width * this.xscale,
      this.height * this.yscale,
      this.angle,
      this.alpha
    );
  } else {
//No image was provided. Just drawing a black block.
    Renderer.drawBlock(
      "black",
      this.x,
      this.y,
      this.width * this.xscale,
      this.height * this.yscale,
      this.angle,
      this.alpha
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GameObject now scales according to 'xscale' and 'yscale' properties and rotates according to the 'angle' property. You have full control over these values 🎮. &lt;/p&gt;

&lt;p&gt;But what happens in both those functions? Let's see&lt;/p&gt;

&lt;h2&gt;
  
  
  Now, let's journey to our Renderer class:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Renderer.js
drawImage(image, x, y, width, height, angle, alpha) {
  this.context.save();
  this.context.translate(x, y);
  this.context.rotate(-angle);
  this.context.globalAlpha = alpha;
  this.context.drawImage(image, 0, 0, width, height);
  this.context.restore();
}

drawBlock(color, x, y, width, height, angle, alpha) {
  this.context.save();
  this.context.translate(x, y);
  this.context.rotate(-angle);
  this.context.globalAlpha = alpha;
  this.context.fillStyle = color;
  this.context.fillRect(0, 0, width, height);
  this.context.restore();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation of the Sequence of Events
&lt;/h2&gt;

&lt;p&gt;Notice something new? The 'drawImage' and 'drawBlock' methods now include 'angle' and 'alpha' parameters.&lt;/p&gt;

&lt;p&gt;Let's break down what's happening in the Renderer's drawImage and drawBlock methods. They both follow a similar sequence of operations.&lt;/p&gt;

&lt;p&gt;1.** Saving the Canvas State** (context.save()): Before any transformations, we save the current state of the canvas. The save() method pushes the current state onto a stack. This allows us to apply transformations and then revert back to the original state after we've completed our drawing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Translating the Origin&lt;/strong&gt; (context.translate(x, y)): The translate(x, y) function shifts the (0,0) origin of our canvas to the provided (x,y) point. This is particularly useful because rotation in the canvas is always performed around the current origin. So by translating the origin to the point around which we want to rotate (in this case, the center of our image or block), we prepare the canvas for rotation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rotating the Canvas&lt;/strong&gt; (context.rotate(-angle)): Now that the origin is at the center of our image or block, we can rotate our canvas. The rotate(angle) function rotates the canvas around the current origin by the specified angle (measured in radians). We use -angle because the canvas's positive rotation is clockwise, while typically in 2D games, we treat positive rotation as counterclockwise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setting Transparency&lt;/strong&gt; (context.globalAlpha = alpha): The globalAlpha property is used to apply transparency to our image or block. It can take a value between 0.0 (fully transparent) and 1.0 (fully opaque).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Drawing the Image or Block&lt;/strong&gt;: With our transformations set, we can now draw the image or block. For images, we use the drawImage(image, 0, 0, width, height) method, which draws the specified image onto the canvas. For blocks, we use the fillRect(0, 0, width, height) method after setting the fill color with fillStyle = color.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Restoring the Canvas State&lt;/strong&gt; (context.restore()): After we're done with drawing, we restore the canvas back to its original state by using the restore() method. This pops the most recently saved state from the stack and applies it. All of the transformations we applied (translation, rotation, and globalAlpha change) are undone, so they won't affect any further drawing on the canvas.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sequence of operations lets us draw images and blocks onto the canvas with control over their position, size, rotation, and transparency, giving a lot of flexibility in how objects can be displayed on the canvas.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;Because we did this, we can now make the bird in our game rotate to make it look like it's falling. &lt;br&gt;
You can try out &lt;a href="https://storage.googleapis.com/ai-game-maker.appspot.com/public/zdfRs9zO3PW6LRPZ0yLlFLcQ3eA3.html"&gt;this variant&lt;/a&gt; of the game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//In the update method of the bird
 //change angle of bird to make it look like it is falling. -90 is straight down
    //dont make it indefinitely dependent on velocityY, or else it will keep rotating
    this.angle = Math.min(this.velocityY * 0.05, 90);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there are some new challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Physics
&lt;/h3&gt;

&lt;p&gt;This cute function is not good enough to handle rotations lol.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; //Adjusted for scaling but NOT rotation
  static checkCollision(object1, object2) {
    return (
      object1.x &amp;lt; object2.x + object2.width * object2.xscale &amp;amp;&amp;amp;
      object1.x + object1.width * object1.xscale &amp;gt; object2.x &amp;amp;&amp;amp;
      object1.y &amp;lt; object2.y + object2.height * object2.yscale &amp;amp;&amp;amp;
      object1.y + object1.height * object1.yscale &amp;gt; object2.y
    );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sprite Origins
&lt;/h3&gt;

&lt;p&gt;So as of now a &lt;strong&gt;Game Object's origin, its x or y is the top left corner of the image.&lt;/strong&gt; This is fine for now but it means that all rotations will happen about that point, making it look like the bird is moving in a bit wierd way... but its a bird so it looks normal lol.&lt;/p&gt;

&lt;p&gt;If you like this and are interested in the development, do consider joining the &lt;a href="https://discord.com/invite/RkH98RgVDr"&gt;discord server&lt;/a&gt;!&lt;br&gt;
The Helicity.ai Team 🚀&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Making Flappy Bird in my Game Engine. How hard can it be? - [Helicity.ai Part 3]</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Sat, 08 Jul 2023 21:27:41 +0000</pubDate>
      <link>https://dev.to/lilshake/making-flappy-bird-in-my-game-engine-how-hard-can-it-be-4m61</link>
      <guid>https://dev.to/lilshake/making-flappy-bird-in-my-game-engine-how-hard-can-it-be-4m61</guid>
      <description>&lt;p&gt;Hello everyone! 🙋‍♂️ I thought I'd share my latest game development adventure with you all. Recently, I thought to myself, &lt;em&gt;"Making Flappy Bird in my own game engine? How hard can it be?" 🤔&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I learned a lot of things I need to add to my Engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://helicity.ai"&gt;Helicity.ai&lt;/a&gt; is my Game Engine. &lt;/p&gt;

&lt;p&gt;Here is the source &lt;a href="https://github.com/lil-shake-code/helicity.ai"&gt;😺github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mgSxr05w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxbzcgmu6wi0hrgadawn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mgSxr05w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxbzcgmu6wi0hrgadawn.png" alt="Image description" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step by Step Guide
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Step 1: Importing the Necessary Modules 📚
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import modules
import { GameObject } from "./Gameobject.js";
import { Input } from "./Input.js";
import { Physics } from "./Physics.js";
import { Renderer } from "./Renderer.js";
import { Game } from "./Engine.js";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First things first, we need to import our modules! They're the backbone of our game and do a ton of heavy lifting for us. 🏋️‍♀️&lt;br&gt;
You can see what every module does on the github link. But they handle specific sections of the game.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Setting Up the Bird 🐤
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var score = 0;
// Create Bird class that extends GameObject
class Bird extends GameObject {
  constructor(x, y, width, height, imageSrc) {
    super(x, y, width, height, "bird", imageSrc);
    this.velocityY = 0;
    this.gravity = 0.3;
  }

    // Check for input to control the bird
    if (Input.getState().keys["space"] || Input.getState().mouseLeftDown) {
      this.velocityY = -7;
    }

    //draw score 
    Renderer.drawText("Score: "+score,30,30,25,"black","Arial")
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;strong&gt;GameObject&lt;/strong&gt; is a Class which takes in constructor &lt;strong&gt;(x, y, width, height, some-type-tag, image-source)&lt;/strong&gt;  The game engine is build around playing with these instances and their update() methods, that have the frame wise logic.&lt;/p&gt;

&lt;p&gt;Here, we're creating a Bird class that extends our GameObject. &lt;br&gt;
The bird is the main object of our game! 🌟 We're giving it a velocity and gravity property to handle its movement. 🌍&lt;br&gt;
Also I'm drawing the score property.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We don't REALLLY need a class for the Bird because it will only have 1 instance but I guess that's good practice?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Moving the Bird 🕹
&lt;/h2&gt;

&lt;p&gt;Inside our Bird class, we also have an update function. This is where all the magic happens - we update the bird's position, check for collisions, and handle user input. 🎮&lt;br&gt;
Basic rectangular collisions are handled by &lt;strong&gt;Physics.checkCollision(gameobject1 , gameobject2)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Bird extends GameObject {
  constructor(x, y, width, height, imageSrc) {
    super(x, y, width, height, "bird", imageSrc);
    this.velocityY = 0;
    this.gravity = 0.3;
  }

  update() {
    // Apply gravity
    this.velocityY += this.gravity;
    this.y += this.velocityY;

    // Check for collision with pipes
    for (const pipe of Game.gameObjects) {
      if (pipe.type === "pipe" &amp;amp;&amp;amp; Physics.checkCollision(this, pipe)) {
        Game.stop();
        Renderer.drawText("Game Over", 100, 100, 30, "black", "Arial");
      }
    }

    // Check for input to control the bird
    if (Input.getState().keys["space"] || Input.getState().mouseLeftDown) {
      this.velocityY = -7;
    }

    //draw score 
    Renderer.drawText("Score: "+score,30,30,25,"black","Arial")
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Creating the Pipes 🌆
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Create Pipe class that extends GameObject
class Pipe extends GameObject {
  constructor(x, y, width, height, imageSrc) {
    super(x, y, width, height, "pipe", imageSrc);
    this.velocityX = -2;
  }

  update() {
    this.x += this.velocityX;

    // Remove pipe when it goes off the screen
    if (this.x + this.width &amp;lt; 0) {
      Game.gameObjects.splice(Game.gameObjects.indexOf(this), 1);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up are our infamous pipes! Just like our bird, we create a Pipe class that extends GameObject. We're giving each pipe a constant velocity to make it move. 🏙&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Adding Our Bird 🎲
&lt;/h2&gt;

&lt;p&gt;After creating our classes, it's time to instantiate our bird or any other game objects and add them to our game 🧩. I just picked up some png from Google.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const bird = new Bird(100, 200, 50, 50, "https://freepngimg.com/thumb/logo/109941-logo-bird-flappy-free-transparent-image-hq.png");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Spawning the Pipes ⏱
&lt;/h2&gt;

&lt;p&gt;We're using a setInterval function to spawn our pipes every two seconds. Every time a new set of pipes is spawned, our score increases. 📈&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Create pipes every second
setInterval(() =&amp;gt; {
  if(Game.isRunning){
    score++;
  }
  const pipeTop = new Pipe(Renderer.canvas.width, 0, 100, Math.random() * 200 + 100, "https://upload.wikimedia.org/wikipedia/commons/9/93/Mario_pipe.png");
  const pipeBottom = new Pipe(Renderer.canvas.width, pipeTop.height + 300, 100, 600 - pipeTop.height - 200, "https://upload.wikimedia.org/wikipedia/commons/9/93/Mario_pipe.png");
  Game.gameObjects.push(pipeTop, pipeBottom);
}, 2000);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WfLOKpIV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcf3onb0o0e6d9t3x3ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WfLOKpIV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcf3onb0o0e6d9t3x3ls.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is when I realised I need xscale and yscale properties ASAP in my game object, I mean look at how the pipes are spawning!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;Finally, we start our game with &lt;code&gt;Game.start()&lt;/code&gt;. &lt;strong&gt;Now, I can tell people I made flappy bird in my own engine! 🎉&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But honestly its more about improving the engine and what this taught me. If I need to make this a real thing, it needs to be usable. Also we need a background component.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So that's it! Creating a Flappy Bird clone in my game engine turned out to be a fun and enlightening experience! 🎈🎊 I hope you found this post helpful and inspiring. Don't hesitate to reach out if you have any questions or comments. Happy coding! 🚀🚀🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Discord link - Support Development
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://discord.com/invite/RkH98RgVDr"&gt;Discord&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>gamedev</category>
      <category>learning</category>
    </item>
    <item>
      <title>Game Engine with AI✨ Part 2 - DALL E Sprites</title>
      <dc:creator>Abhishek</dc:creator>
      <pubDate>Fri, 07 Jul 2023 22:09:55 +0000</pubDate>
      <link>https://dev.to/lilshake/game-engine-with-ai-part-2-dall-e-sprites-38m2</link>
      <guid>https://dev.to/lilshake/game-engine-with-ai-part-2-dall-e-sprites-38m2</guid>
      <description>&lt;p&gt;Hey,  devs! 🖐🎮&lt;br&gt;
Hope you're all having a nice day! I have some cool updates on &lt;a href="//helicity.ai"&gt;helicity.ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For reference, this was part 1 (nobody saw it🙃)&lt;br&gt;
&lt;a href="https://dev.to/lilshake/im-making-an-ai-js-browser-game-engine-helicityai-2p9p"&gt;I'm making an AI JS Browser Game Engine&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inbuilt DALL E Support
&lt;/h2&gt;

&lt;p&gt;I've integrated DALL-E support! 🎨🖌️ Yes, so from now on, you can define your sprite URL as &lt;strong&gt;"lookup: some description"&lt;/strong&gt;, and Helicity.ai will generate a unique sprite for you on the fly using DALL-E. Create unique, custom images without having to leave the IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I made it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;So it all happens in the &lt;strong&gt;Gameobject.js&lt;/strong&gt; module. Whenever you make a new instance of the GameObject, this code runs&lt;/li&gt;
&lt;li&gt;When you put &lt;strong&gt;"lookup:" string&lt;/strong&gt; in your image source, it takes this as a request and calls a firebase function made in Express&lt;/li&gt;
&lt;li&gt;The firebase function calls the DALL E API looking up the string after &lt;strong&gt;"lookup:"&lt;/strong&gt; and asynchronously returns the image-url, this is sent back to the game object.&lt;/li&gt;
&lt;li&gt;The game object image is drawn every frame using *&lt;em&gt;render() *&lt;/em&gt;(automatically in the game loop)  or else, its just a black box&lt;/li&gt;
&lt;li&gt;The savedImages makes sure that if 2 game objects are created with the same lookup description, multiple called aren't made to dall e. For example pipes in flappy bird.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Gameobject.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var savedImages = {};

export class GameObject {
  constructor(x, y, width, height, type, imageSrc) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.type = type; // can be Used for collision detection
    this.image = new Image();
    this.image.loaded = false;

    //check if imagesrc contains the string lookup:
    if (imageSrc.includes("lookup:")) {
      //check if the image is already saved
      if (savedImages[imageSrc]) {
        this.image = savedImages[imageSrc];
        this.image.loaded = true;
      } else {
        //make a post request. this is in html to use XMLHttpRequest
        var xhr = new XMLHttpRequest();
        xhr.open(
          "POST",
          "https://us-central1-myaigameengine.cloudfunctions.net/api/Image",
          true
        );
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.send(
          JSON.stringify({
            userPrompt: imageSrc.split("lookup:")[1],
          })
        );
        xhr.onreadystatechange = () =&amp;gt; {
          if (xhr.readyState == 4 &amp;amp;&amp;amp; xhr.status == 200) {
            //console.log(xhr.responseText);

            //get the imageURL from the response
            var imageURL = JSON.parse(xhr.responseText).image_url;
            this.image = new Image();
            this.image.src = imageURL;
            this.image.onload = () =&amp;gt; {
              this.image.loaded = true;
              //save the image
              savedImages[imageSrc] = this.image;
            };
            this.image.onerror = () =&amp;gt; {
              console.error(`Error loading image ${this.imageSrc}`);
            };
          }
        };
      }
    } else {
      this.imageSrc = imageSrc;
      this.image = new Image();
      this.image.src = imageSrc;
      this.image.onerror = () =&amp;gt; {
        console.error(`Error loading image ${this.imageSrc}`);
      };
      this.image.onload = () =&amp;gt; {
        this.image.loaded = true;
      };
    }

    Game.addGameObject(this);
  }

  update(deltaTime) {
    // Overridden by child classes
  }

  render() {
    //draw a black rectangle if there isnt an image else draw it
    if (this.image.loaded) {
      Renderer.drawImage(this.image, this.x, this.y, this.width, this.height);
    } else {

      Renderer.context.fillStyle = "black";
      Renderer.context.fillRect(this.x, this.y, this.width, this.height);
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Firebase function's Express Image Endpoint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post("/Image", async (req, res) =&amp;gt; {
  //var uuid = req.body.uuid;
  var userPrompt = req.body.userPrompt;
  //console.log("uuid is " + uuid);
  console.log("user prompt is ");
  openai
    .createImage({
      prompt: userPrompt,
      n: 1,
      size: "256x256",
    })
    .then((result) =&amp;gt; {
      image_url = result.data.data[0].url;
      console.log(image_url);
      res.send({
        success: true,
        image_url: image_url,
      });
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Thats it!
&lt;/h3&gt;

&lt;p&gt;Think about it - need a sprite of a "purple dragon with a top hat?" 🐉🎩 Just type lookup: purple dragon with a top hat and voila, your personalized sprite is ready to be used in your game! It's that simple! 🎲🚀&lt;/p&gt;

&lt;p&gt;Multiplayer support is coming soon!&lt;/p&gt;

&lt;p&gt;If you'd like to talk about and participate in the development, hit me up on discord!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://discord.gg/RkH98RgVDr"&gt;https://discord.gg/RkH98RgVDr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for more updates! Happy coding 🎮💖&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>ai</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
