Show HN: Naval Strike – simultaneous turn-based fleet combat in the browser

navalstrike.app

4 points by pinchydev 2 days ago

A few weeks ago there was a thread about using AI to finish abandoned projects, and a comment from avereveard https://news.ycombinator.com/item?id=47905088 on building their 100x100 grid battleship got my spark. I didn’t build that, but it pushed me to finally finish a combat idea I’ve been wanting to play for ages.

Introducing Naval Strike!

It’s a simultaneous turn-based fleet vs fleet on a grid played in the browser. There’s no account or signups needed. Both players plan their moves, then the turn resolves at once.

There’s three different play styles:

* Solo. Procedural maps and uses guided “AI” opponents (in the same way that 1990s games had “AI” opponents)

* Scenarios. Objective missions on procedural maps like "rescue the downed pilot" or "destroy the convoy"

* Campaigns. Historical battles on real-world maps (Sink the Bismark in the Atlantic, or escort the tankers through the strait of hormuz)

A few things I figured HN would ask:

I designed the architecture and Claude did implementation. While 90% of the decisions are mine 90% of the lines are AI-written. Lots of micro managing short bursts to get it to look/feel right. I think I consumed a week’s worth of tokens just to get the fog working how I wanted. Eventually I learned that having lots of small bursts of code with testing got me to where I wanted much faster than longer sessions. I built preview pages so I could test animations, sequencing etc without affecting the codebase so I didn’t chew through my tokens.

Stack. TypeScript/Canvas 2D, hosted on Cloudflare. The server is a tiny WebSocket relay, it pairs two players by room code and blindly forwards messages, with no game logic. So there’s no accounts and no tracking beyond default Cloudflare insights. Just open the URL and play. Opponent AI is guided scripted tactics with situational decision trees.

Art is a mix of AI/hand. I’m not artistic enough to do everything by hand, but there’s a lot of manual pixel by pixel editing on the assets. Assets are stored as JSON arrays and drawn directly to screen with a colour palette.

I ended up building a small map editor that lets me "trace" Google Maps screenshots to get the campaign maps geographically close to the real engagements. Sounds are from open source libraries - you can mute them with the little speaker button but they are on by default which might upset a few people.

Although this was largely coded by AI, I got heaps of enjoyment being able to focus on the UX, style, gameplay and UI to be just how I wanted. Being able to test (and throw away many!) ideas so quickly was awesome fun.

Feedback welcome. Especially on balance and the campaign design and gameplay, it’s hard to play-test every variable!

dash2 22 hours ago

I've played it a bit.

* The move ratio for cruisers/aircraft carrier feels low. Maybe have it 2 vs 3 instead of 1 vs 2? Actually in general I think more moves would make it more fun and dynamic.

* Why can I only move in a straight line when I plan my moves beyond 1 turn? And only in one of the 8 points of the compass?

* At first it felt weird to play the game of "where shall I shoot". Like, just shoot at the ship, it's right there! But then I got used to the dynamic of "is he gonna move?" and trying to anticipate it.

* The AI isn't good enough, or at least, I won most games after the first one. I think they could use aircraft more effectively.

* Needs a bit more hand holding early on, like "what are those dots on the radar actually revealing?" I worked out they could be land, or ships. But I still found it hard to use radar effectively.

* Yeah, the ships are very tiny and hard to see. You could afford more pixels.

* On some maps it might be fun to know the land/sea map already. (That also seems realistic e.g. for historical scenarios.) The first few turns tend to be a bit dull because you're just trying to map the area.

* Relatedly, seems like you usually start at the top and the AI is at the bottom, which loses a bit of the excitement of finding the enemy. In the death match at least.

* No matchmaking? I don't know where I'd find someone to play with....

* I never use countermeasures. Just moving to get behind the missile/aircraft and/or dodge the gun does the job pretty ok. Maybe that's my mistake though?

vunderba 2 days ago

Nice job. As someone who spends an inordinate amount of time on pixel art, I immediately noticed that something was off on the logo [1]. When I brought the PNG down, it looks like when you were trying to clean the asset (probably a background removal tool that was too aggressive), you accidentally made part of the hull alpha-transparent.

Also, consider adjusting the sprite assets for the frigate and cruiser. Right now they look very similar, which could be frustrating if a player wanted to do a quick visual scan and identify which ships are which.

[1] - https://navalstrike.app/assets/naval-strike-logo-xIcrDNQX.pn...

  • pinchydev 2 days ago

    Thank you - you're right, it must have been when I removed the background surrounding the logo, I did it on a colour not the area and missed that the hull was the same shade. I'll fix that :)

    I'll play with cruiser sprite too, if you're curious this is how I save them:

      frigate: [
        "................",
        "................",
        "................",
        "...kkkkkkkk.....",
        "..kHHHHHHHHkk...",
        ".kHgGGGGGGGgDkk.",
        "kHHgwGttGttwgDkk",
        "kHHgGGGppGGttgDk",
        "kHHgGGGppGGttgDk",
        "kHHgwGttGttwgDkk",
        ".kHgGGGGGGGgDkk.",
        "..kHHHHHHHHkk...",
        "...kkkkkkkk.....",
        "................",
        "................",
        "................",
      ],
    • vunderba 2 days ago

      Nice~ I used to do something similar back when I made little games in BASIC using blocks of sequential DATA keywords to visually represent on/off pixels for the various sprites.

      • pinchydev 2 days ago

        that brings back painful memories of typing lines and lines of DATA keywords from library books into GW BASIC.....

        I'm an embedded engineer, so it's how I would encode a sprite for displaying an LCD character, it seemed natural to do it this way!

        ETA: I've fixed the image transparency and the frigate sprite is less fat, thanks!

        • vunderba 2 days ago

          Very cool. It’s been a while, but years ago I remember using a nice little tool that somebody had made that let you export BMP pictures to an array you could drop into an Arduino C program for displaying on an RGB LED matrix.