Integrated game/music/sprite editor for the bitbox

What is a good name for this program?

  • 16tiles - (current placeholder name)

    Votes: 0 0.0%
  • 16g - (g being 16 in extended "hexadecimal")

    Votes: 0 0.0%
  • 16

    Votes: 1 33.3%
  • 4shift - (>>4 or <<4 also being common)

    Votes: 0 0.0%
  • shift4 - (see above)

    Votes: 1 33.3%
  • nibbles - (a half byte)

    Votes: 1 33.3%
  • and15 - (&15 being a common operation)

    Votes: 0 0.0%

  • Total voters
    3
  • Poll closed .

ible

professional vim user
Joined
Mar 24, 2014
Messages
2,591
Location
Seattle, WA
I wanted to start a bit of a dev feedback and discussion regarding a project I've been working on in my off hours for the last bit. It's inspired by PICO-8, but open-source, of course ;). The bitbox itself is open source, open hardware. Some links for the bitbox in the spoiler.


Part of the challenge for the bitbox is dealing with the limited CPU cycles, and limited RAM, among other things. My project uses a tile/sprite based approach which helps with RAM and makes it easy to race the beam (for drawing to screen), though it's very hybrid with some text stuff layering on top. Here's the git repository:

https://github.com/lowagner/bitbox-16

Oh, and one last thing before I get into the design of the thing: you can emulate bitbox games on CPU-based computers via SDL, so that helps with development. I'll try to figure out how to do bitbox dev on the Pyra, so eventually you'll be able to play bitbox games there, too.

