<?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: Jorge Rubiano</title>
    <description>The latest articles on DEV Community by Jorge Rubiano (@jorger).</description>
    <link>https://dev.to/jorger</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%2F36416%2F7f81ced2-bf0e-404c-8bc5-fafe7ee89de4.jpeg</url>
      <title>DEV Community: Jorge Rubiano</title>
      <link>https://dev.to/jorger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jorger"/>
    <language>en</language>
    <item>
      <title>🎲 Dice Merge - ReactJS - English Version</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Fri, 09 Jun 2023 17:57:46 +0000</pubDate>
      <link>https://dev.to/jorger/dice-merge-reactjs-english-version-58he</link>
      <guid>https://dev.to/jorger/dice-merge-reactjs-english-version-58he</guid>
      <description>&lt;p&gt;This is the english version of this post &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/jorger" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9WH4xvZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--hd6HIkoj--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/36416/7f81ced2-bf0e-404c-8bc5-fafe7ee89de4.jpeg" alt="jorger"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/jorger/dice-merge-reactjs-35gb" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🎲 Dice Merge - ReactJS&lt;/h2&gt;
      &lt;h3&gt;Jorge Rubiano ・ Jun 9 ・ 6 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#games&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#drag&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#recursion&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In this article, I would like to share the latest game I have developed in ReactJS called "Dice Merge".&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Game URL:&lt;/strong&gt; &lt;a href="https://dice-puzzle.vercel.app/"&gt;https://dice-puzzle.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6pO9cs_J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ec0pkvsvqw7zdwh0622.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6pO9cs_J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ec0pkvsvqw7zdwh0622.gif" alt="image02" width="406" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drag the dice onto a 5x5 grid:&lt;/strong&gt; The objective of Dice Merge is to place the dice on a grid with 5 rows and 5 columns. To do so, simply drag the dice to the desired position on the grid.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merge dice of the same type:&lt;/strong&gt; When a dice is placed near two or more dice with the same value, they will merge to form the next value. For example, if you have multiple dice with a value of 4 nearby, they will combine to form dice with a value of 5.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merge dice until reaching the value six:&lt;/strong&gt; When dice with a value of six are merged, a special dice is created that combines all the nearby dice. This can open up new strategic opportunities for you.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merged dice disappear:&lt;/strong&gt; Once you make a successful combination, the merged dice will disappear from the grid. This frees up space for you to place more dice and continue searching for more combinations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Draggable Dice
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Random dice:&lt;/strong&gt; Each turn, you will be randomly given one or two dice to drag and place on the grid. These dice can have different values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adjustable orientation:&lt;/strong&gt; If you are provided with two dice, you have the option to rotate them to change their orientation before placing them on the grid. This allows you to plan your moves strategically and search for the best possible combinations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scoring.
&lt;/h2&gt;

&lt;p&gt;The score is based on the combinations you make. For example, if you combine three dice with a value of 2, you will score six points.&lt;/p&gt;

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

&lt;p&gt;However, if you make multiple combinations in the same turn, the score doubles. For example, if you combine three dice with a value of 1 (3 points) and then combine additional dice, the score doubles. If you achieve three combinations, it triples, and so on.&lt;/p&gt;

&lt;p&gt;When a merged dice is created, &lt;strong&gt;you earn 100 points.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Power-ups.
&lt;/h2&gt;

&lt;p&gt;The game also includes four power-ups that you can use to improve your chances of success. These power-ups refresh daily, and you can use them according to your strategic needs.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Undo:&lt;/strong&gt; This power-up allows you to undo the last move you made. You can use it up to a maximum of 5 times. Use it wisely to correct mistakes or try different strategies.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trash:&lt;/strong&gt; With this power-up, you can discard the dice you have been given and get new dice in return. This can be useful if you don't find a good location for the current dice. Just like with the "Undo" power-up, you can use it up to 5 times.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bomb:&lt;/strong&gt; The bomb power-up allows you to destroy a dice that is already on the grid. This can be useful if you need to free up space or get rid of an unwanted dice. However, keep in mind that you can only use the bomb power-up up to 3 times.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Star Die:&lt;/strong&gt; This special power-up provides you with a dice that can be merged with any other dice on the grid. This gives you more strategic options and flexibility for making combinations. Just like with the bomb power-up, you can use the Star Die up to 3 times.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Development Challenges:
&lt;/h2&gt;

&lt;p&gt;The development of Dice Merge presented several interesting challenges that were successfully overcome. These challenges include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation of drag and drop:&lt;/strong&gt; To allow players to drag the dice onto the grid, the &lt;a href="https://dndkit.com/"&gt;dnd-kit &lt;/a&gt;library was used. This library facilitates the implementation of drag and drop in ReactJS and ensures an intuitive and smooth interaction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Combination validation:&lt;/strong&gt; A validation system based on &lt;a href="https://en.wikipedia.org/wiki/Recursion"&gt;recursion&lt;/a&gt; was implemented to determine if neighboring dice or newly placed dice on the grid could be merged. This ensures that only valid combinations are made and prevents incorrect moves.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State management and animations:&lt;/strong&gt; To animate the dice and reflect changes on the grid, efficient state management was necessary. Different states were implemented for the dice, allowing for smooth animations and clear visual representation of the made combinations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple combinations:&lt;/strong&gt; Dice Merge allows for multiple combinations in a single turn if new combinations are created after a successful combination. A listening event was implemented to check for changes on the grid and determine if there are new possible combinations after each merge. This adds excitement and additional strategy to the game.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interrupts in animations:&lt;/strong&gt; Although React automatically updates the user interface after a state change, interrupts were necessary for CSS animations to ensure a smooth and pleasant visual experience (a library was not used for this process). These interrupts were carefully applied to ensure that the animations run correctly and smoothly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In conclusion, the development of Dice Merge was an exciting and rewarding challenge. One of the highlights was handling recursion, which proved to be a complex but crucial topic for implementing the validation of dice combinations on the grid.&lt;/p&gt;

&lt;p&gt;Recursion is a powerful technique in programming, but it can also be difficult to understand and apply correctly. In the case of Dice Merge, it was necessary to use recursion to check if neighboring dice or newly placed dice on the grid could be merged. This process involved exploring all possible combinations and evaluating if they met the game's rules.&lt;/p&gt;

&lt;p&gt;Overcoming this challenge of handling recursion in the development of Dice Merge was an enriching experience. It allowed me to improve my problem-solving skills and expand my knowledge in the field of programming.&lt;/p&gt;

&lt;p&gt;In summary, the development of Dice Merge presented a significant challenge, particularly in handling recursion. However, thanks to careful approach and deep understanding of the concept, it was possible to successfully implement the validation of dice combinations. The result is an exciting and challenging game that provides players with a unique and satisfying gaming experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Would you like to learn how to develop a game like Dice Merge? Leave us your comment!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wBHW2Rkp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wi3rngbkej1kbaadyp9r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wBHW2Rkp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wi3rngbkej1kbaadyp9r.jpg" alt="Course" width="750" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are interested in learning to create games using ReactJS, you're in luck! I have prepared the course &lt;a href="https://www.udemy.com/course/aprende-a-desarrollar-un-juego-de-yatzy-con-react/?referralCode=A524789E1703570AF758"&gt;"Learn to Develop a Yatzy Game with ReactJS/NodeJS and Typescript"&lt;/a&gt; in which I teach how to develop this game from scratch.&lt;/p&gt;

&lt;p&gt;If you are passionate about programming and games, this course will provide you with the skills and knowledge necessary to create exciting games like Dice Merge. From state management and animations to event handling and game logic implementation, you will explore all the key aspects of game development in ReactJS.&lt;/p&gt;

&lt;p&gt;Even though the course is currently in &lt;strong&gt;Spanish&lt;/strong&gt;, don't let that deter you! The concepts and techniques you'll learn are universal and applicable to any language. And who knows? It might even be an opportunity for you to brush up on your Spanish while enhancing your game development skills.&lt;/p&gt;

&lt;p&gt;Feel free to leave a comment if you would like to learn how to make this game or if you have any questions about the course. I'm excited to hear your feedback and provide you with more information on how you can dive into the fascinating world of game development with ReactJS!&lt;/p&gt;

&lt;p&gt;You can check out my other games on my page: &lt;a href="https://bio.link/jorgerub"&gt;https://bio.link/jorgerub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>recursion</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>🎲 Dice Merge - ReactJS</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Fri, 09 Jun 2023 15:26:18 +0000</pubDate>
      <link>https://dev.to/jorger/dice-merge-reactjs-35gb</link>
      <guid>https://dev.to/jorger/dice-merge-reactjs-35gb</guid>
      <description>&lt;p&gt;Juego de combinación de dados desarrollado con ReactJS&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Si quieres aprender cómo desarrollar juegos con ReactJS, he &lt;a href="https://www.udemy.com/course/aprende-a-desarrollar-un-juego-de-yatzy-con-react/?referralCode=A524789E1703570AF758"&gt;preparado un curso&lt;/a&gt; en el cual enseño cómo desarrollar un Yatzy desde cero con está tecnología. &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/jorger" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9WH4xvZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--hd6HIkoj--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/36416/7f81ced2-bf0e-404c-8bc5-fafe7ee89de4.jpeg" alt="jorger"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/jorger/juego-en-reactjs-yatzy-2me5" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Juego en ReactJS - Yatzy&lt;/h2&gt;
      &lt;h3&gt;Jorge Rubiano ・ May 15 ・ 2 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;/blockquote&gt;

&lt;p&gt;En este artículo, deseo compartir el último juego que he desarrollado en ReactJS llamado "Dice Merge".&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;URL del Juego:&lt;/strong&gt; &lt;a href="https://dice-puzzle.vercel.app/"&gt;https://dice-puzzle.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reglas.
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arrastra los dados a una grilla de 5x5:&lt;/strong&gt; El objetivo de Dice Merge es colocar los dados en una grilla de 5 filas por 5 columnas. Para hacerlo, simplemente arrastra los dados a la posición deseada en la grilla.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Combina dados del mismo tipo:&lt;/strong&gt; Cuando un dado se coloca cerca de dos o más dados del mismo valor, se unirán para formar el siguiente valor. Por ejemplo, si tienes varios dados con el valor 4 cerca, se combinarán para formar dados con el valor 5.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Combina dados hasta alcanzar el valor seis:&lt;/strong&gt; Cuando los dados con el valor seis se combinan, se crea un dado especial que combina todos los dados cercanos. Esto puede abrir nuevas oportunidades estratégicas para ti.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dados combinados desaparecen:&lt;/strong&gt; Una vez que realizas una combinación exitosa, el Dado combinado desaparece de la grilla. Esto libera espacio para que coloques mas dados y sigas buscando más combinaciones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dados de arrastre
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dados aleatorios:&lt;/strong&gt; En cada turno, se te entregará al azar uno o dos dados para arrastrar y colocar en la grilla. Estos dados pueden tener diferentes valores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Orientación ajustable:&lt;/strong&gt; Si se te proporcionan dos dados, tienes la opción de girarlos para cambiar su orientación antes de colocarlos en la grilla. Esto te permite planificar tus movimientos estratégicamente y buscar las mejores combinaciones posibles.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Puntuación.
&lt;/h2&gt;

&lt;p&gt;La puntuación se basa en las combinaciones que realizas. Por ejemplo, si combinas tres dados con el valor 2, obtendrás una puntuación de seis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Da30NTYM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ar3598zsc3ryqedl7398.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Da30NTYM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ar3598zsc3ryqedl7398.gif" alt="Múltiples Merges" width="404" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sin embargo, si realizas múltiples combinaciones en el mismo turno, la puntuación se duplica. Por ejemplo, si combinas tres dados con el valor 1 (3 puntos) y luego combinas otros dados la puntuación se duplica, si logras tres combinaciones se triplica y así sucesivamente.&lt;/p&gt;

&lt;p&gt;Cuando se hace merge de un dado combinado, obtienes &lt;strong&gt;100 puntos&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ayudas.
&lt;/h2&gt;

&lt;p&gt;El juego también incluye cuatro ayudas que puedes utilizar para mejorar tus posibilidades de éxito. Estas ayudas se renuevan diariamente y puedes usarlas según tus necesidades estratégicas.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deshacer (Undo):&lt;/strong&gt; Esta ayuda te permite deshacer el último movimiento realizado. Puedes usarla hasta un máximo de 5 veces. Utilízala sabiamente para corregir errores o probar diferentes estrategias.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Descartar (Trash):&lt;/strong&gt; Con esta ayuda, puedes descartar los dados que se te han entregado y obtener nuevos dados en su lugar. Esto puede ser útil si no encuentras una buena ubicación para los dados actuales. Al igual que con la ayuda de "Deshacer", puedes usarla hasta 5 veces.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bomba (Bomb):&lt;/strong&gt; La ayuda de la bomba te permite destruir un dado que ya se encuentra en la grilla. Esto puede ser útil si necesitas liberar espacio o deshacerte de un dado no deseado. Sin embargo, ten en cuenta que solo puedes usar la ayuda de la bomba hasta 3 veces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Eh6UTPbd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6b5cdsv6zmn3ofvtpwfb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Eh6UTPbd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6b5cdsv6zmn3ofvtpwfb.gif" alt="Dado Estrella" width="404" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dado Estrella (Star Die):&lt;/strong&gt; Esta ayuda especial te proporciona un dado que se puede combinar con cualquier otro dado en la grilla. Esto te brinda más opciones estratégicas y flexibilidad para realizar combinaciones. Al igual que con la ayuda de la bomba, puedes usar el Dado Estrella hasta 3 veces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Desafíos del desarrollo:
&lt;/h2&gt;

&lt;p&gt;El desarrollo de Dice Merge presentó varios desafíos interesantes que se superaron con éxito. Estos desafíos incluyen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementación del arrastrar y soltar (drag and drop):&lt;/strong&gt; Para permitir a los jugadores arrastrar los dados a la grilla, se utilizó la biblioteca &lt;a href="https://dndkit.com/"&gt;dnd-kit&lt;/a&gt;. Esta biblioteca facilita la implementación del arrastrar y soltar en ReactJS y garantiza una interacción intuitiva y sin problemas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validación de combinaciones:&lt;/strong&gt; Se implementó un sistema de validación basado en &lt;a href="https://en.wikipedia.org/wiki/Recursion"&gt;recursión&lt;/a&gt; para determinar si los dados vecinos o los dados recién colocados en la grilla pueden combinarse. Esto asegura que solo se realicen combinaciones válidas y evita movimientos incorrectos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manejo del estado y animaciones:&lt;/strong&gt; Para animar los dados y reflejar los cambios en la grilla, fue necesario gestionar el estado de manera eficiente. Se implementaron diferentes estados para los dados, lo que permitió animaciones suaves y una representación visual clara de las combinaciones realizadas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Múltiples combinaciones:&lt;/strong&gt; Dice Merge permite realizar múltiples combinaciones en un solo turno si se crean nuevas combinaciones después de una combinación exitosa. Se implementó un evento de escucha que verifica los cambios en la grilla y determina si hay nuevas combinaciones posibles después de cada merge. Esto añade emoción y estrategia adicional al juego.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interrupciones en las animaciones:&lt;/strong&gt; Aunque React actualiza automáticamente la interfaz de usuario después de un cambio de estado, en el caso de las animaciones CSS fue necesario establecer interrupciones para garantizar una experiencia visual fluida y agradable (no se hizo uso de librería para este proceso). Estas interrupciones se aplicaron cuidadosamente para que las animaciones se ejecuten correctamente y sin problemas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión:
&lt;/h2&gt;

&lt;p&gt;En conclusión, el desarrollo de Dice Merge fue un desafío emocionante y gratificante. Uno de los aspectos más destacados fue el manejo de la recursividad, que resultó ser un tema complejo pero crucial para implementar la validación de las combinaciones de dados en la grilla.&lt;/p&gt;

