<?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: Simone Sturniolo</title>
    <description>The latest articles on DEV Community by Simone Sturniolo (@stur86).</description>
    <link>https://dev.to/stur86</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2155636%2Fdaff1efb-c28c-4035-a62f-2b29a0e9afd3.png</url>
      <title>DEV Community: Simone Sturniolo</title>
      <link>https://dev.to/stur86</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stur86"/>
    <language>en</language>
    <item>
      <title>How I made a Game with Claude from scratch</title>
      <dc:creator>Simone Sturniolo</dc:creator>
      <pubDate>Sun, 01 Nov 2026 21:56:03 +0000</pubDate>
      <link>https://dev.to/stur86/how-i-made-a-game-with-claude-from-scratch-amd</link>
      <guid>https://dev.to/stur86/how-i-made-a-game-with-claude-from-scratch-amd</guid>
      <description>&lt;p&gt;Coding agents are quite powerful. Claude Opus 5.5 in particular has been hailed for its smarts and creativity from its release (especially compared to its relatively contained cost in comparison to the behemoth Fable, or the OpenAI rival Astra). There's tons of examples of images, videos, and even music made with Claude, and I'm sure quite a lot of games too. I decided to experiment with it myself to test the limits of it, and what it could do. My challenge was to make a game &lt;em&gt;entirely&lt;/em&gt; with Claude. No separate AI models for image or music generation and basically no manual coding - just me prompting my way to a full, functional browser game. The chance was offered to me by the &lt;a href="https://itch.io/jam/littlejs-jam" rel="noopener noreferrer"&gt;LittleJS Jam 3&lt;/a&gt;, a friendly competition for amateur gaming that is quite accepting of AI coding and asset creation [^1]. The competition's only requirements were that the game should run in the browser, that it should use the LittleJS game framework, and that it should adhere to the chosen theme keyword: &lt;strong&gt;&lt;em&gt;zig-zag&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Read on for my experience and insights in making a game for this jam in just a few days with only a Claude subscription, and what the final result ended up being!&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;First, I decided I wanted full creative control over the high level of the concept and game design. I still wanted this to be &lt;em&gt;my&lt;/em&gt; game in a meaningful sense, not just a full AI creation. My core concept was "Zig-Zag Heroes", a survivors-like (or "bullet heaven") game played entirely in one dimension with just two buttons, left and right. Basically something borrowing in equal parts from &lt;a href="https://store.steampowered.com/app/1794680/Vampire_Survivors/" rel="noopener noreferrer"&gt;Vampire Survivors&lt;/a&gt; and &lt;a href="https://store.steampowered.com/app/264200/One_Finger_Death_Punch/" rel="noopener noreferrer"&gt;One Finger Death Punch&lt;/a&gt;, both masterpieces of dumb and fun arcade gameplay. My core ideas could be summed up as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it'll be about surviving enemy waves from both sides with a character that shoots only in front of them;&lt;/li&gt;
&lt;li&gt;the enemies would drop XP which allows the character to level up and choose passive or active skills to boost themselves;&lt;/li&gt;
&lt;li&gt;the aesthetic and style will be somewhat inspired by classic side scroller shooters and beat 'em ups (think Streets of Rage or Metal Slug), with bombastic and cartoonish visual effects;&lt;/li&gt;
&lt;li&gt;to make the mechanics a bit more varied, since compared to the already simple control scheme of VS I was also taking away one whole dimension of motions, special skills/weapons wouldn't be auto-firing, but triggered via specific key combos relying on order and timing of button presses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these parameters in mind I set to work having Claude lay out an example of game mechanics with a first level and a few basic skills, using only placeholder art (made just of flat colored rectangles, essentially). This actually worked quite well from the get go, and a few tweaks were enough to refine it in a workable loop. One interesting thing that Claude did entirely autonomously: it created a "bot" using scripted behaviour to play the game on its behalf at high speed and accumulated statistics over several runs which it then used to balance the game. The result was really good in my experience; while I did suggest a few tweaks now and then the levels felt challenging and right almost immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Art and Music
&lt;/h2&gt;

&lt;p&gt;After establishing the core gameplay, it was time to start developing the actual style and feel of the game and adding content. This required creating sprites, sounds, and music.&lt;/p&gt;

&lt;p&gt;For art, just a few weeks before I had already developed &lt;a href="https://github.com/stur86/claude-pixet" rel="noopener noreferrer"&gt;Claude Pixet&lt;/a&gt;, my own custom MCP for pixel art, which had already produced fairly good results:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7x33oa1el2kr5e3f4oc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7x33oa1el2kr5e3f4oc.png" alt="An example scene created with Claude Pixet" width="768" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the usage for this project, Claude expanded on the ways to use this tool, including suggesting a new method altogether in which it maps characters to palette colors, then "draws" a pixel image entirely as ASCII. As a result, it produced rather legible and good looking sprites, albeit somewhat generic. Here's the first hero, a clear reference to the classic original 2D Duke Nukem:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkgrcoji9b887tivu6h6b.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkgrcoji9b887tivu6h6b.png" alt="Earl Blastem, the first hero" width="800" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The design was an interpretation of my own direction, as was the case for every successive level, hero and enemy. In general, all art ended up being made by Claude with my steering, which included e.g. listing what kind of items should be visible in each level's scenery. The one case where for some reason Claude seemed to keep getting it wrong and I had to personally intervene was the boss enemy of the first level, the Biker King. There were several attempts which mostly failed in capturing the right pose for someone riding a motorbike. At the end I took it up on my own hands and simply drew the entire sprite with a pixel art editor. It's not particularly good, but that gives you a sense of how bad the Claude versions were.&lt;/p&gt;

