diff options
Diffstat (limited to 'live/blog/g')
-rw-r--r-- | live/blog/g/flappybird_godot_devlog_3.html | 292 | ||||
-rw-r--r-- | live/blog/g/godot_layers_and_masks_notes.html | 6 |
2 files changed, 298 insertions, 0 deletions
diff --git a/live/blog/g/flappybird_godot_devlog_3.html b/live/blog/g/flappybird_godot_devlog_3.html new file mode 100644 index 0000000..953eee4 --- /dev/null +++ b/live/blog/g/flappybird_godot_devlog_3.html @@ -0,0 +1,292 @@ +<!DOCTYPE html> +<html class="theme-dark" lang="en +" + prefix="og: https://ogp.me/ns#"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="icon" href="https://static.luevano.xyz/images/icons/favicon.ico"> +<title>Final improvements to the FlappyBird clone and Android support devlog 3 -- Luévano's Blog</title> + <meta name="description" content="Notes on the final improvements to my FlappyBird clone made in Godot 4.x. Also details on the support for Android."/> +<link rel="alternate" type="application/rss+xml" href="https://blog.luevano.xyz/rss.xml" title="Luévano's Blog RSS"> + <!-- general style --> + <link rel="stylesheet" type="text/css" href="https://static.luevano.xyz/css/style.css"> + <link rel="stylesheet" type="text/css" href="https://static.luevano.xyz/fork-awesome/css/fork-awesome.min.css"> + <link rel="stylesheet" type="text/css" href="https://static.luevano.xyz/font-awesome/css/all.min.css"> + <!-- theme related --> + <script type="text/javascript" src="https://static.luevano.xyz/scripts/theme.js"></script> + <link id="theme-css" rel="stylesheet" type="text/css" href="https://static.luevano.xyz/css/theme.css"> + <!-- misc functions--> + <script type="text/javascript" src="https://static.luevano.xyz/scripts/return_top.js"></script> + <!-- extra --> + + + <!-- highlight support for code blocks --> +<script type="text/javascript" src="https://static.luevano.xyz/hl/highlight.min.js"></script> +<script type="text/javascript"> + hljs.initHighlightingOnLoad(); +</script> +<link id="code-theme-css" rel="stylesheet" type="text/css" href="https://static.luevano.xyz/hl/styles/nord.min.css"> + + + <!-- Specific to GDScript --> + <script type="text/javascript" src="https://static.luevano.xyz/hl/languages/gdscript.min.js"></script> + + <!-- og meta --> + <meta property="og:title" content="Final improvements to the FlappyBird clone and Android support devlog 3 -- Luévano's Blog"/> + <meta property="og:type" content="article"/> + <meta property="og:url" content="https://blog.luevano.xyz/g/flappybird_godot_devlog_3.md"/> + <meta property="og:image" content="https://static.luevano.xyz/images/b/default.png"/> + <meta property="og:description" content="Notes on the final improvements to my FlappyBird clone made in Godot 4.x. Also details on the support for Android."/> + <meta property="og:locale" content="en"/> + <meta property="og:site_name" content="Luévano's Blog"/> + </head> + + <body> + <header> +<nav> + <ul> + <li> + <a href="https://luevano.xyz/"><i class="fas fa-home" alt="Home"></i><span>Home</span></a> + </li> + + <li> + <a href="https://blog.luevano.xyz/"><i class="fas fa-book-open" alt="Blog"></i><span>Blog</span></a> + </li> + + <li> + <a href="https://art.luevano.xyz/"><i class="fas fa-paint-brush" alt="Art"></i><span>Art</span></a> + </li> + + <li><i class="fab fa-git" alt="Git"></i><span>Git</span> + <ul> + <li><a href="https://git.luevano.xyz/" target="_blank"><i class="fab fa-git-alt" alt="Git-alt"></i></a></li> + + <li><a href="https://github.com/luevano" target="_blank"><i class="fab fa-github" alt="Github"></i></a></li> + + <li><a href="https://gitlab.com/dluevano" target="_blank"><i class="fab fa-gitlab" alt="Gitlab"></i></a></li> + </ul> + </li> + + <li><i class="fas fa-box-open" alt="Stuff"></i><span>Stuff</span> + <ul> + <li><a href="https://gb.luevano.xyz/"><i class="fas fa-gamepad" alt="Gameboy"></i><span>Gameboy</span></a></li> + </ul> + </li> + </ul> +</nav> + +<button class="theme-switcher" onclick="toggleTheme()"><i class="fas fa-moon"></i><i class="fas fa-sun"></i></button> + + </header> + + <main> + <div class="return-top"> + <button class="return-top" onclick="returnTop()" id="returnTopButton"> + <i class="fas fa-arrow-up" alt="Return to top"></i> + </button> + </div> + <h1>Final improvements to the FlappyBird clone and Android support devlog 3</h1> + + <p>Decided to conclude my FlappyBird journey with one last set of improvements, following up on devlogs <a href="https://blog.luevano.xyz/g/flappybird_godot_devlog_1.html">1</a> and <a href="https://blog.luevano.xyz/g/flappybird_godot_devlog_2.html">2</a>. Focusing on <strong>refactoring</strong>, <strong>better UI</strong>, <strong>sprite selection</strong> and Android support.</p> +<p>I missed some features that I really wanted to get in but I’m already tired of working on this toy project and already eager to move to another one. Most of the features I wanted to add are just <em>QoL</em> UI enhancements and extra buttons basically.</p> +<p>The source code can be found at <a href="https://github.com/luevano/flappybirdgodot">luevano/flappybirdgodot</a>. Playable at <a href="https://lorentzeus.itch.io/flappybirdgodot">itch.io</a>:</p> +<p style="text-align:center"><iframe src="https://itch.io/embed/1551015?dark=true" width="208" height="167" frameborder="0"><a href="https://lorentzeus.itch.io/flappybirdgodot">FlappyBirdGodot by Lorentzeus</a></iframe></p> + +<h2 id="table-of-contents">Table of contents<a class="headerlink" href="#table-of-contents" title="Permanent link">¶</a></h2> +<div class="toc"> +<ul> +<li><a href="#table-of-contents">Table of contents</a></li> +<li><a href="#refactoring">Refactoring</a></li> +<li><a href="#improvements">Improvements</a><ul> +<li><a href="#background-parallax">Background parallax</a></li> +<li><a href="#sprite-switcher">Sprite switcher</a></li> +<li><a href="#save-data">Save data</a></li> +</ul> +</li> +<li><a href="#android">Android</a></li> +<li><a href="#misc">Misc</a></li> +</ul> +</div> +<h2 id="refactoring">Refactoring<a class="headerlink" href="#refactoring" title="Permanent link">¶</a></h2> +<p>The first part for my refactor was to move everything out of the <code>src/</code> directory into the root directory of the git repository, organizing it a tiny bit better, personal preference from what I’ve learned so far. I also decided to place all the raw aseprite assets next to the imported one, this way its easier to make modifications and then save directly in the same directory. Also, a list of other refactoring done:</p> +<ul> +<li>The way I handled the gameplay means that I needed to make the camera, background and the (ceiling and tiles) “detectors” move along with the player, while restricting their movement in the <code>x</code> axis, really hacky. Instead, I did what I should’ve done from the beginning… just let the tiles move backwards and keep everything static with the player only moving up an down (as how I stated at the beginning of <a href="https://blog.luevano.xyz/g/flappybird_godot_devlog_1.html">FlappyBirdgodot devlog 1</a> but didn’t actually follow).</li> +<li>Moved the <code>set_process</code> methodology to their own scripts, instead of handling everything in <code>main.gd</code> while also taking advantage of how signals work now. Instead of doing:</li> +</ul> +<pre><code class="language-gdscript">func _ready(): + Event.game_pause.connect(_on_game_pause) + +func _on_game_pause(pause: bool): + set_process(pause) +</code></pre> +<p>Just connecting to <code>set_process</code> is enough:</p> +<pre><code class="language-gdscript">func _ready(): + Event.game_pause.connect(set_process) + # and when the signal doesn't send anything: + Event.game_start.connect(set_process.bind(true)) + Event.game_over.connect(set_process.bind(false)) +</code></pre> +<h2 id="improvements">Improvements<a class="headerlink" href="#improvements" title="Permanent link">¶</a></h2> +<h3 id="background-parallax">Background parallax<a class="headerlink" href="#background-parallax" title="Permanent link">¶</a></h3> +<p>First thing was to add a moving background functionality, by adding 2 of the same <code>Sprite2D</code>‘s one after another and everytime the first sprite moves out of the screen, position it right after the second sprite. Some sample code to accomplish this:</p> +<pre><code class="language-gdscript">func _ready(): + # Sprite2D and CompressedTexture2D nodes + background_orig.texture = background_texture + texture_size = background_orig.texture.get_size() + + backgrounds.append(background_orig.duplicate()) + backgrounds.append(background_orig.duplicate()) + backgrounds[1].position = background_orig.position + Vector2(texture_size.x, 0.0) + + add_child(backgrounds[0]) + add_child(backgrounds[1]) + background_orig.visible = false + +# ifirst (index first) it's a boolean value starting with false and +# its a hacky way of tracking the first sprites +# (the one closest to the left of the screen) in the array +func _process(delta: float): + for background in backgrounds: + background.move_local_x(- SPEED * delta) + + # moves the sprite that just exited the screen to the right of the upcoming sprite + if backgrounds[int(ifirst)].position.x <= - background_orig.position.x: + backgrounds[int(ifirst)].position.x = backgrounds[int(!ifirst)].position.x + texture_size.x + ifirst = !ifirst +</code></pre> +<p>Then I added background parallax by separating the background sprites in two: background and “foreground” (the buildings in the original sprites). And to move them separately just applied the same logic described above with 2 different speeds.</p> +<h3 id="sprite-switcher">Sprite switcher<a class="headerlink" href="#sprite-switcher" title="Permanent link">¶</a></h3> +<p>Also added a way to select between the bird sprites and the backgrounds, currently pretty primitive but functional. Accomplished this by holding textures in an exported array, then added a bit of logic to cycle between them (example for the background):</p> +<pre><code class="language-gdscript">func _get_new_sprite_index(index: int) -> int: + return clampi(index, 0, background_textures.size() - 1) + + +func _set_sprites_index(index: int) -> int: + var new_index: int = _get_new_sprite_index(index) + if new_index == itexture: + return new_index + for bg in backgrounds: + bg.texture = background_textures[new_index] + for fg in foregrounds: + fg.texture = foreground_textures[new_index] + itexture = new_index + return new_index +</code></pre> +<p>Then, in custom signals I just call <code>_set_sprites_index</code> with a <code>texture_index +/- 1</code>.</p> +<h3 id="save-data">Save data<a class="headerlink" href="#save-data" title="Permanent link">¶</a></h3> +<p>Moved from manual <code>ConfigFile</code> (which is an <code>.ini</code> file basically) to <code>Resource</code> which is easier to work with and faster to implement.</p> +<p>Accomplished by defining a new <code>data_resource.gd</code>:</p> +<pre><code class="language-gdscript">class_name DataResource +extends Resource + +@export var high_score: int +@export var volume: float +@export var mute: bool +@export var bird: int +@export var background: int + +func _init(): + high_score = 0 + volume = 0.5 + mute = false + bird = 0 + background = 0 +</code></pre> +<p>Where the <code>@export</code>s are not needed unless you need to manage the <code>.tres</code> resource files for testing in-editor.</p> +<p>Then, the <code>data.gd</code> script needs to be changed accordingly, most notably:</p> +<ul> +<li>The file extension is <code>.tres</code> instead of <code>.cfg</code>.</li> +<li>No need for “config sections”.</li> +<li>Saving changes to:</li> +</ul> +<pre><code class="language-gdscript">func save(): + var err: int = ResourceSaver.save(_data, DATA_PATH) + if err != OK: + print("[ERROR] Couldn't save data.") +</code></pre> +<ul> +<li>The loader gets simplified (mostly because the default values are set in the <code>_init()</code> function of the <code>data_resource.gd</code>) to:</li> +</ul> +<pre><code class="language-gdscript">func _load_data(): + if ResourceLoader.exists(DATA_PATH): + _data = load(DATA_PATH) + else: + _data = DataResource.new() + save() +</code></pre> +<ul> +<li>The attributes/config/saved data can be retrieved directly by the <code>data_resource.gd</code> variable name, for example: instead of <code>_data.get_value(SCORE_SECTION, "high_score")</code> it’s now simply <code>_data.high_score</code>. And similar for setting the values.</li> +</ul> +<p>Compared to the <a href="https://blog.luevano.xyz/g/flappybird_godot_devlog_1.html#saved-data">3.x version</a> it is a lot more simple. Though I still have setters and getters for each attribute/config (I’ll se how to change this in the future).</p> +<h2 id="android">Android<a class="headerlink" href="#android" title="Permanent link">¶</a></h2> +<p>I did add android support but it’s been so long since I did it that I actually don’t remember (this entry has been sitting in a draft for months). In general I followed the official guide for <a href="https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_android.html">Exporting for Android</a>, setting up Android studio and remotely debugging with my personal phone; it does take a while to setup but after that it’s as simple as doing <em>“one click deploys”</em>.</p> +<p>Most notably, I had to enable touch screen support and make the buttons clickable either by an actual mouse click or touch input. Some of the <em>Project Settings</em> that I remember that needs changes are:</p> +<ul> +<li><em>display/window/handheld/orientation</em> set to <code>Portrait</code>.</li> +<li><em>input_devices/pointing/emulate_touch_from_mouse</em> and <em>input_devices/pointing/emulate_mouse_from_touch</em> both set to <code>on</code>.</li> +</ul> +<h2 id="misc">Misc<a class="headerlink" href="#misc" title="Permanent link">¶</a></h2> +<p>Found a bug on the <code>ScoreDetector</code> where it would collide with the <code>Ceiling</code>. While this is really not a problem outside of me doing tests I fixed it by <a href="https://blog.luevano.xyz/g/godot_layers_and_masks_notes.html">applying the correct layer/mask</a>.</p> + + <div class="page-nav"> + + <span class="index"> + <a href="https://blog.luevano.xyz" alt="Index"> + <i class="fas fa-home" alt="Home"></i> + <span>Index</span> + </a> + </span> + + <span class="previous"> + <a href="https://blog.luevano.xyz/g/godot_layers_and_masks_notes.html" alt="Previous"> + <i class="fas fa-arrow-right" alt="Arrow right"></i> + <span>Previous</span> + </a> + </span> +</div> + + + <hr> + <div class="article-info"> + <p>By David Luévano</p> + <p>Created: Fri, Mar 01, 2024 @ 10:00 UTC</p> + <p>Modified: Fri, Mar 01, 2024 @ 10:11 UTC</p> + <div class="article-tags"> + <p>Tags: +<a href="https://blog.luevano.xyz/tag/@english.html">english</a>, <a href="https://blog.luevano.xyz/tag/@gamedev.html">gamedev</a>, <a href="https://blog.luevano.xyz/tag/@gdscript.html">gdscript</a>, <a href="https://blog.luevano.xyz/tag/@godot.html">godot</a> </p> +</div> + + </div> + </main> + + <footer> +<span> + <i class="fas fa-address-card" alt="Contact"></i> + <a href="https://blog.luevano.xyz/contact.html">Contact</a> +</span> + +<span> + <i class="fas fa-donate" alt="Donate"></i> + <a href="https://blog.luevano.xyz/donate.html">Donate</a> +</span> + +<span> + <i class="fas fa-rss" alt="RSS"></i> + <a target="_blank" href="https://blog.luevano.xyz/rss.xml">RSS</a> +</span> + +<br> +<span class="created-with"> + <i class="fas fa-hammer" alt="Hammer"></i> + Created with <a href="https://github.com/luevano/pyssg">pyssg</a> +</span> + +<br> +<span class="copyright"> + Copyright <i class="far fa-copyright" alt="Copyright"></i> 2023 David Luévano Alvarado +</span> + + </footer> + </body> +</html>
\ No newline at end of file diff --git a/live/blog/g/godot_layers_and_masks_notes.html b/live/blog/g/godot_layers_and_masks_notes.html index f13805e..1d55d97 100644 --- a/live/blog/g/godot_layers_and_masks_notes.html +++ b/live/blog/g/godot_layers_and_masks_notes.html @@ -103,6 +103,12 @@ <p>While the complete answer is the first, as that is how layers work, the second can be used like a rule: 1) the <code>layer</code> is where the object lives, while 2) the <code>mask</code> is what the object will detect.</p> <div class="page-nav"> + <span class="next"> + <a href="https://blog.luevano.xyz/g/flappybird_godot_devlog_3.html" alt="Next"> + <i class="fas fa-arrow-left" alt="Arrow left"></i> + <span>Next</span> + </a> + </span> <span class="index"> <a href="https://blog.luevano.xyz" alt="Index"> |