&lt;p&gt;La recursividad es una técnica poderosa en la programación, pero también puede ser complicada de entender y aplicar correctamente. En el caso de Dice Merge, fue necesario utilizar la recursividad para verificar si los dados vecinos o los dados recién colocados en la grilla podían combinarse. Este proceso implicaba explorar todas las posibles combinaciones y evaluar si cumplían con las reglas del juego.&lt;/p&gt;

&lt;p&gt;Superar este desafío de manejo de recursividad en el desarrollo de Dice Merge fue una experiencia enriquecedora. Me permitió mejorar mis habilidades de resolución de problemas y ampliar mi conocimiento en el campo de la programación.&lt;/p&gt;

&lt;p&gt;En resumen, el desarrollo de Dice Merge presentó un gran reto, particularmente en el manejo de la recursividad. Sin embargo, gracias a un enfoque cuidadoso y una comprensión profunda del concepto, fue posible implementar con éxito la validación de las combinaciones de dados. El resultado es un juego emocionante y desafiante que brinda a los jugadores una experiencia de juego única y satisfactoria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Te gustaría aprender a desarrollar un juego como Dice Merge? ¡Déjanos tu comentario!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wBHW2Rkp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wi3rngbkej1kbaadyp9r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wBHW2Rkp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wi3rngbkej1kbaadyp9r.jpg" alt="Curso" width="750" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si estás interesado en aprender a crear juegos utilizando ReactJS, estás de suerte, he preparado el curso &lt;a href="https://www.udemy.com/course/aprende-a-desarrollar-un-juego-de-yatzy-con-react/?referralCode=A524789E1703570AF758"&gt;"Aprende a desarrollar un juego de Yatzy con ReactJS/NodeJS y Typescript"&lt;/a&gt;. en el cual enseño a desarrollar este juego desde cero.&lt;/p&gt;

&lt;p&gt;Si te apasiona la programación y los juegos, este curso te brindará las habilidades y conocimientos necesarios para crear juegos emocionantes como Dice Merge. Desde el manejo del estado y las animaciones hasta el uso de eventos y la implementación de lógica de juego, explorarás todos los aspectos clave para desarrollar juegos en ReactJS.&lt;/p&gt;

&lt;p&gt;No dudes en agregar un comentario si te gustaría aprender a hacer este juego o si tienes alguna pregunta sobre el curso. ¡Estoy emocionado de escuchar tus opiniones y brindarte más información sobre cómo puedes sumergirte en el fascinante mundo del desarrollo de juegos con ReactJS!&lt;/p&gt;

&lt;p&gt;Puedes ver mis otros juegos en mi página: &lt;a href="https://bio.link/jorgerub"&gt;https://bio.link/jorgerub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>games</category>
      <category>drag</category>
      <category>recursion</category>
    </item>
    <item>
      <title>Juego en ReactJS - Yatzy</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Mon, 15 May 2023 17:34:25 +0000</pubDate>
      <link>https://dev.to/jorger/juego-en-reactjs-yatzy-2me5</link>
      <guid>https://dev.to/jorger/juego-en-reactjs-yatzy-2me5</guid>
      <description>&lt;p&gt;Desde ya varios años he estado trabajando con ReactJS, para aprender está librería he desarrollado varios juegos, en cada uno aprendí algo nuevo.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/jorger" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9WH4xvZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--hd6HIkoj--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/36416/7f81ced2-bf0e-404c-8bc5-fafe7ee89de4.jpeg" alt="jorger"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/jorger/recreando-el-parques-parchis-en-reactjs-primera-parte-nkk" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Recreando el Parqués/Parchis en ReactJS - Primera Parte&lt;/h2&gt;
      &lt;h3&gt;Jorge Rubiano ・ Mar 7 '20 ・ 5 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#pwa&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#serviceworkers&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#websockets&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Y ahora deseo compartir con ustedes un nuevo juego desarrollado en React, en este caso el Yatzy.&lt;/p&gt;

&lt;p&gt;Yatzy es un juego de dados, cuyo objetivo es obtener la mayor puntuación posible tras sumar los puntos de las 13 combinaciones disponibles en la tabla de puntuaciones. Puede jugar cualquier número de jugadores; incluso se puede jugar en solitario. Tiene una mecánica similar a la de Yahtzee, Yams, Kismet, Balut, la generala y los dados de póquer, y es muy popular en los países escandinavos.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎮 Yatzy ReactJS
&lt;/h2&gt;

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

&lt;p&gt;Esta versión de Yatzy, está compuesta por dos proyectos: frontend con ReactJS/Typescript y el backend con Nodejs/Typescript, tiene 4 modalidades de juego como son:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL del Juego&lt;/strong&gt;: &lt;a href="https://yatzy-react-game.herokuapp.com/"&gt;https://yatzy-react-game.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solo&lt;/li&gt;
&lt;li&gt;Online&lt;/li&gt;
&lt;li&gt;Vs a Friend&lt;/li&gt;
&lt;li&gt;Vs a Bot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 Curso de Udemy.
&lt;/h2&gt;

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

&lt;p&gt;He preparado el curso &lt;a href="https://www.udemy.com/course/aprende-a-desarrollar-un-juego-de-yatzy-con-react/?referralCode=A524789E1703570AF758"&gt;"Aprende a desarrollar un juego de Yatzy con ReactJS/NodeJS y Typescript"&lt;/a&gt;. en el cual enseño a desarrollar este juego desde cero.&lt;/p&gt;

&lt;p&gt;Este proyecto nació de una inspiradora experiencia en la pasada &lt;a href="https://jsconf.cl/"&gt;JSconf Chile&lt;/a&gt;, donde tuve la oportunidad de compartir mi conocimiento sobre el desarrollo de juegos con React (&lt;a href="https://www.youtube.com/watch?v=nReMDgz02qo&amp;amp;t=10553s"&gt;ver conferencia&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Quedé encantado al ver la respuesta entusiasta de los participantes. Desde entonces, al día de hoy he desarrollado más de 13 Juegos utilizando ReactJS, no solo con el objetivo de aprender, sino también con el deseo de compartir mis conocimientos.&lt;/p&gt;

&lt;p&gt;El resultado de esa pasión y dedicación es este curso, que contiene más de 27 horas de videos. Durante el curso, te guiaré en la creación de dos proyectos, uno en el front-end y otro en el back-end, ambos utilizando Typescript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preview
&lt;/h2&gt;

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

</description>
      <category>react</category>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>Part 2/2 - Game in ReactJS - Cuzzle</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Tue, 21 Dec 2021 15:09:58 +0000</pubDate>
      <link>https://dev.to/jorger/part-22-game-in-reactjs-cuzzle-1662</link>
      <guid>https://dev.to/jorger/part-22-game-in-reactjs-cuzzle-1662</guid>
      <description>&lt;p&gt;In these articles I would like to share with you the process of development of the latest game that I developed called Cuzzle &lt;em&gt;&lt;strong&gt;(cube + puzzle = Cuzzle)&lt;/strong&gt;&lt;/em&gt; ReactJS, this game was inspired by the original game called &lt;a href="https://apps.apple.com/us/app/cuzzle/id1185407542"&gt;cuzzle&lt;/a&gt; developed by &lt;a href="https://www.redline.games/games"&gt;Redline Games&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/jorger/part-12-game-in-reactjs-cuzzle-403a"&gt;first part&lt;/a&gt;, we discuss the game and its options, in this part we are going to talk about the technical aspects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can play the game online here: &lt;a href="https://cuzzle-react.vercel.app/"&gt;https://cuzzle-react.vercel.app/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Stack.
&lt;/h2&gt;

&lt;p&gt;As you know the game is developed in &lt;a href="https://reactjs.org/"&gt;ReactJS&lt;/a&gt;, other main libraries that I used were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://create-react-app.dev/"&gt;Create React App (CRA)&lt;/a&gt;:&lt;/strong&gt; This is a library that I have used previously for other games/projects, this is an easy starting point for a react project because we have all our environment configured, for example, we have &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;, hot reloading, &lt;a href="https://developers.google.com/web/fundamentals/primers/service-workers"&gt;service workers&lt;/a&gt; (via &lt;a href="https://developers.google.com/web/tools/workbox"&gt;workbox&lt;/a&gt;) and other features ready to be used, for this type of project I think is the best way to learn React.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://react-spring.io/"&gt;React Spring&lt;/a&gt;:&lt;/strong&gt; Another library in my toolbox of favorite libraries, this library allows us to create animations, in my case I use this library for cubes movements, I like how we can use a hook to indicate movement, for this project I used &lt;a href="https://react-spring.io/hooks/use-spring"&gt;useSpring&lt;/a&gt; hook, in this hook we can indicate the type of animation that we need, also we have an event (&lt;a href="https://react-spring.io/common/props#events"&gt;onRest&lt;/a&gt;) that indicates when the animation ends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/FormidableLabs/nuka-carousel"&gt;Nuka Carousel&lt;/a&gt;&lt;/strong&gt;: This is a good library to manage carousels, I like the simplicity that this library has. I have used this library in the &lt;a href="https://cuzzle-react.vercel.app/levels"&gt;list of levels&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/@reach/router"&gt;Reach Router&lt;/a&gt;:&lt;/strong&gt; This is a library from the same developers of &lt;a href="https://reactrouter.com/"&gt;react-router&lt;/a&gt;, as the name implies it’s possible to set different routers/pages, in the case of the game we have five routes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/qrcode-decoder"&gt;qrcode-decoder&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/qrcode.react"&gt;qrcode.react&lt;/a&gt;&lt;/strong&gt;: The first library helps to read the information of our QR code, with the second we can create the QR, in this QR we save our level (actually the information we save is the URL, as mentioned in the &lt;a href="https://dev.to/jorger/part-12-game-in-reactjs-cuzzle-403a#:~:text=Fourth%20step%20-%20Publish%20level"&gt;first part&lt;/a&gt; the level created in the editor is saved in the URL).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/howler"&gt;howler&lt;/a&gt;:&lt;/strong&gt; Is an audio library. It defaults to Web Audio API and falls back to HTML5 Audio. This makes working with audio in JavaScript easy and reliable across all platforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/react-keyboard-event-handler"&gt;react-keyboard-event-handler&lt;/a&gt;:&lt;/strong&gt; A React component for handling keyboard events (keyup, keydown and keypress), it's only available in the desktop version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/sweetalert"&gt;sweetalert&lt;/a&gt;:&lt;/strong&gt; A beautiful, responsive, customizable, accessible replacement for Javascript's popup boxes (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/alert"&gt;alert&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm"&gt;confirm&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt"&gt;prompt&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/share-api-polyfill"&gt;share-api-polyfill&lt;/a&gt;:&lt;/strong&gt; This is a polyfill for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share"&gt;Web Share API&lt;/a&gt; which can also be used on the desktop, it is very useful because if the browser does not support the Web Share API, the user can still share the information without problems.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also I used other packages like &lt;a href="https://www.npmjs.com/package/prop-types"&gt;prop-types&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/lodash.clonedeep"&gt;lodash.clonedeep&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other &lt;code&gt;devDependencies&lt;/code&gt; used were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/vercel"&gt;Vercel&lt;/a&gt;&lt;/strong&gt;: This package help to publish the game in the &lt;a href="https://vercel.com/"&gt;service&lt;/a&gt; with the same name, this service is very good, it’s simple to publish a project, I’m using this service for several years (even when the name of the service was &lt;code&gt;now&lt;/code&gt;) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/serve"&gt;Serve&lt;/a&gt;&lt;/strong&gt;: Sometimes was necessary to test the game on real devices, in that case, I used this package to create an URL that I can use on my local (when I needed to share the URL with other people I used &lt;a href="https://www.npmjs.com/package/ngrok"&gt;ngrok&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/features/codespaces"&gt;CodeSpaces&lt;/a&gt;&lt;/strong&gt; This is a great tool, because this allows us to have a complete development environment in the cloud, I had the option to open the project on different devices through the browser or open it in &lt;a href="https://code.visualstudio.com/docs/remote/codespaces"&gt;VS code&lt;/a&gt;, this was very useful for me, because I had the option to develop the game on different computers (even on an iPad).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. CSS.
&lt;/h2&gt;

&lt;p&gt;Most of the interface of the game was developed in CSS, sometimes I use SVGs in this case for the icons, I know there are a lot of good libraries to use with CSS, in my case I used “regular CSS” In this case, each component has their CSS file (if it’s necessary) sometimes when I need to change something in the interface I used the style property or using the className method, but also I used the option to share variables between CSS and JS, in this case with the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/setProperty"&gt;setProperty&lt;/a&gt; (create a CSS variable o modify its value).&lt;/p&gt;

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

&lt;p&gt;In games like this it is possible to use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;canvas&lt;/a&gt;, sometimes it's the best option, for this particular game (actually almost &lt;a href="https://github.com/Jorger"&gt;all the games&lt;/a&gt; I have developed in react don't use canvas) I only use CSS, for me CSS is enough, yes, the performance is sometimes not the best, but for me the idea is to learn, not just ReactJS but CSS as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Technical challenges.
&lt;/h2&gt;

&lt;p&gt;This is the second isometric game that I have developed (I previously developed a game with isometric style &lt;a href="https://hocus-taupe.vercel.app/"&gt;Hocus&lt;/a&gt;). My previous games/projects were mostly 2D, the challenges in this project were mainly related to the depth of the cubes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component creation
&lt;/h3&gt;

&lt;p&gt;With ReactJS (and other libraries/frameworks based on components) it's "easy" to create new components (and reuse them), in this game we have several components, but it was a special challenge creating visual components like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OmGUI9-F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r8qdray5kh1bip32x7om.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OmGUI9-F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r8qdray5kh1bip32x7om.gif" alt="floors" width="586" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Floors&lt;/strong&gt;: As we saw in the &lt;a href="https://dev.to/jorger/part-12-game-in-reactjs-cuzzle-403a#:~:text=Fist%20step%20-%20Add%20floors"&gt;first part&lt;/a&gt; we have different types of floors, but at the end of the day it is just one component that changes its behavior based on its &lt;code&gt;props&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./styles.css&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;SIZE_FLOOR&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;../../../utils/constants&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="nx"&gt;PropTypes&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;prop-types&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="nx"&gt;React&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;react&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="nx"&gt;Variants&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;./variants&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;Floor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SIZE_FLOOR&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="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;animated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;shake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`floor-wrapper &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;shake&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shake&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="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;up&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="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;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="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Variants&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;animated&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"floor-base"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"floor"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Floor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;shake&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Floor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example we can see the &lt;code&gt;&amp;lt;Floor /&amp;gt;&lt;/code&gt; component, but also we can see the &lt;code&gt;&amp;lt;Variants /&amp;gt;&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;SUFIX_ARRIVAL_POINT&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;../../../../utils/constants&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="nx"&gt;ArrivalPoint&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;./arrivalPoint&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="nx"&gt;Portal&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;./portal&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="nx"&gt;Switch&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;./switch&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;Variants&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;finalType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&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="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extendprops&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="nx"&gt;props&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;props&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;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SUFIX_ARRIVAL_POINT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;finalType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SUFIX_ARRIVAL_POINT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;extendprops&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;white&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;variants&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrival-point&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArrivalPoint&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;extendprops&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;    &lt;span class="na"&gt;portal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Portal&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;extendprops&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;finalType&lt;/span&gt;&lt;span class="p"&gt;]&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="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Variants&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cube:&lt;/strong&gt; This component is simpler compare to floors, but only when it's a static cube.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./styles.css&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;SIZE_FLOOR&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;../../../utils/constants&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="nx"&gt;PropTypes&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;prop-types&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="nx"&gt;React&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;react&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;Cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SIZE_FLOOR&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&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="nx"&gt;opacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cube &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;opacity&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; opacity&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="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;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="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;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="nx"&gt;Cube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Cube&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see it's just one div, I like to use just one div when possible, sometimes it's possible to do a lot of things with just &lt;a href="https://a.singlediv.com/"&gt;one div&lt;/a&gt; and I think it's good, because as you know when we use less DOM elements it's good for performance.&lt;/p&gt;