The idea for the integrated dev environment/game maker -- is to force almost everything into 4 bits... so you get 16 choices for things. There are 16 colors, 16 tiles, 16 sprites (though each consists of 4*2 frames for right/left/up/down animation), 16 instrument commands. Oh, and each character in the font fits into 16 bits, which is quite compact. (Though, that doesn't exactly fit the 4 bit theme, although each row of each character is 4 bits...) Each level is also somewhat constrained in size, although that is somewhat arbitrary. Though you'll probably want to load up different levels with different tiles for variety. Here are some screenshots.

filename.png track-edit.png sprite-edit.png map-edit.png save-screen.png instrument-edit.pngbsod.png

Done:
  • Tile and sprite pixel editor - 16 tiles and 16 sprites with 8 frames each, each with 16x16 pixels.
  • Map editor - place tiles and sprites, adjust map width and height (min 22x17 tiles)
  • Tile property editor - safe to land on, water, air, solid, passable in certain directions, etc.
  • Sprite property editor - safe to land on, vulnerable to certain attacks, etc.
  • Sprite pattern editor (for enemies and NPCs, and also players)
  • Sprite collisions - and damage, based on attack types, invulnerability, and side properties
  • Palette editor - choose 16 colors, each with 32 values per channel (15 bit RGB)
  • Instrument editor - command based, can make arpeggiators, etc.
  • Track editor - command-based, can also adjust global song speed, transpose, and track length
  • Song editor - "piano-roll" based
  • Most awesome 4x4 font
  • Excellent BSOD screen showcasing the font
  • Saving and loading from (micro) SD card
Yet to do:
  • Better wiki page and documentation (https://github.com/makapuf/bitbox/wiki/16)
  • Game modes (platformer, top-down adventure, maybe RPG...)
  • "Unlock" command editor, for when hitting switches etc., can add or delete tiles, or add sprites
  • Allow levels to link to other levels (load from SD card different palettes, sprites, tiles, music, etc.)
  • ???
  • ???
  • ???
  • Not run out of 1MB program memory...
Random design decisions:
  • Decided to go with a bare-bones track editor, just like the instrument editor, over which you have very precise control, though perhaps not intuitive control. This also works as the basis for the sprite pattern editor and the unlock pattern editor, the latter of which hasn't materialized yet.
  • Maybe allow each tile to have 2 frames for an animation loop. Currently you can animate tiles in a slightly different way, but it might be more consistent with the sprite animation if we give each tile two frames. You could make each frame have a different property (one is stab you to death, the other is nice, for example). DECIDED AGAINST. keep things simple, and global, for tiles. this should be easier to compute than something individually for each tile.
  • ??? will discuss more about these.

If it's not already clear, this thing is pre-beta, so don't attempt to make games with it yet. But you can make some pixel art, and play a bit around with a chiptune engine. There's also no timeframe for release or anything, though I hope to have most of the editing stuff (for tiles, sprites, music) finalized soon, though the game engine/editing will come later.

[edit] sprite collisions with damage enabled
 
Last edited:
My nerd machine is overheating. Can I post this to my YouTube channel's Facebook page? ;)
 
sure, but just know it's still a long ways out before something playable manifests. (though editing will work well before then, hopefully.)
 
Some updates on the instrument/track/song editor. You can save stuff, but the full music engine isn't completely implemented. (Though the most basic one is.) The instrument editor is described in detail on the wiki:
https://github.com/makapuf/bitbox/wiki/16#instrument-editor

You all have homework to make random blinky computer noises (as given in the above link).
 
Last edited:
Here's a rough navigation chart in the spoiler.
more up-to-date navigation on the wiki:
https://github.com/makapuf/bitbox/wiki/Palette-16-Tile-Editor#user-manual
old one in the spoiler.
Palette16Tile Navigation.png

oh, and "Save/Load" wraps back around to "Game" when pressing select. Also, Verse <=> Track, and the second "Edit Instr." should be "Instr. Menu", sorry!
I'm considering making the song and track editors less like piano rolls (where you fill in the track or instrument note you want to play), and more like the instrument editor, where you have a certain set of commands that the track will run (to play various notes, to randomize things, etc.). It makes it a little more explicit than the state-machine stuff I was going to do:
original idea:
Code:
        notes:
            0 (black) - stop noise
            2 (white) - repeat last note.
            1 (gray) - volume control
                the "common" gray control statements can wrap to the next track in a song,
                but any involving a pink block MUST come before the end of a track.

                if some sound was just playing (either by a colored or white block or blocks):
                    fade out previous note
                    fade to zero volume in as many blocks as the note was held
                        (white notes only count as one, since they are repeating something.)
                    if not as many gray blocks as color blocks,
                        the note will continue sounding, unless black is encountered.
                    if there are more grays than blocks that the previous note was held:
                        fade out to 0% then fade in to 100%, then repeat.
                elif gray then some color (or white):
                    no note was sounding, fade in next note.
                    look ahead for next note, and count how long it is held, put into C.
                        (white counts as C=1).
                    also count how many G grays there are before the note is hit.
                    case G == C:
                        crescendo to 100% volume over G units of time, hit note at 100%.
                    case G < C:
                        crescendo to G/C*100% volume over G units of time,
                        then hit note with 100% volume.  (e.g. sudden loudness.)
                    case G > C:
                        crescendo to 100% volume over G units of time, then
                        hit color with C/G*100% volume.
                        (e.g. dramatic fade in to very soft note)
                elif gray then black:
                    next note gets emphasis.
                    if multiple grays, that many notes get emphasis.
                now for UNCOMMON gray control statements
                elif gray then pink:
                    reset vibrato, slide, octave, volume, bitcrush,
                    and other instrument state variables to their start-of-the-song values.
                        everything except "relative octave", which is temporary anyway,
                        as described below. (also it shouldn't be possible to do that anyway.)
                    also, read index increments to after pink, so that pink won't act again.
                elif gray then gray then pink:
                    toggle GLOBAL major/minor.  this only has an effect if a track is labeled in a key.
                elif 2+X grays then pink:
                    (where X >= 1)
                    do not play the next X notes that you encounter.
                    or possibly randomize the next X notes (within the given key)

            3 (pink) - control/command
                if color then pink then same color:
                    toggle vibrato
                elif color then pink then a different color:
                    toggle inertia

                for pink to act as the beginning of one of the following control statements,
                it must come after a white or a black,
                or a gray which was fading out something.
                    (black gray pink resets stuff, as described above.)
                the only pink control statement which can survive a track changing
                    is the first one (if pink then a color);
                    i.e. if pink is the last color in a track, then any track which
                    follows it in the song will get "relative octave" set to true:

                if pink then a color:
                    until a cease-noise black is encountered, octave is "relative".
                    when deciding to play the octave of the next note, check
                    what is closest to the previous note, going up, down, or staying same.
                    black values encountered in control statements (such as those found below)
                        DO NOT COUNT as a cease-noise black,
                        and so do not break the relative octave action.
                elif pink then black:
                    lower octave (if below the lowest, wrap around to highest)
                elif pink then white:
                    increase octave (if above the highest, wrap around to lowest)
                elif pink then gray:
                    toggle vibrato
                elif pink then pink,
                    then black:
                        decrease volume of instrument, but not all the way to zero.
                        (however, but something very quiet is.)
                    then gray:
                        toggle bitcrusher
                    then white:
                        increase volume of instrument, but not beyond some max.
                    then a color:
                        toggle slide, and
                        proceed in relative octaves until a cease-noise black occurs.
                elif pink then pink then pink:
                    then black
                        GLOBAL song speed down
                    then white
                        GLOBAL song speed up
                    then gray
                        GLOBAL song speed reset to initial
                    else:
                        GLOBAL song transpose.
                        some of them will switch from maj to min, or vice versa.

                        4   -> +1    (red).  do not toggle maj/min
                        5   -> +2   if maj, switch to min
                        6   -> +3
                        7   -> +5
                        8   -> +6
                        9   -> +7
                        10  -> -6
                        11  -> -5
                        12  -> -4
                        13  -> -3
                        14  -> -2
                        15  -> -1    (last note color).  do not toggle maj/min

            4 - 15 (ROYGBIV'ish) - notes C through B, with all semitones.
                hold a note by adding more of that color.
                repeat a note by using white.

                if maj, the semitones read:
                 
                    note    relative    key e.g. C
                        4   ->  0   ->  C
                        5   ->  1   ->  C#
                        6   ->  2   ->  D
                        7   ->  3   ->  Eb
                        8   ->  4   ->  E
                        9   ->  5   ->  F
                        10  ->  6   ->  F#
                        11  ->  7   ->  G
                        12  ->  8   ->  Ab
                        13  ->  9   ->  A
                        14  ->  10  ->  Bb
                        15  ->  11  ->  B
             
                if min, the semitones change for 7 and 8 (make minor third)
                and also for some higher notes:

                        4   ->  0   ->  C
                        5   ->  1   ->  C#
                        6   ->  2   ->  D
                        7   ->  4   ->  E
                        8   ->  3   ->  Eb
                        9   ->  5   ->  F
                        10  ->  6   ->  F#
                        11  ->  7   ->  G
                        12  ->  9   ->  A
                        13  ->  8   ->  Ab
                        14  ->  11  ->  B
                        15  ->  10  ->  Bb
             
                each track has a maj/min label, and there's a global maj/min toggle.
                e.g.
                    track   global toggle   actual key
                    C maj   0               C maj
                    C maj   1               C min
                    C min   0               C min
                    C min   1               C maj

Then I can potentially be a little lazier in implementing the track engine, since it's more up to the user, and it might feel more consistent, at least between tracks and instruments. Songs would still probably look like a piano roll, though...
 
Last edited:
i think i have a mostly finished music engine now. i've gone with a command-driven track editor:
https://github.com/makapuf/bitbox/wiki/16#track-editor

some details:
i've taken out JUMP in the track command context, since you can just repeat commands (there is more space, 32 commands possible, than in the instrument editor with 16 commands). it also makes it less work to do the RANDOMIZE commands, which should worry about WAITing before JUMPing again.

for the instrument commands, i squished VIBRATO_DEPTH and VIBRATO_RATE into one command, VIBRATO, so that i could resurrect BEND from the old LFT chiptune engine, which someone might want to use. (BEND adds or subtracts a constant amount from the frequency at each time step.)

also, is it strange that my hex character specifier goes up to 'v' ?

will try to post a song written in it eventually...

[edit] the challenge is in thinking like a MIDI file, which thinks in terms of time steps before the next thing will happen, rather than the absolute time at which it happens (though this can be more or less achieved with the FILL command, which waits to a given "quarter" note, or 4 times the smallest time unit (no resolution smaller than a "sixteenth" note, at least from the track editor -- the instrument editor can do things faster than that)). the track time-span can be up to 64 times the smallest time unit, which would be something like 16/4, or four measures of 4/4 -- though you can't fit 64 notes into a track, since you need a wait command and then the note command, which would limit you to 16 notes max (due to only having 32 track commands available), and fewer if you want to add some other commands (like fade in/out, add vibrato on top of any instrument vibrato, etc.).

it makes my head hurt a little bit, the old classical conventions (quarter notes aren't always a quarter of the measure, etc), so i left them out in the track editor, and use the smallest time resolution (a track 'tick' if you will) as the unit of measurement.

also, i'm not very good at transcribing my jam music, as i don't have much abstract-thought rhythm, though i hope i have at least a little practical rhythm. ;)... i was terrible in sight-reading sheet music, and usually had to hear someone else play it before i understood the rhythm. anyhoo, it's something else to get better at.
 
Last edited:
alright, here's a crappy song i created using the editor:

and it's based on this other jam:
(if you notice a difference, it's because of my lack of rhythm-matching skills, mentioned in the previous post ;))

i'll try to do a "tutorial" video showcasing some stuff with the music editor.
 
Last edited:
i've adjusted a few of the track/instrument commands, cramming in the "bend" command (so you can have frequencies bend up and/or down over time), and a repeat note command for the track, so we can have up to 31 notes in a track. for the track, this was accomplished by adding a secondary functionality to the BREAK command, and removing the FILL command, but making the BREAK so it can act as a FILL, depending on what the parameter is. for the instrument, we got BEND because we made vibrato take only one spot instead of two (vibrato depth and vibrato frequency). instrument also gets a parameter for BREAK, though the somewhat different logics of BREAK (for track vs. instrument) makes things a bit more complicated, but it should be fairly self-explanatory, given the wiki and on-screen text.

also been a bit pokey because the next few editing tools need to have some more planning, based on how the game will work. i.e. the sprite and tile properties have to be closely related to what the game will throw at you: tiles/sprites that can hurt you if you touch them on the wrong side (or any side), or you can win if you get to a certain block (maybe make it look like a finish line), etc. i'm thinking of platformers, but the properties should be valid for top-down adventures, too. i hope to be finished at least with a better rough draft today, so i can start implementing some of it soon.

i'll probably create a track-like command editor for tile and sprite patterns, given the fun it's been to create track/instrument editors. this will allow further randomization to the game (if desired), given the possibility for randomization commands.

[edit] another question is, should i go full command mode and do the song editor in the same way? (a list of commands, play this track with this transposition, etc.) it might be interesting, but i'm not sure there are enough commands to fill a song editor... there's RANDOMIZE (as in which track to play), JUMP, TRANSPOSE, PLAY_TRACK... anyway, something to keep in mind... on the backburner...
 
Last edited:
(random aside) .. given bitbox is a subset of Zikzak (but actually in production, unlike Zikzak :), I wonder if I could make a layer to run bitbox stuff on zikzak. ie: bb iirc is just an stm32 with vga out more or less .. but I wonder if I could make the memory map work in ZZ and otherwise be binary compatible, or make an easy-to-port thing so it'd be source compatible. Huh.

Nice project you have going :)

jeff
 
yeah, i'm not sure, but yes that's roughly the bitbox (with stereo audio out -- i forget what the zz does for audio). maybe something to ask makapuf. most projects' sources are available, so you can always try to have it easy to port (an included Makefile with all the complicated cross-platform stuff already thrown in), though binary compatibility is always nice. i'd love to get something like the uzebox emulator working on the bitbox, too, and thus hijack a lot of neat games from that open platform using just the binaries. the trick is different video outputs, and choosing how to display that on the bitbox. i haven't figured out/realized the other hard stuff in porting the emulator, so that project is still in the "stare at someone else's source code, scratch head" phase.

your posts on the zikzak inspired me to discuss my dev-work here, so thanks for the encouragement!
 
added sprite editing to maps (cut/paste sprites), and map property editing (change width/height). also added some GUI improvements to the music section: a song position marker which tracks along where the song is (when playing the song), and a marker for the track and for the instrument commands too. this should help to make things a little easier to grasp when writing songs.

also had a nice bug, when resetting the sprites, i was updating the linked list, but i was forgetting to reset the drawing configuration (which is saved, to speed up drawing), so that was crashing the system... anyhoo, quick fix (drawing_count = 0). ;)
 
made a small detour to create a "w8v" player (wav format but encoded in bytes specifically for the bitbox stereo output, no headers or anything -- simple shell script to generate). if it's a desired thing, i can make the game editor smart enough to play one of these w8v files instead of the chiptune tracks, but the w8vs take up more memory. surprisingly, it sounds pretty good! (though i am not a recording artist.) it does sound a little wispy when the volume is low, but 8 bits for each channel isn't much to get that low volume...

https://github.com/lowagner/bitbox-noisebox

[edit] on closer inspection, running such an intensive operation (streaming from SD card for music) impairs the visuals (though they are still there, just with artifacts). it would not be a good idea to run this with the game editor :(. but the track editor is fun and working out pretty good.
 
Last edited:
thought i could start getting some feedback in a poll! please select a name or two, or suggest your own.

i hope to finish the editor phase soon. some of the last pieces: sprite pattern editor (how do enemies move based on player location, etc.), game editor (RPG, platformer, etc.), unlock pattern editor (you can hit buttons to do some unlock action, maybe add some tiles here or there, etc.).

here are some ideas for the sprite pattern commands:
  • wait
  • look for player (and set forward direction relative to player's location)
  • change speed
  • set chase if player within some multiple of speed distance away
  • jump (literally, off the ground, not a command jump)
  • command goto, if within chase mode
  • command goto, if in the air
  • command goto, unconditional
  • turn
  • move forward (some number of paces)
  • set edge behavior (turn, fall, jump)
  • randomize command
  • follow player input (can reverse it, or only in one direction, etc.)
  • shake screen
  • spawn other sprite (like projectile)
  • make noise
here are some ideas for the unlock pattern commands (can also unlock your doom):
  • wait
  • set spawn location x, y
  • spawn sprite
  • spawn tile (this can also destroy a tile if you spawn an "air" tile)
  • randomize command
  • set spawn location to player location
  • set spawn location delta x, y
  • shake screen
  • make noise
so don't forget to vote in the poll...
 
added the chiptune engine/editor to my snake program:
https://github.com/lowagner/bitbox-snake
super quick hack job, so we'll see if there are any bugs. er, features. [edit] surprisingly not too bad! was missing some hold-button functionality, but everything seems to work. (and now you can hold down certain keys to zoom around faster in menus and such.)[/edit]

now we can use music in two programs...

soon, the world!!!
 
Last edited:
here's a video with a general overview of the music editor, being used in the snake game:


i made one final (?) tweak to the chiptune editor: now the "side" command (stereo side, or panning), can be set from L to LR to R, with some intermediaries. it's not exactly continuous, since i'm just using bit shifting (dividing by twos rather than dividing by any intermediary values).
 
been thinking about the engine, and am about ready to do the first draft of the sprite patterns...

in the meantime, i put in the chiptune engine/creator/editor into a tetris clone:
https://github.com/lowagner/bitbox-tetris

not every tetromino is implemented (just I and O), but many game modes are possible, like coop and duel, and you can also wrap tetrominos around (if game mode "torus" is activated):

CoopPlay.png
 
Last edited:
Back
Top