<?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: Antonio Salvati 🦊</title>
    <description>The latest articles on DEV Community by Antonio Salvati 🦊 (@salvan13).</description>
    <link>https://dev.to/salvan13</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%2F126728%2F6f834cf0-f97d-4407-b4ae-ada01693d7f6.png</url>
      <title>DEV Community: Antonio Salvati 🦊</title>
      <link>https://dev.to/salvan13</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/salvan13"/>
    <language>en</language>
    <item>
      <title>Backshot Tactics - A Multiplayer Game for js13kGames</title>
      <dc:creator>Antonio Salvati 🦊</dc:creator>
      <pubDate>Thu, 03 Oct 2019 16:52:30 +0000</pubDate>
      <link>https://dev.to/salvan13/backshot-tactics-a-multiplayer-game-for-js13kgames-47ie</link>
      <guid>https://dev.to/salvan13/backshot-tactics-a-multiplayer-game-for-js13kgames-47ie</guid>
      <description>&lt;h3&gt;
  
  
  The Competition
&lt;/h3&gt;

&lt;p&gt;This game was made for &lt;a href="https://js13kgames.com/" rel="noopener noreferrer"&gt;js13kGames&lt;/a&gt;, a JavaScript coding competition for HTML5 Game Developers. The fun part is the file size limit set to 13 kilobytes. Theme for 2019 was &lt;em&gt;back&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Initial Idea
&lt;/h3&gt;

&lt;p&gt;Since I enjoy play multiplayer and competitive games, the initial idea was to create a multiplayer online 1vs1 tactical game, inspired by &lt;a href="https://na.leagueoflegends.com/en/featured/events/teamfight-tactics" rel="noopener noreferrer"&gt;Teamfight Tactics&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%2Fmultiplayer.net-cdn.it%2Fthumbs%2Fimages%2F2019%2F07%2F02%2Fteamfight-tactics-02_jpg_1400x0_q85.jpg" 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%2Fmultiplayer.net-cdn.it%2Fthumbs%2Fimages%2F2019%2F07%2F02%2Fteamfight-tactics-02_jpg_1400x0_q85.jpg" alt="tft"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even if the final result is a completely different game as you can see&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fihmjoqqw8pqnpl8pz63n.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fihmjoqqw8pqnpl8pz63n.png" alt="the initial splash screen"&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0688q7yuoayttmw2m23o.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0688q7yuoayttmw2m23o.png" alt="the ingame view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Process
&lt;/h3&gt;

&lt;p&gt;It was way too complex to do everything in 13kb and in the spare time I had, so I started removing features from the initial idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removed different characters, they are all equal (no different sprites / UI to create)&lt;/li&gt;
&lt;li&gt;The characters are placed on the field from the beginning (no drag and drop to implement)&lt;/li&gt;
&lt;li&gt;Removed armor, weapons and character classes (less code and complexity)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Prototype
&lt;/h3&gt;

&lt;p&gt;With less features I could write a prototype in almost 6 hours, and I demonstrated it in Berlin at the &lt;a href="https://ebaytech.berlin/js13kgames-a-review-c10cbe9a39e3" rel="noopener noreferrer"&gt;JS13kGames 2019 hackday&lt;/a&gt; alongside with other awesome devs&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1163823307264679940-55" src="https://platform.twitter.com/embed/Tweet.html?id=1163823307264679940"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1163823307264679940-55');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1163823307264679940&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  The Evolution
&lt;/h2&gt;

&lt;p&gt;In the initial prototype two players had just to pick their characters at the beginning and then they were fighting automatically, I've found it boring and probably complex for players to understand what's going on.&lt;/p&gt;

&lt;p&gt;So I've changed the gameplay: It became a turn based game, each turn the player chose the character to activate and he moves in a predefined direction then he attacks an opponent.&lt;/p&gt;

&lt;p&gt;Other changes I made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The character always attack the nearest opponent&lt;/li&gt;
&lt;li&gt;The damage is calculated based on the characters distance&lt;/li&gt;
&lt;li&gt;if the character is hit from the &lt;strong&gt;back side&lt;/strong&gt; the damage is much higher&lt;/li&gt;
&lt;li&gt;"Characters" became "Ships" :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I polished the UI, added mobile support, and added a ranking based on the &lt;a href="https://en.wikipedia.org/wiki/Elo_rating_system" rel="noopener noreferrer"&gt;Elo rating system&lt;/a&gt; &lt;iframe class="tweet-embed" id="tweet-1166747182583767040-82" src="https://platform.twitter.com/embed/Tweet.html?id=1166747182583767040"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1166747182583767040-82');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1166747182583767040&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Then the final rules became clear&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick phase: select your &lt;strong&gt;4&lt;/strong&gt; ships on the grid.&lt;/li&gt;
&lt;li&gt;Play phase: When your turn come, you can &lt;strong&gt;activate&lt;/strong&gt; a ship