&lt;p&gt;Who creates the "magic" to show a cube is CSS, in this case using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform"&gt;transform&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient()"&gt;linear-gradient&lt;/a&gt; properties with  the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::before"&gt;before pseudo-element&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cube depth
&lt;/h3&gt;

&lt;p&gt;In a 2D game, the elements are at the same level, but in games like this, depth is an important aspect to take into consideration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XWRwTt3b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tiwcino8kj2sgicb8phf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XWRwTt3b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tiwcino8kj2sgicb8phf.gif" alt="depth_example" width="588" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you know in CSS we have the concept of &lt;a href="https://web.dev/learn/css/z-index/"&gt;stacking context&lt;/a&gt;, when we have two elements with absolute positions the element that is in the right position and/or below by default will be on top of the other element, if we want to change that behavior it is necessary to use the &lt;a href="https://developer.mozilla.org/es/docs/Web/CSS/z-index"&gt;z-index&lt;/a&gt; property, but for it to work all elements need to be in the &lt;a href="https://www.joshwcomeau.com/css/stacking-contexts/#layers-and-groups"&gt;same stacking context&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I use the z-index only in the component where the user can move the cubes, in the editor wasn’t necessary because all the elements are static at that point, all the floors render from left to right and  top to down, in this case, all the floors have an absolute position (the positions were calculated by a helper) due to behavior of rendering by default a floor have the right position and depth with respect to the other floors, I mean the next floor will have a greater depth than the previous one, the same strategy was applied for the cubes with one exception, in this case, the cubes have a z-index (the same z-index), the reason is, it was necessary to make sure the cubes are located above the floors, I don’t use another container for the cubes, the floors and the cubes are in the same container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Movement of the cubes
&lt;/h3&gt;

&lt;p&gt;This was one of the most challenging parts of the game because I needed to move the cube or cubes (sometimes the player can move two cubes at the same time), to do that I used the &lt;a href="https://react-spring.io/"&gt;react-spring&lt;/a&gt; library, with this library and its &lt;a href="https://react-spring.io/hooks/use-spring"&gt;useSpring&lt;/a&gt; hook I can indicate the move I need (left, top), the move only happens if it passes some validations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A cube only can move if:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oJlJPhst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/opwgxg8iisoy72wa46o0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oJlJPhst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/opwgxg8iisoy72wa46o0.gif" alt="move_cube" width="588" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is a floor:&lt;/strong&gt;, if the player wants to move a cube to a new position, that position needs to have a floor, it sounds fun to say that, but a level code was necessary to have such validation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In front, there is another cube and there is a floor:&lt;/strong&gt; In this case, the validation of the floor is made for the second cube, this means when the main cube has in front of another cube, it’s necessary to know if the new position of the second cube has a floor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In front, there is another cube and in front of that cube, there is no other cube:&lt;/strong&gt; This scenario is when we have three cubes, the main cube wants to move to a position where there is another cube, now it’s necessary to know if the new poison the second cube is available, if in that position there is another cube, there will be no movement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Portal validation.
&lt;/h3&gt;

&lt;p&gt;Validate this type of cube was also challenging, some considerations that were necessary to have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jiY3LOhU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2q2v8tk3w4jlwypeeha.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jiY3LOhU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2q2v8tk3w4jlwypeeha.gif" alt="Portals" width="588" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not accepting movement input while teleporting a cube:&lt;/strong&gt; when the user indicates the movement, it is possible to maintain a sustained movement, this means that the user does not need to leave the cursor finger (or keyboard in desktop) to indicate a new movement, wit portals it’s a little different because when a cube enters to a portal, this cube change to a new position, at that moment we have an animation that shows the change, to prevent a strange behavior, the input from the user is ignored, when the teleportation animation ends, the inputs are enabled again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validate that the portal exit point is available:&lt;/strong&gt; All the cubes in the game can be teleport, if a regular cube is teleported the exit of the portal is blocked for that cube, in that case when a cube enters a portal the cube moves normally, this means that the portal behaves like a regular floor, this is convenient sometimes for some levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Undo validation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xCeOkkXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnst4vnfsfizoqewkkuz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xCeOkkXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnst4vnfsfizoqewkkuz.gif" alt="Undo" width="702" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The game has the option to restart a level, but the undo action is different because it needs to show the level in the previous state, to achieve this action was necessary to create a new state, in this state we save the previous state of the level, but no all the complete state, this means, that it only saves the things that change at that moment, for example, if the user only moves a cube, it’s not necessary to save the state of the floors or the state of the other cubes.&lt;/p&gt;

&lt;p&gt;For example when a cube or cubes move, in that case, we save in an object called floors, the previous position where the cube was, always we have at least a cube moving.&lt;/p&gt;

&lt;p&gt;But when it’s necessary to validate undo option for floors we have to take into consideration the type of the floor, for example, if the floor is a shaking floor, when the undo option is applied it’s necessary to show the floor again in the same position that we have before, other case is when we have a switch floor, it’s necessary to save the floors that were related with the switch and hide that floors again.&lt;/p&gt;

&lt;p&gt;For portals the logic was different, in this case, we don’t have the teleportation animation because it’s possible to press the undo button many times, in that case, we only save the previous position of the cube and when the user press the undo button, the cube returns to the previous position, in that case, we see an animation of the cube from the current position to its previous position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Save level solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The state that was used for the undo option also was utilized for the solution option, in this case, only it saves this data when we are in the editor, the same state was utilized because when the user uses the undo option, at the same time is removing that movement from the solution.&lt;/p&gt;

&lt;p&gt;The solution is saved in an array, this array contains the valid moves (if a user made a movement and the cube doesn’t move that movement isn’t saved) to prevent a big solution the editor has a limit of 250 movements, but a potential array of 250 movements continues to be a big value, that’s why the solution has a special treatment to save, in this case, the array is converted to a string, eliminating the repeated values ​​and saving the number of times a value is repeated (when it is consecutive), when a level is loaded there is a conversion to the array again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hrXLC5mG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6rbuzc13wguellr6dtmz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hrXLC5mG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6rbuzc13wguellr6dtmz.gif" alt="save_solution" width="702" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example &lt;strong&gt;37,27,12,42,32,44,23&lt;/strong&gt; is the solution for the level in the gif, in this case &lt;code&gt;37&lt;/code&gt; means that it's necessary move the cube seven times to the position 3 (right-top)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run solution.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hj1lS8so--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lfb9y1mi7dw4vyy7b1zd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hj1lS8so--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lfb9y1mi7dw4vyy7b1zd.gif" alt="run_solution" width="586" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user can play many times a particular level, can restart it, and also can use the undo option the times that are necessary, but there are moments that a level is very complex, that is why the game has the option to show the solution of the level, that is the reason why in the editor to play the level and validate that the level has a solution, that solution is saved and later is executed to show the solution.&lt;/p&gt;

&lt;p&gt;In other game that I developed &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo"&gt;Mr. Square&lt;/a&gt;, we have the same option to show the solution of the level, but in that case, the user needs to follow the movements to complete the level, but this game is different because the user doesn’t need to make any movement, all the movements are automatically executed, in this case the player only is a viewer, because of that, was necessary to disable all the inputs for the user, also if the user had made movements before, was necessary to restart el level before to start executing the solution.&lt;/p&gt;

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

&lt;p&gt;This game was a good challenge for me, this is the ninth game that I develop in ReactJS, with each game I learn something new, I do not consider myself a game developer, I do this type of project because it is fun and at the same time I learn new concepts of this library.&lt;/p&gt;

&lt;p&gt;In these articles I wanted to share on a high level how I developed this game, the game code at the moment is private, just like the other games, my idea is maybe to create a course where I can show you how you can develop these games.&lt;/p&gt;

&lt;p&gt;I'm not a native english speaker, actually this is my first articule in English, to be honest was more complex to me write these articules that develop the game 😅, but was a good experience, the next game (I have a new game in my head right now 😅) that I develop the idea is to write another articles in English, I know that I can improve day by day.&lt;/p&gt;

&lt;p&gt;Thanks for reading these articles, you can find me at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/ostjh"&gt;Twitter.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Jorger"&gt;Github.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/jorge-rubiano-a8616319"&gt;Linkedin.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>css</category>
      <category>pwa</category>
    </item>
    <item>
      <title>Part 1/2 - Game in ReactJS - Cuzzle</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Mon, 13 Dec 2021 20:39:19 +0000</pubDate>
      <link>https://dev.to/jorger/part-12-game-in-reactjs-cuzzle-403a</link>
      <guid>https://dev.to/jorger/part-12-game-in-reactjs-cuzzle-403a</guid>
      <description>&lt;p&gt;In these articles I would like to share with you the process of development of the latest game that I developed called Cuzzle &lt;em&gt;&lt;strong&gt;(cube + puzzle = Cuzzle)&lt;/strong&gt;&lt;/em&gt; ReactJS, this game was inspired by the original game called &lt;a href="https://apps.apple.com/us/app/cuzzle/id1185407542" rel="noopener noreferrer"&gt;cuzzle&lt;/a&gt; developed by &lt;a href="https://www.redline.games/games" rel="noopener noreferrer"&gt;Redline Games&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this first part, I'm going to show you about the game and the different options it has.&lt;/p&gt;

&lt;p&gt;In the second part, we are going to talk about the technical aspects and challenges in the development of this game.&lt;/p&gt;

&lt;h2&gt;
  
  
  The game
&lt;/h2&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%2Fwwfjsmikv99kr7yr1vcb.gif" 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%2Fwwfjsmikv99kr7yr1vcb.gif" alt="Cuzzle-level"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can play the game online here: &lt;a href="https://cuzzle-react.vercel.app/" rel="noopener noreferrer"&gt;https://cuzzle-react.vercel.app/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuzzle ReactJS is an &lt;a href="https://en.wikipedia.org/wiki/Isometric_video_game_graphics" rel="noopener noreferrer"&gt;isometric&lt;/a&gt; puzzle game, inspired by &lt;a href="https://en.wikipedia.org/wiki/Sokoban" rel="noopener noreferrer"&gt;Sokoban&lt;/a&gt;, the 1981 transport puzzle game in which the player has to push boxes around a warehouse to get them into different locations. Cuzzle ReactJS add collapsing floors, switches, and some nice graphics.&lt;/p&gt;

&lt;p&gt;The idea behind the development of this game was to learn more about &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;ReactJS&lt;/a&gt;, as you know ReactJS is a library that allows us to develop rich user interfaces with encapsulated components that manage their own state.&lt;/p&gt;

&lt;p&gt;Actually, this is the &lt;a href="https://github.com/Jorger/Jorger/blob/main/README.md" rel="noopener noreferrer"&gt;ninth game&lt;/a&gt; that I developed in ReactJS and with every new game I learn something new, also this gives me the opportunity to test new features and/or strategies using this library. &lt;/p&gt;

&lt;p&gt;In cuzzle ReactJS the user has 85 levels, divided into 4 sections, each section has a different level of difficulty.&lt;/p&gt;

&lt;p&gt;On desktop, you can use the movement arrows and swipe events on mobile.&lt;/p&gt;




&lt;h2&gt;
  
  
  Game options
&lt;/h2&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%2Fyczalv28e8aesh61g1pd.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%2Fyczalv28e8aesh61g1pd.png" alt="Lobby"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this screen the user can access to the different sections of the game: &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. List of levels.&lt;/strong&gt;
&lt;/h3&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%2F1b3jltxsc4sr4xfnlowj.gif" 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%2F1b3jltxsc4sr4xfnlowj.gif" alt="Levels"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;On this page, users can access the different levels of the game, in this case, we have four sections, by default the first level of each section is enabled (also has a different background color), to play the other levels it's necessary to complete the previous one.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Editor.&lt;/strong&gt;
&lt;/h3&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%2Fypuos8lvupi96bm7mzzp.gif" 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%2Fypuos8lvupi96bm7mzzp.gif" alt="floors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On this page users can create new levels (the 85 levels were created with this editor), the editor is divided into four steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fist step - Add floors:&lt;/strong&gt; the first step is to add the floors of the level, we have five types of floors:&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%2Fplowoih48fc7mpbkqr7l.gif" 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%2Fplowoih48fc7mpbkqr7l.gif" alt="floors_behavior"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Regular:&lt;/strong&gt; This is a normal floor, depending on other validation a regular floor can change its behavior, a regular floor could be:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shake floor:&lt;/strong&gt; this is a temporal floor, if the main cube passes over a shaking floor the floor will fall.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Switch floors:&lt;/strong&gt; When a switch is activated this kind of floor will appear, by default when the level load these floors aren’t visible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Arrival points:&lt;/strong&gt; These are the places where the cubes must be located to finish a level, at the same time we have two types of arrival points.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regular:&lt;/strong&gt; This is represented by the white rectangles, it’s possible to add a maximum of 8 of this type and at least one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Main:&lt;/strong&gt; As the name implies, this is the position where we need to locate the main cube, we have the option to change the color to &lt;code&gt;red&lt;/code&gt;, &lt;code&gt;yellow&lt;/code&gt;, or &lt;code&gt;green&lt;/code&gt;, in this case, it’s only possible to add only one floor of this type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Switch:&lt;/strong&gt; this floor has the trigger that will activate the floors that will appear. When we add a switch to the board we have an option to indicate which floor will be visible when we activate the switch, we only can add one switch for level. If we remove a switch and previously we have floors related to it, those floors will return to their original state.&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%2Fetm96wzl2i3abp1l005e.gif" 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%2Fetm96wzl2i3abp1l005e.gif" alt="Portals"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Portals:&lt;/strong&gt; this is a special floor, that allows the cubes to “teleport” between two points because that condition we only have the option to add two floors of this type (entrance point and exit point respectively).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this step we have other options, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change background color:&lt;/strong&gt; It is possible to change the background of the level for four predefined colors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Load preloaded levels:&lt;/strong&gt; If we want to create/fork a level from an existing level, this is very useful because we don't need to start from scratch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Load a level from a QR:&lt;/strong&gt; As I mentioned before, the game doesn't have a backend, instead, the levels are saved in a QR, if we create a level previously we can load the QR and create a new one from this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remove all items:&lt;/strong&gt; Sometimes we start to create a new level but we aren't very happy with the result, if we want to start over, it's not necessary to remove each element one by one, with this option we can remove all the elements and start again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relocate level positions:&lt;/strong&gt; Sometimes we finish a level, but the level isn't in a good position (it's not centered for example), instead of removing the cubes and starting over, we can use this option to move all elements of the level at the same time.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Second Step - Add cubes:&lt;/strong&gt; When we have already add the floors that we need for our level, it’s possible to add the cubes, the number of cubes depends on the number of arrival points that we add in the first step, the minimum value is two (one regular and main) or the maximum value is nine (8 regular one main).&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%2Fbg1mlfu6toh0ejmk12g7.gif" 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%2Fbg1mlfu6toh0ejmk12g7.gif" alt="second-step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The color of the main cube depends on the option that we choose in the first step (it’s possible to return to the previous step and change the color).&lt;/p&gt;

&lt;p&gt;It’s possible to add the cubes on the following floors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular.&lt;/li&gt;
&lt;li&gt;Shake cubes.&lt;/li&gt;
&lt;li&gt;Arrival points.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, isn’t possible to add the cubes on the following floors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch.&lt;/li&gt;
&lt;li&gt;Switch floors.&lt;/li&gt;
&lt;li&gt;Portals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we add the cube on a switch the other floors will be active immediately, in the case of the switch floors, these aren’t visible when the level loads, and finally on portals the cube will be “teleport” to another position.&lt;/p&gt;

