What belongs in the core library?

I wanted to create a place to discuss this as I see it being mentioned in a lot of other places. So far we technically have 2 real high level libraries… audio/tunes and Arduboy. Arduboy has all the system stuff and audio/tunes has all the audio/music stuff. Arudboy exposes audio and tunes as variables that it manages (so you don’t have to create them yourself).

Coming from Ruby I tend to like sep responsibilities for things (and it’s so easy in Ruby). So that makes me somewhat prefer arudboy.tunes.method() and arduboy.buttons.method() over everything being directly in arduboy itself. This also helps separate some of the code, variables, etc. I think it does a lot of readability also:

if arduboy.buttons.pressed(DOWN_BUTTON)

Thought at that point we should consider “DOWN”… I worry it’s too broad since defines can go global pretty easily.

There has been some discussion of porting games from gamebuino and “compability” with other libraries… I thought I’d create a thread to have a focused place for some of those discussions.


I’ve also hear it said we need to leave some things more difficult or raw beacons this is a “learning” platform. I’d love it is @bateske could jump in here. Are people learning about game development or low-level Atmega32U4 specifics? I tend to think he library should be high enough that people who want to focus on game development can do so without getting tripped up by the library all the time and having to think about low-level stuff. Obviously anyone who wants to can edit/play with/contribute to the core library. That shouldn’t be required to build software on the platform.

I try to build a game and instead I’m having to write a menu to get simple choices from the user and raw button code to handle trigging events every-so-often if a button is held. These are things the library should do for me. And if not the core library then I’d like to get an idea of what the official team considers core or not so those who want to build higher level could start focusing their attention on a higher-level library and leave the “core” library alone.

Maybe the right answer is subclassing some of these other existing libraries and building our changes there… I think one problem with that is it becomes hard to get rid of things (extra variables, things they’ve chose to store in PROGMEM, etc). Some of the existing libraries are very broad to work with a ton of hardware, but to do that they sacrifice a lot of space and performance.

Docs from gamebuinos core lib:

http://gamebuino.com/wiki/index.php?title=Reference

