The place where random ideas get written down and lost in time.
2022-06-18 - Android Studio Emulator
Category DEVIn the latest version of Android Studio, the emulator shows up in a pane in the IDE. This is annoying and absolutely unusable on a small laptop screen. How do I get rid of that and have a separate window as usual?
To get rid of that: AS > File > Settings > Tools > Emulator > uncheck “Launch in a tool window”.
Also keep creating the AVD with the “Cold Boot” setting instead of “Quick Boot”. Most of the time the emulator starts “unpowered” in quick boot, nothing on screen, and no idea on how to fix it.
If I had to rebuild Asqare today, which framework would I choose?
Clearly I would use an existing one instead of rolling my own. There are lots of choices out there.
- Godot is one obvious choice. It’s even officially listed in the Using a game engine on Android guide.
- libGDX is another obvious choice for something lower level. It’s not a “full stack” game engine, yet it’s a good foundation for someone to roll their own renderer.
For Jump!, the idea was to use scenes to implement everything in Godot. It’s a Godot thing, which just happens to export to Android. Some functionality can be provided by plugins, such as the screen sharing/export provided by GodotShare.aar → this is done by generating an “aar” library, and making it available to Godot..
For something like Asqare, the native Android implementation has some advantages as the gameplay screen is a view in an actual activity. It would be nice to know how to implement that level of integration using Godot. E.g. ideally a scene is just one view, or maybe one fragment, which is controlled by an otherwise “pure” Android app. That is, I want the reverse: instead of adding android library functionality to Godot, I’d like Godot to generate a library that I integrate in an external android app. This mode doesn’t quite seem supported but this seems the closer we can get:
https://docs.godotengine.org/en/3.5/tutorials/export/android_custom_build.html#
The obvious cons here is that this implies we now have to deal with two tools/frameworks and they might have incompatible release schedules or requirements.
Generally speaking for all these small games, there’s a strong desire to reorganize them in a clear MVP or MVC pattern -- model-view-presenter or model-view-controller. MVC makes the most sense here: the model is the core gameplay, which can be coded in a separate library (e.g. an aar import), the view is an android skeleton and/or godot, and the presenter is godot.
It’s worth pointing out that games like Asqare and even Nerdkill are already architectured like that.
In a sense that seems to run contrary to the default Godot game implementation: Godot naturally tends to architecture a game around its scene graph as being the directing entity. The scene graph is the model. Furthermore entities in the scene graph embed part of their own logic such as collision and event handling.
In the Asqare case, that’s not incompatible with the MVC pattern: the “core” Asqare game can be modeled as a board representation (an array of e.g. integers) and a function computing the name board state as well as a list of view updates. The presenter part in Godot would basically map each board cell to a sprite entity. Updates are actions like select (implemented as blinking or rotating a sprite), vanish, or animate an entry. This is the way the game is currently implemented in its Java micro “game engine”, even though it’s all hard coded functions and nothing is really generic.
From that description, it does read like using Godot for Asqare would be a bit of a stretch actually:
- Godot drives the android app creation, instead of being an embedded view/fragment.
- Godot strives to be the model with its scene graph.
The only benefit of using Godot is to use it as an animation engine (and without having to learn a new one). That’s more or less what using libGDX would do.
I should make the point that Nerdkill on Godot does make a lot of sense. The “scene graph is the model” works fine for Nerdkill.
But what about Asqare. If not Godot, then what?
What do I want, ideally?
- Some kind of scene graph thingy.
- An animation engine with some basic effects.
- Optional: 3d support with an orthographic top view. Would allow to draw elements in Blender and animate them without having to render them to static image maps
- The cons of that is the added complexity of a 3d GL view.
What if we took a different approach? Kotling game engines:
- MiniGDX: https://gamefromscratch.com/minigdx-kotlin-game-development-framework/
- Besides the name, this has no affiliation with libGDX. It uses ljgl and al.
- This is just a one-person game engine with no pedigree and no support team.
- Same person has contributed to libKTX.
- libGDX is well known and documented.
- Does both 2d and 3d.
- https://libgdx.com/wiki/jvm-langs/using-libgdx-with-kotlin
- https://libktx.github.io/
- Korge: https://korge.org/
- https://gamefromscratch.com/korge-engine-kotlin-powered-open-source-game-engine/
- Korge is a set of libraries + some IJ plugin.
- It focuses on 2d.
- Kotlin-is-fabulous indoctrination is a cons.
- That Flutter-simple-game thing?
- Meh to Dart.
- No desire to use it long term.
- Android Jetpack Compose?
In my case, looking at the long-term, say I update an app next in 5-10 years:
- The IDE project may be obsolete. E.g. some of my projects still use Eclipse.
- The project configuration may be obsolete, even if the IDE is still the same.
- Example: gradle groovy now vs maybe gradle kotlin later.
- Who knows about stuff from e.g. Godot?
- The language could become obsolete.
- Example: go1 projects not compatible with go1.5, etc.
- C# has the same issue. I expect Kotlin to have the same issue.
- Java has this “legacy” thinking model which saves it for now.
- Who knows about GDScript?
- Library support for Android and older API models changes.
- Compat library is min 14 these days.
- A lot of stuff at G is min 21.
Having an app/game that depends on e.g. Godot + Android means to have to deal with all that, times 2, for each platform, plus their intersection.
I found the sources for both under the old Autosettings project.
Back then I was using branches, instead of placing such projects in their own repository.
I should move them under their own git repo under bitbucket/ralfoide.
Flashlight matters; Brighteriffic not so much yet I may update it if it isn’t too cumbersome.
In both cases it makes sense to duplicate the autosettings repo entirely to preserve history, and limit it to these app folders only.
<fork autosettings repo>
$ git clone git@bitbucket.org:ralfoide/brighteriffic.git
$ git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached -r AlarmTest branches Flashlight wiki distrib/[aAfqtT]* trunk/AutoSettings trunk/TimerifficTest'
$ git push --force
Spent the last week or so “rebuilding” Asqare.
Only needs “one last little change”.
Tradeoffs:
- See plenty of things I could change in the game, but that would delay release.
- Did a few minor things to make the game usable on Android 12.
- Will release a “1.4” which is mostly the same thing.
- Wrote dev notes and maybe will do a “1.5” that has game changes.
One thing that works well: Android 12 + Android Studio chipmunk ⇒ Wireless Debugging. Enable in android settings, customize a quick setting tile to toggle it. Very convenient to push/debug from AS that way.
Question: can command-line adb also use Wireless Debugging?
For release, using the B3 script to create a bundle (aab), without the flavors.
This produces a signed AAB (for Dev Console) + temporary APKS for local deployment.
My script signs the AAB using the old jarsigner. I had to work around it that way because the key format is old and I failed to update into a newer format.
Issue: the local APKS are signed with a debug key. Which means I can’t push and update an app store signed binary.
⇒ According to this SO, I should be able to sign the AAB with release and thus the APK should be signed too?
For the Dev Console, the only choice is to upload an AAB. I’m using the self-signed method where the console does not sign the APK for me (I think?)
When uploading the AAB: “Error: To upload an Android App Bundle you must be enrolled in Play App Signing.”
When uploading the signed APK: “You uploaded an APK with an invalid signature (learn more about signing). Error from apksigner: ERROR: MIN_SIG_SCHEME_FOR_TARGET_SDK_NOT_MET: Target SDK version 32 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme”
The “signature scheme v2” is explained here: https://source.android.com/security/apksigning/v2
The tool to use is “apksigner” available in build-tool 24.0.3 and above.
However I had already tried it years before and my signature uses an older SHA-1 which is now considered obsolete; I had tried to change the keyfile with no success.
Plan B:
“Google isn't protecting the app signing key for your app. Opt in to use Android App Bundles”
I had to do that for Bearing and Seeds: see “\pɔʁt.na.wak\”
Learning for these:
- The Opt In selection in the Dev console is FINAL. The choices are confusing, poorly explained, and there’s no way to change them later on. <grrr>
- Be very careful to select the option to keep using my signing key and not let the store generate a new one. This is NOT the default and it’s a PITA to use.
- Need their PEPK tool to sign the release key to set it up the first time.
- Need the upload key from the store.
Opt In:
- In screen “Let Google Play manage your app signing key”:
- Use option “Use existing app signing key from Java KeyStore”
- Generated a release key based on my key using PEPK ⇒ that’s the same signature arguments as used for Bearing, so maybe keep that file around and write down where it is!
- Upload release key
- Save
IMPORTANT:
- My keystore has 2 aliases. Asqare uses alias 1. Bearing/Seeds used alias 2. Because history.
In the Dev Console:
- Upload an AAB to the Internal Testing track.
- WAIT for an email from Firebase Test to get a health check on many devices.
- Takes at least 5 hours, but less than 24 h.
- Once it’s fine, convert it to a prod push.
- There’s an email when it’s available.
2022-05-11 - Updating Android Apps
Category DEVThe new google play mandate is that apps must somewhat follow the latest API level, or risk getting booted out of the store after a certain delay.
https://developer.android.com/google/play/requirements/target-sdk
“Starting in November 2022, app updates must target API level 31 or above and adjust for behavioral changes in Android 12;”
https://support.google.com/googleplay/android-developer/answer/11926878
- New Apps: API 31 by 2022-08-01.
- App Updates: API 31 by 2022-11-01.
- Existing Apps: API 31 by 2023-11-01 / API 30 by 2022-11-01.
TL;DR: So that means all apps should be API 30 by Nov 2022, but because they would be updates they need to be API 31, so we might as well bring them to API 32 right away.
The plan is to try to update apps on a rotating basis, for example one per month.
For that, I need a list, and I’ll reuse my gradle-version spreadsheet.
List has been updated:
Ralf Flashlight (done) |
Prod v123 |
4 |
3 |
4 |
Nerdkill (done) |
Prod v105 |
4 |
3 |
4 |
Mandelbrot Map 2 |
Prod v13 |
11 |
4 |
11 |
Asqare (done) |
Prod v102 |
1 |
1 |
1 |
Brighteriffic |
Prod v103 |
4 |
3 |
4 |
Cangrejo |
Testing v1 |
29 |
18 |
29 |
Jump! |
Prod v4, Testing v3 |
29 |
27 |
29 |
Project E |
Testing v1 |
29 |
18 |
29 |
Seeds (done) |
Prod v402005 |
28 |
2022-05-11 - Google I/O 2022
Category DEVThings to try:
- Jetpack Compose for Android UI (e.g. Timer app)
- Flutter 3
- Google Cloud Run as an alternative to Amazon w/ React
Nerdkill could be a good subject to try the latest “Flutter 3 Casual Game Kit” thingy.
I’ve been thinking about how Lacan uses his Arduino for his aircraft animation.
What he needs is really a sequence controller to create time-base sequences triggered by input events.
If I had to program this from scratch, what would I do? I’d create a “mini language” using either macro or C++ objects which represents states to change over time:
- LED timings is really just a list of (start timestamp, LED pin, LED state).
- Servos: (start timestamp, servo pin, angle to reach, speed or duration)
- Motors: (start timestamp, motor pin, power level, direction)
- Instructions to end sequence, repeat N times, or chain to another sequence.
Depending on the specific needs:
- Sequence(s) are started by an input (with either forced restart or don’t retrigger).
- Need more than one concurrent sequence? Make each sequence independent. That is each sequence is started and actuates by itself on main clock.
- Need to make sequences run solo? Have an instruction that stop/cancel all other sequences.
- Maybe put sequences in groups (e.g. “servo groups”, “lights groups”) and make the group exclusive as in only 1 sequence runs in the group, or be able to stop any running sequence in the group.
For example for the case of the variable geometry plane:
- IR button 1 ⇒ sequence 1 = stop sequence 2, move servo N up to 60. No retrigger.
- IR button 2 ⇒ sequence 2 = stop sequence 1, move servo N down to 0. No retrigger.
- IR button N ⇒ sequence N for lights.
It seems so obvious that I would be surprised if this had not been done before and be made available as a customizable library for arduino.
For model trains, there are a couple obvious usages:
- Sequencing road traffic lights, e.g. to animate a city.
- With the addition of a “random LED value” instruction, animate anything from a camp fire to a building in fire.
2022-02-20 - Cat Litter Box Timer
Category DEVWhere’s the source for the current “Timer” app used for the litter box?
Device it uses: Tmo (saffire?) 3g something… running Android 2.2 (aka Froyo).
API level ⇒ API 8
As an exercise, it would be nice to rewrite this in Kotlin to see if it can run on Froyo. (FAQ says there’s no min sdk req).
2021-12-25 - Conductor 2
Category DEVIt's time to reflect on Conductor 2 again.
The repo branch has been going nowhere lately. I moved the project to a new repo (in the randall-layout workspace) and only copied the conductor 1 part. That made me realize I'd be throwing away a valuable part with the SVG map.
So first I want to salvage that part. The UI is and should be separated from the engine. This UI was going to drive a simulator, and I can likely make that happen on top of conductor 1.
The next part I want is to formalize the spec for conductor 2. Forget the syntax for now, I need to get the requirements right first: block handling, route management, and fully convert a current script. Also write some examples for eg window block handling.
(Reading between the lines, what I’m saying is that the Conductor-2-with-Groovy-DSL shows me that in fact I want more profound changes than “just a DSL”. I really want to rethink the entire way the automation scripting is done.)
Then once we have that we can figure the implementation. Maybe getting entrenched in groovy is not helpful here. There's clearly some value in not writing my own language, unless it slows me down.
The discussion continues in the Conductor 2 doc.
2021-12-19 - Status of Conductor 2
Category DEVI haven’t written one so it’s worth explaining the status of Conductor 2:
- Entirely rewrote the current v44 script using an “enhanced” version of Conductor 1 syntax to explore a realistic way to describe and use the new routes concept.
- Considered whether it’s worth pursuing the Groovy DSL vs extending the Conductor 1 DSL…
- The decision is that the former Conductor 2 Groovy DSL is obsolete. It was premature. Part of the issue was that it was getting entrenched in bridging the functionality and implementation (at the same time) with the former Conductor 1 engine. That is not the proper way to prototype.
- Instead, modularized the Conductor 1 source code to move the engine/DSL into a sub-project.
- And added a mock Conductor Groovy DSL rewritten from scratch, focusing on how the syntax would work rather than the actual implementation. There are unit tests but they only validate that the DSL can actually encode what it’s supposed to.
- The goal is to later also do a mock Kotlin DSL and compare.
- I still need to create a fat jar where this is invoked as Jython add-on from JMRI, to ensure there’s no library mismatch for example when running Groovy or Kotlin runtime code.
- That led me to explore the fundamental issue with the current route system, namely that we must have “managers”, “active routes”, and the sequence/shuttle manager should deal with a node graph instead of a “block list”. After much back-and-forth debate, I think I finally have a system I can endorse. Now I must encode it using the Groovy DSL.