<?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: Martin Grignard</title>
    <description>The latest articles on DEV Community by Martin Grignard (@martingrignard).</description>
    <link>https://dev.to/martingrignard</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%2F775500%2Fce577f7c-21cc-4e5b-a84c-11db60f01203.png</url>
      <title>DEV Community: Martin Grignard</title>
      <link>https://dev.to/martingrignard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/martingrignard"/>
    <language>en</language>
    <item>
      <title>My game dev journey begins: Flappy Bee 🐝</title>
      <dc:creator>Martin Grignard</dc:creator>
      <pubDate>Thu, 28 Aug 2025 19:26:40 +0000</pubDate>
      <link>https://dev.to/martingrignard/my-game-dev-journey-begins-flappy-bee-53c1</link>
      <guid>https://dev.to/martingrignard/my-game-dev-journey-begins-flappy-bee-53c1</guid>
      <description>&lt;p&gt;On a quest to learn about game development with the &lt;a href="https://godotengine.org" rel="noopener noreferrer"&gt;Godot Engine&lt;/a&gt;, I recently took on the &lt;a href="https://20_games_challenge.gitlab.io" rel="noopener noreferrer"&gt;20 Games Challenge&lt;/a&gt;. This whole challenge revolves around the idea that finishing a series of small scoped projects of increasing complexity is better than not finishing a Dream Game™.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Done is better than perfect."&lt;/em&gt;&lt;br&gt;
&lt;small&gt;- Sheryl Sandberg&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this article, I present how I finished my first game ever&lt;sup id="footnote-1-return"&gt;1&lt;/sup&gt; while respecting the following constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://20_games_challenge.gitlab.io/how/#2-constrain-yourself" rel="noopener noreferrer"&gt;&lt;em&gt;"20 hours [...] as a starting time limit"&lt;/em&gt;&lt;/a&gt;: This one is pretty self-explanatory.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://20_games_challenge.gitlab.io/how/#1-no-tutorials-are-allowed" rel="noopener noreferrer"&gt;&lt;em&gt;"No tutorials allowed"&lt;/em&gt;&lt;/a&gt;: I extended this one to &lt;em&gt;"No LLM allowed"&lt;/em&gt;. My goal here is to learn, not to copy-paste some code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" rel="noopener noreferrer"&gt;&lt;em&gt;"Push it as far as possible"&lt;/em&gt;&lt;/a&gt;: This is a self-inflicted one. The 20 Games Challenge provides a set of stretch goals for each game to push the scope and the difficulty further up a bit. I want to reach them while remaining under the time limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A matter of choice
&lt;/h2&gt;

&lt;p&gt;For the ten first games, the challenge provides a selection of good candidates from which one can choose. The first two being &lt;a href="https://en.wikipedia.org/wiki/Pong" rel="noopener noreferrer"&gt;Pong&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Flappy_Bird" rel="noopener noreferrer"&gt;Flappy Bird&lt;/a&gt;. I have always loved the story behind the latter: A game so addictive that its creator felt guilty enough to shut it down and remove it from the app stores, despite the massive ad revenues generated.&lt;/p&gt;

&lt;p&gt;So... Flappy Bird it is!&lt;/p&gt;

&lt;h2&gt;
  
  
  A bee's first flight
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://kenney.nl" rel="noopener noreferrer"&gt;Kenney's assets&lt;/a&gt;, I quickly got all the assets needed to achieve this first game. After reading parts of the wonderful &lt;a href="https://docs.godotengine.org/en/stable" rel="noopener noreferrer"&gt;Godot documentation&lt;/a&gt;, I had a working version of &lt;em&gt;Flappy Bee&lt;/em&gt; that met all &lt;a href="https://20_games_challenge.gitlab.io/games/flappy" rel="noopener noreferrer"&gt;the requirements&lt;/a&gt; but one: the game-over screen. I chose not to include it since I find the game more addictive when there is no real break in the gameplay.&lt;/p&gt;

&lt;p&gt;In the following sections, I will discuss how I implemented some of the mechanics of the game. If you cannot wait to try it, feel free to skip to the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  A story of physical attraction
&lt;/h3&gt;