&lt;p&gt;If all the cubes are in the arrival points the editor will show a message because in that case the level is resolved, that doesn’t mean that isn’t possible to add cubes on arrival points, but at least one cube should be outside of an arrival point.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Third step - Play/Test Level:&lt;/strong&gt; In this step we test that our level has a solution, this is very important, because that solution is saved, to prevent having an infinite solution or a solution with too many movements, the editor has a restriction of maximum 250 movements.&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%2Ff5c9pahye2sjghrhdvld.gif" 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%2Ff5c9pahye2sjghrhdvld.gif" alt="Third-step"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Fourth step - Publish level:&lt;/strong&gt; in this step, we can download our level in a QR code, or share our level through a URL, the game hasn’t a backend infrastructure, the levels that we created in the editor are saved in the URL.&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%2F129qoyzjfnnkpwhcvc87.gif" 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%2F129qoyzjfnnkpwhcvc87.gif" alt="four_step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, this is the QR for the level in the gif and this is the &lt;a href="https://cuzzle-react.vercel.app/l/o7lHih4pbr0QKd3ujZkbsGzgsvuBYNTKFzCWpGJtqRN2yIytCsfOiG5RQ8ZSQ-z2IaiBlr0A4c8k6-0l6Kll5oq08yKKICD2dyjTgWgxFhT8KiySFGg93_NdX63Fpdyr-l4JuJ34WMoga7rhuKeAySasyywyu5v4UWBNdWIVAiYJLzFa2CNEvUsZmr_Ge7YHCZJDt8LPea9iooMHNBiU8w" rel="noopener noreferrer"&gt;corresponding URL&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%2F7thcltfoebal5eckgqvo.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%2F7thcltfoebal5eckgqvo.png" alt="QR_example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this screen we have a copy button as well, this saves in the clipboard the structure of the level that is utilized to save the preloaded levels, at the end of the day is a string, this string has all the necessary information to recreate the level.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Other options:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;On the lobby page it is possible to change other game options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable/disabled sounds.&lt;/li&gt;
&lt;li&gt;Upload QR code: We can "upload" (actually it’s not a real upload, because the game doesn’t have a backend, in this case, we read the content of the QR, but it’s necessary to have the option to select it, this is the reason we use a file input to do this action) the QR that we create in the editor if the QR is valid the user can 
play the level.&lt;/li&gt;
&lt;li&gt;Share option: As the name implies, with this option we can share the game (also we have de option to share a level and a custom level), on mobile, it's used the native  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share" rel="noopener noreferrer"&gt;navigator.share&lt;/a&gt; and on desktop (or browsers that don't support share) it's used the &lt;a href="https://www.npmjs.com/package/share-api-polyfill" rel="noopener noreferrer"&gt;share-api-polyfill&lt;/a&gt; package.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In this first part, we talked about the game, we saw its options, in the second part, we are going to discuss the technical aspect of the game and the challenges to develop it.&lt;/p&gt;

&lt;p&gt;You can continue with the &lt;a href="https://dev.to/jorger/part-22-game-in-reactjs-cuzzle-1662"&gt;second part&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>css</category>
      <category>pwa</category>
    </item>
    <item>
      <title>Zeek The Geek en ReactJS - Cuarta Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sun, 17 Jan 2021 01:14:28 +0000</pubDate>
      <link>https://dev.to/jorger/zeek-the-geek-en-reactjs-cuarta-parte-26bm</link>
      <guid>https://dev.to/jorger/zeek-the-geek-en-reactjs-cuarta-parte-26bm</guid>
      <description>&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-primera-parte-1ch4"&gt;primera parte&lt;/a&gt; de esta serie de artículos, hablamos de la historia del juego original, la motivación del desarrollo de esta nueva versión, sus opciones así como el stack de tecnología utilizada.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-segunda-parte-499n"&gt;segunda parte&lt;/a&gt; se mostró cada uno de los bloques que componen el juego, así como la interacción que pueden tener éstos con el personaje.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-tercera-parte-2928"&gt;tercera parte&lt;/a&gt; se abordó algunos retos técnicos que tuvo el desarrollo del juego, así como se entregó una solución a los mismos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL del juego:&lt;/strong&gt; &lt;a href="https://zeek.jorge-rubiano.vercel.app/"&gt;https://zeek.jorge-rubiano.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esta cuarta y última parte deseo compartir algunas funcionalidades extras que posee el juego, así como el ambiente de desarrollo utilizado para el mismo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creación de nuevos niveles.
&lt;/h1&gt;

&lt;p&gt;El juego como tal posee 220 niveles precargados, pero en este caso deseaba dar la posibilidad a los usuarios de crear sus propios niveles, como tal el editor fue de gran ayuda en el momento de crear los niveles del juego, pero deseaba que está herramienta no sólo quedará para el momento de desarrollo, sino que fuera parte del juego, a diferencia de &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo#:~:text=Back-end"&gt;Mr. Square&lt;/a&gt; que si tiene una base de datos donde se pueden almacenar lo niveles, Zeek no cuenta con está opción, entonces para "almacenar" lo nivles se hace uso de la URL o de códigos QR, tuve la inspiración para realizar está acción en una coferencia de la Chrome Dev Summit del año 2019, en la cual mostraban un ejemplo de como se podía compartir un juego y sus niveles a través de estás opciones.&lt;/p&gt;

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

&lt;p&gt;Un ejemplo de un nivel es el siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f7DoCzsV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hnl9wflrygsolabmlpyp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f7DoCzsV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hnl9wflrygsolabmlpyp.jpg" alt="Alt Text" width="880" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El mismo nivel se puede acceder a través de &lt;strong&gt;&lt;a href="https://zeek.jorge-rubiano.vercel.app/l/oyMGKbDQQvyIO-mQPKF9UAgWN0b03rSASBuL_rMOjTsSml2X_HBgW8UMm-BF4sY1E08dGeE_rDSqIUjUGR1np-cZIGnwCMMaQuj2x1NjMIDPr5OcL_SXo3g7h0lkjBQ7wyVsGDx1AlSwPUBy6IPkl6EhNYgwoLxTLpjYQkYxYnIUAY1JN4cGZdtQfU2r0lpUYsYty8y28XBWAoBKnA804Waxc8TEkRoQJ2POPKLMNoM"&gt;este link&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Esto permite que se pueda compartir fácilmente cualquier nivel creado, además se ahorra la necesidad de tener esta información almacenada en una base de datos.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ambiente de desarrollo.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pr0nvTOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sssp9mxj57b2fb9h1m71.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pr0nvTOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sssp9mxj57b2fb9h1m71.gif" alt="Alt Text" width="690" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inicialmente empecé a desarrollar el juego en &lt;a href="https://codesandbox.io/"&gt;codesandbox&lt;/a&gt; este permite protopiar aplicaciones de forma rápida, en &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo#:~:text=codesandbox"&gt;juegos anteriores&lt;/a&gt; ya había utilizado este ambiente para la fase inicial de desarrollo, posteriormente finalizaba el juego en mi ambiente local, pero perdía lo que codesandbox me daba que era la opción de poder escribir código en cualquier momento y en cualquier equipo, deseaba tener lo mismo y es así que empecé a utilizar &lt;a href="https://github.com/features/codespaces"&gt;codespaces&lt;/a&gt; este es un servicio de Github (actualmente aún está en fase de prueba), el cual permite tener todo un ambiente de desarrollo en la nube, es posible utilizarlo directamente en el navegador o a través de VS Code a través de una &lt;a href="https://docs.github.com/en/github/developing-online-with-codespaces/using-codespaces-in-visual-studio-code"&gt;extensión&lt;/a&gt;&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G-uC7qMa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1345437724422107136/pu/img/Llp_XUvmSa9ijQ3l.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaxpkXqm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1139905258551988224/0-AS5H2g_normal.jpg" alt="Jorge Rubiano profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge Rubiano
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ostjh
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      &lt;a href="https://twitter.com/hashtag/CodeSpaces"&gt;#CodeSpaces&lt;/a&gt; from &lt;a href="https://twitter.com/github"&gt;@github&lt;/a&gt; is great, it is possible to have a programming environment in the cloud, even to program from the iPad 🤯🤯 &lt;a href="https://twitter.com/hashtag/reactjs"&gt;#reactjs&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/js"&gt;#js&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      18:32 PM - 02 Jan 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1345437929167007745" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1345437929167007745" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1345437929167007745" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Fue incluso posible hacer pruebas en el iPad, aunque a decir verdad no es lo mejor, no por codespaces sino por el iPad en sí, ya que acciones como utilizar el scroll fue difícil, cabe anotar que en las pruebas hice uso de un mouse y teclado, ya que sin ellos no sería una buena experiencia.&lt;/p&gt;

&lt;p&gt;El uso de codespaces fue genial y me permitió que el código estuviera siempre disponible, sin la necesidad de estar en un sólo dispositivo, codespaces tiene una integración muy buena con github, por lo que me parece una buena opción para futuros proyectos.&lt;/p&gt;

&lt;h1&gt;
  
  
  Despliegue de la aplicación
&lt;/h1&gt;

&lt;p&gt;A diferencia de otros juegos en este caso hice uso del servicio conocido como &lt;a href="https://vercel.com/"&gt;vercel&lt;/a&gt;, ya que el juego es estático y no requiere de backend, en juegos pasados había utilizado &lt;a href="https://www.heroku.com/"&gt;Heroku&lt;/a&gt;, aún sigue siendo mi servicio favorito, pero en este caso no era necesario, ya que como lo mencionaba el juego es 100% estático, vercel en este caso fue muy bueno para mí, ya anteriormente lo había utilizado cuando se denominaba &lt;a href="https://vercel.com/blog/zeit-is-now-vercel"&gt;ZEIT&lt;/a&gt;, y desde ese entonces me gustaba mucho.&lt;/p&gt;

&lt;p&gt;Cuando desplegué la aplicación por primera vez, tuve un inconveniente con las rutas, el juego al ser una &lt;a href="https://en.wikipedia.org/wiki/Single-page_application"&gt;SPA&lt;/a&gt;, todo lo relacionado a la rutas se maneja en el front, lo cual presentaba un problema, ya que al ingresar directamente a un ruta por ejemplo: &lt;a href="https://zeek.jorge-rubiano.vercel.app/levels"&gt;https://zeek.jorge-rubiano.vercel.app/levels&lt;/a&gt; vercel me indicaba que esa ruta no existía, en la &lt;a href="https://vercel.com/docs/configuration#routes/advanced/spa-fallback"&gt;documentación&lt;/a&gt; se explicaba como solucionarlo y en este caso era agregando un archivo de configuración indicando ese caso.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vercel.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rewrites"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/(.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/index.html"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Muchas gracias por leer estos artículos, estas son algunas conclusiones.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusiones
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Realizar este juego presentó un gran desafío y muchos aprendizajes, los cuales sé que podré usar en mi vida profesional y además en la creación de nuevos juegos.&lt;/li&gt;
&lt;li&gt;Fue divertido rehacer un juego después de 13 años, en tecnologías diferentes, ahora con la posibilidad de ser jugado en cualquier dispositivo que cuente con una navegador web.&lt;/li&gt;
&lt;li&gt;ReactJS es una librería que tiene muchas posibilidades, no sólo para crear interfaces sino también en la creación de juegos, la comunidad así lo ha demostrado e iniciativas como &lt;a href="https://github.com/pmndrs/react-three-fiber"&gt;react-three-fiber&lt;/a&gt; demuestran lo que es posible hacer, espero en un futuro cercano poder hacer uso de esta librería para desarrollar un nuevo juego.&lt;/li&gt;
&lt;li&gt;Juegos de este tipo entregan un gran reto, ya que es necesario tener en cuenta muchas validaciones y variaciones, es sorprendente que el juego original tenga más de 25 años, considero que es un gran juego y además fue un gran reto.&lt;/li&gt;
&lt;li&gt;Este juego me permitió explorar más acerca de como aprovechar más lo que nos entrega la web, en este caso el poder de una URL, a decir verdad es algo que ha estado desde el inicio de la internet, poder compartir a través de una URL y eso es lo que nos entrega la web, sin necesidad de descargar nada podemos acceder directamente a lo que necesitamos y en este caso ser utilizada como un medio de almacenamiento.&lt;/li&gt;
&lt;li&gt;Hacer uso de codespaces me pareció genial, en este caso lo utilicé para un proyecto 100% estático, pero es posible incluso hacer uso de funcionalidades de backend, seguiré explorando este ambiente y espero que pronto salga de la fase de pruebas y esté disponible para todos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Jorge Rubiano.
&lt;/h2&gt;

&lt;p&gt;Me pueden encontrar en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/ostjh"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/jorge-rubiano-a8616319/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Jorger"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>pwa</category>
      <category>games</category>
      <category>css3</category>
    </item>
    <item>
      <title>Zeek The Geek en ReactJS - Tercera Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sun, 17 Jan 2021 01:14:23 +0000</pubDate>
      <link>https://dev.to/jorger/zeek-the-geek-en-reactjs-tercera-parte-2928</link>
      <guid>https://dev.to/jorger/zeek-the-geek-en-reactjs-tercera-parte-2928</guid>
      <description>&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-primera-parte-1ch4"&gt;primera parte&lt;/a&gt; de esta serie de artículos, hablamos de la historia del juego original, la motivación del desarrollo de esta nueva versión, sus opciones así como el stack de tecnología utilizada.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-segunda-parte-499n"&gt;segunda parte&lt;/a&gt; se mostró cada uno de los bloques que componen el juego, así como la interacción que pueden tener éstos con el personaje.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL del juego:&lt;/strong&gt; &lt;a href="https://zeek.jorge-rubiano.vercel.app/"&gt;https://zeek.jorge-rubiano.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esta tercera parte me gustaría hablar acerca de los retos técnicos del juego.&lt;/p&gt;

&lt;h1&gt;
  
  
  Movimiento del personaje.
&lt;/h1&gt;

&lt;p&gt;El personaje puede moverse de tres formas como son:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Haciendo uso del teclado, a través de las teclas de movimiento.&lt;/li&gt;
&lt;li&gt;A través del control integrado en el juego.&lt;/li&gt;
&lt;li&gt;Indicando el punto de destino al cual deberá dirigirse Zeek. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Los tres tipos pueden ser usados en desktop, mientras en dispositivos móviles se puede hacer uso de las opciones 2 y 3.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Para mover el personaje y por consiguiente a los bloques que Zeek puede mover, se hizo uso de la librería conocida como &lt;a href="https://www.react-spring.io/"&gt;react-spring&lt;/a&gt;, está librería permite indicar el punto de origen del movimiento así como su punto de destino, una vez se ha completado la animación, se entrega un evento.&lt;/p&gt;

&lt;p&gt;Una vez se tiene este evento se puede evaluar el entorno del personaje, esto también aplica a elementos como los dinos, es decir, para los dinos se utilizó la misma lógica, con la diferencia que el movimiento es indicado por el sistema y no por el usuario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LZYSdEOU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ayef59afh86mmywkan7q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LZYSdEOU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ayef59afh86mmywkan7q.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uno de los retos en el movimiento del personaje fue validar si el personaje se podría mover o no, por lo que se debía validar el tipo de bloque que existía antes de moverse, pero si el bloque que existía a la posición a la que se quería mover el personaje se podía mover, se debía validar si la posición de ese elemento estaría libre.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/naughty-agnesi-19yt6"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Para garantizar que el personaje y el elemento que se esté moviendo finalizan al mismo tiempo, se validó que no se acepta eventos de movimiento antes que finalice el movimiento, esto permitió que sí se hace un cambio de movimiento rápido, Zeek sólo responderá una vez que haya finalizado de moverse.&lt;/p&gt;

&lt;h1&gt;
  
  
  Movimiento Zeek indicando el punto de destino.
&lt;/h1&gt;