&lt;p&gt;For music, I did not need to develop a custom tool. Instead I just told Claude to use the music programming language &lt;a href="https://chuck.stanford.edu/" rel="noopener noreferrer"&gt;ChucK&lt;/a&gt;. It was a good fit since I needed chiptune, not any kind of realistic-sound sampled music, so this way Claude could design simple synths for its instruments, the compose with them. For example, for the space level, I told it to use theremin-sounding synths and generally evoke cheesy 50s science fiction, mixed with the boppiness and energy of the &lt;a href="https://www.youtube.com/watch?v=dWRWYYt47RI" rel="noopener noreferrer"&gt;disco cover of the Star Wars theme&lt;/a&gt;. It came up with a plan that it writes as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// "Galactic Boogie" - Outer Space level theme. Space disco: E Dorian (with heroic C and D major chords), 120 BPM.
// Form (loops forever): F (4 bars, brass fanfare over string stabs) - G (8 bars, the groove: octave disco bass,
// funky muted guitar, string pads, laser zaps) - C (4 bars, the brass theme) - K (4 bars, breakdown: arpeggio,
// bass and claps) - L (4 bars, last chorus: the theme with everything, arpeggio on top, a B7 turnaround).
// 24 bars at 120 BPM = 48 s: keep music/songs.jsonc "seconds" in step if the form or tempo changes.
//
// Voices: disco bass (square and saw through a plucky filter), string synth (detuned saws, slow attack), brass
// lead (three detuned saws, a filter that opens on each note, vibrato), muted funk guitar (a short filtered
// chord), arpeggio (square with an echo), laser zaps (fast falling sweeps), drums (four-on-the-floor kick, claps,
// open and closed hats, toms).
// Melodies are sixteenths in MIDI: 0 = rest, -1 = hold.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://jumpshare.com/share/86E3OiJ0MCzZaNQfiQIO?b=6typDo1pVIZ7Wsur96Ro" rel="noopener noreferrer"&gt;Here you can hear the result&lt;/a&gt;. It's notable that unlike with images, Claude can't take in audio input, so there basically was no feedback loop possible - it was composing effectively "deaf". Even so, the result is perfectly serviceable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing, design, gameplay
&lt;/h2&gt;

&lt;p&gt;Most of the rest of the development was directed extremely qualitatively by me, and almost immediately caught on an expanded upon by Claude. I won't say it literally one-shotted everything, but it came pretty close. The first draft of anything was almost always very good and it only needed tweaks, often a matter of taste more than necessity. &lt;/p&gt;

&lt;p&gt;Gameplay, past the basics, required mostly establishing what each skill would do and the various enemy patterns and bosses. I described most of those (for example "the Nuke skill has a certain % chance of killing each enemy on screen", or "the Galactic Emperor boss fires a ray gun and calls for missiles from his fleet"), diving more in depth into patterns and ideas, but almost never gave numbers. These were refined by Claude via basic formulas and the bot runs.&lt;/p&gt;

&lt;p&gt;The writing was not the biggest crux of the game, given that all it amounts to is quippy flavour text, but it's the one thing where I actually took the most hands on approach. I had Claude essentially defer for all text data to JSON files where I then mostly rewrote all of it myself. That said, a few of Claude's original ideas remain wherever I thought they were funny enough and I couldn't come up with anything better (such as "Tanks for Playing" after defeating the Tank Bros).&lt;/p&gt;

&lt;h2&gt;
  
  
  Token usage
&lt;/h2&gt;

&lt;p&gt;The project took me about a week of my Pro subscription from start to finish. Usually just generating a level could be as much as a whole 5 hour session's worth of tokens. That's not a lot in the grand scheme of things (it could have been done in a couple of sessions on a Max subscription), but it was troubling how much the usage tended to grow as the project did, even if I used compaction regularly. Part of the problem was likely that I did most of it in a single thread, hoping that this would help with stylistic consistency. In hindsight I might have had better efficiency breaking tasks down, but ultimately, for a project of this size, it worked out nevertheless.&lt;/p&gt;

