{"id":1315,"date":"2026-09-08T18:28:56","date_gmt":"2026-09-08T18:28:56","guid":{"rendered":"https:\/\/runonur.xyz\/?p=1315"},"modified":"2026-09-08T18:28:56","modified_gmt":"2026-09-08T18:28:56","slug":"building-hello-world-chase-a-libgdx-mini-game-and-a-qa-pass-on-my-own-code","status":"publish","type":"post","link":"https:\/\/runonur.xyz\/index.php\/2026\/09\/08\/building-hello-world-chase-a-libgdx-mini-game-and-a-qa-pass-on-my-own-code\/","title":{"rendered":"Building &#8220;Hello World Chase&#8221;: A libGDX Mini-Game, and a QA Pass on My Own Code"},"content":{"rendered":"\n<p>I recently put together a tiny arcade game in <strong>libGDX<\/strong> called <em>Hello World Chase<\/em>. The premise is simple: you&#8217;re the text string &#8220;Hello World&#8221;, dodging (and shooting) enemies made of literal bug names \u2014 &#8220;Bug&#8221;, &#8220;Lag&#8221;, &#8220;Error&#8221;, &#8220;Crash&#8221;, &#8220;Null&#8221; \u2014 while the game speeds up the longer you survive. It&#8217;s a fun little exercise in game-loop basics: input handling, collision detection, spawning, and UI with libGDX&#8217;s Scene2D.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What the game actually does<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>Main<\/code><\/strong> extends libGDX&#8217;s <code>Game<\/code> class and owns a shared <code>Skin<\/code> (fonts, colors, button styles) so both screens can reuse the same look.<\/li>\n\n\n\n<li><strong><code>MenuScreen<\/code><\/strong> is a simple Scene2D <code>Stage<\/code> with a title label and two buttons: New Game and Exit.<\/li>\n\n\n\n<li><strong><code>GameScreen<\/code><\/strong> is where the action happens:<\/li>\n\n\n\n<li>The player is literally the string &#8220;Hello World&#8221;, moving at a constant speed in whatever direction you last pressed (arrow keys or WASD).<\/li>\n\n\n\n<li>Enemies spawn from screen edges at random angles and bounce off walls.<\/li>\n\n\n\n<li>Pressing Space fires a bullet (&#8220;*&#8221;) in the player&#8217;s current direction, on a cooldown.<\/li>\n\n\n\n<li>Bullets that hit enemies remove both and award bonus points.<\/li>\n\n\n\n<li>Touching an enemy, or drifting off the edge of the screen, ends the run.<\/li>\n\n\n\n<li>Everything ramps up over time: player speed increases, enemy spawn interval shrinks, enemy speed scales with elapsed time.<\/li>\n\n\n\n<li>A HUD (score, speed, enemy count) and a Game Over overlay round it out.<\/li>\n\n\n\n<li>It&#8217;s a compact, self-contained example of a full mini game loop \u2014 menu, gameplay, restart, all in one file.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"636\" height=\"514\" src=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/h2.png\" alt=\"\" class=\"wp-image-1317\" srcset=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/h2.png 636w, https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/h2-300x242.png 300w\" sizes=\"auto, (max-width: 636px) 100vw, 636px\" \/><\/figure>\n\n\n\n<p>The QA pass<\/p>\n\n\n\n<p>To make the game&#8217;s behavior actually testable, I pulled the core simulation out of the libGDX <code>GameScreen<\/code> and into its own file, <code>GameLogic.java<\/code> \u2014 a plain Java class with no rendering dependencies, just player movement, enemy spawning, bullet updates, collisions, and scoring. Alongside it, I wrote <code>GameLogicTest.java<\/code>, a JUnit 5 suite that exercises <code>GameLogic<\/code> directly: movement and boundary checks, shooting cooldown timing, enemy spawning with a seeded <code>Random<\/code> for determinism, bullet-enemy collisions and scoring, and precise edge cases around player-enemy collision (like adjacent-but-not-touching versus one-pixel-overlap). Separating logic from rendering this way meant I could test the actual rules of the game.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"660\" src=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q1-1024x660.png\" alt=\"\" class=\"wp-image-1318\" srcset=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q1-1024x660.png 1024w, https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q1-300x193.png 300w, https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q1-768x495.png 768w, https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q1.png 1121w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"932\" height=\"821\" src=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q2.png\" alt=\"\" class=\"wp-image-1319\" srcset=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q2.png 932w, https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q2-300x264.png 300w, https:\/\/runonur.xyz\/wp-content\/uploads\/2026\/09\/q2-768x677.png 768w\" sizes=\"auto, (max-width: 932px) 100vw, 932px\" \/><\/figure>\n\n\n\n<p>None of these issues stop the game from working \u2014 it runs fine and is fun to play for a few minutes. But that&#8217;s the point of a QA pass: small bugs that don&#8217;t matter now are the ones that confuse players later or cause problems once you add more features. Reviewing your own project like it&#8217;s someone else&#8217;s pull request is a simple way to catch that stuff early.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"340\" height=\"171\" src=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2023\/08\/cropped-cropped-altinoran-1.1.png\" alt=\"\" class=\"wp-image-1184\" style=\"width:211px;height:auto\" srcset=\"https:\/\/runonur.xyz\/wp-content\/uploads\/2023\/08\/cropped-cropped-altinoran-1.1.png 340w, https:\/\/runonur.xyz\/wp-content\/uploads\/2023\/08\/cropped-cropped-altinoran-1.1-300x151.png 300w\" sizes=\"auto, (max-width: 340px) 100vw, 340px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-left\"><strong><em><code>RunOnuR \/ Summer of 2026<\/code><\/em><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently put together a tiny arcade game in libGDX called Hello World Chase. The premise is simple: you&#8217;re the text string &#8220;Hello World&#8221;, dodging (and shooting) enemies made of literal bug names \u2014 &#8220;Bug&#8221;, &#8220;Lag&#8221;, &#8220;Error&#8221;, &#8220;Crash&#8221;, &#8220;Null&#8221; \u2014 while the game speeds up the longer you survive. It&#8217;s a fun little exercise in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1315","post","type-post","status-publish","format-standard","hentry","category-game-development"],"_links":{"self":[{"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/posts\/1315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/comments?post=1315"}],"version-history":[{"count":1,"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/posts\/1315\/revisions"}],"predecessor-version":[{"id":1320,"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/posts\/1315\/revisions\/1320"}],"wp:attachment":[{"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/media?parent=1315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/categories?post=1315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/runonur.xyz\/index.php\/wp-json\/wp\/v2\/tags?post=1315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}