&lt;p&gt;The Godot engine comes with a series of &lt;a href="https://docs.godotengine.org/en/stable/tutorials/physics/physics_introduction.html" rel="noopener noreferrer"&gt;2D physics related components&lt;/a&gt;. In &lt;em&gt;Flappy Bee&lt;/em&gt;, I used four of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_staticbody2d.html" rel="noopener noreferrer"&gt;&lt;code&gt;StaticBody2D&lt;/code&gt;&lt;/a&gt;: The world borders, used to detect when the bee is leaving the screen and when obstacles are out of bound, are nothing but static colliders. Hence, this component, coupled with a &lt;a href="https://docs.godotengine.org/en/stable/classes/class_collisionshape2d.html" rel="noopener noreferrer"&gt;&lt;code&gt;CollisionShape2D&lt;/code&gt;&lt;/a&gt; setup with a &lt;a href="https://docs.godotengine.org/en/stable/classes/class_worldboundaryshape2d.html" rel="noopener noreferrer"&gt;&lt;code&gt;WorldBoundaryShape2D&lt;/code&gt;&lt;/a&gt; was exactly what I needed to model them.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_characterbody2d.html" rel="noopener noreferrer"&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt;&lt;/a&gt;: Well... What component would better fit the bee than this one? (Really though, if you think there is a better option, let me know in the comments)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_animatablebody2d.html" rel="noopener noreferrer"&gt;&lt;code&gt;AnimatableBody2D&lt;/code&gt;&lt;/a&gt;: Since they are &lt;em&gt;"useful for moving platforms, doors, and other moving objects"&lt;/em&gt;, they were perfect for the obstacles which are just horizontally moving platforms.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_area2d.html" rel="noopener noreferrer"&gt;&lt;code&gt;Area2D&lt;/code&gt;&lt;/a&gt;: To increment the score whenever the bee passes through a hole between two obstacles, I needed a way to detect a collision between the bee and something that would not push on the bee when colliding with it. This component did just that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A path strewn with obstacles
&lt;/h3&gt;

&lt;p&gt;The most interesting part of this first challenge was to implement the obstacles and their spawning mechanism. To make the level infinite, I needed an easy way to instantiate new obstacles with randomly placed and sized along the Y-axis.&lt;/p&gt;

&lt;p&gt;Therefore, I made great use of the &lt;code&gt;@tool&lt;/code&gt; and &lt;code&gt;@export&lt;/code&gt; decorators and built a parametric &lt;code&gt;ObstaclePair&lt;/code&gt; scene.&lt;/p&gt;

&lt;p&gt;Then, I used it in an &lt;code&gt;Obstacles&lt;/code&gt; scene that is responsible for the difficulty management using both a &lt;code&gt;hole_size&lt;/code&gt; and &lt;code&gt;spread&lt;/code&gt; variables. While the &lt;code&gt;hole_size&lt;/code&gt; is easy to comprehend, the spread is used to constraint where a hole on the next obstacle can be located based on the current one. The greater the &lt;code&gt;spread&lt;/code&gt; value, the further the next hole can be on the Y-axis.&lt;/p&gt;

&lt;h3&gt;
  
  
  A waggle dance
&lt;/h3&gt;

&lt;p&gt;Just like honey bees communicate together using a &lt;a href="https://en.wikipedia.org/wiki/Waggle_dance" rel="noopener noreferrer"&gt;waggle dance&lt;/a&gt;, nodes in Godot communicate with &lt;a href="https://docs.godotengine.org/en/4.4/getting_started/step_by_step/signals.html" rel="noopener noreferrer"&gt;signals&lt;/a&gt;. While this construct is very powerful and allows for event driven logic, connecting nodes located far apart in the scene tree can be tedious and fragile if done wrong.&lt;/p&gt;

&lt;p&gt;To prevent adding hard coded, exported node paths or signal forwarding logic on multiple components of the game just to connect a few signals (&lt;em&gt;e.g.&lt;/em&gt; when the bee passes through a hole), I defined an event bus using a &lt;a href="https://gameprogrammingpatterns.com/singleton.html" rel="noopener noreferrer"&gt;singleton&lt;/a&gt;, or, as they are called in Godot, an &lt;a href="https://docs.godotengine.org/en/4.4/tutorials/scripting/singletons_autoload.html" rel="noopener noreferrer"&gt;autoload&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While I know that the singleton pattern is often referred to as an anti-pattern, it proved to be very useful in that setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;After assembling all these scenes into one, adding a few UI components and connecting them all together using the event bus, &lt;em&gt;Flappy Bee&lt;/em&gt; was complete, ready to be played!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fy3bphgb0uwjmwkcx84qi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fy3bphgb0uwjmwkcx84qi.png" alt="A screenshot of Flappy Bee showing a little bee going through a series of obstacles."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://martingrignard.itch.io/flappy-bee" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Try Flappy Bee 🐝 on Itch.io&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;For the most curious out there, the sources for the game are available &lt;a href="https://github.com/MartinGrignard/flappy-bee" rel="noopener noreferrer"&gt;on Github&lt;/a&gt;. Feel free to give feedbacks here in the comments and to report any bug you encounter using an issue.&lt;/p&gt;




&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;span id="footnote-1"&gt;&lt;/span&gt;
More than a decade ago, I tried to learn game development with &lt;a href="https://unity.com" rel="noopener noreferrer"&gt;Unity&lt;/a&gt; (It was all the fuss at that time) and started several projects, but never ever did I finish one. At that time, all I did was follow some tutorials and glue things together with horrendous spaghetti code. Then, I took on an engineering degree and left my game dev dreams behind for a while.
↩
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>gamedev</category>
      <category>godot</category>
      <category>challenge</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
