Watchface — Adventure

Hi folks, I recently completed a new watchface called "Adventure". Here's what it looks like.



https://apps.garmin.com/en-US/apps/84a8873e-3c97-49f6-ba16-05c67a38d72e

It utilises a "full screen" scrolling effect. It's reasonably taxing on the hardware, so it's only available for the fenix5 series, and the 935.
I'll be adding HR, steps, and weather shortly. Happy to hear some feedback!
  • I want to see "Colossal Cave"! xxyyz! :)

    Just kidding Franco! It looks cool!
  • I've just released version 1.1. It now supports nearly every Garmin watch, except for the fr920xt :)
    As a bonus, it will show you the current HR if you have a built-in sensor.

    As you can imagine, it was a real drama to pack all this into less than 58kb!
    I'm happy to discuss how this was built if anyone's interested.
  • Former Member
    Former Member over 7 years ago
    Ha! I currently have 3 of your watchface installed on my Forerunner 235. :-)

    I'd be very interested in knowing how you made this and/or the Vaders! watch face please.
  • Ha! I currently have 3 of your watchface installed on my Forerunner 235. :-)

    I'd be very interested in knowing how you made this and/or the Vaders! watch face please.


    Oh cool! Glad you like them..

    I might start with "Adventure", and leave "Vaders!" for another post...

    So, "Adventure" uses a long utilised technique in old school game programming, which is tile maps. It's too "expensive" memory wise to have large scrolling bitmaps, so the background is made up of smaller bitmaps, like a patchwork quilt.

    For "Adventure", there's close to about 30 different bitmap assets, or "tiles". I could have probably stored more, but I would have hit memory restrictions on devices like the vahr. For efficiency, each bitmap is represented as a symbol in a look up table (a dictionary).

    sprite_map = {
    "tr" => sprite_tree_1,
    "pt" => sprite_plant_1,
    "f2" => sprite_flower_2,
    "g4" => sprite_grass_4,
    ...
    };



    The background, or patchwork quilt, is stored as a large 2d array of these symbols to represent the map.
    The map is about 10 tiles high, and 20 tiles wide — however, the screen only renders a small window of about 4x5 tiles.

    map = [
    ["tr","f2","wl","wr","g3" ... ],
    ["pt","g4","h1","g3","pt" ... ],
    ...
    ];


    Now, drawing the map is really simple. We basically draw the bitmaps in two loops...

    for (var y = map_y_offset; y < tiles_y_to_draw+map_y_offset; y++) {
    for (var x = map_x_offset; x < tiles_x_to_draw+map_x_offset; x++) {
    var this_sprite = map[y][x];
    dc.drawBitmap(((x-map_x_offset)*sprite_size)-scroll_x, ((y-map_y_offset)*sprite_size)-scroll_y, sprite_map.get(this_sprite));
    }
    }


    The scrolling is done via this neat trick. Basically, the entire patchwork quilt is shifted slightly each "frame", and a new tile is picked up from the 2d map array (represented by the green blocks). Once the new green block is in view, we repeat the process.



    From a performance perspective, it is reasonably "expensive" whenever you draw to the screen in CIQ.
    Bitmaps have the best performance (you're just copying memory), while drawing primitives (lines), and fonts are slower.

    With "Adventure", I'm drawing about 30 or so bitmaps to the screen — so it's reasonably heavy, but still fast enough to not look too sluggish on older devices.

    More to come...
  • Former Member
    Former Member over 7 years ago
    Wow! Thank you very much for that - you've gone to a lot of effort to explain this! And it's very interesting indeed.