About Quest of Magic
Quest of Magic is a 2D side-scrolling action game with RPG elements. You select a starting race (e.g. Human, Dwarf, Durian) and an available preset for it (e.g. Warrior, Mage) and jump into in an action side-scrolling platformer.
While playing, you collect items and grind experience, making your character stronger.
About this DevLog
This DevLog is meant to outline the progress of the game's development, presenting my thoughts, decisions and issues during each step. I originally uploaded the game when the Beta phase started, so everything prior to this is mostly for the sake of completeness.
I've always wanted to make a fantasy game where magic and crafting are full of possibilities. I have occasionally toyed with various ideas, such as having various elements that interact and combine with each other to generate multiple effects. However, most such paths lead to overly complex systems that are difficult to easily get the hang of. I wanted something much more easy to understand but limitless in its possibilities.
After painstacking thought and a lot of trial and error, I arrived at the idea of having few magic elements with unique properties that imbue those properties in the spell being casted. My vision was for the player to add elements to a spell, each contributing to a different factor. After careful consideration, I arrived at the following basic spell properties;
- damage (including things like ongoing damage)
Conveniently enough, those basic properties can easily be distributed to basic elements; Air can obviously produce spell movement, Water can be attributed as extending spell duration, while Fire usually deals massive damage. Admittedly, there is not place for Earth in this list and this just rubs me the wrong way, but I could not come up with anything else that would meaningfully interact with a 2D environment. I also decided to correlate spell area with spell duration and have the spell diminish (in size) as it deals damage.
After roughly outlining the above system, I realized that I also wanted spells to interact with each other; particularly opposing spells. In the end, I settled towards clashing spells diminishing each other, thus making high-duration elements (such as Water) a form of counter-magic.
With this starting aspirations I dived into the first cycle of development.
I chose to develop Quest of Magic in Java, mostly because it's the easiest language to debug (raising a detailed exception trace without explicitly using a debugger is a huge advantage), the scope was light enough and the engine simple enough to develop from scratch.
I started development in 2014. In the first prototype, my main emphasis was put towards creating a coherent physics engine that seems to produce the envisioned magic and item interactions. The art was exceedingly horrible and characters could only cast spells.
In later prototypes, I also introduced a simplified way to use items, as spawnable projectiles. I decided to go for item durability and break rate and make items of the same material repair each other. Then I noticed that items worked surprisingly similarly to spells (i.e. had movement, duration, damage/defense components) and thus decided to implement a crafting system that could bind spells on items. This quickly resulted to overpowering items, making me introduce a break rate increase through crafting.
Having mostly completed the crafting system, I then decided on a semi-random terrain generation algorithm. In earlier games I had developed, I opted to go for a fully-random approach, resulting to interesting terrains but with a repeatable feel. Here, I wanted to try something different, so I made a generator that randomly selects chunks among a predetermined set. This seemed to work reasonably well, so I stuck with it.
Nearing the end of this first development period, I realized that my (decent for the time) computer had trouble keeping up with the physics engine and decided to make processing multi-threaded. This naturally resulted to all hell breaking lose, as multiple threads competing with the same terrain objects was frequent enough. Not wanting to make multiple locks that would slow down the system and gobble-up more memory (it did not suffice to just make all functions synchronized), I opted to have a different process function for terrain objects that would run in parallel difficult calculations (mostly AI decisions) and another function to be called after joining the threads to apply those calculations (e.g. make the AI decisions happen). This mechanism worked well in the end. I don't know how game engines usually handle multi-threading, but I presume they employ a similar method.
As I was repeatedly testing the game, I realized that it was tempting to just have a bunch of high-level saves and switch between them each time I opened the game. However, this was not the experience I wanted to present. I wanted players to stick mostly with a single character they had groomed. Furthermore, the ability to select among so many races and presets when starting a new game seemed to be tiring and detrimental to the experience.
Searching for some sort of cost for loading high-level characters, I initially toyed with requiring some amount of money, but this just didn't feel very intuitive. It was then that I was inspired for the Karma mechanic.
Karma would be needed to load high-level previous saves and would be hard to come by (it would naturally accumulate while playing though). This approach solved the multiple-save problem. Furthermore, I could also lock components out of the game, requiring Karma to unlock. This way, fewer but more meaningful choices are presented to the novice player, while still retaining all possibilities. In addition, I also made most merchants unlockable with Karma, so that grinding would have to also aim towards karma instead of just money. Finally, as now situations developed with a lot of unloadable high-;level saves, I also introduced the possibility of trading high-level saves with Karma. As a last touch on the mechanic, I also allowed for some items to have Karma requirements in their usage and introducedRagnarock, a sword that kills almost enything in one hit but depletes one Karma to use.
At this point, I was creating presets for various races and realized that, although I wanted to create a playable healer class, I had no way for them to defeat the enemy, unless they were undead. Hence, I introduced the concept of losing conviction if healed enough. This made the healer the bane of fighter classes, as I decided to base the loss of conviction and resistance to it on max magic.
Finishing Alpha Development
After the above first development period that lasted half a year, I was satisfied with the learning experience and tossed the project aside as a partially finished idea that needed a lot of polish before completion.
I came across Quest of Magic again while digging through some backups during the summer of 2016 and decided to further develop and polish it. Indeed, with some aesthetic improvements, such as better animations (thanks to Pivot) and replacing programmer stubs with something less representative of chaos theory, I was actually satisfied with the general look and feel. Furthermore I got to implement the item I always aspired to find in a game; a Blanket that is good against Ghosts!
After also strengthening dark magic influences with the ability to destroy graves with Necrotic damage to produce undead and the Ghost Caller item, I deemed the project suitable for a serious release, hopefully gathering feedback as it progresses.
So, here we are! I will further add to this blog post as the game nears its completion.