Skip to content

Instantly share code, notes, and snippets.

@Bananattack
Created October 29, 2016 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bananattack/0f4f236866b60df6b8f05b11dfe52d05 to your computer and use it in GitHub Desktop.
Save Bananattack/0f4f236866b60df6b8f05b11dfe52d05 to your computer and use it in GitHub Desktop.
Map format for arduboy

Arduboy Platformer Map Format

braindump for planning a little sidescroller on the Arduboy

System Specs

  • 128x64 px screen
  • monochrome 1-bit color (strictly black and white)
  • ATmega32u4 16 MHz cpu
  • 2.5K RAM (~50% reserved by runtime libraries, huge chunk is screen buffer AFAICT, so we have less than NES)
  • ~22K ROM (~50% reserved by runtime libraries)
  • other stuff that doesn't really matter so much for this
  • arduino / avr gcc, C++ does does not include C++ std libraries, nor new/delete.
  • Placement new / delete so polymorphism is possible if you add toplevel default placement new/delete operators and make your own allocator into a fixed buffer or something. AFAICT, violates strict aliasing but you're pretty much stuck if you did want virtual calls. (ended up not doing this)
  • missing anything to deal with templates/traits, need to reimplement stuff by hand to use rvalue references (eg. std::forward, std::move).
  • Basically: need to resort to C style code unless trickery is used.
  • Would write entirely C89 compliant code, but arduino + arduboy is C++, so forced to write gross inbetween-language code. Otherwise neat.
  • Program memory is in separate address space so macros are required to read data from program space / ROM, and extra attributes are needed to place const data in ROM. PROGMEM and pgm_read_byte/word calls all over, but it's still cheaper than having all that crap in RAM.
  • Need a map format that uses very little runtime RAM, and is also space efficient in ROM.
  • Not enough RAM to really uncompress things at runtime, so compression must basically be levels of indirection.

Tilemap System

  • Horizontal scrolling only
  • 1D map of column references, horizontal scroll
  • columns of 1x4 block references
  • blocks of 2x2 arrangements of physical tiles: tile indexes + attribute for each tile (hflip/vflip/color invert + empty/solid/slope/spikes/etc)
  • tiles of 8x8px bitmap data, arranged in column major bitpacked format (8 bytes wide, each byte is 1 x 8 px)
  • map -> columns -> blocks -> tiles
  • 12.4 fixed-point position/velocity on map (12 bits pixel position + 4 bits subpixel)
  • 0 .. 4095 pixel pos (~34 seconds of to walk through at a rate of 2px / frame)
  • Max map size: 4096 px / 16 px/column = 256 columns

Entities

Entities are the creatures, npcs, collectable items that are placed on the map.

Each will have Spawn Data consisting of:

  • x
  • y
  • type
  • flag (maybe optional)

This is used to create live entities:

  • Spawn list for is pre-sorted so it's easy to search, and we can keep leftmost .. rightmost pointer as things scroll for easy on-screen detection. Just adjust pointers as the camera moves
  • Quick to binary search.
  • When a spawn entry enters the "screen", we spawn a new critter
  • don't spawn again until the spawn point has left off screen.
  • Live entities themselves check if they go off-screen, for deletion/despawn purposes.

This format could probably be reused for an NES map engine, if the column data was expanded to 1x15, or the columns/blocks were with another size of "chunk". Maybe use increasing powers of two all the way up, so every thing is a 2x2 block of subblocks until you get to physical tiles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment