Software for My Loved Ones: Piggy Birthday

Objective

Tap enough piggies to get a special message.

System

GameMaker Studio 2 Android Game using the GMS2 physics engine.

Story

Made for someone special. 🙂

Everything, except the high-quality last image and icon, was done by me in less than 24 hours to make something someone could download as an internal test from Google Play.

The cute last image and icon were done by my husband.

Slider Puzzle (SPuzzle) Changelog

Cumulative Status is a cumulative summary of all features, limitations, and issues of the most recent version of the game. All other sections list items that are particular to that specific revision in reverse chronological order.

Cumulative Status

Features (Cumulative)

  • Shuffle button gives you a fresh chance at an easier puzzle if you get stuck.
  • Optional autosaving of puzzle progress allows you to pick up where you left off if you close the app.
  • Dark and light themes.
  • Functions offline.

System Requirements (Cumulative)

  • Android Smart Device

Limitations (Cumulative)

  • Only 4 x 4 puzzles.
  • Only numbers.
  • Not accessibility targeted.
  • Banner ad supported.

Issues (Cumulative)

  • There may be significant lag when first entering a screen on resource-limited systems, because of a limitation with Flutter. (1.1.0)

    • The workaround is to never actually fully close the app after starting it for the first time.

    • If this lag is so irritating that it makes you stop wanting to play the game, please send me feedback using the form at my website and mention the CPU speed and amount of RAM you have on your system. I will try to look into seeing if there are any more ways to work around this framework flaw or speed up other parts of my code.

1.1.0

Modifications (1.1.0)

  • Added dark theme option.
  • Added ability for player to turn off puzzle autosaving.

New Issues (1.1.0)

  • There may be significant lag when first entering a screen on resource-limited systems, because of a limitation with Flutter.

    • The workaround is to never actually fully close the app after starting it for the first time.

    • If this lag is so irritating that it makes you stop wanting to play the game, please send me feedback using the form at my website and mention the CPU speed and amount of RAM you have on your system. I will try to look into seeing if there are any more ways to work around this framework flaw or speed up other parts of my code.

1.0.2

Modifications (1.0.2)

  • To further minimize wear on your device memory, I have removed periodic save in favor of only saving when the app is paused or properly closed. If the system crashes or abruptly closes the app, data may become corrupt, and a new puzzle will be created when you restart the app. If periodic save is desired, please create a Feature Request on my website, and I will put it back in.

New Issues (1.0.2)

  • None.

1.0.1

Modifications (1.0.1)

  • Fixed FREEZE for Nokia 1 phones.
  • Changed save data writes to be only as necessary to minimize wear on memory hardware.
  • Edited ads to follow international regulations regarding what can be shown to and collected from children.

New Issues (1.0.1)

  • None.

1.0.0

Modifications (1.0.0)

  • Initial release to Google Play Store!
  • Periodically saves puzzle data in case the app crashes, so that the user can continue the puzzle they were on.
  • Shuffle button gives you a fresh chance at an easier puzzle if you get stuck.
  • Functions offline.
  • Only 4 x 4 puzzles.
  • Only numbers.
  • Not accessibility targeted.
  • Banner ad supported.

New Issues (1.0.0)

  • None.

Slider Puzzle (SPuzzle) Privacy Policy

Below are all the Privacy Policies for all versions of Slider Puzzle (SPuzzle) in reverse chronological order.

1.1.0

Notation

The version number is included in the notation so that is is easier to know the applicable app version of the Privacy Policy you are reading.

  • (💻 LOCAL 1.1.0) indicates information stored LOCALLY on your device. This means that this data is NOT collected and sent over the Internet. However, this also means there is no way to create an account with us to back up your data. Thus, if you uninstall the app, this data will most likely be irrecoverably deleted.

  • (🌐 INTERNET 1.1.0) indicates information COLLECTED and TRANSFERRED over the Internet. If you do NOT want this information to be collected and transferred, the game is still playable if you turn off your smart device’s Internet connection BEFORE starting the app.

  • (💾 AUTOSAVED) indicates settings that are AUTOSAVED when the app is closed or, for smart devices, put into the background. Save writes only occur if the data in permanent memory is different than the current setting.

    • Most of this data is so that you can continue the same puzzle if you close the app. Unfortunately, if this data gets corrupted somehow or you uninstall and reinstall the app, you will just be given a new puzzle.

All Data