&lt;p&gt;Como lo indicaba anteriormente uno de los métodos para mover a Zeek, es indicando su punto de destino, para ello se busca la ruta más corta &lt;strong&gt;(más no la más segura)&lt;/strong&gt; a seguir, para lograr este objetivo, se hizo uso de la librería &lt;a href="https://www.npmjs.com/package/pathfinding"&gt;pathfinding&lt;/a&gt;, está librería utiliza una gran variedad de &lt;a href="https://www.npmjs.com/package/pathfinding"&gt;algoritmos&lt;/a&gt; para lograrlo, para el juego hice uso de &lt;a href="http://coecsl.ece.illinois.edu/ge423/spring06/Apath/design.htm"&gt;A* Finder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La librería en este caso solicita una &lt;a href="https://github.com/qiao/PathFinding.js#basic-usage"&gt;matriz&lt;/a&gt;, en la cual se indica que posiciones son disponibles/vacías y cuáles no, una vez realizado este proceso, la librería entregará un array de posiciones indicando la ruta más corta encontrada.&lt;/p&gt;

&lt;p&gt;Un ejemplo de ello es el siguiente escenario, a pesar de tener varios caminos, se ha ido por la ruta más corta encontrada por A* Finder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F6kymTRS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/waf083mhq2ot83z96gv3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F6kymTRS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/waf083mhq2ot83z96gv3.gif" alt="Alt Text" width="676" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gráficamente está búsqueda se puede visualizar de esta forma.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CInUk1re--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/816uus5ac9jigi8upvzf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CInUk1re--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/816uus5ac9jigi8upvzf.gif" alt="Alt Text" width="672" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se puede probar los demás algoritmos de esta librería en esta url: &lt;a href="http://qiao.github.io/PathFinding.js/visual/"&gt;http://qiao.github.io/PathFinding.js/visual/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como lo comentaba la librería espera una matriz para así entregar la ruta más óptima, más no la más segura, ya que no se valida si en la ruta encontrada existan peligros que puedan eliminar a zeek, aún así hay validaciones que buscan minimizar este peligro, por ejemplo no se puede indicar que el punto de destino sea una flor púrpura o azul.&lt;/p&gt;

&lt;p&gt;Una vez que se tiene la ruta se debe indicarle a Zeek los movimientos, como tal zeek sólo recibe direcciones (right, left, down, up), por lo que se debe hacer una conversión de las coordenadas a direcciones, esta acción se realizó a través de la siguiente función.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Es posible cambiar la dirección del personaje en cualquier momento, es decir, si se le ha indicado la ruta al personaje y se presiona alguna tecla del teclado, esta ruta se cancelará aceptando la última entrada dada.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creación de muros
&lt;/h1&gt;

&lt;p&gt;Como tal el juego cuenta con una gran variedad de bloques que son interactivos, bien sea por que desaparecen al contacto con otro bloque (flores amarillas, tesoros, etc) o que el personaje puede mover en el escenario (dinamita, manzanas, cristales mágicos, etc), pero los muros como tal son elementos estáticos, cada elemento en el escenario es un componente como tal por lo que se debe renderizar, en el caso de los muros se debe igualmente renderizar, pero en este caso no hacen acción alguna, más que bloquear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uo22bfZ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3bipdh3hesp3rjjn7con.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uo22bfZ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3bipdh3hesp3rjjn7con.gif" alt="Alt Text" width="608" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por ello los muros no se renderizan, sino que se crea una imagen, para ello existe un función que recibe el escenario y busca en éste los elementos de tipo muro, a partir de esto crean una imagen haciendo uso de canvas.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Esto permitió liberar el render del juego de elementos innecesarios, ya que los muros se renderizan como un sólo background, aún así dentro del estado si se valida si existe un muro en una posición, más no se renderizan.&lt;/p&gt;

&lt;h1&gt;
  
  
  Animaciones de los bloques.
&lt;/h1&gt;

&lt;p&gt;Como lo había indicado anteriormente los movimientos del personaje y de otros elementos del escenario, se realizaron a través de react-spring, pero para las demás animaciones, como pasos, explosiones y demás se hizo uso de las animaciones de CSS.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/laughing-bose-600nj"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;La animación proviene de un sprite que contiene todos los movimientos necesarios para el juego.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yt_owQr5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/85520ez00y8hkzbfr58n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yt_owQr5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/85520ez00y8hkzbfr58n.png" alt="Alt Text" width="288" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por ejemplo para indicar que el personaje estaba caminando hacía la derecha, se pasaba una clase la cual iniciaba la animación de los pasos, de la misma manera si se deseaba indicar si el personaje estaba durmiendo.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Como se puede apreciar se hizo uso de variables en CSS, las cuales cambian dinámicamente dependiendo del tipo de estado que tenga el personaje.&lt;/p&gt;

&lt;p&gt;Haciendo uso de animaciones en CSS, ayudó a liberar al render del juego.&lt;/p&gt;

&lt;h1&gt;
  
  
  Temporizador de bloques.
&lt;/h1&gt;

&lt;p&gt;En el juego existen varios bloques que una vez activados tienen un tiempo para realizar una acción, por ejemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Al activar una dinamita.&lt;/li&gt;
&lt;li&gt;Al colisionar dos cristales mágicos.&lt;/li&gt;
&lt;li&gt;Al comer una manzana la flor púrpura.&lt;/li&gt;
&lt;li&gt;Al digerir una manzana.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Para manejar estos tiempos, se hizo uso de un custom hook, denominado &lt;a href="https://overreacted.io/making-setinterval-declarative-with-react-hooks/"&gt;useInterval&lt;/a&gt;, este permitió indicar los tiempos que cada acción debían esperar, este hook sólo se activa sólo cuando se requiere una animación, es decir, si no existe algún elemento que requiera un temporizador useInterval no estará en ejecución.&lt;/p&gt;

&lt;h1&gt;
  
  
  Validación explosión dinamita.
&lt;/h1&gt;

&lt;p&gt;El bloque de tipo dinamita, es un bloque interesante, ya que puede eliminar una gran variedad de otros bloques, incluido a Zeek, pero igualmente puede activar otra dinamita, existen escenarios donde esta característica le entrega un tiempo límite para terminar el escenario.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Pero para que la dinamita sepa que debe eliminar una vez explote, debe conocer su entorno, además debe estar en reposo, es decir si el personaje está moviendo la dinamita y el tiempo de explosión ha acabado, sólo cuando la animación de movimiento haya acabado explotará y por consiguiente eliminará a Zeek.&lt;/p&gt;

&lt;h1&gt;
  
  
  Validación del Láser.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--40iwuib5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bgbnxuoy2ck70hhtuh9p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--40iwuib5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bgbnxuoy2ck70hhtuh9p.gif" alt="Alt Text" width="680" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El láser es un elemento estático, que sólo puede ser eliminado por una dinamita, el láser siempre estará observando a Zeek, si éste se encuentra en su vista lo eliminará, si existe algún elemento entre Zeek y el láser no podrá eliminarlo, para ello desde el editor fue necesario realizar esa acción&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OcONk7XF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x47q9pth3jfrilpi2pvj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OcONk7XF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x47q9pth3jfrilpi2pvj.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el juego se tuvo que realizar la misma acción, en este caso revisar si la nueva posición del personaje estaba a la "vista" del láser y si no había algún elemento que lo bloqueará, fue necesario hacer una validación especial cuando el elemento de bloqueo es un dino, por la misma naturaleza del mismo, es decir a diferencia de los demás bloques, este está en constante movimiento, por lo que se debía validar no sólo en que posición estaba sino además en qué posición estaría después.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h1&gt;
  
  
  Validación movimiento Dino (Piclasops)
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nAAqYqxU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qejgmo0rw5zwws2y9hit.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nAAqYqxU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qejgmo0rw5zwws2y9hit.gif" alt="Alt Text" width="676" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A diferencia de los demás bloques el Dino, se mueve automáticamente, además de existir la posibilidad de existir varios dinos al mismo tiempo, era necesario validar que un dino no quedará en la misma posición de otro, por lo que se válido que una vez un dino haya seleccionado su próxima posición, los demás dinos tomarían esa posición como bloqueante&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pHGXdrRf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dk7g9uu1ljkiw9z0vqrq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pHGXdrRf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dk7g9uu1ljkiw9z0vqrq.gif" alt="Alt Text" width="674" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Otra validación fue relacionada a los elementos que mueve Zeek, un dino puede ser bloqueado y pasar a un estado estático, no era posible establecer la lógica de establecer una posición bloqueante a un movimiento futuro de un dino, si el elemento que iba a tomar esa posición era un bloque que estaba moviendo Zeek (más no Zeek, por que en este caso moriría), por lo cual fue necesario saber si un bloque futuro estaría en esa posición.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;p&gt;En esta tercera entrega quería compartir algunos retos técnicos en el desarrollo del juego, como tal es un juego que tiene muchas "partes movibles", fue desafiantes ponerlas en conjunto y que funcionarán como un todo, la validación de movimiento así como las acciones de bloques como los láseres representó un gran reto.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-cuarta-parte-26bm"&gt;cuarta y última&lt;/a&gt; entrega hablaremos acerca del ambiente de desarrollo utilizado y otras características que tiene el juego.&lt;/p&gt;

</description>
      <category>react</category>
      <category>pwa</category>
      <category>games</category>
      <category>css3</category>
    </item>
    <item>
      <title>Zeek The Geek en ReactJS - Segunda Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sun, 17 Jan 2021 01:14:17 +0000</pubDate>
      <link>https://dev.to/jorger/zeek-the-geek-en-reactjs-segunda-parte-499n</link>
      <guid>https://dev.to/jorger/zeek-the-geek-en-reactjs-segunda-parte-499n</guid>
      <description>&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-primera-parte-1ch4"&gt;primera parte&lt;/a&gt; de esta serie de artículos, hablamos de la historia del juego original, la motivación del desarrollo de esta nueva versión, sus opciones así como el stack de tecnología utilizada.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL del juego:&lt;/strong&gt; &lt;a href="https://zeek.jorge-rubiano.vercel.app/"&gt;https://zeek.jorge-rubiano.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esta parte se abordará los bloques que componen el juego.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bloques del juego.
&lt;/h1&gt;

&lt;p&gt;El juego cuenta con una variedad de tipos de bloques como son:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Zeek
&lt;/h2&gt;

&lt;p&gt;Es el personaje principal, Zeek debe moverse a través del escenario, su objetivo es el de recoger tantas flores amarillas y tesoros pueda, su objetivo final será recoger el hongo que le permitirá finalizar el escenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--keod7MQy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i5f6kgjpph4giszc1zhr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--keod7MQy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i5f6kgjpph4giszc1zhr.gif" alt="Alt Text" width="674" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si no se mueve Zeek por un buen tiempo, se dormirá, se despertará cuando se indique que se debe mover de nuevo o si algo externo lo despierta (un láser o Piclasops)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aX0b3d5l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gext273guq7wfs7w5671.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aX0b3d5l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gext273guq7wfs7w5671.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si llegase a comerse una flor azul o un hongo malvado (Toadstools), será envenenado, si se encuentra con un Piclasops (dino), morirá o si se encuentra en la vista de un láser será eliminado 😞&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Piclasops (Dino).
&lt;/h2&gt;

&lt;p&gt;Piclasops (o dino) eliminará algunos bloques en el escenario &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flores amarillas, azules, púrpura&lt;/li&gt;
&lt;li&gt;Huevos&lt;/li&gt;
&lt;li&gt;Manzanas/Manzanas con hongos&lt;/li&gt;
&lt;li&gt;Hongos (tanto buenos como malos)&lt;/li&gt;
&lt;li&gt;Píldoras de invisibilidad.&lt;/li&gt;
&lt;li&gt;Y a Zeek&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Si un dino se come a un hongo bueno y es el único en el escenario, Zeek morirá. 💀&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Swb7He39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/smfmd652hqyvd5l8an79.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Swb7He39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/smfmd652hqyvd5l8an79.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reglas que rigen al dino.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nQ-GoiJa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/006jvoe4na1pn35m3wdv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nQ-GoiJa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/006jvoe4na1pn35m3wdv.gif" alt="Alt Text" width="676" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pueden existir varios dinos en el escenario, cuando un dino se encuentra con otro colisionará, &lt;/li&gt;
&lt;li&gt;Un dino buscará girar siempre hacia la izquierda si no está disponible, buscará la dirección que esté disponible (en el sentido de las manecillas del reloj), si no existe ninguna regresará por el mismo camino en venía&lt;/li&gt;
&lt;li&gt;Un dino puede estar inicialmente bloqueado y haciendo uso de otro bloque se puede desbloquear.&lt;/li&gt;
&lt;li&gt;Se puede eliminar un dino a través de una dinamita &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dino como ayuda de Zeek.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aFfh2Keo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kj9x2ff6m12ppe4u8imf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aFfh2Keo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kj9x2ff6m12ppe4u8imf.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El dino también puede servir como ayuda para Zeek, ya que puede eliminar bloques malos para Zeek, como las flores azules y el hongo malo, además de servir como elemento de bloqueo en movimiento contra los láseres.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Manzanas.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7AtYBaH9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v3nuoj6ovl1isy7try43.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7AtYBaH9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v3nuoj6ovl1isy7try43.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Las manzanas son un bloque que Zeek puede mover en el escenario, son útiles para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bloquear un láser.&lt;/li&gt;
&lt;li&gt;Alimentar a las flores púrpura.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Una manzana con un gusano, hará que la digestión de la flor púrpura dure más.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Flores púrpura.
&lt;/h2&gt;

&lt;p&gt;Estás flores son uno de los principales enemigos de Zeek esta tiene tres estados:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hSiO1UDV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dp7s4zgdr9jrr58qb55v.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hSiO1UDV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dp7s4zgdr9jrr58qb55v.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cerrada: En este estado es inofensiva para Zeek, pero si éste se acerca a la flor cuando está en este estado, se abrirá, si Zeek permanece quieto la flor se lo comerá.&lt;/li&gt;
&lt;li&gt;Abierta: Si Zeek pasa cerca se lo comerá.&lt;/li&gt;
&lt;li&gt;Digiriendo: Si a la flor se le da una manzana, comenzará digerir, lo cual hará que sea inofensiva, una vez termine de digerir pasará a un estado cerrado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Puerta.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KTg4juqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zy8md8u81p5fgput758y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KTg4juqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zy8md8u81p5fgput758y.gif" alt="Alt Text" width="674" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Actúa como un bloque de bloqueo, no se puede pasar quitar una puerta si no se cuenta con una llave, o si se elimina con una dinamita&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Llave.
&lt;/h2&gt;

&lt;p&gt;Permite abrir las puertas que se describieron anteriormente, Zeek sólo puede tener una llave al mismo tiempo, es decir si ya ha recogido una llave, no podrá recoger otra.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Tesoros.
&lt;/h2&gt;

&lt;p&gt;Zeek podrá tomar estos tesoros, otorgándole 1000 puntos por cada tesoro que recoja.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Dinamita.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1nr5V2JS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aylk1geuakp5n1dvmaar.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1nr5V2JS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aylk1geuakp5n1dvmaar.gif" alt="Alt Text" width="676" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es un elemento que Zeek puede mover, al moverla la activará, es por ello que Zeek debe ser cuidadoso, si Zeek está cerca cuando al dinamita explota eliminará a Zeek también, la dinamita tiene la habilidad de eliminar la mayoría de los elementos a su alrededor, si uno de los bloques que elimina es el "hongo bueno", y si es el único hongo en el escenario, Zeek morirá&lt;/p&gt;

