Recently, I implemented one of many game ideas. Let’s start with the basics: each match involves two players sending
troops to defeat their opponent’s castle. So far, so good. Many people have implemented this part already. Now, one of
the hard parts of such a game is balancing, the art of adjusting troops’ attributes so that no one strategy is too
powerful.
I’ve come up with an easier solution for this problem (or maybe just a more complicated version):
The entire battlefield is a big scale, and every troop has a weight calculated from damage and health. If your
attack is too strong, all the troops will fall down, giving your opponent a chance to recover.
Tech-Stack
As I wanted to quickly get my hands on a prototype, I chose Unity, which I’m already familiar
with.
For the networking part, I used Mirror, a high-level networking library based on
previous versions of Unity’s Networking. While developing multiplayer games, I highly
recommend ParrelSync; the plugin allows you to start a second Unity Editor
with the same project. ParrelSync is a huge time saver as you can simulate two players without building and running the
game and have the editor view on both sides.
Main Mechanic: The Scale
First, I worked on the main mechanic, the moving scale. That’s pretty doable with Unity’s physics engine: a sprite with
a Box2D
Collider plus a Rigidbody2D as the ground and then some joint attachment. I had not worked a lot with joints
before, so I made an entire scene dedicated to experimenting with them:

It’s not the most beautiful scene, but it was a good way to get a feeling for the different joint types and how they
work.
Ultimately, I decided to go with a spring joint on each end. This provides a fairly stable connection while also
allowing for rapid displacement of troops.
Implementation Issues
Next up was the actual gameplay. I spent quite a long time on “the resolution issue”: mobile devices can have varying
screen sizes, but the scale should always span the entire screen (ignoring the two castles). First, I tried using
the PositionUtil
script to calculate the desired size and position, but this quickly became very complicated. The
castles shouldn’t be split on the edge of the screen but rather fully visible, the scale needs to take the
castles into account, and so on.
I ended up using a hacky solution: there’s a script with the sole purpose of setting the camera’s
aspectRatio
to 16:9. If you can think of a better way, please let me know.
The networking came with its own bunch of bugs and issues, but as I’ve worked with Mirror before, this went pretty well. There’s an obvious design issue caused by not having dedicated servers. One of the players needs to be a host, both server and client at the same time, and as the server is authoritative and knows everything, this player could cheat without limits. For a LAN-only prototype, this is not an issue, though.
Gameplay
There’s an energy bar and four different types of troops for now. Big thanks to TrulyMalicious for providing free graphics; these cute images really improve the look. Now let’s see some actual gameplay:
Then I also threw together a main menu, and it’s a game. Play means you’re the server, Find Server allows you to join a game on the local network, and Exit closes the game.

How to play / Source Code
If you want to play it, download the binary for your OS and grab
a friend. Player One hits Play, and Player Two joins the game with Find Server. There is currently no way to restart
the game after you’ve won, so you’ll have to close and reopen the game ;).
The entire project is available on GitHub if you want to experiment with
it further.
Webmentions
No webmentions were found.
{% for webmention in webmentions %}-
{{ webmention.content }}
{% if webmention.author %}
{{ webmention.author.name }}
{% endif %}
{% if webmention.pubdate and webmention.url %}on{% endif %}
{% if webmention.pubdate %}
{% endif %}
{% endfor %}
{% else %}No bookmarks were found.
{% endif %}{% for webmention in webmentions %}-
{% endfor %}
{% else %}No likes were found.
{% endif %}{% for webmention in webmentions %}-
{{ webmention.content }}
{% if webmention.author %}
{{ webmention.author.name }}
{% endif %}
{% if webmention.pubdate and webmention.url %}on{% endif %}
{% if webmention.pubdate %}
{% endif %}
{% endfor %}
{% else %}No links were found.
{% endif %}{% for webmention in webmentions %}-
{{ webmention.title }}
{% if webmention.pubdate %}
{% endif %}
{% endfor %}
{% else %}No posts were found.
{% endif %}{% for webmention in webmentions %}-
{{ webmention.content }}
{% if webmention.author %}
{% if webmention.author.photo %}
{% endif %}
{{ webmention.author.name }}
{% endif %}
{% if webmention.pubdate and webmention.author %}on{% endif %}
{% if webmention.pubdate %}
{% endif %}
{% endfor %}
{% else %}No replies were found.
{% endif %}{% for webmention in webmentions %}-
{% endfor %}
{% else %}No reposts were found.
{% endif %}{% for webmention in webmentions %}-
{{ webmention.author.name }}
{{ webmention.content }}
{% endfor %}
{% else %}No RSVPs were found.
{% endif %}{% for webmention in webmentions %}-
{% if webmention.author %}
{% if webmention.author.photo %}
{% endif %}
{{ webmention.author.name }}
{% endif %}
{% if webmention.content %}
{{ webmention.content }}
{% else %}
{{ webmention.title }}
{% endif %}
{% if webmention.pubdate %}
{% endif %}
{% if webmention.pubdate and webmention.url %}|{% endif %}
{% if webmention.url %}
Permalink
{% endif %}
{% endfor %}
{% else %}No webmentions were found.
{% endif %}Comments