Here's the next development update for Flashcard Clash, a fun game to help study Japanese. Not a lot to publicly show this week, as there's been a bit of backend database tinkering, but i'll get ot that in a bit.
The big change this week was actually pretty simple, changing the 'reviews remaining' counter to show the actual number of answers the player needs to give before they are done.
Some backstory is needed for this. Cards in Flashcard Clash can have multiple 'sides' or questions to them, for example a vocabulary card could have 4:
I think this gives a deeper understanding as it requires the player to pull out the knowledge in different ways,
So the player will need to answer those four sides correctly before that card is considered completed. Now coming back to the reviews remaining counter, since it was based off cards remaining, it would only tick down sporadically, about once every four questions.
This leads to a bit of ambiguity in how much work actually remains for the day, which can be slightly disheartening. Now that the counter has been changed to show the number of individual answers remaining, it ticks down with each answer, giving in indication of progress every time, which feels better.
Following up on the new way I’m storing and handling vocab cards from last week, I do not like how the final result is in game.
Currently a vocabulary card in a deck will accept any possible answer, eg: the game might accept お父さん or とーちゃん or ちち for the word "father". Which is all well and good in that you won't get a card wrong if you gave the wrong word that meant the same thing. The bad part is that it was intended for you to learn a specific word, for example in Yotsubato learning とーちゃん for father, and you can skip around that giving a different answer. Which means you'll pass the card and think you've learnt it, but then not be able to read it in the manga since you studied the wrong answer.
I think the correct way to go from here is have a card only cover a specific reading and meaning of a vocabulary. And if you answer with a different reading or meaning, the game can say "that's not the answer we're looking for" and let you correct it and carry on.
But before I do that, I need to update the editor so I can more easily create vocabulary and eventually be able to select what meanings/readings I want for a card.
That's it! That's what happened this week!
So I'm going to attempt to try and to weekly updates on the status of Flashcard Clash. Even tho I figure most of the changes are all backend technical things that usually don't have any pretty pictures to go along with them. I hope you like words!
I've added prestiging to the game, basicly once you've battled through enough dungeons and it's too hard to contine, you can reset all your characters and the dungeons back to level 1. In doing so, you get rewards for how far you progressed and these rewards make it easier to go deeper the next time round.
Currently the rewards are pretty slim, just a useless gem, and there's not even any fanfare animations or sparkles. But I wanted to add it in anyway as my own personal account was running into a dead end and I needed to reset my progress :P.
We've been working hard behind the scenes with Ariane for a little while now to get our main characters animated before we can start showing them off publicly. One of these characters, the Adventurer, has a scarf that turned out to be a bit of a challenge to animate. A scarf animation is pretty simple technically, the first bone swings backwards and forwards about 15 degrees in a smooth motion, and each child bone swings the same way, but is slightly delayed. Hopefully you can make that out in the animation below:
It's pretty simple to animate the first bone, you just set key frames for the left and right positions and Spine will animate through them in a smooth motion. Which you can see as the red checks in this very exelent diagram I have created.
The trouble comes when animating the second (green) bone, beacuse it's delayed, you can see that it does not have a check on the orange line, which is where the animation starts. Te way Spine works, is all bones will be in their default position at the start of an animation, and the first time they are keyframed, they will jump to the correct position, so you need a keyframe on the orange line.
We could add a new keyframe at the start of the animation, but we'd have to manually work out the start position and somehow adjust the interpolation so it matched the existing stuff. Which all seemed like a bit of a pain.
Note the keyframe on the far left, before the animation starts. Being able to set a keyframe there would be my dream solution to this problem, but alas Spine does not support that.
My solution as a programmer was to overengineer things, and precompute a sin wave and use that to set the angles for the animation. For this I used the most powerful program in the world, Excel.
In the far right columns you can see what angle the bone needs to be at what frame, which was easy enough to setup, but a lot more effort than just having left and right keyframes with smoorth interpolation. The bonus was that for the child bones, we could just copy and paste these keyframes and delay them easily.
Another option mentioned on the Spine forums was to force the animation to loop between a set of frames, ie: use frames 50 to 150 instead of 0 to 100. This would have worked as well but it kind of breaks everything else that expects animations to start at frame 0 and end at the last keyframe, like exporting gifs. The game code would also have to be updated to support this.
Previously all cards in Flashcard Clash are free standing, with a bit of text for the question and answer. It's a little bit more complex than that, with things like dynamic cards, but it's still all based on a fixed set of text on the cards.
Currently reusing cards between decks is possible, but error prone. So adding a new type of card which is slimplified toto "this card uses this vocabulary" will make it easier to stop cards being accidentally duplicated. Which also means that if you learned a word in one deck, you can skip it in any other deck since the game will know that you already have it.
Longer term i'm looking to have things like automagic substitution for nouns, eg: currently I have a card that switches between "there is a cat" and "there is a dog", but those permutations are fixed. What I'd like to have one day is that if you learn "fish" then that card will dynamicly pull that in and become "there is a fish". That's a long way off, but the first step is building a solid vocabulary in the database to be able to reference.
Currently the only Vocabulary cards are the new ones I'm adding to the Yotsuba decks. I'll need to go back and convert previous cards, and cleanup a lot of those old decks in general, but I'm just focusing on the things I am studying at the moment :P.
That's it! That's what happened this week!
Since Flashcard Clash can be run in the browser, I've tried to keep it as tiny as possible so it can be downloaded quickly. Also keeping the size down allows me to bundle all the assets in with the game on mobile platforms like Android, so there's no ridiculous second download process once launching the game. Specifically with audio assets, there's two parts, music and sound effects.
The music is created by Juhani Junkala in a 'tracked' music format from the 90s called Extended Module or XM. Tracked music allows you to create instruments as sound samples (eg: a single drum hit) then reuse them throughout the song, as opposed to more regular music formats that just stores the final sound data directly (eg: multiple drum beats with a voice singing over it). This means that tracked music can be smaller than the regular formats, which is great for us.
Originally I was using libxm to playback the music, it was easy to add to the game and use, but it sounded too different from the output of MilkyTracker, the tool Juhani was using to create the music. This brings me to what seems to be a common issue with XM music, every piece of software I’ve tried seems to play it differently. I think this is due to there not really being a definitive description of the format since it is based off what people have inferred from digging through the output of FastTracker2, the original tool to create them.
Luckily for me, Miky Tracker is not closed source, and the licensing for their playback library is permissive enough to use in my game. So by using that, I can ensure that the songs will sound exactly as the musician intended. There was just a day of hacking on the library to rip out all the things I didn't need, create a simpler interface for the game to use, and to create a wrapper for the code as it is written in C++ and the game is written in C.
On the sound effects front, instead of using a normal format that stores sound waves like a WAV file, I've forced Juhani to use BFXR instead. BFXR lets you create parameters for sounds, so that they can be generated later by the game. Since we are only storing the parameters and not the actual sound, the asset size is much smaller (currently 28kb vs 2.5mb). While these sounds can be a bit simple, BFXR also allows us to layer them together which improves them somewhat, and since the game is going for an old school JRPG kind of feel that does not hurt either.
BFXR hasn't always been awesome tho, we've had a lot of trouble with it breaking files, and also being very specific about what it can load. I didn't even know that SVN changed the line endings of text files until BFXR files stopped loading after I committed them.
BFXR is also open source, but it was written in AS3, which is a different language from the game. It wook a while to copy the code to C and get it running, but hopefully that’s sorted now and I don't need to spend any more late nights trying to work out why a sound is borked.
We were originally generating the sound effects in real time as the game ran, but it turns out that was VERY slow, especially on the web version. I have since switched to generating the sounds when the game starts up and storing them for play back as needed. This works ok with 30 sounds, but in the future I’ll need to do something smarter to generate sounds as needed (eg: only generate sounds for a monster when you are loading into a battle with that monster).
Once all that's done we have simple waveform data we can pass off to whatever platform we are running on to play the sounds. Currently we are defaulting to 16bit signed ints, but I think I might try to change to float as that's the native format for web browsers and that will mean less data conversion so it will run faster.
Over the last few days i've been working on a little tool to be able to edit battle formations.
A lot of data for the game, like monster stats and battle formations are stored in the database. Obviously it's not wise to directly update these things in the live database, so I need to be able to set it up in such a way that I can make the changes locally and be able to repeat the changes later on the live server.
I do have an existing setup that does something like this, using numbered SQL files. The server keeps track of the last sql file it ran, and will not run it again. So since the server last ran the number 10 file, i can put all my changes into file 11 and test them locally. Once I push it live, i can run a script that will then process file 11 and those changes will go live.
This works pretty well with low level changes, like adding or changing tables, or other simple things. But adding a battle can be a bit painful, as it involves having to add multiple rows and looking up the monster ids. So I created a tool to edit the battles that you can see below.
It's ugly but it works!
It would be too much work to have the tool creating sql files for every change, so I make it just output a simple save file. This save file is loaded by the update script and it makes the changes to the database to match the save. That way I can edit the file as much as I want, test it locally then update on the live server.
It's a little bit simple right now, but in future i'll move more of the static data into this file, like monster stats, stage backgrounds and music. So it's one stop shopping for anybody on the team to be able to make changes to the game.
The art for the endless mode I mentioned in the previous blog post has come in, and you can see it in the image below:
I've been having some issues with the UI systems in Flashcard Clash, and I was expecting to go in and fix them after the alpha release, but supporting different screen sizes has brought this all to a head. The main issue is that a snapping the ui to pixels will make animations less fluid, so things like windows sliding in and out not look as nice.
My plan with supporting different screen sizes is to make a virtual screen of about 640x480 pixels and approximate the actual screen to it. This should make UIs a bit easier to universally layout rather than having to work with the native pixels that could be anyhting between 640 to 4000.
After spending a day or so converting to floating point for the UI, and another day or so trying to make it not look too blurry when compared to pixel perfect coordinates, I started on supporting resoultion changes whilst the game is still running. The UI system was quite easy to update, I just trigger another reflow and the elements correct themselves, but I also had to rerender the SVGs so they are the correct scale for the new screen size. I still need more work to have the Spine model support changing the underlying texture, but that is in third party code that I don't want to deal with so ill postpone that as long as possible.
I don't think there's anything left in the game to do before the first public alpha test, just cleaning up the site and making sure things make sense for new users.
Recently I was lucky enough to have some people try out Flashcard Clash at the Melbourne IGDA meetup. From that I saw two main gameplay issues that I've been working on.
Firstly when entering battle, the game recieves 10 cards from the server and they are all you get for the battle. The problem with this is that when you are getting brand new cards, you should have to answer them a few times in short succession to help drill it in, and the logic to do this is on the server. But with the existing system, you'd have to finish the battle to send your result to the server snd have the card ready for review. So you'd just work through each card in order, taking on new cards even if you should be reviewing older cards first.
I've updated the game to now download one card from the server at a time, so you can answer a card during battle, and then have it come back for review in the same battle. The trade off is that the game now makes a server connection every time you attack, as opposed to once at the start and end of battle. Since I'm the only one playing right now that's not a big issue, but we'll see how that goes once we get some active players. This also updates the counters at the top of the screen in real time which is neat too.
The second change i've made is to the Endless mode. It was all a bit confusing and allowed the player to jump straight to the boss before they were ready. I've changed it now that the player has to proceed through several substages before the boss unlocks. Previously the player was also able to go back to previous dungeons, but later in the game, this leads to a giant menu of every dungeon the player has visited. Now once the player defeats the boss, they move to the next area and are not able to return.
I've also updated the svg rendering to crop backgrounds to what is actually visible on screen. This is a good speed boost on iPhone where almost half of the background is not visible.
This week has been a lot of playtesting, or should I say actually studying with the game. I've been playing through the Tae Kim decks created by Megumi and fixing any bugs that have popped up.
I had the first actual crash bug in a while related to a badly formatted card causing an infinite loop. Interestingly on Windows, it would plod along forever creating and releasing memory without increasing the total used. Meanwhile on iOS, this same loop will actually run out of memory and crash. I assume the system only fully releases memory once you return control to it.
A second bug had to do with my hiragana to kanji code that I always knew was there. The way the code works is it will auto convert the text the player is entering into hiragana then into kanji if it is part of the answer. Eg: wa-ta-shi-ta-chi becomes わたしたち which is then converted into 私達 as you type. The problem then is when you have another shorter kanji replacement, such as し -> 死 then it triggers first and messes up your string. Eg: わたしたち becomes わた死たち which is not what we want. The current fix is to store the location in the string where the replacement should be happening, so we know 私達 is at the start of a string and 死 is towards the end. It feels a little hacky, but it seems to work nicely for now.
Before and after fixing the bug.
Otherwise there were a lot of little grammar changes to the english answers just to make the game less strict on what it will accept as the correct answer.
With our efforts to pretty up Flashcard Fight in order to release a demo, some problems have cropped up with our fonts. Mainly that the fonts Kristy has selected for use in the updated UI don't actually support Japanese.
There's a saying that "All good things must come to an end," and with the flip of the calendar to the new year, our favorite webmaster, Adam, has decided to focus exclusively now on the development of the language learning game that he's making so useful for you. He's been kind enough to allow me to write to you today from the heart, so I'll share with you how my life has changed because we lived and traveled in Japan and the Far East for more than a decade. Perhaps, partly from my humble words, you can draw some understanding or inspiration about how your life may be affected if you travel and learn about Japan. As Dr. Seuss wrote, "Oh, the places you'll go" and "Oh, the Things that you'll see!"