&lt;ul&gt;
&lt;li&gt;It moves in the active direction (the highlighted arrow below the ship) by &lt;strong&gt;4&lt;/strong&gt; cells (when it reach the border the ship wraps on the opposite side)&lt;/li&gt;
&lt;li&gt;It shots the nearest opponent damaging him by &lt;strong&gt;distance between them * 3&lt;/strong&gt; (bullets don't wrap the field)&lt;/li&gt;
&lt;li&gt;If the opponent is hit on the &lt;strong&gt;back side&lt;/strong&gt; the damage is &lt;strong&gt;tripled&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Kill all the enemy ships to win&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  The 13kb limit
&lt;/h3&gt;

&lt;p&gt;13kb (zipped) seems not much space, but it is a lot if you don't use assets and libraries (or just very small ones like those &lt;a href="https://js13kgames.github.io/resources/" rel="noopener noreferrer"&gt;listed here&lt;/a&gt;) there is lot of room to write code. That's why for my game there was no images, only a font and an external library to make sound effects (jsfxr).&lt;/p&gt;

&lt;p&gt;Here listed all the game files in the submitted version (minified, unzipped):&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frc9ihk0cuijmbhv3qwve.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frc9ihk0cuijmbhv3qwve.png" alt="List of all the game files"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Competitive game
&lt;/h3&gt;

&lt;p&gt;I wanted make a game &lt;em&gt;easy to play&lt;/em&gt; but &lt;em&gt;hard to master&lt;/em&gt;, it's easy to start playing the game, you have just to click on ships, you can do it without thinking, you can also win plying like this. But it's hard to master, only with practice you can understand which ships are better to pick and which moves to do.&lt;/p&gt;

&lt;p&gt;Also I wanted make a game without randomness during the game.&lt;br&gt;
There is an initial random setup when the ships and directions are created and placed on the field before the game starts, but then the game is completely drove by player choices. (only in one case there is randomness involved: when two or more ships are at same distance, the one to shot is chosen randomly, but I plan to remove this behaviour and pick the ship with less HP instead)&lt;/p&gt;
&lt;h3&gt;
  
  
  Technical details
&lt;/h3&gt;

&lt;p&gt;The game was made for Desktop, Mobile and Server categories using the &lt;a href="https://github.com/js13kGames/js13kserver/" rel="noopener noreferrer"&gt;js13kServer sandbox&lt;/a&gt;, it works on Firefox, Chrome, Safari, Opera, and &lt;em&gt;probably&lt;/em&gt; on all modern browsers.&lt;/p&gt;

&lt;p&gt;Web Sockets are used to send events between the two clients and the server who manage the Game logic.&lt;/p&gt;

&lt;p&gt;The client is HTML, CSS and JS based, no canvas involved, I already used this approach in my previous game &lt;a href="https://js13kgames.com/entries/spacefield-league" rel="noopener noreferrer"&gt;Spacefield League&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Client side all the dimensions are relative to the viewport, so the interface scales well on all kind of screens, thanks to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/length#Viewport-percentage_lengths" rel="noopener noreferrer"&gt;viewport relative units&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/length#rem" rel="noopener noreferrer"&gt;rem units&lt;/a&gt;, percentages and CSS custom properties.&lt;br&gt;
All animations are made via CSS transitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.field&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--field-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90vmin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--field-size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--field-size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* --h and --w are set via js based on server game state */&lt;/span&gt;
  &lt;span class="py"&gt;--cell-h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--field-size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--h&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="py"&gt;--cell-w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--field-size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--w&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--black&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cell-w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cell-h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.field&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cell-h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cell-w&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* again --x and --y are set via js based on server game state, see the next js snippet */&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cell-w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--x&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cell-h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--y&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new-pos&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;e&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;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;positionX&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="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;positionY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Ships are DIVs clipped via &lt;code&gt;clip-path&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.char&lt;/span&gt; &lt;span class="nc"&gt;.body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a single Game class who manage the game state.&lt;br&gt;
There are also some tests to be sure the game logic is working&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;game&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;Game&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="cm"&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;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;while&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;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;play&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="c1"&gt;// get the id of the current turn player&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pid&lt;/span&gt; &lt;span class="o"&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;players&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;turn&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;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// pick a random available player character&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick&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;chars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hp&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// move that character&lt;/span&gt;
    &lt;span class="k"&gt;await&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;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// at a certain point the game should end&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ok&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;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="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="s1"&gt;Game test OK&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Future Plans
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Improve the game thanks to all the feedbacks from experts and other competition's participants&lt;/li&gt;
&lt;li&gt;Add a real login&lt;/li&gt;
&lt;li&gt;Add a turn timer&lt;/li&gt;
&lt;li&gt;Manage disconnections / re-connections&lt;/li&gt;
&lt;li&gt;Progressive web app and port on other platforms (like messenger instant games or mobile stores)&lt;/li&gt;
&lt;li&gt;Remove randomness on shots when more ships are at same distance&lt;/li&gt;
&lt;li&gt;Web monetisation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://js13kgames.com/" rel="noopener noreferrer"&gt;JS13KGames&lt;/a&gt;&lt;br&gt;
&lt;a href="https://js13kgames.com/entries/backshot-tactics" rel="noopener noreferrer"&gt;Entry page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/salvan13/backshot-tactics" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://backshot-tactics.herokuapp.com/" rel="noopener noreferrer"&gt;Play the game!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1171735059084337154-437" src="https://platform.twitter.com/embed/Tweet.html?id=1171735059084337154"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1171735059084337154-437');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1171735059084337154&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;The result was so good and unexpected&lt;/p&gt;

&lt;p&gt;Overall: 19th place&lt;br&gt;
Mobile: 5th place&lt;br&gt;
Server: 1st place&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1180479097455157248-878" src="https://platform.twitter.com/embed/Tweet.html?id=1180479097455157248"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1180479097455157248-878');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1180479097455157248&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>gamedev</category>
      <category>js13k</category>
    </item>
    <item>
      <title>Working alone</title>
      <dc:creator>Antonio Salvati 🦊</dc:creator>
      <pubDate>Fri, 08 Feb 2019 17:29:07 +0000</pubDate>
      <link>https://dev.to/salvan13/working-alone-2mh</link>
      <guid>https://dev.to/salvan13/working-alone-2mh</guid>
      <description>&lt;p&gt;I am a web developer, I enjoy creating web apps and games.&lt;/p&gt;

&lt;p&gt;But I really enjoy it only when I work alone.&lt;/p&gt;

&lt;p&gt;Working in a team bores me after a little while.&lt;/p&gt;

&lt;p&gt;I still don't really get why.&lt;br&gt;
Maybe because I want control everything, but I can't in a team.&lt;/p&gt;

&lt;p&gt;Does anyone have this problem?&lt;br&gt;
Have you found a reason?&lt;br&gt;
How do you face it?&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Searchable Select 🤔</title>
      <dc:creator>Antonio Salvati 🦊</dc:creator>
      <pubDate>Sat, 12 Jan 2019 13:04:57 +0000</pubDate>
      <link>https://dev.to/salvan13/searchable-select--1f7a</link>
      <guid>https://dev.to/salvan13/searchable-select--1f7a</guid>
      <description>&lt;h2&gt;
  
  
  The Select
&lt;/h2&gt;

&lt;p&gt;The HTML &lt;em&gt;select&lt;/em&gt; element is super useful, but sometime we need somthing more powerful, when we have hundreds of options (eg. a list of all the world's countries) it would be nice to let the user to be able to filter the elements, unluckily we don't have a &lt;em&gt;searchable&lt;/em&gt; or &lt;em&gt;filterable&lt;/em&gt; attribute for it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Please select your country&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"it"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Italy&lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"fr"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;France&lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;
  ... and so many other options ...
&lt;span class="nt"&gt;&amp;lt;select&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  The Input
&lt;/h2&gt;

&lt;p&gt;A way to search elements inside a list with native HTML elements is with an &lt;em&gt;input&lt;/em&gt; plus &lt;em&gt;datalist&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Please select your country&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;list=&lt;/span&gt;&lt;span class="s"&gt;"country-list"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;datalist&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"country-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Italy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"France"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/datalist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this way we have an input with hints, but the user can still write anything he want.&lt;br&gt;
So we need to validate it!&lt;/p&gt;
&lt;h2&gt;
  
  
  The Validation
&lt;/h2&gt;

&lt;p&gt;Let's use the &lt;em&gt;pattern&lt;/em&gt; attribute to validate the input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Please select your country&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;list=&lt;/span&gt;&lt;span class="s"&gt;"country-list"&lt;/span&gt;
  &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"Italy|France"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Please select a country"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;datalist&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"country-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Italy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"France"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/datalist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cool, now we have an Input with searchable options, and only the defined ones are allowed!&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;The only problem I see here is that it is not very clear at first glance that it is not a normal text input, but a (let me say it) &lt;em&gt;searchable select&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Only after a user interaction the dropdown will be shown.&lt;/p&gt;

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

&lt;p&gt;HTML give us many tools, let's see if we can use and combine them before build our own solutions 😃&lt;/p&gt;

&lt;p&gt;Let me know what do you think about this approach!&lt;/p&gt;

</description>
      <category>html</category>
      <category>web</category>
      <category>form</category>
      <category>validation</category>
    </item>
  </channel>
</rss>
