The place where random ideas get written down and lost in time.
GDSCript: https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/index.html
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html
var damage = 10.5 ⇒ no typing, this is essentially a Variant
var damage:= 10.5 ⇒ inferred typing
var damage: float = 10.5 ⇒ explicit typing
For constants:
const MOVE_SPEED = 50.0 ⇒ inferred (= and := are the same)
const MOVE_SPEED := 50.0 ⇒ inferred
const MOVE_SPEED: float = 50.0 ⇒ explicit
For functions:
func sum(a: float = 0.0, b: float = 0.0) -> float: …
func sum(a := 0.0, b := 0.0) -> float:
Which types to use:
Types can be:
- Variant, void (only function return, see below)
- Built-in types, global classes, inner classes (gdscript has inner classes?!)
- Native classes, enums (gdscript has enums?!)
- Constants that are preloaded as class types (see below)
func blah() -> Variant: … ⇒ forces the function to return something
func blah() -> void: … ⇒ forces the function to not return a value
Click here to continue reading...
https://amzn.to/4bJ0iUw is the 10 Inch Android 12 Tablet I’m using for Enphase Enlighen.
It has a 1280x800 screen.
Even though it’s a “production” one, I can run a debug app from Android Studio.
When enabling developer settings, there’s a Drawing > “Plus petite largeur d'écran” to control DPI:
- 432 dp ⇒ makes all takes larger (simulates smaller screen)
- 592 dp ⇒ the default value.
- 601 dp ⇒ better for Enphase (better view of the graph)
- 740 dp ⇒ makes everything look smaller (simulates larger screen like 1920x1200)
When trying out RTAC, the font for the throttles is way too big. It’s calibrated for the Chuwi’s 1920x1200 display. I realize I should customize it by “screen size”.
A few months ago I updated the Conductor project to new libraries, notably switching to Kotlin DSL 1.9. That made building with Java 11 a requirement.
In turn, that broke the way the Kotlin DSL is loaded under JMRI. I’m not sure why.
So fine, I reverted the Gradle files to a “Java 1_8” compatibility mode, and reverted to the older Kotlin DSL 1.6. This works fine when building the fat JAR, but it fails when trying to run the tests. It works fine when I actually build with a Java 1.8 JDK instead.
When building with Java 11 and running the tests, I get this cryptic gradle error: “Incompatible because this component declares an API of a component and the consumer needed a runtime of a component”
To be clear, the “build” part works. I get the fatJAR just fine. It’s the testing that fails, and only when doing it from Gradle on the command line. In IJ, I get the same behavior by selecting Conductor > All Tests on the root project.
I should try to replicate it with the gradle --info flag to see if that gives me more details on what is really breaking.
Another limitation is that only LibUtils v2 works with Java 1.8. LibUtils v3 already has Mockito dependencies that require Java 11.
But that seems all academic anyway. What I really want is to build with a Java 11 compatibility target since at this point even JMRI requires 11.
Then once I get that working, I need to retry with Kotlin DSL 1.9.
One thing for sure is from now on, when updating, I need to account for these scenarios:
- Testing does not work the same way under IJ or under command-line Gradle.
- Kotlin DSL loading does not work the same in standalone (simulator) vs from JMRI.
2024-02-18 - C++ unique_ptr
Category DEVIt’s time to update SDB to use more unique_ptr and/or shared_ptrs.
Some simple examples come to mind:
class SdbModManager {
std::vector<SdbMod*> _mods;
std::map<String, SdbMod*> _modsmap;
std::vector<SdbSensor*> _sensors;
std::vector<SdbServer*> _servers;
std::vector<SdbBlock*> _blocks;
}
All these should be either unique or shared pointers to clarify the ownership.
There are 2 or 3 aspects to clarify:
- How a new object is created.
- How a ptr is “moved” into the vector.
- Users of the vector.
For each collection, I have a simple getter that returns the vector as a reference:
const std::vector<SdbServer*>& servers() const { return _servers; }
and then I use that in a for/auto loop:
for(auto* s: _manager.servers()) { … s->name() … }
The other kind of usage is the vector for Events. One goal here is to change that from a struct holding to holding unique ptrs, with the goal that events get automatically released when pulled out of the vector and used.
So first, I need to write down a few things about how to use unique_ptrs correctly.
https://en.cppreference.com/w/cpp/memory/unique_ptr
#include <memory>
auto p = std::unique_ptr<Class>(new Class())
std::unique_ptr<Class> function() {
return std::unique_ptr<Class>(new Class());
}
C++ ref mentions creating the instances using std::make_unique(), but apparently I don’t have that in the ESP IDF projects (N.D.L.R. it should be in ESP IDF 5.x but I’m using the previous one).
2024-01-01 - Defold vs Godot
Category DEVWeek of 2023-12-24 to 2023-12-31, I wrote Nerdkill Defold. Worked well, was easy to use and get something.
One thing that was nice was that I ported the original game, with all the original 8 “weapons”.
Started looking at Nerdkill w/ Godot 4.2, just to compare with Defold.
Not sure there's a point in concluding that one though.
A new Asqare using Godot 4 for Android would make more sense.
One angle of Nerdkill w/ Godot would be how to create a project that can produce both a web version and a mobile version? More specifically, I’d want the screen form factor to be different.
- Nerdkill “desktop” in landscape can use the cartouche with the 8 weapons.
- Nerdkill “mobile” in portrait can use the 5 weapons.
I could of course change the mobile version to have the same 8-weapons row, but I feel the mobile version looks better that way.
(Alternate idea: consider using 7 weapons on mobile; drop the flag. 2 rows of 5 slots each, the cartouche would occupy the 3 middle bottom slots.)
So one thing I realize I don’t know if it’s possible is to configure the window size dynamically, or at least static by export type. Or maybe it could be two projects using the same resources.
https://forum.godotengine.org/t/how-to-change-window-size-using-gdscript/2861/3
“get_window().size = Vector2i(width, height)”
https://docs.godotengine.org/en/stable/tutorials/rendering/multiple_resolutions.html
“the size in Project Settings > Display > Windows… think of it as the design size”
“to support both landscape and portrait, consider using e.g. 720x720”
Click here to continue reading...
2023-12-24 - Defold
Category DEVStarted going through the Defold tutorials.
I have 3 possible learning projects I could try with this:
- Nerdkill.
- Could be limited to an HTML5 output, purely as-is with no changes (e.g. no goals), and visible only via the Nerdkill web page.
- Asqare.
- This would be an Android output. I’d limit it to one of the 2 engines.
- One goal would be to “finish” the game by adding more animation / interactions, and power ups, and better scoring.
- Cangrejo.
- That could be HTML and Android.
On the Android side, an aspect would be to check the Play Game integration. E.g. leaderboards, achievements, profile management, saves/restores, etc.
One open question, similar to Godot: how does one separate the engine from UI, and how does one provide unit tests for the engine part? There seems to be a clear lack of MVC or MVP design in these tutorials.
2023-11-21 - Rig4 Index
Category DEVJust a quick thought on something that still bugs me with Rig4’s generated blog:
- I write pages with 10 posts per page, from 00NN.html down to 0001.html.
- I then write an index with the 10 most recent posts.
The rationale is:
- The numbered pages are “stable”: older pages (with lower numbers) don’t change when new posts are added “normally”, that is when posts are added for the most recent day.
- It’s exceedingly rare that I’d add a “late” post in the middle.
- The last numbered page fills up and, once it reaches 10 posts, becomes stable.
- I never link to page numbers, but I do expect them to be indexed by search engines and I’d like these links to become stable.
The downside:
- The index page necessarily duplicates N < 10 posts from the last page.
- When clicking the “next page” button from the index, we land on the top most page, which basically duplicates the same content, and that’s a bit confusing.
That last bit is what annoys me. I don’t have a solution for it.
Trying to make any sense of the “T&&” notation in C++.
It means “an r-value reference” “a forwarding reference”.
https://stackoverflow.com/questions/4549151/c-double-address-operator
https://stackoverflow.com/questions/5481539/what-does-t-double-ampersand-mean-in-c11 (*)
It’s referenced in the C++11 “range-based for loop” loop construct:
https://en.cppreference.com/w/cpp/language/range-for
for (auto&& [first, second] : mymap) { … } ← WAT?
The summary of the SO (*) above is:
- rvalue is the result of an expression or any temporary (e.g. type conversion).
- Typically, it would be used as a “copy” using a “const T&” reference and becomes an lvalue. E.g. the user cannot modify the value (since it becomes const).
- T&& is used as a receiving argument type in a function.
- An argument of “T&&” preserves (forwards) the “rvalue” property and passes it down as-is. The user can modify the value (since it is not const).
- When used in a template, “T&&” becomes either “T&” (for an lvalue), or “T” (for an rvalue / temporary).
- As such it’s named a “forwarding reference” and is associated with std::forward<T>.
About std::forward<>, it’s equivalent to performing a static cast of “T&&” to preserve its rvalue:
Coming back to that “range-based for loop” construct:
https://en.cppreference.com/w/cpp/language/range-for
- for (auto x : array) {} → access by value (I guess “copy”)
- for (const T& x : array) {} → access by const reference
- for (auto&& x : array) {} → access by “forwarding reference” (not const)
are all possible.
2023-10-06 - CMake
Category DEVhttps://cmake.org/cmake/help/latest/guide/tutorial/index.html
In a file called CMakeLists.txt:
cmake_minimum_required(version)
project(name)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
target_include_directories(ProjectName PUBLIC list_of_dirs)
for an exe, the minimum is add_executable(Name file_list)
for a library, add_library(Name file_list)
2023-09-20 - Game Engines to Look at
Category DEVGame engines to look at:
Defold seems like an interesting choice to explore. It’s the King (candy crush) engine. I don’t think it’s truly open source. Programming is done in Lua.