Data Description How It Is Handled
Theme Color scheme. 💻 LOCAL 1.1.0, 💾 AUTOSAVED
Puzzle Save Frequency Controls if certain game data is saved or not. 💻 LOCAL 1.1.0, 💾 AUTOSAVED
Puzzle Row Count Number of rows in the puzzle. Currently hardcoded to 4. 💻 LOCAL 1.1.0, 💾 AUTOSAVED if Save Frequency is set to save.
Puzzle Column Count Number of columns in the puzzle. Currently hardcoded to 4. 💻 LOCAL 1.1.0, 💾 AUTOSAVED if Save Frequency is set to save.
Puzzle Sequence Puzzle piece sequence. 💻 LOCAL 1.1.0, 💾 AUTOSAVED if Save Frequency is set to save.
Banner Ad Info See the Banner Ad Info section below. 🌐 INTERNET 1.1.0

Banner Ad Info

This app is supported by Google AdMob ads. At the time of writing, the most recent policy of what Google collects is available at:

If you do NOT want the ad to display, please manually turn off your connection to Wi-Fi and Mobile Data before you launch the app. A blank placeholder will state that an ad is being fetched, but nothing will show up, since there is no connection to send and receive data.

This app utilizes all available Google AdMob settings that minimize data collection, especially from children. Specifically, it complies with the Children’s Online Privacy Protection Act (COPPA) and the General Data Protection Regulation (GDPR) by using the settings listed at this link:

The settings used are:

  • TagForChildDirectedTreatment.yes
  • TagForUnderAgeOfConsent.yes
  • MaxAdContentRating.g

1.0.0, 1.0.1, 1.0.2

The following information is stored LOCALLY on your device. This means that this data is NOT collected and sent over the Internet. However, this also means there is no way to create an account with us to back up your data. Thus, if you uninstall the app, this data will most likely be irrecoverably deleted.

  • Puzzle State – This is periodically autosaved so that you can continue the same puzzle if you close the app. Unfortunately, if this data gets corrupted somehow or you uninstall and reinstall the app, you will just be given a new puzzle.

The following information is COLLECTED and TRANSFERRED over the Internet. If you do NOT want this information to be collected and transferred, the game is still playable if you turn off your smart device’s Internet connection BEFORE starting the app.

This app utilizes all available Google AdMob settings that minimize data collection, especially from children. Specifically, it complies with the Children’s Online Privacy Protection Act (COPPA) and the General Data Protection Regulation (GDPR) by using the settings listed at this link:

Slider Puzzle (SPuzzle) Devlog #2: Let’s Prevent Memory Wear! Release of 1.0.2 to Google Play Store

Story

So, I was thinking about making my own note-taking app a month or so ago, after I first published Slider Puzzle. As I was planning it out, I came across the idea of undo and saving, which prompted me to remember that SAVING, called WRITING in programming can wear down your hardware memory. Flash can only handle like 10,000 – 100,000 writes for its lifetime. After those writes, it will just die and not function anymore. Also, Flash isn’t like an EEPROM in which you can target a specific byte. If you only change a single character in your file, Flash has to change in blocks of data, so it will erase and rewrite over data that you haven’t changed that is in the same block.

Even worse, when I was looking at how Flutter and Windows handle files and remembering how all computers handle it for that matter, the realized the WHOLE FILE is rewritten. This is the limitation of how computers read data. Unlike humans, that can “input” (see) the whole screen at once, computers actually have to read things byte-by-byte. Thus, if you change something at the top of a file, the middle of the file, and the bottom of the file, the computer doesn’t know you changed anything until it reads the WHOLE file. It starts at the top, and reads left-to-right, top-to-bottom, ironically like a winning Slider Puzzle sequence. This means, when the computer is reading at the top, it doesn’t know of the middle and bottom changes. This means that, even if you never made a bottom change, the computer would not know if you had made a bottom change or not until it read all the way to the end. It’s like if you were told that you had to read a paragraph you have never read before out loud and could not skip around.

Data is also stored in a POSITIONAL way. For example, if you REMOVE, data from within a file, all the characters after that point SHIFT up in the file. This change in position, even though the characters themselves don’t visually change, actually changes the file. Think of it like this, you have “ABC”. If you remove “B” to create “AC”, what happens under the hood is NOT that “AC are unchanged and B is removed”; what happens is that “B is changed into C and the last character of the file is removed”.

Anyway, 10,000 – 100,000 writes is not a lot if you save too often. If you save ONCE every day using the low quality memory, that’s 10,000 / 365 which is roughly equal to 27 years [i.e. 10,000 writes * (1 day / 1 write) * (1 year / 365) ~= 27 years]. So now, imagine if you saved every hour, so you had (1 day /24 writes) versus just (1 day / 1 write); that’s only about 1 year! Imagine your phone dying in one year!

Granted, if you have a lot of space on your device, most modern systems supposedly minimize wear by shifting your data around under the hood. It spreads out the writes so that one “cell” isn’t constantly being written to. You don’t see this as an end-user and it just looks like the same file, because the CONTENT is the same. It’s that POSITION of everything in hardware memory that changes.

So anyway, with all that in mind. I decided to change the puzzle to only save if the app was paused (i.e. placed in the background) or closed. No wonder so many games want to save to the cloud. Imagine if all of your online account and game data was constantly being written on your tiny device every fraction of a second. Your device might be toast in a few minutes.

I’m greatly considering if saving is worthwhile at all at this point. Do people care to save their progress, or do they not mind losing it when the app closes?

If you are interested in memory wear and your device’s longevity, here’s a research paper that I found that explains the problem nicely. https://oscarlab.github.io/papers/mobisys19-wearout.pdf

Things I Learned & Did

  • How to use AppLifecycleState.

Slider Puzzle (SPuzzle) Devlog #1: “Flutter Puzzle Hack” Release of 1.0.0 to Google Play Store

Story

So, I am currently trying to live a less materialistic lifestyle, which means, when special occasions come around, I do not want any physical things as gifts. So, what does that mean? Well, it means I am incredibly hard to get a gift for! It doesn’t mean I expect a gift, but if you wanted to give one to me, and knew me well enough to want to try to respect my values, you might end up drawing a blank as to what I would want. Anyway, to help my husband out as my birthday rolled around this year, I told him that I wanted a Game Jam for my birthday. I felt like we had fun making Bug Planet Escape and Signal Crash together, so I wanted to work together again. Granted those two games took longer than a day, but I thought I had a one-day idea in mind already. For the past few weeks, or maybe months, there was simple game idea mulling about in my head, which I knew would be easy to create in GameMaker Studio 2. We wouldn’t have to burn any time having to come up with the game idea on the day of… or so I thought.

A few days before my birthday, since I was so excited about it, I began to more clearly define the design. However, I began to realize that I the concept was not as fully fleshed out in my mind as much as I thought. It wasn’t that I didn’t have ideas, it was more like I was still in the brainstorming phase; I had TOO many ideas. This meant that the implementation was FUZZY, and I could not decide on the ultimate direction of the game. Since I couldn’t form concrete instructions to give my husband, I decided to change to a more clearly defined game. Enter the other thing that was wandering about in the back of my mind.

Before my birthday, I had noticed the “Flutter Puzzle Hack” hackathon. The idea was to create a Slider Puzzle for the web, and there were prizes for the winners. After our first experience with Bug Planet Escape and Signal Crash, I knew that my chances of winning were pretty slim. According to former Google employee, Filip Hráček, the app that will win isn’t necessarily the most “beautiful” and also, you could be competing against TEAMS of like 100’s of PROFESSIONAL developers. The other thing that the entry needed was an unexpected amount of marketing materials, which I immediately knew would be a waste of my time on Earth personally. If Google is going to do a showcase, it should make the resources itself versus push it onto the developer that is already on a time crunch to finish the technical aspect. However, again, that means the target audience for this hackathon was probably a TEAM. One person could handle the media, one could handle bugs, etc. Another drawback to these sorts of things is that you CANNOT monetize your project and it is forced to be open source; the community can take it and do what they want with your idea and monetize it, but you can’t.

So, I thought the Flutter Puzzle Hack was a cool thing, but I had shelved the idea of actually participating. One of the main reasons to shelve the idea was also that I just SUCKED at completing slider puzzles as a kid and didn’t know how to possibly make the algorithm to ensure it was solvable…. or so I thought. As time passed, the Flutter Puzzle Hack just kept taking over my consciousness at random points in the day, and my mind tried to figure out how to code the algorithm. Then, I figured it out…. Suddenly, the temptation to participate in the Flutter Puzzle Hack was breathing down my neck. I had the solution in mind, and it was pestering me to be implemented. Originally, I had shoved this nuisance to the back of my mind, but when I decided to scrap my original Birthday Game Jam idea, this Slider Puzzle game came up.

Since I didn’t really know how to make sliding pieces on the screen with Flutter, I had resolved myself to using GameMaker Studio 2 (GMS2). The Flutter Puzzle Hack was just a prompt, but actually, I just wanted to make the Slider Puzzle game, because I had come up with the algorithm for something that my previous self had thought was impossible for me to solve. The first requirement for the game was that I should be able to place an ad so I could generate income to work towards my dream of making games for a living. Of course, I was in it more for the exercise, but I might as well put the ad in, or else the purpose of the game wouldn’t have any meaning. If I want income, I have to stay practiced in the skills that will generate it.

