While work is keeping me busy, over the past few weeks I’ve had a couple of good evenings to work on Arcane Deathmatch.
Last weekend I poked around with a second spell, “Infernal Nova”:
This Saturday I added a leader board, a gold reward when you kill someone, and fixed some bugs. Tonight I added a UI for shopping spells, made the leader board prettier, and added a Teleport spell. Woo! Check it out below:
Hopefully I’ll keep making steady progress and I can start very very early tests against real people this week or next.
The last few months it’s been busy with three weddings (including my own) and a vacation. Every once in a while I’ve been tinkering with a game prototype with a smaller scope than Dungeon Fodder - and now I’ve finally reached a point where I can say that I’ll be pursuing this concept instead of Dungeon Fodder. I first had to make sure Unity’s (fairly lacking) networking APIs would be suitable for developing this.
The game is tentatively named “Arcane Deathmatch”, and it’s a third person / top down, fast paced, RPG-inspired multiplayer action game. The gameplay is similar to the Warcraft 3 custom map “Warlocks” (I think?): You control a wizard/warlock on a relatively small battlefield. You’re pitted against a few adversaries, all of you armed with whatever spells you’ve purchased. As you survive and kill off your opponents you’re awarded gold with which to purchase new spells between rounds.
Every time you’re hit by a spell, you lose some health and get knocked back. The less health you have, the easier you are to knock around. If you get knocked off the map, you’ll probably sustain damage wading through a lava pit, be nibbled on by piranhas as you swim to shore, or fall off the map.
So far, I’ve got rudimentary networking and gameplay working - two or more players can connect to eachother and fight it out (armed with Magic Missile!), and getting knocked off the map means falling to your death. It doesn’t look like much - but that’s never stopped me before! ;-)
Vital things that are missing are more spells, rewards, a way to buy said spells, more interesting maps / terrain / obstacles, and a scoreboard. (Probably in that order)
I hope you’ll follow my blog as I post status updates and my experiences developing this game :-)
I’ve attracted some people who are following the progress of this project, so I figured I should give a quick update on my (lack of) progress.
I’m in the middle of organizing a wedding reception, so there won’t be any time for working on my projects until after the 26th of June. I look forward to getting back to it!
So far, updates have been on a weekly schedule. I intend to continue with that pace - or maybe biweekly, depending on how much time I have. Right before this lack of updates began, I started prototyping a game based on some of the same concepts, but with a smaller scope. I might pursue that so that I have a playable, “done” game at an earlier point. If so, it’ll be featured in an upcoming post. :)
Thank you all for your feedback and interest! This is exactly why I publish this publicly!
(This is similar to Requiring a minimum version of the Android NDK, but for SDK versions)
Again, I was tinkering with our build system at work, which is a set of small Makefiles that are responsible for invoking ndk-build (to build our C component) and ant (for the Java component). These files also maintain the dependency graph for the cross-domain dependencies, so things like header files being generated from class-files using
javah and APKs depending on the produced shared libraries.
I recently made some changes to the
ant build step by creating our own
custom_rules.xml, exposing the “hidden” -compile target. What I noticed was that
build.xml only did an
<import file="custom_rules.xml" optional="true" /> if you were on a fairly recent Android SDK version. This isn’t a problem for our Jenkins builds, since we’ve got an in-house system that ensures a strict version dependency between a specific source checkout and SDK/NDK versions, so they were always using the newer SDK. It was a problem for our developers - we’ve yet to roll this system to our development machines, so developers are responsible for checking out and updating their own SDKs.
To prevent this from getting in the way, I wrote a little snippet of bash that’s run from the Makefile, that ensures that the SDK version is at least the given version.
You can find the shellscript as a gist on GitHub
Put the script into
assert_sdk_version.sh, and put the following at the top of your
Makefile, and voilà! Builds should now fail with a more understandable message if someone’s using the wrong NDK version. :-)
1 2 3
If you’re curious how this works: It checks the
tools/source.properties file in your Android SDK, looking for a line like
Pkg.Revision=XX, and extracts the version (
XX) from that.
It’s pretty straight forward, but I couldn’t find anything online on how to check the SDK version from the command line, so I figured I’d share it.
A little busy the past two weeks (Diablo 3 and a lot to do at work), but here’s what I had time to do:
- Reworked minimap
- Inventory management
- New spell, “Barrier”
- Non-active player switched to Behave-based AI - he now shoots at enemies!
I added some rudimentary (but functional) inventory management:
Didn’t get too much done this week, but I cleaned up the minimap:
I also added a dungeon level indicator:
And finally I switched the non-player character to use the same AI engine as the zombies (AngryAnt’s Behave), though with a different behavior tree. So far this just means that the non-player character actually attacks enemies. Woo!
Hopefully I’ll have time to make the inventory management more complete and do a dev diary this weekend. We’ll see.
This week I added level transitions and automatic saves! :)
Not too much time this week: I added a second (simultaneous) character and some more rudimentary UI.
EDIT: Eventually I expect to have a certain chance that a level will be a “special” level that’s been made by hand instead of randomly generated. Same for rooms - some of them will be “special” rooms.
There’re a lot of improvements that can be made to this approach - and so far it doesn’t add much content to the rooms, just the infrastructure. Here’s a quick explanation of how it currently works!
Rooms are created as regular 3D Unity GameObjects, complete with scripts and all. Then, the dungeon generation script takes each of these objects, converts their dimensions to a 2D tile-based system and determines where the room has openings for corridors.
Rooms are split into “large” and “small” rooms, so that the engine can produce many small rooms and a couple of large ones, depending on what feel the level should have.
The script then chooses a random number of rooms of each size, based on a range for the level. For each room it wants to place, it picks a random rotation (n * 90°), and places it at a random location in the world. If the location is taken by another room, it starts searching for a free spot outwards from the initial random location.
Large rooms are placed before small rooms, to prevent the fragmentation from getting out of hand. A random “large” room is picked to be the “spawn” room.
Monsters & loot
Each level has a configured range of “monsters per tile”, like [0.1, 0.4]. For each room, it picks a random number in that range, and multiplies that number with the “square tileage” of the room. It skips the “spawn” room.
Currently, the spawn algorithm is very naïve. There’s also no loot being spawned.
Then, each “opening” in a room is connected by the shortest path to a neighboring room (using an implementation of the A* algorithm), but if a room has more than one “opening” then they are connected to different rooms. We tell our A* to count unpathed tiles as a bit more expensive than pathed tiles, so that paths will get reused.
Finally, each room is connected to the spawn room to ensure that we don’t have any disjoint “sub-dungeons” that aren’t connected to the rest of them. This time we configure our A* to count unpathed tiles as much more (currently 20x) expensive than pathed tiles, to encourage it to not create unneccessary paths.