&lt;p&gt;Si se encuentra otra dinamita cerca se activará, creando una reacción en cadena.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Píldora de invisibilidad.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S6Gxn3Z3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ii6dvwiqvezfupmaeail.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S6Gxn3Z3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ii6dvwiqvezfupmaeail.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Permite que Zeek zea invisible a los láseres y las flores púrpura, durante el tiempo que es invisible podrá pasar cerca de estos bloques y no será eliminado, pero no es invisible a los dinos o a los bloques como flores azules y dinamita&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Láser.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FAQtv02Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g8eqjwtkm4nkexqqawwt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FAQtv02Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g8eqjwtkm4nkexqqawwt.gif" alt="Alt Text" width="676" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los láseres siempre estarán mirando a Zeek, si no existe ningún elemento entre Zeek y el láser lo eliminará.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Cristales Mágicos.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZcdBwSvA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/81bta48h6l2hgrdzy0yd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZcdBwSvA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/81bta48h6l2hgrdzy0yd.gif" alt="Alt Text" width="674" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Son elementos que puede mover Zeek, pueden servir para bloquear a un láser, pero si un cristal mágico colisiona contra otra u otros, se eliminará.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Hongo.
&lt;/h2&gt;

&lt;p&gt;Hongos que Zeek recolecta para el suministro de su energía, una vez que Zeek se ha comido un hongo, podrá pasar al siguiente escenario, otros elementos pueden destruir un hongo como son el dino o la dinamita, si esto llegase a pasar Zeek morirá (siempre y cuando sólo exista un hongo en el escenario)&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Toadstools (Hongo malo)
&lt;/h2&gt;

&lt;p&gt;Toadstools que son fatales si se comen, la idea es engañar a Zeek, ya que son muy parecidos.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Flores Amarillas.
&lt;/h2&gt;

&lt;p&gt;Estás flores le darán a Zeek 50 puntos cada vez que las recoge, además sirven como elementos de bloqueo contra un láser.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. Flores Azules.
&lt;/h2&gt;

&lt;p&gt;Son flores malvadas, si Zeek llegase a tomar una morirá.&lt;/p&gt;

&lt;h2&gt;
  
  
  16. Huevo Azul.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---CtqxTxF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7nelfete1j020uyxj3bl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---CtqxTxF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7nelfete1j020uyxj3bl.gif" alt="Alt Text" width="676" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando Zeek toma un huevo azul, todas las flores amarillas se convierten en flores azules, del mismo modo las flores azules se convierten en flores amarillas.&lt;/p&gt;

&lt;h2&gt;
  
  
  17. Bola Amarilla.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oeZEl8s6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/limynzfexf0vkh47jv0x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oeZEl8s6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/limynzfexf0vkh47jv0x.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es un bloque que Zeek puede mover en el escenario, sirve para bloquear láser e incluso bloquear a los dinos, no es un elemento que se pueda destruir con una dinamita.&lt;/p&gt;

&lt;h2&gt;
  
  
  18. Barriles amarillos.
&lt;/h2&gt;

&lt;p&gt;Son elementos que no se pueden mover o eliminar, se pueden clasificar como muros.&lt;/p&gt;

&lt;h2&gt;
  
  
  19. Muros.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gLpDioBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cr9dald9r9mjesv9q4k0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gLpDioBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cr9dald9r9mjesv9q4k0.gif" alt="Alt Text" width="678" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Son elementos que no se pueden mover, pero si actúan como elementos bloqueantes, en total existen 10 tipos de muros, los cuales se pueden combinar de diferentes formas.&lt;/p&gt;




&lt;p&gt;En esta segunda parte quise ahondar en cada uno de los bloques del juego, así como mostrar como se comportan estos con el personaje o con otros bloques.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-tercera-parte-2928"&gt;tercera parte&lt;/a&gt; mostraré más acerca de los retos técnicos que tuvo el desarrollo de este juego haciendo uso de ReactJS&lt;/p&gt;

</description>
      <category>react</category>
      <category>pwa</category>
      <category>games</category>
      <category>css3</category>
    </item>
    <item>
      <title>Zeek The Geek en ReactJS - Primera Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sun, 17 Jan 2021 01:14:10 +0000</pubDate>
      <link>https://dev.to/jorger/zeek-the-geek-en-reactjs-primera-parte-1ch4</link>
      <guid>https://dev.to/jorger/zeek-the-geek-en-reactjs-primera-parte-1ch4</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%2Fi%2F55k34hks979mee2hxjrt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F55k34hks979mee2hxjrt.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL del juego:&lt;/strong&gt; &lt;a href="https://zeek.jorge-rubiano.vercel.app/" rel="noopener noreferrer"&gt;https://zeek.jorge-rubiano.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esta serie de cuatro artículos, me gustaría compartir la experiencia de desarrollo de un nuevo juego desarrollado en &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;ReactJS&lt;/a&gt;, en este caso un juego clásico como es Zeek The Geek.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-segunda-parte-499n"&gt;Segunda Parte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-tercera-parte-2928"&gt;Tercera Parte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-cuarta-parte-26bm"&gt;Cuarta Parte&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  El Juego
&lt;/h2&gt;

&lt;p&gt;Zeek the Geek es un juego similar al &lt;a href="https://en.wikipedia.org/wiki/Sokoban" rel="noopener noreferrer"&gt;Sokoban&lt;/a&gt;. El objetivo es guiar a Zeek, un geek del otro lado de la galaxia (donde los geeks no son tan diferentes de los de la Tierra) alrededor de un nivel similar a un laberinto en busca de deliciosos hongos. En el camino puede recoger flores amarillas, cofres del tesoro y cristales mágicos.&lt;/p&gt;

&lt;p&gt;Recoger el hongo mueve a Zeek al siguiente nivel. Pero cuidado, porque también hay trampas y monstruos en cada laberinto: las flores rosadas lo devorarán si camina cerca de ellas, hongos mortales envenerará a nuestro héroe si decide meter uno en su garganta, y la dinamita, aunque útil, puede ser peligrosa en las manos equivocadas. O pies.&lt;/p&gt;

&lt;p&gt;El juego fue desarrollado originalmente por &lt;a href="http://cd.textfiles.com/hotgames/PROGRAMS/ZEEK1_10/ZEEK.TXT" rel="noopener noreferrer"&gt;Sidewalk Software&lt;/a&gt; y lanzado en 1995 para Windows&lt;/p&gt;

&lt;h1&gt;
  
  
  Motivación.
&lt;/h1&gt;

&lt;p&gt;He venido desarrollando juegos haciendo uso de ReactJS, con el objetivo de afianzar los conocimientos de está librería, así como aprender nuevos conceptos que la misma tiene.&lt;/p&gt;

&lt;p&gt;Este es el sexto juego que he desarrollado en ReactJS, otros juegos son:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Litle Professor
&lt;/h3&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%2Fgithub.com%2FJorger%2Flittle_professor_reactjs%2Fraw%2Fmaster%2Fpublic%2Fimages%2Flittle_professor_calculadora.gif%3Fraw%3Dtrue" 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%2Fgithub.com%2FJorger%2Flittle_professor_reactjs%2Fraw%2Fmaster%2Fpublic%2Fimages%2Flittle_professor_calculadora.gif%3Fraw%3Dtrue" alt="LP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Url del juego: &lt;a href="https://jorger.github.io/little_professor/" rel="noopener noreferrer"&gt;https://jorger.github.io/little_professor/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Binary fun:
&lt;/h3&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%2Fgithub.com%2FJorger%2Fbinary_fun_reactjs%2Fraw%2Fmaster%2FBinary_fun.gif%3Fraw%3Dtrue" 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%2Fgithub.com%2FJorger%2Fbinary_fun_reactjs%2Fraw%2Fmaster%2FBinary_fun.gif%3Fraw%3Dtrue" alt="BF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;URL: &lt;a href="https://github.com/Jorger/binary_fun_reactjs" rel="noopener noreferrer"&gt;https://github.com/Jorger/binary_fun_reactjs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Calculator the game
&lt;/h3&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%2Fgithub.com%2FJorger%2FCalculator_The_Game_ReactJS%2Fraw%2Fmaster%2Fimages%2Fresolve_level.gif%3Fraw%3Dtrue" 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%2Fgithub.com%2FJorger%2FCalculator_The_Game_ReactJS%2Fraw%2Fmaster%2Fimages%2Fresolve_level.gif%3Fraw%3Dtrue" alt="CG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Url del juego: &lt;a href="https://calculator-game-reactjs.now.sh/" rel="noopener noreferrer"&gt;https://calculator-game-reactjs.now.sh/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. El Parqués/parchis.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/f3f2fc69be112c9ea857f058c087fabf222eade18cc23ff86e136f5bfb7249c1/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f70726163746963616c6465762f696d6167652f66657463682f732d2d3259395073664f4e2d2d2f635f6c696d6974253243665f6175746f253243666c5f70726f6772657373697665253243715f3636253243775f3838302f68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f4a6f726765722f70617263686973692d67616d652f6d61737465722f696d616765735f7475746f7269616c2f696d675f30312e676966253346746f6b656e253344414141484b59564f41373458363345534c59453333434b364b50354157" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/f3f2fc69be112c9ea857f058c087fabf222eade18cc23ff86e136f5bfb7249c1/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f70726163746963616c6465762f696d6167652f66657463682f732d2d3259395073664f4e2d2d2f635f6c696d6974253243665f6175746f253243666c5f70726f6772657373697665253243715f3636253243775f3838302f68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f4a6f726765722f70617263686973692d67616d652f6d61737465722f696d616765735f7475746f7269616c2f696d675f30312e676966253346746f6b656e253344414141484b59564f41373458363345534c59453333434b364b50354157" alt="parchis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Url del juego: &lt;a href="https://parchisreact.herokuapp.com/" rel="noopener noreferrer"&gt;https://parchisreact.herokuapp.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Artículo relacionado: &lt;a href="https://dev.to/jorger/recreando-el-parques-parchis-en-reactjs-primera-parte-nkk"&gt;https://dev.to/jorger/recreando-el-parques-parchis-en-reactjs-primera-parte-nkk&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Mr. Square
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/60adad3fdfcbb70f2f4878f4227bb5dad4419dcf9258115b7c63fd0718dcf454/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f70726163746963616c6465762f696d6167652f66657463682f732d2d5f6d306175774d472d2d2f635f6c696d6974253243665f6175746f253243666c5f70726f6772657373697665253243715f3636253243775f3838302f68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f692f30687467756479613831383378676768616a616c2e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/60adad3fdfcbb70f2f4878f4227bb5dad4419dcf9258115b7c63fd0718dcf454/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f70726163746963616c6465762f696d6167652f66657463682f732d2d5f6d306175774d472d2d2f635f6c696d6974253243665f6175746f253243666c5f70726f6772657373697665253243715f3636253243775f3838302f68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f692f30687467756479613831383378676768616a616c2e676966" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Url del juego: &lt;a href="https://mrsquare.herokuapp.com/" rel="noopener noreferrer"&gt;https://mrsquare.herokuapp.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Artículo relacionado: &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo"&gt;https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;En este sexto juego deseaba poner en práctica lo aprendido en &lt;a href="https://mrsquare.herokuapp.com/" rel="noopener noreferrer"&gt;Mr. Square&lt;/a&gt;, puntualmente el uso de &lt;a href="https://www.react-spring.io/" rel="noopener noreferrer"&gt;react-srping&lt;/a&gt; para las acciones de movimiento, éste juego me presentaba la oportunidad de hacerlo, algo curioso es que ya había hecho una versión de este juego hace más de 13 años haciendo uso de &lt;a href="https://en.wikipedia.org/wiki/Visual_Basic" rel="noopener noreferrer"&gt;Visual Basic 6.0&lt;/a&gt; y &lt;a href="https://en.wikipedia.org/wiki/Adobe_Flash" rel="noopener noreferrer"&gt;Flash&lt;/a&gt; (usaba flash para el manejo de sprites, cada fotograma representaba la posición de movimiento de cada elemento, tiempos aquellos)&lt;/p&gt;

&lt;p&gt;Zeek en VB6/Flash&lt;/p&gt;

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

&lt;p&gt;El mismo nivel en la nueva versión web:&lt;/p&gt;

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

&lt;p&gt;Pero a diferencia de esa versión, está cuenta con la posibilidad de ser multiplataforma y multidispositivo gracias a que es web, además de contar con muchos más niveles (220) que la versión anterior que sólo contaba con 20 niveles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opciones del Juego.
&lt;/h2&gt;

&lt;p&gt;El juego cuenta con las siguientes opciones:&lt;/p&gt;

&lt;h3&gt;
  
  
  Start
&lt;/h3&gt;

&lt;p&gt;Esta opción mostrará los niveles precargados del juego, en total existen 220 niveles, cada uno con un nivel de dificultad diferente, a su vez este tiene las siguientes opciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seleccionar nivel:&lt;/strong&gt; El usuario podrá seleccionar el nivel que desee jugar, em este caso no hay dependencia de niveles&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nivel aleatorio:&lt;/strong&gt; A través de está opción se mostrará un nivel aleatorio de los 220 existentes.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cargar nivel a través de QR:&lt;/strong&gt; En está opción se podrá cargar un nivel que previamente se haya creado a través de editor.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Editor
&lt;/h3&gt;

&lt;p&gt;Permite la creación de nuevo niveles, a su vez tiene las sigientes opciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Barra de bloques:&lt;/strong&gt; Muestra todos los bloques disponibles para crear un escenario, en total existen 18 tipos de bloques que a su vez tienen diferentes tipos, por ejemplo un tipo muro, tiene a su vez 11 tipos, un tipo flor púrpura tiene dos tipos (flor abierta y cerrada), el tipo manzana tiene dos tipos (manzana normal y manzana con gusano)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Play:&lt;/strong&gt; Permite probar el nivel creado, un nivel es válido si al menos tiene a Zeek y al hongo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outline:&lt;/strong&gt; Opción que permite crear un contorno en el escenario con un bloque de tipo muro, puerta, flor amarilla y flor azul, está opción estará bloqueada a no ser que el bloque seleccionado se de los tipos anteriormente mencionados.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Leveles:&lt;/strong&gt; Muestra los niveles precargados del juego, a partir de estos niveles se pueden crear nuevos niveles (está opción, no modificará los niveles existentes)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load QR:&lt;/strong&gt; Cargará algún nivel que previamente se haya creado, al igual que la opción anterior sólo se podrá crear un nuevo nivel a partir de éste y no modificará el nivel cargado.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Share
&lt;/h3&gt;

&lt;p&gt;Permite compartir el juego en redes sociales, si el navegador no soporta la opción nativa de share, se hace uso del paquete &lt;a href="https://www.npmjs.com/package/share-api-polyfill" rel="noopener noreferrer"&gt;share-api-polyfill&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sounds
&lt;/h3&gt;

&lt;p&gt;Habilita/deshabilita los sonidos del juego.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Como lo he mencionado el juego ha sido desarrollado en &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;ReactJS&lt;/a&gt;, en este caso haciendo uso del paquete conocido &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt;, a diferencia de otros juegos como el &lt;a href="https://parchisreact.herokuapp.com/" rel="noopener noreferrer"&gt;parchís&lt;/a&gt; y &lt;a href="https://mrsquare.herokuapp.com/" rel="noopener noreferrer"&gt;Mr. Square&lt;/a&gt; éste juego no cuenta con un componente de backend&lt;/p&gt;

&lt;p&gt;Otros paquetes utilizados son:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/nuka-carousel" rel="noopener noreferrer"&gt;nuka-carousel&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Esta librería permite el uso de un carousel de forma muy fácil, en este caso fue utilizado para mostrar el listado de niveles que componen el juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/qrcode.react" rel="noopener noreferrer"&gt;qrcode.react&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Librería que permite la creación de códigos QR, está ha sido utilizada para "almacenar" los niveles creados en el editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/qrcode-decoder" rel="noopener noreferrer"&gt;qrcode-decoder&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Está librería permite leer un QR, en este caso sólo se hizo uso de la opción de leer un QR desde una imagen, aunque la librería tiene la opción de leer un QR desde la cámara.&lt;/p&gt;

