Sylvia Kosowski

27 Jan 2015

The size of the Pebble Watch reminded me of the Tamagotchi toys I used to play with as a kid, so I decided to make a project featuring a Time Monster, which the owner of the watch must look after. It also functions as a watch of sorts, though it only really works with telling relative time. Every minute, the monster will become sad and the watch will buzz. The monster will demand some sort of display of affection from the user. To make the monster happy again, the user can shake the watch. The monster demands the same thing every minute, but every 15, 30, 45, and 60 minutes, it will demand something unique. By following the pattern of these unique demands, the user is able to gain a relative sense of how much time has passed within an hour.

The concept for this Time Monster also stemmed from the fact that people are constantly checking the time throughout the day in order to make plans, arrive at destinations, etc. Time is a very demanding entity, so I wanted to personify this quality in the form of a demanding pet to look after.

Stills:

hugme

“Hug Me” is displayed at the 15 min mark of each hour.

"Feed me" is displayed at the 30 min mark of an hour.

“Feed me” is displayed at the 30 min mark of an hour.

"Tell me a story" is displayed at the 45 min mark of an hour.

“Tell me a story” is displayed at the 45 min mark of an hour.

"Love me" is displayed every hour.

“Love me” is displayed every hour.

"Wanna play?" is displayed every minute which is not one of the 0-15-30-45 min markers.

“Wanna play?” is displayed every minute which is not one of the 0-15-30-45 min markers.

This shows when the monster is content, between minutes.

This shows when the monster is content, between minutes.

Concept sketch

Concept sketch

Below is the code:

#include <pebble.h>

static Window *s_main_window;

static BitmapLayer *s_image_layer;
static GBitmap *bestFriend;
static GBitmap *feedMe;
static GBitmap *hugMe;
static GBitmap *loveMe;
static GBitmap *tellMeStory;
static GBitmap *playWithMe;

bool isDemanding;

static void update_time() {
 // Get a tm structure
 time_t temp = time(NULL); 
 struct tm *tick_time = localtime(&temp);
 
 
 if(tick_time->tm_min == 0) {
 vibes_long_pulse();
 bitmap_layer_set_bitmap(s_image_layer, loveMe);
 isDemanding = true;
 } else if(tick_time->tm_min == 15) {
 vibes_long_pulse();
 bitmap_layer_set_bitmap(s_image_layer, hugMe);
 isDemanding = true;
 } else if(tick_time->tm_min == 30) {
 vibes_long_pulse();
 bitmap_layer_set_bitmap(s_image_layer, tellMeStory);
 isDemanding = true;
 } else if(tick_time->tm_min == 45) {
 vibes_long_pulse();
 bitmap_layer_set_bitmap(s_image_layer, feedMe);
 isDemanding = true;
 } else if(tick_time->tm_sec == 0) {
 vibes_short_pulse();
 bitmap_layer_set_bitmap(s_image_layer, playWithMe);
 isDemanding = true;
 }
 
}

//Handles the time
static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {
 update_time();
}

//Handles accelerometer stuff
static void tap_handler(AccelAxisType axis, int32_t direction) {
 if(isDemanding) {
 if(direction != 0) {
 isDemanding = false;
 bitmap_layer_set_bitmap(s_image_layer, bestFriend);
 }
 }
}

static void main_window_load(Window *window) {
 
 bestFriend = gbitmap_create_with_resource(RESOURCE_ID_BEST_FRIEND);
 feedMe = gbitmap_create_with_resource(RESOURCE_ID_FEED_ME);
 hugMe = gbitmap_create_with_resource(RESOURCE_ID_HUG_ME);
 loveMe = gbitmap_create_with_resource(RESOURCE_ID_LOVE_ME);
 tellMeStory = gbitmap_create_with_resource(RESOURCE_ID_TELL_ME_STORY);
 playWithMe = gbitmap_create_with_resource(RESOURCE_ID_PLAY_WITH_ME);
 
 s_image_layer = bitmap_layer_create(GRect(0, 0, 144, 168));
 bitmap_layer_set_bitmap(s_image_layer, bestFriend);
 layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(s_image_layer));

}

static void main_window_unload(Window *window) {
 
 // Destroy GBitmaps
 gbitmap_destroy(bestFriend);
 gbitmap_destroy(feedMe);
 gbitmap_destroy(hugMe);
 gbitmap_destroy(loveMe);
 gbitmap_destroy(tellMeStory);
 gbitmap_destroy(playWithMe);
 
 // Destroy BitmapLayer
 bitmap_layer_destroy(s_image_layer);
}

static void init() {
 isDemanding = false;
 
 //Register with TickTimerService
 tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);
 //Register with Accelerometer tap event service
 accel_tap_service_subscribe(tap_handler);
 
 //Create main Window element and assign to pointer
 s_main_window = window_create();
 
 //Set handlers to manage the elements inside the Window
 window_set_window_handlers(s_main_window, (WindowHandlers) {
 .load = main_window_load,
 .unload = main_window_unload
 });
 
 //Show the Window on the watch, with animated=true
 window_stack_push(s_main_window, true);
 
 update_time();
}

static void deinit() {
 //Destroy Window
 window_destroy(s_main_window);
}

int main(void) {
 init();
 app_event_loop();
 deinit();
}