This meant mobile development in GMS2, since I had a mobile export license for GMS2. However, that’s all that I had. GMS2 has terrible mobile support in the sense of backwards compatibility. I had made a previous game with ads, so I thought I could just reuse that code, but I was GRANDLY wrong. They had completely REMOVED their original Google Ad Mob plugin without warning and left a message in its place to migrate to the next plugin. Basically, I cannot compile and fix my old project anymore, because they pulled the old plugin without warning, and the library is NOT baked into the project; it is linked to your account, so you are basically screwed if you update. Just trying to compile their SAMPLE project didn’t work with the minimum SDK I was targeting for Android. I kept discussing this with one of their support members, but they just could not understand the problem, nor did they bother to even test out the sample project themselves until like the 4 or 5th email. In fact, their email was so vaguely worded, I don’t even know if they did it in the end. This reminded me that they also notoriously do NOT let you change the Android versionCode yourself.

Anyway, since I couldn’t get my old GMS2 code to compile nor the sample project, my “easy” jump start approach basically failed. The lackluster experience with GMS2 support didn’t help either. So, if I really had to start from scratch, I decided I would make the game using Flutter, since I also had a previously working app with ads there. I began to laugh, because this jam would line up with the Flutter Puzzle Hack, and I entertained the idea of entering it. However, I confirmed that it was for web only, needed media materials, and needed to be open source and free; which means, I re-resolved myself into not actually entering.

The sad part was that changing to Flutter meant that my husband couldn’t participate as much as I planned and that the project would probably take more than a day. Way before this, I had taught myself how to do remote Git hosting so that I could work with my husband in GMS2. He’s not a programmer, but generally understands GMS2. Version control was a nightmare during Bug Planet Escape and Signal Crash, so I wanted to use this Birthday Game Jam to set up a better coordination method. I researched and tried several hosts, and finally ended up on one. I painstakingly then went through the whole process of learning to push, branch, etc., so that I could explain it to my husband. Originally, I was going to make a tutorial series for him to watch on YouTube, but my video production skills are really slow, and I didn’t have a lot of time. I even researched a beginner friendly UI for handling Git. I had basically got all this research done for collaborating with him, only to not use most of it.

Okay, back to the Flutter. I originally didn’t want to use Flutter, because I didn’t know how I could create the sliding motion. However, my husband reminded me that it would be okay to just teleport the numbers. It’s not a “slider” puzzle anymore, but at this point, I just wanted to prove the algorithm worked and, at the end of the day, I wanted to work on something with my husband. So he handled the design and graphics, and I did the coding; it was just like our GMS2 projects, except that he didn’t have the set up to compile and test it.

So, sometime when I was being proud of getting basic functionality, Very Good Ventures, in partnership with Google, PUBLISHED basically “the answer” to the Flutter Puzzle Hack online. They published a sample code that you could just grab and edit. It felt kind of like a slap in the face really. Why give us the answer to the challenge. I’m pretty sure it was guide us into some basic quality and help beginners feel like they actually made something cool. That’s nice…. However, I think they should have provided the example in the FIRST post of the rules, not AFTER people have been working on an implementation already. Anyway, since I wasn’t even entering the contest to begin with, I told myself to avoid using the shiny thing, and keep trying to get better at writing from scratch. My game would not be flashy and have nice code structure and documentation, but it would be MY code. It would be my battle scars.

So, like a lot of coders, I continued to do it the hard way. No one will know how awesome it is under the hood, because it’s not as flashy and fancy as code made by a team of developers, but I can say that I coded it without copying the “answer”. I actually skimmed over the “answer” to see how close I was, and it looks like it uses the Bloc Architecture. I definitely wasn’t going to waste time switching over from Riverpod. Also, my guaranteed solution algorithm was completely different from theirs. I also didn’t use super fancy packages, and just used those that can be traced specifically to Google or are Google Favorites (except Riverpod, which is the successor the Flutter Favorite Provider) to try to ensure security and stability.

I’m so proud of us for actually pretty much making the deadline. If we had started at the time the Flutter Puzzle Hack was actually announced, I’m fairly certain we would have made the March 14, 2022 deadline. The app itself was done; I just didn’t have the time to bundle, sign, gather media, etc. for review in the Google Play Store. However, all of that was resolved in a week or so, so I’m happy. 🙂

Anyway, have an awesome day! Thanks for reading!