as a game developer it would be more convenient for me to just have the libraries take care of the lower end stuff for example
if(arduboy.pressed(A_BUTTON)){ // should mean was the button pressed at this exact frame

if(arduboy.held(A_BUTTON)){ //should mean if the button was already held when the check occured.

if(arduboy.released(A_BUTTON)){ //this should check if the button was released since last check (cycle)

This will give the game developer more flexibility as far as controls are concerned and beginners wont have to worry about how to handle their button presses with booleans and such.

See, currently I’ve been using pressed (it’s currently pressed, stateless, justPressed (it was just pressed) and justReleased (it had been held but it was just released)… Honestly pressed and held are ambiguous… it could be pressed for 1 second or held for one second, same thing… so I think a better term is needed.

Also we need handlers that fire every x unit of time… like pressed_every_millis(LEFT_BUTTON, 100)… but this type of checking requires having counts for the button state… so 7 butters means 7 bytes lost to track the extended push state… so you can get things like repeat fire every 100 ms by holding the button down without having to track the buttons bit flipping inside your app. Of course someone might complain about the lost 7 bytes - so it gets down to how high/low level do we want the lib to be. I think we should use the RAM for things like extend button tracking.

Also I have a physics branch that adds Rects, Points, and collision checking of Rects and Points against each other and the screen edge. It also adds draw* variants that take Rects and Points for draw operations… if you have them, why not pass them directly? Though more often you’ll probably be using drawBitmap… I could see this being part of core lib or I could also see it being split out into a separate library. Thoughts?

I think that an high level library is a must, but it has to be modular. We are very tight on space on the device so, as @Dreamer3 said we should separate sections so that by default only the low level stuff like button access and drawing pixels is included. Then complex modules such as physics and music can be added to facilitate development

This is also the approach I would take. Either a few branches for functionality or modules that expand upon the base draw library. Although I don’t make many contributions to the github, I would even think about separating the draw libraries into their own class. The possible downside to this approach is of course it requires a user to have access to clear and concise documentation to each module.

The most important feature I see needed is for everyone to start using doxygen who is going to make PR. @Dreamer3 I would start doing this now for your headers as come release we can roll this into a proper documentation website generated from the source.

Here is a link to the doxygen website
http://www.stack.nl/~dimitri/doxygen/

I think the core library needs to be as basic/empty as possible to save space. Game development for these is simple enough that wasting flash space to pretty up button reads is not really needed (and I say that with GBA being the platform I learned to code on which was very low level where the hardware was accessed through volatile memory pointers).

I’m all for making a few modular high level libraries that are optimize to simpily bigger task like Audio or scrolling backgrounds but I think they should be separate things we can include and not be in the core lib.

The games we made at TEAM a.r.g. mostly only used

  • drawSprite(x,y,sprite, frame, mask, framemask)
  • clearDisplay()
  • updateDisplay()
  • readInputs(); (put it in a byte 0b00000000) (place for 8 buttons) pressed or not pressed nothing more
  • playTone();
  • playMusic();
  • no fonts (all done with bitmaps)
  • no lines, circles, rectangles, …)

things like menu’s we created on the fly (with game templates), even background scrolling, map tilling was al done in the games itself

Keep in mind that the compiler is pretty smart. If a function is not used by your sketch, and no other function that you’re using depends on it, then it won’t be pulled in and waste code space in your sketch. This is regardless of whether the function is included in the same library that contains other functions that you are using, or if it’s in a separate library.

This means that we could have one single library, containing all desired functions, without worrying about increased code size for a given sketch, over having multiple libraries.

Even so it needs to be clearly setup so there isn’t to much cross dependency which tends to happen when you have an all in one library. Nobody wants to see their sketch blow out just because they used one function (I’ve seen it happen time and time again in the past).

I agree to both @subbie and @MLXXXp If been well setup, it wont blow out.

We also need to watch out for hidden dependencies… like drawChar using fillRect… that code still gets compiled even if no one uses double sized fonts. Maybe we should have another method for rendering fonts larger than life? I’m not sure how to best solve this problem.

We have all of that right now except for good sprite methods, which we need to work on.

I started some work on sprites but I’m not sure how to minimize the flash usage while keeping up the speed… because really we have 4 different render modes for sprites (that I can count). The inner x/y loop realy should have as little responsibility as possible. It should mostly just shifts bytes from the image into the buffer (with whatever bit ops need to be done)… and since those bit ops are quite different depending on the mode you end up with something like this:

case (drawMode):
case SPRITE_MASKED:
// Copy the sprite masking off areas in your mask
case SPRITE_UNMASKED:
// The idea being to copy the sprite directly 1s and 0s to the buffer.
case SPRITE_IS_MASK:
// Treat the sprite itself as a mask (similar to current color WHITE)
case SPRITE_IS_MASK_ERASE:
// Treat the sprite itself as a mask but paint BLACK, not white

How would you go about optimizing the code so that if all someone used was masked sprites and sprite (as mask) that the other two branches wouldn’t waste space? Would we have to have conditional defines for all these things and program creators would choose which of the modes they wanted?

Should each mode be a separate draw* method? There is a lot of init and bounds checking (reduce the draw if it hits a screen edge, etc) that happens in the main draw routine so I thought having a super function that knew about the various modes would save space in that regard - vs repeating that logic everywhere.

Thoughts?

Maybe if you could pass a transform function that did the inner loops work? But if the compiler inlines it you’re right back to where you started… and if not the CALL/RET plus preserving all the registers would use significantly more cycles.

You could probably wrap the bounds checking up into it’s own function that twas shared… so then the different sprite function signatures would call the underlying implementations (that were different)… so then if you never used ERASE mode it would never get compiled. But it seems anytime the toggle is in software you’re right back to the same issue… say I want a little higher level so I have a Sprite class.

class Sprite {
int x, y, frame;
*char image;
*char mask;
void drawToScreen();
}

So the idea would be that I just make a new sprite, set it’s properties and then go… but in that case the drawToScreen method would likely contain calls to all the different sprite drawing routines… forcing them all to get compiled and included (even if not used)… is there some solution to this?

Me from the sleep mode thread:

I kind of feel like the lib should simply hide long presses on start from the app… if someone hits it shortly it registers… if someone holds it for x seconds it triggers sleep or wake. This is pretty easy if someone is using the built in frame loop.

This comes back to this topic of “what is the core lib”. I’d kind of like a standard “OS-level” way to adjust brightness, sound, sleep, wake, etc… not have these things randomly or differently supported by every other application. I think it’d be great if those things were all built into the library… if they could be built into the bootloader I think that’d be even better but it seems like there is really no room there except to maybe add a logo or something small.

1 Like

I kind of feel that with the limited amount of resources we are dealing with here, building out any form of an os will just make things more complicated with lesser space to work with.

I’m not sure really why we need a sleep instead of just powering the device off.

EVERY other devices I own I never turn off they all sleep - so thats’ where I"m coming from. If I’m playing a slower game (dungeon crawler, etc… ) or I"m in-between levels it’s the most natural thing to just lay the device down and pick it up later. It’s what I do with all my other devices. Yeah you could say “don’t do that”, but if the flash cost is low to have a real sleep mode and it would last a month or so, I think it would be win win.

Again, I’m very much in favor of compile time flags… If brightness and audio controls use up 200 bytes and someone REALLY wants to throw them out the door, they could choose to compile their game that way - and do their own thing. We’re not forcing anyone to do anything - just trying to make the platform as a whole easier for developers and nicer for end users.

ALSO If I turn it off I have to save the game state into a small amount of bytes (EEPROM, <1k if shared across apps)… where-as if I just leave it on I have all 2,500 bytes of usable RAM that stays powered up holding the game state until I can return to the game later.

Interesting thoughts here on class design and encapsulation:

You have to stick with it until at least page 2 to start to really get what he’s saying. Very interesting POV.

Few things. Due to the limited nature of the device I don’t see eeprom sharing happening (along with the code over head that will require). With that 1k eeprom is loads to work with with just writing out what needs to be saved. the 2.5KB of ram looses 1KB if you use the buffer (which most will since we’re talking core library here) and that 1.5k will go fast with everything else in it not to mention there will be some overhead added to the ram with the more of these features thrown into the library.

Even if modern devices have sleep, I think it’s needlessly trying to complicate what is meant to be a simple low end device.

I plan to built it and prove it’s not that much overhead. Whether people will use it or it’l get included in core lib remains to be seen. I certainly plan to compile all my own games against it (eat my own dogfood). So all my games will be completely playable at any time without losing your saved game when you install a new program - as I think it should be. If no one wants to follow suit then that’s on them. Shrugs. To me it’s the responsibility thing to do for users UNLESS your game really really needs all 1k. If you only need 100 bytes and the overhead of the management lib is small, I don’t know why people wouldn’t opt-in.

1 Like

No OOP ; this is a chip without a huge amount of working space. Full OOP is probably over the top.

I think it needs stabilising and documenting. There is also a case for maintaining an SDL equivalent to the basic functionality so Arduboy games can be developed without uploading them to the emulator (plus the Arduino IDE is pretty terrible).