Player
is just a placeholder for whatever you want to pass to the action associated with each button.
Unless you meant
using MenuAction = void (*)(Player *);
in which case thatâs C++'s type-alias using
(like typedef
, but backwards (or rather the right way around - typdef
is the backwards one)) of a function pointer. (You could also use a class with a virtual function if you prefered, but a function pointer is probably cheaper and easier.)
I just updated the repo.
Now MenuAction
is using MenuAction = void (*)(Player &);
instead, you you donât have to worry about pointers.
Iâve also added ApplyMenuAction
and ApplyProgmemMenuAction
and updated the .ino
to demonstrate their use.
Basically you just fill in the Player
with whatever data the player has and fill in the bodies of the functions GivePlayerTable
, GivePlayerOrnament
and GivePlayerLaptop
.
Iâve only used function pointers to show that the system can give flexibility, depending on your menu system it might be cheaper to use something else (like just an item).
Iâm sure youâll be able to work it out from my changes, but if you have any other questions donât hesitate to ask. If you already know how your player, inventory system and items are going to be structured I can help you integrate the menu system if youâd like.
Theyâre not that obscure, theyâre just less well known techniques.
Explanation for AsFlashStringHelper
:
Arduino provides a type called __FlashStringHelper
to allow print systems to differentiate a pointer to a block of text from a pointer to a byte-sized integer (since technically they use the same types).
If you try to use:
// somewhere in global
const char text[] PROGMEM = "Hello World";
// somewhere in a function
arduboy.println(text);
The string gets garbled because itâs interpreted as something different.
However if you do:
// somewhere in global
const char text[] PROGMEM = "Hello World";
// somewhere in a function
arduboy.println(AsFlashStringHelper(text));
You get the correct result, because the text is converted to a const __FlashStringHelper *
which the arduboy then correctly interprets as a string in progmem. The reason the F
macro doesnât produce garbled strings is because it returns a const __FlashStringHelper *
.
ArrayLength
is a function template.
Templates are a very powerful C++ feature that aparently not many people here are particularly well acquainted with.
I canât really give a proper explanation without explaining templates in full, so Iâll give a very brief glossed-over explanation to give you an idea of how it works.
template< typename T, size_t N > constexpr size_t ArrayLength(T (&)[N])
{
return N;
}
The template<typename T, size_t N>
part is the actual template part, and the T
and N
are called template arguments.
The T
is a name that stands in for any type and the N
is a name that stands in for any size_t
value. In a sense theyâre a bit like actual function arguments in that they can be different values, but theyâre constant, exist only at compile time and can refer to type names.
The clever bit is (T (&)[N])
. C++ has a thing called âtemplate deductionâ where the compiler will try to match up any of the values in the angle brackets based on the arguments given to the function. The argument (T (&)[N])
matches a reference to an array of any type and of any length, the T
template argument matches the type and the N
argument matches the length. The function itself returns the length and the constexpr
makes almost certain that itâs calculated at compile time, so itâs no different to just manually sticking the array length in, except the compiler does it for you.