Things I Learned & Did

  • Became acquainted with Flutter statement management using Provider and Riverpod packages.
  • Learned null safety and Dart null syntax shorthand.
  • Learned the definition of mutability and immutability, and its importance in state management.
  • Gained a clearer picture of the difference between the Dart language and Flutter framework.
  • Learned a significant amount of Dart classes and syntax.
    • Dart style tends to use single quotes (') verus double quotes (") to denote strings, although both are still valid.
    • Three quotes (''') or three double quotes (""") observe whitespace characters, like newline characters, as TYPED in the CODE. So you don’t need to use '\n'.
      • These can be combined with regular strings with the + operator.
    • Learned that Lists can be O(1) with hashmaps.
    • Learned what a hashmap is.
    • Learned that underscore (_) defines scope, or, if it is a parameter, it is just a placeholder variable name convention (having other passed-in parameters that have more than one underscore just the parameter names different from each other to meet the syntax regulation of having uniquely-named parameters).
    • Learned keywords part versus library versus part of.
      • Making a dart-file a part is like making c-file which will have other C-FILES included into it using a preprocessor directive (#include "file.c").
      • Making a dart-file a part of is like including it into the part file that you specify.
      • There can only be only one part, but multiple part ofs and they are all treated as one giant file.
        • Putting part of 'cat.dart'; at the top of a file means that it is considered as part of the cat.dart file.
    • Keywords final versus const.
    • Learned you can rename the library in the local context using as in case there are name collisions between libraries.
      • import 'global.dart' as globs;
      • Then use it like this globs.ClassInGlobalDotDar.
    • Named constructors.
      • Cat() verus Cat.sleeping().
    • Optional parameters, required parameters, positioned parameters, named parameters.
  • Gained a clearer picture of what the three Flutter trees do and how they interact with each other:
    • Widget
    • Element
    • RenderObject
  • Learned the difference between imperative and declarative programming.
  • Learned what Flutter keys are and why they are needed since the Widget Tree looks at Widget Type and not an object ID to determine redraw. Keys enforce an ID if an object must move around the screen via an automatic or used-controlled animation.
  • Used SharedPrefrences to store and read from non-volatile data.
  • Learned what a Tuple is.
  • Gained a better idea of how the google_mobile_ads Flutter package works.
    • Relearned how to implement a banner ad.
  • Implemented an implicit animation.
  • Got REALLY GOOD at solving 4×4 puzzles during testing. I remember being frustrated at not being able to do it as a kid, so I feel so smart now.
  • Created a custom Snackbar widget.
  • Used a Stack to create a complex layout.
  • Relearned the difference between a Stateless and Stateful widget.
  • Relearned how to create a timer.
  • Had a eureka moment in understanding asynchronous and synchronous code.
    • Learned about isolates.
    • Heavily used the "await" keyword and didn’t block main thread.
    • Learned that a Future.delayed(Duration.zero,(){} is useful if you want to postpone the execution of a function in init() to occur AFTER the first called to build(). An example scenarios is if you want to display a SnackBar for an error during init(); SnackBar requires a BuildContext, so build() needs to have been called once or else you won’t have any draw context for the SnackBar to attach to and pop off from.
  • Learned about Semantics and about Flutter’s accessibility features.
  • Gained experience in trying to use TalkBack.
  • Became acquainted with Git, GitHub, and Bitbucket.
  • Learned how to push.
  • Learned how to tag.
  • Learned how to pull.
  • Learned how to branch.
  • Learned how to navigate GitHub.
  • Learned the Markdown language and how to use MarkdownBody from a Flutter package.
  • Learned how to rebase.
  • Learned that commit is local and pushing is to the remote (i.e. Internet Hosted).
  • Learned how an amended commit works.
  • Connected my local repository to the remote repository.
  • Learned how to use GitHub Desktop.
  • Became more acquainted with Advanced IDE capabilities, in particular, for VSCode.
  • Learned that "///" will help you make comments for Intellisense for your code. Using "///" versus "//" will cause the "///" comment directly above a function, etc. to pop up on a mouseover of the function name in other parts of the code.
  • Learned how to use code snippets.
  • Learned that VSCode can automatically reformat your code to a particular style on saving a file.
  • Learned how to create my own VoidCallback to passthrough a custom onPressed function to a custom button I made.
  • Relearned how to implement a:
    • Scrollbar.
    • ListView.
    • Scaffold.
    • SafeArea.
    • DeviceOrientation.
    • showDialog() with an AlertDialog.
    • Image.asset().
    • showLicensePage().
  • Relearned how to import your own .ttf fonts.
  • Learned about and used extension methods.
  • Learned how to create a ModalBarrier.
  • Learned how to properly use a LayoutBuilder to get the parent height and width verses using MediaQuery. MediaQuery is a global call for dimensions.
  • Learned how to check the type T of a generic class to only implement it for specific types and throw an error if it that type is not implemented.
  • Learned the existence of assert() and the difference between using assert() and throwing an error/exception.
  • Learned the difference of the Dart Team’s differentiaton between an Exception versus Error.
    • An Exception is something that the program should be able to recover from, kind of like a switch-case for expected possible problems. If properly handled, the user will probably not know that an Exception has occurred.
    • An Error is an irrecoverable state in which the program probably will display an message to the user and shutdown. The developer might want to store some state information to crash logs to look for the BUG that caused this Error to trigger.
  • And much more that I’m probably forgetting to write!

Slider Puzzle (SPuzzle)

A pretend slider puzzle that has pieces that are made up numbers and the letters that make up the game name "Slider Puzzle".

How To Play

This emulates a physical slider puzzle. Tap on a numbered piece to move it into the adjacent blank space. The goal is to get the pieces into sequential order from top-left to bottom-right going left-to-right and top-to-bottom.

Features

Some of these features may not be available yet, because we are in the process of publishing the newest version. In particular, autosaving cannot be turned off yet, and the dark theme is not available yet.

  • Shuffle button gives you a fresh chance at an easier puzzle if you get stuck.
  • Optional autosaving of puzzle progress allows you to pick up where you left off if you close the app.
  • Dark and light themes.
  • Functions offline.

The above is a list of features for the most recent version of the app. If you would like to view the changelog for your specific app version, please see the following link:

https://whitemagehealinggames.wordpress.com/2022/09/17/slider-puzzle-spuzzle-changelog/

System Requirements

Android smart device.

Known Issues & Limitations

These are only for the most recent version. Feel free to ask for features. If enough people request them, and I have the resources, I’ll try to implement them.

  • Only 4 x 4 puzzles.
  • Only numbers.
  • Not accessibility targeted.
  • Banner ad supported.

Install Options

Credits

CONCEPT & DEVELOPMENT

UI & UX

https://skykiyabu.com

Privacy Policy

Any permissions that this app requires are for advertising (i.e. requires the Internet). Other than that, this app does not collect any information from you, and should not require any unusual permissions like access to photos, contacts, etc. If it does, please contact me IMMEDIATELY, because I would have to work with the app hosting site to look for a breach in app integrity.

An itemized of list of how your data is handled, organized by app version, is available at the following link:

https://whitemagehealinggames.wordpress.com/2022/09/17/slider-puzzle-spuzzle-privacy-policy/

Future

These are some future features I’ve thought about implementing; however, they may require a great time commitment on my part. I am working on my software in my free time, so I may not implement these UNLESS you send me a Feature Request. Submitting a Feature Request shows me that you are interested in it and will use it when it is implemented; in other words, it will be worth my time to implement because it will make your life more enjoyable to live.

  • Sound.
  • More puzzle sizes.
  • Pictures.
  • Themes.
  • Better accessibility.
  • No-ad mode unlock.

Contact Me

Do NOT put private information in this form, because I’m not sure how secure it is.

Unfortunately, the only way for me to be able to contact you if you would like a response is if you leave your email address. Also, unfortunately, depending on how crazy my life situation is, I may not be able to respond to all feedback.

DevLog

Legalese

Google Play and the Google Play logo are trademarks of Google LLC.

Radical Blocks

Gameplay

Tap the blocks in the correct stroke sequence for the target Japanese Kanji to score points! As you get more and more points, the game will get more challenging with extra distractor blocks and a faster fall speed.

System Requirements

Android smart device.

Known Issues and Limitations

These are only for the most recent version.

  • It only has target kanji for 1st grade.
  • Current version is ad-supported.

Install Options

https://whitemagehealing.itch.io/radical-blocks

https://play.google.com/store/apps/details?id=roxanne.whitemagehealing.radicalblocks

Privacy Policy & Credits

This game is supported by ADS using Google AdMob. If you do not want to send data to this service, please play the game without Internet (i.e. turn off your WIFI and mobile data temporarily). The ad screen will still be there and attempt to fetch an ad, but the ad shouldn’t load.

Future

These are some future features I’ve thought about implementing; however, they will take a great time commitment on my part. I am working on my software in my free time, so I may not implement these UNLESS you send me a Feature Request. Submitting a Feature Request shows me that you are interested in it and will use it when it is implemented; in other words, it will be worth my time to implement because it will make your life more enjoyable to live.

  • Sound.
  • More than just first grade kanji.
  • Zen mode with controllable speed and no high score.
  • Ability to select available target kanji.
  • Ability to turn off English.
  • Affordable ad-free one-time payment version.

Contact Me

Do NOT put private information in this form, because I’m not sure how secure it is.

Unfortunately, the only way for me to be able to contact you if you would like a response is if you leave your email address. Also, unfortunately, depending on how crazy my life situation is, I may not be able to respond to all feedback.

Reasons for Limitations

Why only first grade kanji?

Creating this kanji matching database isn’t automated. I have to manually input every target character, valid character, English definition, Japanese definition, etc. It’s a tremendous amount of work, so if no one is play my game, then I don’t want to waste my precious life on it. This game already took a little over half a year of my life away. If there is interest; then I maybe I can make a Kickstarter or something.

Why do some strokes look weird?

Some strokes look weird because that is a limitation of the Unicode Standard. Unicode characters must exist in certain way and if the Unicode administers haven’t added a specific stroke to the Standard, even if it exists in outside of the tech world, it will not exist in the font. Also, it is completely up to the Font Creator (person who makes the font) if they want to implement the Standard; they could choose to not include that character at all. I could painstakingly make custom images by hand and manually make a my own “extension to Unicode” locally, but that would take a long time. It also would slow down the game and take up a lot more storage space on your device. If there is interest; then I maybe I can make a Kickstarter or something.

If the target character appears in the component falling blocks, why can’t I use that as the correct answer? Why do I have to only select the strokes?

Although it is possible to have the “same character” “appear” as a component falling block, that is not what is actually happening. When that occurs, it means that the target kanji is also considered a RADICAL. Falling blocks consist of only strokes and radicals, so if the target kanji, itself, counts as a radical, it might show up as a falling block. Why can’t I just accept this as the right answer anyway? Well, that would mean I would have to manually scrub through all Unicode character duplicates and make special cases (may cause game lag) for EVERY kanji-is-also-a-radical overlap.

The RADICAL for 木 is a different Unicode number than the KANJI (under the hood, every character is a number) and in order for them to match, the numbers must be equivalent. So even though they look the same visually, the numbers can be different. I don’t make the rules; I’m a victim of them like everybody else (even their creators!). Don’t get me started on character and stroke variations! Even as I type this webpage, I’m cheating with whatever Unicode 木 I copied from some other page without checking which block of Unicode it is actually coming from. Is it a radical or is it its own kanji?

I’ve already scrubbed through the whole radical and stroke set to make the current version of this game happen; that’s like 2,000 characters or something. That doesn’t even include stroke VARIATIONS. I don’t mind trying to do it; however, it will take a SIGNIFICANT amount of time. If there is interest; then I maybe I can make a Kickstarter or something, but I would also require TREMENDOUS amounts of debugging help from players like you. 🙂

Fun Fact: The fallings blocks used to consist of radicals, strokes, AND all kanji (used as distractor characters to make later levels more challenging); however, the overlap between the 20,000 kanji characters that I had to look through to try to accept all legal matches was just too insane, so I had to chop out all the kanji to save my sanity. It’s possible if I hire a team of Unicode linguists or something, but I certainly don’t have that kind of money.

Why is the only answer to select the radicals first and then the strokes?Why do I even have to select the strokes anyway if there is a radical equivalent?

Imagine you have a character that has several radicals and strokes. For instance, consider 森. Now, this character can be considered to be any of the following:

  • 木木⼀⼁⼃㇏
  • 木⼀⼁⼃㇏木
  • ⼀⼁⼃㇏木木
  • 木木木

If you wanted me to accept ALL of these answers, I would have to painstakingly go through EVERY target kanji character and check for EVERY possible permutation and input all that by hand. This particular character isn’t even as difficult, because it has radicals that are the same; imagine if the radicals were different! Which radical would you choose to break out into strokes? So if you want me to accept all of these answers, you should be willing to note down all permutations yourself in a spreadsheet and send them to me. ALSO, don’t forget, you need to use the Kangxi Radicals Unicode Block, CJK Strokes Unicode Block, CJK Radicals Supplement Unicode Block; NOT the CJK Unified Ideographs, extensions, or supplements (unless you are designating the target kanji).

Why are some of your fonts not nice and rounded like fonts in other areas of your game?

So, there is a dearth of free rounded attribution-and-royalty-free fonts that have ALL the characters I need. To make this work, I actually had to combine more than one font. Strangely, and I don’t know WHY, but creators of these fonts do not FILL all the characters in the kanji sets and leave some Unicode spaces in the block unimplemented. Maybe those characters just were defined in the standard when the font was made, or maybe they figured the system would use a different code for substitution. In one case, the character in the font was just plain WRONG, so I don’t know if the person just put accidentally or purposefully put the “wrong character” (i.e. not what the standard says) in the Unicode slot or if the standard changed after they created it. In any case, I had to manually decide which font of the following two to use whenever I drew a kanji, radical, or stroke to the screen:

Handling Asian fonts is a currently a HUGE pain in Game Maker Studio 2 in English. It doesn’t want to import nicely (i.e. too many characters), so you have to load the whole font at once at runtime instead of generating a font asset. I’m not sure how it is in Japan, but hopefully it is better in their own country with their own gamemaking frameworks.

Things I Learned To Do During This Project

  • Use GameMaker Studio 2 (GMS2) to create an Android game.
  • Figure out .aab format versus .apk.
  • Deal with multiple unknown phone aspect ratios and Android phone emulation.
  • Work with Google AdMob banner, interstitial, and rewarded ads in GMS2 and allow the viewing to be player-controlled and rewardable.
  • Handle persistent local game data storage of high score and ad-unlock (i.e. no cloud storage, and the data will be deleted if the app is uninstalled).
  • Create the ad screen that does not load when ad-unlock criterium is detected.
  • Randomly color assets at runtime using blend modes (using GMS2’s strange backwards definition of BGR versus RGB color values).
  • Change the shading of a button to show when it is active or deactive.
  • Swap .ttf and font asset texture at runtime to handle lack of a full Asian font in the style I wanted.
  • Optimize font handling and frontloading font files to avoid lag during main game play.
  • Learn how crazy Asian Unicode character overlap and font underdevelopment is for free Asian fonts.
  • Import CSV data in the proper UTF-8 encoding format.
  • Test GMS2 android bundles on a real phone.
  • Implement custom tap controls to deal with GMS2 bugs and underdeveloped mobile support.
  • Use Android Studio: Image Asset Studio to generate icons to overwrite the GMS2 generated ones with and work around GMS2′ underdeveloped handling of Adaptive Icons.
  • Implemented a basic pause screen.
  • Debug GMS2 and GMS2 projects, so that I can submit bug reports to YoYo Games as necessary.
  • Create an itch.io page, upload a game to it, and add someone as a collaborator.
  • Create Contact form using Gutenberg on a WordPress.com blog.
  • Work around WordPress.com limitation of NO INLINE images for numbered lists.
  • Learn that WordPress.com makes extra copies of images that you drag and drop into the image block, so it is safer to first upload to the Media Library and link to there to avoid wasting your precious space; “unattached” images are NOT what you may think and may still be used in a post so you need to still be extra careful if deleting any image.
  • Do NOT use reusable blocks in WordPress.com, because they can suddenly go missing (i.e. breaking EVERY post and page that reference them). It is best to just duplicate a previous post you like as a template, and update older posts as needed. (This is for small bloggers like me that don’t need a lot of consistency; for large businesses, they probably want to invest in a business account and find stable plugins that have a custom and safer way to implement reusable block behaviour.)
  • Create a GMS2 utility project to help convert assets into the proper format to use in the actual game project.
  • Create and manage GMS2 Texture Groups.

Signal Crash

Description

An Opera GX Game Jam 2021 entry created by my husband and me. I didn’t contribute as much programming to this one as in Bug Planet Escape; however, I am super proud of myself for thinking up and implementing the 2-player revive mechanic of picking up the damaged player and bringing them back to the mothership! Sky did all the art, animations, sound, and most of the programming by himself! He posted it on Game Jolt on August 13th, 2021.

This in an infinite HTML game that had a small footprint requirement. It will temporarily save your high score so you can try to beat your own record! You’ve lost your WIFI antenna, so let’s go replace it with recycled parts!

Play The Game At

https://itch.io/embed/1225381

https://gamejolt.com/games/signalcrash/638583

Gameplay

Screenshots

Contact Me

Do NOT put private information in this form, because I’m not sure how secure it is.

Unfortunately, the only way for me to be able to contact you if you would like a response is if you leave your email address. Also, unfortunately, depending on how crazy my life situation is, I may not be able to respond to all feedback.

Things I Learned To Do During This Project

  • Work around itch.io’s underdeveloped game page for HTML games.

Bug Planet Escape

Description

An Amaze Me Game Jam 2021 entry created by my husband and me. This is the first ever complete published game for both of us! It is published as a PC Windows game using GameMaker Studio 2. We posted it on June 18th, 2021.

Defend and charge up your rescue beacon to escape the bug planet!

Download

https://itch.io/jam/amaze-me-game-jam/rate/1093092

Gameplay

When I did the screen capture, I actually hadn’t played for a while, so I kept losing at my own game! Hahaha! The winning run starts at about 6 minutes in.

Screenshots & Credits

Contact Me

Do NOT put private information in this form, because I’m not sure how secure it is.

Unfortunately, the only way for me to be able to contact you if you would like a response is if you leave your email address. Also, unfortunately, depending on how crazy my life situation is, I may not be able to respond to all feedback.

Things I Learned To Do During This Project

  • Use GameMaker Studio 2.
  • Implement player movement controlled via a game controller, enemy AI, sound effects, and collision detection.
  • Find free sound asset and sound making resources.
  • Edit sound in Audacity.
  • Enter a game jam on itch.io.