&lt;h2&gt;
  
  
  The final product
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Forlxkgvoilikj6v3luv9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Forlxkgvoilikj6v3luv9.png" width="800" height="450"&gt;&lt;/a&gt;&lt;br&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmdctinkuoi7vcojh40hw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmdctinkuoi7vcojh40hw.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can play the game &lt;a href="https://lightcone-games.itch.io/zig-zag-hero" rel="noopener noreferrer"&gt;on Itch.io&lt;/a&gt; or &lt;a href="https://wavedash.com/games/zig-zag-hero" rel="noopener noreferrer"&gt;here on Wavedash&lt;/a&gt;, with achievements and cloud saves.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>gamedev</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>How many Python packages are versioned correctly?</title>
      <dc:creator>Simone Sturniolo</dc:creator>
      <pubDate>Thu, 03 Oct 2024 21:09:16 +0000</pubDate>
      <link>https://dev.to/stur86/how-many-python-packages-are-versioned-correctly-5l8</link>
      <guid>https://dev.to/stur86/how-many-python-packages-are-versioned-correctly-5l8</guid>
      <description>&lt;p&gt;The other day, as I was looking into a database of vulnerabilities in Python packages, I realized that some of the package versions in there could not be easily parsed and compared with other version strings because they did not abide by the standards of Python versioning - either the old &lt;a href="https://peps.python.org/pep-0440/" rel="noopener noreferrer"&gt;PEP 440&lt;/a&gt; or the &lt;a href="https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers" rel="noopener noreferrer"&gt;Version Specifiers&lt;/a&gt; specification that superseded it. So I started wondering how common this was. How many packages on the Python Package Index &lt;em&gt;actually&lt;/em&gt; have valid versions?&lt;/p&gt;

&lt;p&gt;The obvious answer was: go check. So I created a new virtual environment, downloaded &lt;code&gt;requests&lt;/code&gt;, and proceeded to write a multiprocessing script to query the PyPI API for literally &lt;em&gt;every version string used by every package&lt;/em&gt; . It took me a few hours even running on all cores but by the end of it I had retrieved over 6,057,703 version strings from 545,018 packages, stored in a neat SQLite database. &lt;a href="https://www.kaggle.com/datasets/sstur86/python-version-strings/data" rel="noopener noreferrer"&gt;You can find it on Kaggle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next came parsing. I found two libraries that promised to validate a version string for compliance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/pepver/" rel="noopener noreferrer"&gt;&lt;code&gt;pepver&lt;/code&gt;&lt;/a&gt;: "PEP-440 version parsing, interpretation and manipulation"&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/parver/" rel="noopener noreferrer"&gt;&lt;code&gt;parver&lt;/code&gt;&lt;/a&gt;: "parver allows parsing and manipulation of PEP 440 version numbers"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that to be fair both these still stick to PEP-440, which has now been replaced, so I will keep that in mind, especially when looking at the strings marked as non compliant.&lt;/p&gt;

&lt;p&gt;After another couple of hours of intense multiprocessing I had updated my database with two boolean columns indicating whether the strings parsed successfully with these two packages (also on Kaggle).&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&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%2Fjpessy0mo6uc04a3kzoa.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%2Fjpessy0mo6uc04a3kzoa.png" alt="Validity of version strings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a quick summary of my findings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;out of 6,057,703 version strings, 5,542 (0.09%) were found defective;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;out of 545,018 packages, 1,285 (0.24%) had at least one defective version string.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So overall the state of the repository seems pretty healthy! The version strings found wrong by both libraries are of all kinds. Some simply use the suffixes in a non-standard way but overall follow the semantic versioning paradigm while others are just commit hashes or strings of words and numbers.&lt;/p&gt;

&lt;p&gt;The cases where the two libraries disagree are more interesting. These are the ones that pepver does not validate but parver does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.0.2.R
0.0.2.R3
0.0.2.R4
0.0.2.R5
0.0.2.R6
0.0.2.R7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, I would say pepver is in the wrong. Per PEP440 and current versioning rules, &lt;code&gt;r&lt;/code&gt; is an acceptable spelling for the post-release tag (standardised to &lt;code&gt;post&lt;/code&gt;), and letters are case-insensitive. So effectively &lt;code&gt;0.0.2.R3&lt;/code&gt; normalizes to &lt;code&gt;0.0.2.post3&lt;/code&gt; &lt;a href="https://packaging.python.org/en/latest/specifications/version-specifiers/#post-release-spelling" rel="noopener noreferrer"&gt;and is perfectly legal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Meanwhile, here is a random sample of versions that pepver admits but parver does not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.0.1dev-20141025
1.5.0-dev-618
0.3.4.dev.20180830
1.15.0-dev-1552
1.4.0-dev-510
0.0.9.dev-20121012
0.2dev-20101203
0.3.4.dev.20180905
1.15.0-dev-1606
0.2.1dev-20110627
1.12.0-dev-1379
1.1.1-dev-275
1.3.1-dev-427
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They all have in common the tendency to use other numbers (occasionally dates) after the &lt;code&gt;dev&lt;/code&gt; suffix, with some separator. This is indeed also wrong, as the specification doesn't allow for the separator in this case. So again parver seems right. &lt;/p&gt;

&lt;p&gt;Anyway, that pretty much satisfied my original curiosity, and reassured me that for the vast majority of cases, the standard methods of parsing and comparing versions will be sufficient. Even among the non-standard versions it's often fairly easy to identify an order, as the deviations are minimal. Still, it's useful to be aware of all the quirks of the official versioning, and to know when we can or can not rely on them.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
  </channel>
</rss>