&lt;p&gt;En este caso la librería se utilizó para leer el QR generado en el editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/react-keyboard-event-handler" rel="noopener noreferrer"&gt;react-keyboard-event-handler&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Permite capturar de forma sencilla los eventos del teclado, en este caso fue utilizada para capturar las teclas de movimiento para así mover al personaje en el escenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/share-api-polyfill" rel="noopener noreferrer"&gt;share-api-polyfill&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Si el navegador donde se está jugando el juego no cuenta con la opción de &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share" rel="noopener noreferrer"&gt;compartir nativa&lt;/a&gt;, se ejecutará está librería, la cual presenta la misma interfaz de la api nativa.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/sweetalert" rel="noopener noreferrer"&gt;sweetalert&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Está librería reemplaza los mensajes nativos del navegador, como &lt;code&gt;alert()&lt;/code&gt;, &lt;code&gt;prompt()&lt;/code&gt;, en este caso fue utilizada para mostrar mensajes de error o informativos en el juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/pathfinding" rel="noopener noreferrer"&gt;pathfinding&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Librería que ayuda a encontrar la ruta más corta/óptima dado dos puntos, en este caso fue utilizada para indicar el camino que puede tomar el personaje cuando el usuario se lo indica en el escenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/howler" rel="noopener noreferrer"&gt;howler&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Librería para el manejo de sonidos, una característica especial que tiene está librería es la capacidad de manejar &lt;a href="https://howlerjs.com/#sprite" rel="noopener noreferrer"&gt;"sprites de sonidos"&lt;/a&gt;, lo que permite al igual que los sprites de imágenes, descargar un sólo archivo, en vez de varios, lo cual ayuda a la carga del juego.&lt;/p&gt;




&lt;p&gt;En esta primera parte quería compartir acerca del juego original, las motivaciones, las opciones de está versión del juego que he desarrollado en ReactJS, así como el stack de tecnología utilizada.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/zeek-the-geek-en-reactjs-segunda-parte-499n"&gt;segunda parte&lt;/a&gt; veremos más acerca del juego, así como los bloques que lo componen.&lt;/p&gt;

</description>
      <category>react</category>
      <category>pwa</category>
      <category>games</category>
      <category>css3</category>
    </item>
    <item>
      <title>Mr. Square en ReactJS - Primera Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sat, 08 Aug 2020 01:02:33 +0000</pubDate>
      <link>https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo</link>
      <guid>https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo</guid>
      <description>&lt;p&gt;En este artículo deseo compartir la experiencia de desarrollo de juego llamado Mr. Square ReactJS, el juego está desarrollado haciendo uso de #ReactJS entre otras tecnologías, que iré ampliando durante el resto del artículo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enlace del juego:&lt;/strong&gt; &lt;a href="https://mrsquare.herokuapp.com/"&gt;https://mrsquare.herokuapp.com/&lt;/a&gt;&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RK3DVeK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1291798218951581698/pu/img/HgEm13BZoCCdrnr8.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaxpkXqm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1139905258551988224/0-AS5H2g_normal.jpg" alt="Jorge Rubiano profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge Rubiano
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ostjh
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Mr. Square &lt;a href="https://twitter.com/hashtag/reactjs"&gt;#reactjs&lt;/a&gt; ⚛ &lt;a href="https://t.co/XfbxT1CAvy"&gt;mrsquare.herokuapp.com&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/PWA"&gt;#PWA&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/shortcuts"&gt;#shortcuts&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/games"&gt;#games&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      18:08 PM - 07 Aug 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1291798302648926210" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1291798302648926210" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1291798302648926210" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Algunas cifras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El juego cuenta con &lt;strong&gt;245 niveles&lt;/strong&gt;, repartidos en 16 capítulos.&lt;/li&gt;
&lt;li&gt;Cuenta con 10 personajes.&lt;/li&gt;
&lt;li&gt;Esta disponibles en 8 idiomas (gracias a Google Translate, lamento algún error en ese aspecto)&lt;/li&gt;
&lt;li&gt;Cuenta con un editor para la creación de nuevos niveles (requiere autenticación a través de redes sociales)&lt;/li&gt;
&lt;li&gt;Jugabilidad a través del teclado (desktop) o a través de eventos swipe (deslizar) en desktop y en móvil.&lt;/li&gt;
&lt;li&gt;Cuenta con tema oscuro (dark mode).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;El desarrollo de este juego tomó en gran parte las experiencias adquiridas durante el desarrollo del Juego &lt;a href="https://dev.to/jorger/recreando-el-parques-parchis-en-reactjs-primera-parte-nkk"&gt;El Parchís&lt;/a&gt;, el cual igualmente fue desarrollado en ReactJS&lt;/p&gt;

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

&lt;h1&gt;
  
  
  El juego
&lt;/h1&gt;

&lt;p&gt;Mr. Square es un juego originalmente desarrollado por el estudio de desarrollo &lt;a href="https://ludicside.com/"&gt;Ludic Side&lt;/a&gt;, desde el primer momento en que lo jugué, me pareció un juego con una dinámica única la cual deseaba emular haciendo uso de ReactJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objetivo del juego.
&lt;/h2&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VnkrwYGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1286406403276578828/pu/img/5cvpM_0_EcTpfWSu.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaxpkXqm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1139905258551988224/0-AS5H2g_normal.jpg" alt="Jorge Rubiano profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge Rubiano
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ostjh
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      &lt;a href="https://twitter.com/dan_abramov"&gt;@dan_abramov&lt;/a&gt; Hi, I used react-spring &lt;a href="https://t.co/7OdnSXdHIZ"&gt;react-spring.io&lt;/a&gt;   for this game &lt;a href="https://t.co/XfbxT1CAvy"&gt;mrsquare.herokuapp.com&lt;/a&gt; and I had good results to make the animation of the character 👍 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      21:02 PM - 23 Jul 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1286406437095309313" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1286406437095309313" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1286406437095309313" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;El objetivo del juego es mover un personaje (a través de deslizar el personaje en dispositivos móviles o desktop o a través del teclado en desktop), cada vez que el/los personajes se mueven, deja un bloque por donde ha pasado (en aquellas posiciones donde sea posible, existen posiciones donde no se dejan bloques, como es el caso de los portales, las flechas y los magnetos), la idea es completar todo el escenario con dichos bloques.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_m0auwMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0htgudya8183xgghajal.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_m0auwMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0htgudya8183xgghajal.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Desarrollo del juego.
&lt;/h1&gt;

&lt;p&gt;El juego está desarrollado haciendo uso de ReactJS y de las últimas tecnologías que está librería ofrece, como es el caso de los hooks.&lt;/p&gt;

&lt;p&gt;Inicialmente cree un "styleguide" con los elementos que harían parte del juego, estos elementos (bloques) fueron creados en su mayoría en CSS, cuando no me fue posible hacerlo en css (caso de los portales y magnetos) se utilizó svgs.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/xenodochial-robinson-qt2zk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Como se puede apreciar, en este "styleguide" están todos los bloques que se usan en el juego, así como las animaciones que tendrán, como es bien sabido el uso de componentes facilita en gran medida el desarrollo de aplicaciones, y para este juego no es la excepción, cada bloque es un componente el cual recibe los props necesarios para ser renderizados, por ejemplo para indicar si será o no animados (como es el caso de las flechas), las dimensiones (ancho y alto) la posición, entre otras opciones.&lt;/p&gt;

&lt;p&gt;Inicialmente el juego lo inicie desarrollando en &lt;a href="https://codesandbox.io/"&gt;codesandbox&lt;/a&gt;, esta es una gran herramienta que ayuda a iniciar un rápido prototipado sin la necesidad de instalar nada localmente, debido a que el juego tiene un componente en backend, no me fue posible desarrollar completamente el juego en este ambiente.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tecnologías:
&lt;/h1&gt;

&lt;p&gt;El juego cuenta con dos proyectos, uno relacionado al frontend y otro para la funcionalidad del backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Front-end.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--An-VPyVL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6x13uknqie4sovgdxwqi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--An-VPyVL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6x13uknqie4sovgdxwqi.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ReactJS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://es.reactjs.org/"&gt;https://es.reactjs.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es una librería que ayuda a crear interfaces de usuario interactivas de forma sencilla. &lt;/p&gt;

&lt;p&gt;Permite diseñar vistas simples para cada estado de nuestra aplicación y React se encargará de actualizar y renderizar de manera eficiente los componentes correctos cuando los datos cambien.&lt;/p&gt;

&lt;p&gt;Para una fácil configuración del proyecto, se utilizó el paquete conocido como &lt;a href="https://create-react-app.dev/"&gt;Create React APP&lt;/a&gt; o CRA, este paquete entrega muchos beneficios, como por ejemplo configurar por nosotros &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;, además de dar soporte a &lt;a href="https://developers.google.com/web/fundamentals/primers/service-workers"&gt;service workers&lt;/a&gt; a través de &lt;a href="https://developers.google.com/web/tools/workbox"&gt;workbox&lt;/a&gt; permitiendo que el juego sea una &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps"&gt;PWA&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;react-spring&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.react-spring.io/"&gt;https://www.react-spring.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es una librería de animación basada la física denominada &lt;a href="https://en.wikipedia.org/wiki/Spring_(device)#:~:text=In%20classical%20physics%2C%20a%20spring,atoms%20of%20an%20elastic%20material"&gt;spring-physic&lt;/a&gt; que cubre la mayoría de las necesidades de animación relacionadas con la interfaz de usuario. &lt;/p&gt;

&lt;p&gt;Esta librería brinda herramientas lo suficientemente flexibles para realizar animaciones complejas.&lt;/p&gt;

&lt;p&gt;En el caso del juego esta librería fue usada para manejar la animación de movimiento del/los personajes en el escenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;reach/router&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://reach.tech/router/"&gt;https://reach.tech/router/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esta librería permite un fácil manejo de las diferentes pantallas que componente el juego, ya había tenido una experiencia de usarla en el juego del parchís, por lo que su inclusión para este juego fue relativamente fácil.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;nuka-carousel&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/FormidableLabs/nuka-carousel"&gt;https://github.com/FormidableLabs/nuka-carousel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paquete para el manejo de un carousel, esta librería fue ampliamente utilizada en todo el juego, en secciones como: &lt;em&gt;Listado de capítulos&lt;/em&gt;, &lt;em&gt;listado de niveles&lt;/em&gt; y en &lt;em&gt;listado de personajes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;nuka-carousel, entrega una fácil configuración y permite ser extendido en sus estilos de forma sencilla.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;react-swipeable&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-swipeable"&gt;https://www.npmjs.com/package/react-swipeable&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paquete que entrega la funcionalidad para establecer eventos de tipo swipe de forma sencilla a través del uso de hooks.&lt;/p&gt;

&lt;p&gt;Este paquete fue utilizado para establecer los eventos de movimiento del personaje, tanto para dispositivos móviles, así como para desktop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back-end.
&lt;/h2&gt;

&lt;p&gt;El componente del servidor fue ampliamente reutilizado del proyecto del parchís (pero sin la capa de websockets), en este caso se hace uso de la misma lógica utilizada para la autenticación de usuarios a través de redes sociales.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wCfcxhED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ubolz8uhuglvtfvptdnb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wCfcxhED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ubolz8uhuglvtfvptdnb.gif" alt="Alt Text" width="690" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;También es posible almacenar los niveles creados por lo usuarios, lo cual amplía la cantidad de niveles existentes en el juego.&lt;/p&gt;

&lt;p&gt;En el backend se hace uso de NodeJS y de las siguientes paquetes:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ExpressJS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://expressjs.com/"&gt;https://expressjs.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paquete que permite manejar las rutas a nivel de backend, en este caso son las rutas relacionadas al API del juego, como la autenticación, obtención de niveles y creación de los mismos, además de servir los assets del juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;PassportJS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://www.passportjs.org/"&gt;http://www.passportjs.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paquete que permite realizar la autenticación con redes sociales, este paquete permite serializar la respuesta de cada uno de los servicios, a través de un API unificada, lo que facilita manejar múltiples tipos de autenticación a través de las denominadas "estrategias" que posee.&lt;/p&gt;

&lt;p&gt;Para el caso puntual del juego se utilizaron tres estrategias como son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.passportjs.org/packages/passport-twitter/"&gt;passport-twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.passportjs.org/packages/passport-github2/"&gt;passport-github2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.passportjs.org/packages/passport-google-oauth2/"&gt;passport-google-oauth2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Redis&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://redis.io/"&gt;https://redis.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En este caso se hizo uso de redis para el almacenamiento de sesión de usuarios, cuando se realiza la autenticación, esto previene que la sesión de usuario caduque.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;MySql&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Como persistencia de datos se optó el uso de una base de datos relacional como es el caso de Mysql.&lt;/p&gt;

&lt;p&gt;La base de datos es relativamente pequeña, ya que cuenta con 4 tablas como es:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;usuarios&lt;/li&gt;
&lt;li&gt;Listado de redes sociales&lt;/li&gt;
&lt;li&gt;Listado de likes por usuarios&lt;/li&gt;
&lt;li&gt;Listado de niveles creados por los usuarios.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Continuará...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;En la &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-segunda-parte-53kn"&gt;segunda parte&lt;/a&gt; de este artículo hablaré de los retos de desarrollo del juego.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En la &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-tercera-parte-8c"&gt;tercera parte&lt;/a&gt; de este artículo compartiré algunas de las funcionalidades que tiene el juego.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>html</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>Mr. Square en ReactJS - Segunda Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sat, 08 Aug 2020 01:00:38 +0000</pubDate>
      <link>https://dev.to/jorger/mr-square-en-reactjs-segunda-parte-53kn</link>
      <guid>https://dev.to/jorger/mr-square-en-reactjs-segunda-parte-53kn</guid>
      <description>&lt;p&gt;En la &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo"&gt;primera parte&lt;/a&gt; del artículo, se habló acerca del juego Mr. Square, las reglas que lo rigen, así como las tecnologías que se utilizaron para su desarrollo.&lt;/p&gt;

&lt;p&gt;En esta segunda parte hablaré de los retos de desarrollo del juego.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enlace del juego:&lt;/strong&gt; &lt;a href="https://mrsquare.herokuapp.com/"&gt;https://mrsquare.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Movimiento del personaje.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tLXWQZy7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e4pvwbxlggwfk3xurd3r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tLXWQZy7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e4pvwbxlggwfk3xurd3r.gif" alt="Alt Text" width="656" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este fue uno de los temas más complejos para manejar en el juego, uno de los primeros acercamientos que hizo fue intentar mover el personaje a través de css, pero en este caso es necesario tener un evento que indique cuando la animación ha finalizado, y esto se debía hacer cada vez que el personaje completaba una celda, es por ello que que se hizo uso del paquete &lt;a href="https://www.react-spring.io/"&gt;react-spring&lt;/a&gt;, el cual otorga el hook conocido como &lt;a href="https://www.react-spring.io/docs/hooks/use-spring"&gt;useSpring&lt;/a&gt; dando la capacidad de establecer la posición del elemento, además tiene un evento llamado &lt;a href="https://www.react-spring.io/docs/hooks/api"&gt;onRest&lt;/a&gt;, este evento se "dispara" cada vez que la animación ha finalizado, es en este punto donde se realizan las evaluaciones del personaje.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Validación movimiento del personaje contra otro personaje
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tTO6UslZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aqfuvnnr7fzudpygl85z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tTO6UslZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aqfuvnnr7fzudpygl85z.gif" alt="Alt Text" width="390" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cada vez que el personaje se ha movido una celda, debe evaluar su entorno, además de evaluar la celda donde se encuentra.&lt;/p&gt;

&lt;p&gt;Cada vez que el personaje inicia un movimiento debe validar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choca por que ha llegado al límite del escenario.&lt;/li&gt;
&lt;li&gt;Choca por que existe un bloque.&lt;/li&gt;
&lt;li&gt;Choca por que existe un bloque que ha dejado.&lt;/li&gt;
&lt;li&gt;Choca contra otra personaje&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Los tres primeros tipos de choque, no representa mucha dificultad ya que se puede validar el siguiente movimiento antes de que el personaje lo haga.&lt;/p&gt;

&lt;p&gt;No sucede lo mismo cuando existen dos personajes en el escenario, ya que son elementos que están en movimiento, por lo cual cada uno de los personajes debe estar "consciente" de la posición del otro, cuando dos personajes van en sentido contrario, cada uno evalúa en qué posición estará el otro&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Vy_5qkZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/snfj961z319f5gxmodmh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Vy_5qkZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/snfj961z319f5gxmodmh.gif" alt="Alt Text" width="388" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En este caso se aplicó la siguiente regla:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si os personajes se encuentran de forma horizontal, se dará prioridad al personaje que esté a la izquierda.&lt;/li&gt;
&lt;li&gt;Del mismo modo si se encuentran de forma vertical, se le da prioridad al personaje que se encuentra arriba.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con estas reglas se evitó que los personajes quedarán uno sobre otro, lo cual sucedió en muchas ocasiones en el tiempo del desarrollo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lyxQ6WeC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u7e6cgbys9fozmgp91ex.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lyxQ6WeC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u7e6cgbys9fozmgp91ex.gif" alt="Alt Text" width="388" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Otro caso es cuando dos personajes llevan la misma dirección, ya que se debe evaluar si el personaje que está al frente ha dejado un bloque, si es así deberá chocar, pero si la posición donde estaba un personaje no deja bloque, deberá permitirle moverse de forma normal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validación del entorno del personaje.
&lt;/h3&gt;

&lt;p&gt;El juego cuenta con diferentes tipos de bloques, los cuales cambian el comportamiento del personaje, como son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portales&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XSIWp4uD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5de0d8irwp0a6ifvuj9d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XSIWp4uD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5de0d8irwp0a6ifvuj9d.gif" alt="Alt Text" width="390" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Permite que el personaje se "teletransporte" de un punto a otro, cuando el personaje entra a un portal será enviado al portal de salida, si en esa posición ya hay otro personaje, no se podrá "teletransportar", cuando un personaje deja un portal, no dejará bloque, permitiendo que sea reutilizado.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flechas&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N-pcbGYj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/twr2ufy4s7a7jtt0f6ku.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N-pcbGYj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/twr2ufy4s7a7jtt0f6ku.gif" alt="Alt Text" width="390" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando un personaje se encuentra sobre una flecha, la dirección del personaje es igual al de la flecha sobre la cual está ubicado, es por que ello que cuando un personaje termina cada celda, requiere saber sobre qué tipo de celda se encuentra, en el caso de las flechas no sólo conocer qué es una flecha, sino que además saber la dirección que tiene, cuando un personaje deja una celda de tipo flecha, no dejará bloque alguno.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Puentes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IEchYOTx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dwf7amer1mu8h37jp2mp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IEchYOTx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dwf7amer1mu8h37jp2mp.gif" alt="Alt Text" width="388" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este tipo de bloques, sólo permite que el personaje vaya en una sola dirección, cuando un personaje detecta que al frente de él hay un puente debe evaluar si tiene la misma dirección que lleva el personaje, igualmente si está encima de un puente sólo podrá moverse en la dirección que el puente tiene, cuando un personaje deja este tipo de celda deja un bloque, por lo que no se podrá pasar dos veces por el mismo puente.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Magnetos&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2iTgf804--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/junuoneoh8xn3ks579dc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2iTgf804--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/junuoneoh8xn3ks579dc.gif" alt="Alt Text" width="390" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando un personaje pasa cerca de un magneto, el personaje se verá "atraído" al magneto, haciendo que el personaje se detenga, desde el editor está validado que no pueden existir magnetos cercanos al personaje y a otros magnetos, cuando un personaje deja un magento no dejará bloque, por lo que es posible pasar por un magneto más de una vez.&lt;/p&gt;




&lt;h1&gt;
  
  
  Personajes.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vzj_pcBU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ojvu54i88h3rfacvrf26.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vzj_pcBU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ojvu54i88h3rfacvrf26.gif" alt="Alt Text" width="380" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para darle variedad al juego, éste cuenta con 10 personajes, cada uno con su propia "personalidad" y color, esto permite que cada vez que se seleccione un personaje, el color de los bloques que dejará en el escenario serán iguales al color que representa el personaje.&lt;/p&gt;

&lt;p&gt;Cada personaje se basa en el mismo bloque, pero a través de envío de &lt;code&gt;props&lt;/code&gt;, de define que tipo de personaje será y se aplicará los accesorios que tendrá cada uno, estos "accesorios" son en su mayoría SVGs.&lt;/p&gt;




&lt;h1&gt;
  
  
  Internacionalización (i11n)
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5FBfkt0W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x69g36fy6b8lau2i1bmj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5FBfkt0W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x69g36fy6b8lau2i1bmj.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El juego cuenta con 8 idiomas, en este caso no se utilizó alguna librería y/o paquete para realizar está acción, debido a que el juego no cuenta con demasiadas pantallas, en este caso se creo un archivo (json) que contiene cada uno de los textos que se usan en el juego y dependiendo del idioma que esté seleccionado se seleccionará los textos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Se hizo uso de Google translate para realizar la traducción, algunos de los textos pueden no ser los adecuados, si llegase a ser el caso en este &lt;a href="https://github.com/Jorger/mr-square-game-report-bugs/issues/new"&gt;link&lt;/a&gt; es posible documentar el issue&lt;/em&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Workshop (Taller).
&lt;/h1&gt;

&lt;p&gt;Es la única sección del juego que requiere autenticación y conexión a internet ya que las opciones requieren comunicación con el servidor, desde guardar/eliminar un nivel, hasta jugar el nivel de otros usuarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crear niveles.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nk7SyiEP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ofq2x6yb0bsddaj9tt9b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nk7SyiEP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ofq2x6yb0bsddaj9tt9b.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El juego cuenta con 245 niveles ya precargados, los cuales se pueden jugar con o sin conexión, pero existe la posibilidad de crear nuevos niveles, esto a través del editor integrado con el que cuenta el juego, esto permite que los usuarios puedan crear sus niveles y compartirlos con los demás usuarios.&lt;/p&gt;

&lt;p&gt;Un ejemplo de cómo se ve una url de un nivel compartido es: &lt;br&gt;
&lt;a href="https://mrsquare.herokuapp.com/level/11852"&gt;https://mrsquare.herokuapp.com/level/11852&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Top 10
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jEVxp8mG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dlnnb2gn7gfzqtb8nvoy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jEVxp8mG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dlnnb2gn7gfzqtb8nvoy.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es posible que los usuarios califiquen un nivel, a través de botones me gusta/no me gusta, con este valor en la sección de Top 10 se entregan los niveles mejores calificados entre los niveles que han creado los usuarios.&lt;/p&gt;

&lt;p&gt;Es una lista que va variando dependiendo de lo que los usuarios califican, cada vez que el usuario ingresa a esta sección se realiza una query la cual entrega está información.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nivel aleatorio
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dYjK0R6Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1bgd1kcal9ejt1cjuis0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dYjK0R6Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1bgd1kcal9ejt1cjuis0.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como su no nombre lo indica cada vez que el usuario selecciona está opción se le entrega un nivel aleatorio entre los niveles creados por lo usuarios, esto posibilita que aquellos niveles que no aparezcan por ejemplo en el Top 10, puedan ser jugados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buscar nivel.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---55-bLZF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8oauj1hxalbe12e11fn9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---55-bLZF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8oauj1hxalbe12e11fn9.gif" alt="Alt Text" width="382" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Opción que permite jugar un nivel determinado, el usuario deberá ingresar el código del mismo, esto es útil cuando se desea que un nivel que se ha creado pueda ser jugado directamente por otros usuarios y no depender que el nivel salga en la sección de niveles aleatorios.&lt;/p&gt;




&lt;p&gt;En la &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-tercera-parte-8c"&gt;tercera parte&lt;/a&gt; de este artículo compartiré algunas de las funcionalidades que tiene el juego.&lt;/p&gt;

</description>
      <category>react</category>
      <category>html</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>Mr. Square en ReactJS - Tercera Parte</title>
      <dc:creator>Jorge Rubiano</dc:creator>
      <pubDate>Sat, 08 Aug 2020 00:58:16 +0000</pubDate>
      <link>https://dev.to/jorger/mr-square-en-reactjs-tercera-parte-8c</link>
      <guid>https://dev.to/jorger/mr-square-en-reactjs-tercera-parte-8c</guid>
      <description>&lt;p&gt;En la &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-primera-parte-49eo"&gt;primera parte&lt;/a&gt; de esta serie de artículos se habló acerca del juego Mr. Square, las reglas que lo rigen, así como las tecnologías que se utilizaron para su desarrollo.&lt;/p&gt;

&lt;p&gt;En la &lt;a href="https://dev.to/jorger/mr-square-en-reactjs-segunda-parte-53kn"&gt;segunda parte&lt;/a&gt; de compartí algunos de los retos de desarrollo de este juego.&lt;/p&gt;

&lt;p&gt;En esta tercera y última parte compartiré algunas de las funcionalidades que tiene el juego.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enlace del juego:&lt;/strong&gt; &lt;a href="https://mrsquare.herokuapp.com/"&gt;https://mrsquare.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Jugabilidad offline:
&lt;/h1&gt;

&lt;p&gt;Gracias al uso de &lt;a href="https://developers.google.com/web/tools/workbox"&gt;workbox&lt;/a&gt; que viene incluido en &lt;a href="https://create-react-app.dev/"&gt;CRA&lt;/a&gt; el juego es posible jugarlo sin conexión a internet, con excepción de workshop, ya que los assets del juego son almacenados a nivel local, esto también ayuda a que la carga del juego sea rápida, debido a que no tiene que hacer la descarga de los assets cada vez que se ingresa al juego.&lt;/p&gt;

&lt;h1&gt;
  
  
  Instalación del juego.
&lt;/h1&gt;

&lt;p&gt;Gracias a que el juego es una &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps"&gt;PWA&lt;/a&gt; el juego es posible ser "instalado", lo cual permite que el usuario pueda acceder a este directamente desde su pantalla, como si de una aplicación nativa se tratase.&lt;/p&gt;

&lt;p&gt;En el caso de Android, Windows y MacOs, la "instalación" del juego es posible hacerla a través de navegadores basados en Chromium/webkit, como es el caso por ejemplo de Chrome y Edge.&lt;/p&gt;

&lt;p&gt;En el caso de iOS, safari otorga la opción de "instalación" también, pero no soporta el denominado &lt;a href="https://web.dev/add-manifest/"&gt;manifest.json&lt;/a&gt; el cual permite indicar el comportamiento que tendrá el juego una vez haya sido "instalado"&lt;/p&gt;

&lt;h1&gt;
  
  
  Compartir.
&lt;/h1&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B5JEdodv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1291892183247859712/pu/img/GWoDR0UlxnNzwNho.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaxpkXqm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1139905258551988224/0-AS5H2g_normal.jpg" alt="Jorge Rubiano profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge Rubiano
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ostjh
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Mr. Square &lt;a href="https://twitter.com/hashtag/reactjs"&gt;#reactjs&lt;/a&gt; share level &lt;a href="https://t.co/XfbxT1CAvy"&gt;mrsquare.herokuapp.com&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      00:21 AM - 08 Aug 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1291892231570370562" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1291892231570370562" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1291892231570370562" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Esta es una funcionalidad que permite en navegadores que la soporta mostrar la función de &lt;a href="https://web.dev/web-share/"&gt;share nativa&lt;/a&gt;, esto otorgar una gran flexibilidad ya que el usuario podrá compartir sin la necesidad de acudir a otro servicio y utilizará la misma funcionalidad que utiliza en aplicaciones nativas.&lt;/p&gt;

&lt;p&gt;En el caso que el navegador no soporte está acción, se redirigirá a Twitter directamente (no se desarrolló un fallback que permita otras redes sociales)&lt;/p&gt;

&lt;h1&gt;
  
  
  Shortcuts.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://web.dev/app-shortcuts/"&gt;Shortcuts&lt;/a&gt; como su nombre lo indica permite establecer acceso directos a opciones de la aplicación, en este caso a opciones del juego.&lt;/p&gt;

&lt;p&gt;Al momento de escribir este artículo Shortcuts está disponible en Android a través de Google Chrome (o navegadores basados en Chromium).&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YX-jru3B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1285993362944909313/pu/img/FI7Pg81BE8E8LuCg.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaxpkXqm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1139905258551988224/0-AS5H2g_normal.jpg" alt="Jorge Rubiano profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge Rubiano
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ostjh
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Mr. Square ReactJS uses new features like &lt;a href="https://twitter.com/hashtag/shortcuts"&gt;#shortcuts&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/pwa"&gt;#pwa&lt;/a&gt; &lt;a href="https://t.co/XfbxT1CAvy"&gt;mrsquare.herokuapp.com&lt;/a&gt; &lt;a href="https://twitter.com/jungkees"&gt;@jungkees&lt;/a&gt; &lt;a href="https://twitter.com/slightlylate"&gt;@slightlylate&lt;/a&gt; 😀 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      17:44 PM - 22 Jul 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1285994088802680833" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1285994088802680833" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1285994088802680833" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Igualmente en Windows.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R57TMNH---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1289279444687949827/pu/img/t1vpNOrTp4QRnG2y.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--EaxpkXqm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1139905258551988224/0-AS5H2g_normal.jpg" alt="Jorge Rubiano profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge Rubiano
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @ostjh
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      &lt;a href="https://twitter.com/hashtag/shortcuts"&gt;#shortcuts&lt;/a&gt; on windows &lt;a href="https://twitter.com/hashtag/pwa"&gt;#pwa&lt;/a&gt; -&amp;gt; Mr. Square &lt;a href="https://twitter.com/hashtag/reactjs"&gt;#reactjs&lt;/a&gt; ⚛️&lt;a href="https://t.co/XfbxT1kZ6Y"&gt;mrsquare.herokuapp.com&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      19:21 PM - 31 Jul 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1289280011724152832" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1289280011724152832" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1289280011724152832" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;En el momento macOS no soporta esta funcionalidad y en iOS como se comentó anteriormente no es soportado el &lt;a href="https://web.dev/add-manifest/"&gt;manifest.json&lt;/a&gt; que es donde se establece esta opción (como es bien sabido en iOS el único navegador que es permitido es safari, incluso navegadores como Chrome en iOS están basado en safari)&lt;/p&gt;




&lt;p&gt;Gracias por llegar a esta parte del artículo, en este intenté recopilar todo acerca del proyecto, ha sido un proyecto que busca aprender más sobre React y el ecosistema que éste tiene, así como aprovechar las nuevas funcionalidades que los navegadores nos entrega&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusiones.
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;El desarrollo de este juego fue muy desafiante, no sólo por la parte gráfica, sino por las validaciones necesarias para el personaje.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El desarrollo de este juego no es exclusivo para ReactJS, otras librerías o frameworks podrían ser utilizadas, incluso librerías especializadas en el desarrollo de juegos, por ejemplo &lt;a href="https://phaser.io/"&gt;PhaserJS&lt;/a&gt;, en este caso no se hizo uso de &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;canvas&lt;/a&gt;, que en muchos casos es la mejor opción para el desarrollo de juegos de este tipo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Esta experiencia de desarrollo de este juego, ha ayudado a tener un mejor conocimiento de ReactJS, las fortalezas que esta librería nos ofrece, en este caso para el desarrollo de un juego.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El desarrollo basado en componentes, ayuda en gran medida a una rápido desarrollo, en el caso de este juego se pudo evidenciar, una vez creados los componentes base, se facilitó la creación de los demás elementos que compone el juego.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aprender una librería y/o tecnología a través de juegos presenta una gran oportunidad, ya que nos encontramos con casos que tal vez no veamos en otros tipos de proyectos.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>react</category>
      <category>html</category>
      <category>javascript</category>
      <category>css</category>
    </item>
  </channel>
</rss>
