/*! * Asks for data from the accelerometer, and schedules itself for the future */ void accel_timer_callback() { AccelData accel = {0, 0, 0, 0, 0}; accel_service_peek(&accel); accel_handler(&accel, 1); accel_timer = app_timer_register(20, accel_timer_callback, NULL); }
Layer* virtual_screen_init( GRect screen_bounds, GSize virtual_size, VirutalScreenMode virtual_screen_mode) { s_max_point = GPoint(virtual_size.w-screen_bounds.size.w, virtual_size.h-screen_bounds.size.h); s_center_point = GPoint(s_max_point.x/2, s_max_point.y/2); switch(virtual_screen_mode) { case VIRTUAL_SCREEN_MODE_DIRECT: { s_accel_point = s_center_point; AccelData accel_data; accel_service_peek(&accel_data); s_reference_point = GPoint(accel_data.x, accel_data.y); s_timer = app_timer_register(VIRTUAL_SCREEN_UPDATE_TIMEOUT_MS, prv_direct_callback, NULL); break; } case VIRTUAL_SCREEN_MODE_AUTO: { s_timer = app_timer_register(VIRTUAL_SCREEN_UPDATE_AUTO_TIMEOUT_MS, prv_auto_callback, NULL); break; } case VIRTUAL_SCREEN_MODE_CENTERED: case VIRTUAL_SCREEN_MODE_TOP_LEFT: case VIRTUAL_SCREEN_MODE_TOP_RIGHT: case VIRTUAL_SCREEN_MODE_BOTTOM_LEFT: case VIRTUAL_SCREEN_MODE_BOTTOM_RIGHT: { s_timer = app_timer_register(10, prv_corner_callback, (void*)virtual_screen_mode); break; } } s_layer = layer_create(GRect(0, 0, virtual_size.w, virtual_size.h)); return s_layer; }
static void prv_direct_callback(void* data) { static AccelData last_accel_data; AccelData accel_data; accel_service_peek(&accel_data); if( ABS(accel_data.x, last_accel_data.x) > VIRTUAL_SCREEN_UPDATE_THRESHOLD || ABS(accel_data.y, last_accel_data.y) > VIRTUAL_SCREEN_UPDATE_THRESHOLD) { s_accel_point = GPoint( s_center_point.x-(s_reference_point.x - accel_data.x)/VIRTUAL_SCREEN_UPDATE_SENSITIVITY, s_center_point.x+(s_reference_point.y - accel_data.y)/VIRTUAL_SCREEN_UPDATE_SENSITIVITY); if(s_accel_point.x > s_max_point.x) s_accel_point.x = s_max_point.x; if(s_accel_point.x < 0) s_accel_point.x = 0; if(s_accel_point.y > s_max_point.y) s_accel_point.y = s_max_point.y; if(s_accel_point.y < 0) s_accel_point.y = 0; GRect bounds = layer_get_bounds(s_layer); bounds.origin = GPoint(-s_accel_point.x, -s_accel_point.y); layer_set_bounds(s_layer, bounds); layer_mark_dirty(s_layer); } last_accel_data = accel_data; s_timer = app_timer_register(VIRTUAL_SCREEN_UPDATE_TIMEOUT_MS, prv_direct_callback, data); }
// Advance the display by one tick static void tick() { AccelData accel; accel_service_peek(&accel); int16_t movement = 0; movement += abs_int16t(accel.x - old_accel.x); movement += abs_int16t(accel.y - old_accel.y); movement += abs_int16t(accel.z - old_accel.z); movement = deadzone_int16t(movement, 150); old_accel = accel; if (movement > 0) { level = level - STATUS_RECHARGE; } else { level = level + STATUS_CLOAK; } level = clamp(level, 0, STATUS_MAX); app_log(APP_LOG_LEVEL_DEBUG, __FILE__, __LINE__, "Accel: %d, Level: %d, Status: %d", movement, level, level / (STATUS_MAX / 10)); }
static void updateScreen(Layer *layer, GContext* ctx) { AccelData a; SnowFlake *s; int i, d, w; graphics_context_set_stroke_color(ctx, GColorWhite); graphics_context_set_fill_color(ctx, GColorWhite); if (accel_service_peek(&a) < 0) { w = 0; } else { w = a.x/250; } for (i=0; i<NUMSNOWFLAKES; i++) { s = &snowflakes[i]; if (s->p.y >= h[s->p.x]) { newSnowFlake(i, false); for (d=s->p.x-s->r; d<=s->p.x+s->r; d++) { stackSnowFlake(d); } } s->c++; if (s->c < MAXSTEPS) { d = 0; } else { s->c = 0; d = rand()%FUZZYNESS; if (rand()%2) d = -d; } s->p.x += d + w; if (s->p.x < 0) { s->p.x += WIDTH; } if (s->p.x >= WIDTH) { s->p.x -= WIDTH; } s->p.y += s->vs; graphics_fill_circle(ctx, s->p, s->r); } for (i=0; i<WIDTH; i++) { graphics_draw_line(ctx, GPoint(i, h[i]), GPoint(i, HEIGHT)); } graphics_context_set_text_color(ctx, GColorBlack); for (i=0; i<4; i++) { graphics_draw_text(ctx, hourText, fontHour, bgHourRect[i], GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #if defined(SHOWDATE) graphics_draw_text(ctx, dateText, fontDate, bgDateRect[i], GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #endif } graphics_context_set_text_color(ctx, GColorWhite); graphics_draw_text(ctx, hourText, fontHour, hourRect, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #if defined(SHOWDATE) graphics_draw_text(ctx, dateText, fontDate, dateRect, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #endif }
static void layer_update_callback(Layer *me, GContext* ctx) { // preparations GRect bounds = layer_get_bounds(me); uint16_t width = bounds.size.w; uint16_t height = bounds.size.h; uint16_t stride = (bounds.size.w + 31) / 32 * 32; uint16_t max = (height - 1) * stride + width; uint16_t shake = stride - width; uint16_t shake_stride = shake * stride; // handle shake if (do_shake) { do_shake = false; light_enable_interaction(); for (uint16_t i = 0, j = rand(); i < NUM_FLAKES; i++, j+=31) { for (uint16_t k = 0; k < 2; k++, j+=31) { uint16_t next = flakes[i] + j % (max * 2) - max; if (next < max && next % stride < width && get_pixel(ctx, next) == GColorBlack) { flakes[i] = next; break; } } } last_time = 0; } // update time text time_t t = time(NULL); if (t / UPDATE_S > last_time) { last_time = t / UPDATE_S; char time_text[6]; clock_copy_time_string(time_text, sizeof(time_text)); graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_rect(ctx, bounds, 0, GCornerNone); GRect rect = (GRect) {{0, 60}, {width, 50}}; GFont font = fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD); graphics_draw_text(ctx, time_text, font, rect, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL); graphics_context_set_stroke_color(ctx, GColorWhite); for (uint16_t i = 0, j = rand(); i < NUM_FLAKES; i++) { if (get_pixel(ctx, flakes[i]) == GColorBlack) { graphics_draw_pixel(ctx, GPoint(flakes[i] % stride, flakes[i] / stride)); } else { for (uint16_t k = 0; k < 8; k++, j++) { uint16_t next = flakes[i] + (j % 9 / 3 - 1) * shake_stride + (j % 3 - 1) * shake; if (next < max && next % stride < width && get_pixel(ctx, next) == GColorBlack) { flakes[i] = next; graphics_draw_pixel(ctx, GPoint(flakes[i] % stride, flakes[i] / stride)); break; } } } } } // apply physics AccelData accel = {.x = 0, .y = 0, .z = 0}; accel_service_peek(&accel); uint16_t absx = accel.x < 0 ? -accel.x : accel.x; uint16_t absy = accel.y < 0 ? -accel.y : accel.y; uint16_t span = (absx + absy + 10) * SPEED; for (uint16_t i = 0, j = rand(), k = rand(), l = rand(); i < span; i++, j++, k++, l++) { uint16_t index = j % NUM_FLAKES; uint16_t next = flakes[index]; int16_t sideway = k % 3 == 0 ? l % 5 - 2 : 0; int16_t accx = accel.x + accel.y * sideway; int16_t accy = accel.y - accel.x * sideway; absx = accx < 0 ? -accx : accx; absy = accy < 0 ? -accy : accy; if (absx > absy || k % absy < absx) { if (accx > 0) { next++; } else { next--; } } if (absy > absx || l % absx < absy) { if (accy > 0) { next -= stride; } else { next += stride; } } if (next < max && next % stride < width && get_pixel(ctx, next) == GColorBlack) { graphics_context_set_stroke_color(ctx, GColorBlack); graphics_draw_pixel(ctx, GPoint(flakes[index] % stride, flakes[index] / stride)); graphics_context_set_stroke_color(ctx, GColorWhite); graphics_draw_pixel(ctx, GPoint(next % stride, next / stride)); flakes[index] = next; } } if (!timer) timer = app_timer_register(UPDATE_MS, timer_callback, NULL); } static void handle_accel(AccelData *accel_data, uint32_t num_samples) { // or else I will crash } static void accel_tap_handler(AccelAxisType axis, int32_t direction) { do_shake = true; } static void root_update_callback(Layer *me, GContext* ctx) { // hack to prevent screen cleaning } static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); layer_set_update_proc(window_layer, root_update_callback); GRect bounds = layer_get_bounds(window_layer); layer = layer_create(bounds); layer_set_update_proc(layer, layer_update_callback); layer_add_child(window_layer, layer); uint16_t width = bounds.size.w; uint16_t height = bounds.size.h; uint16_t stride = (bounds.size.w + 31) / 32 * 32; for (uint16_t i = 0; i < NUM_FLAKES; i++) { flakes[i] = rand() % height * stride + rand() % width; } }
void simply_accel_peek(SimplyAccel *self, AccelData *data) { if (self->data_subscribed) { return; } accel_service_peek(data); }
static void data_handler(void* out) { app_timer_register(30, data_handler, NULL); layer_mark_dirty(s_player_layer); //you win if (playerY == mazeHeight-1 && playerX == mazeWidth-1 && dx==0 && dy==0){ vibes_short_pulse(); load(mazeWidth,mazeHeight,corridorSize); return; } int speed = difficulty==1?2:1; if(dx!=0 || dy!=0) { if(dx<0) dx+=speed; if(dx>0) dx-=speed; if(dy<0) dy+=speed; if(dy>0) dy-=speed; return; } AccelData* data = malloc(sizeof(*data)); accel_service_peek(data); if(data->x*data->x + data->y*data->y > 150*150) { //left, right, up, down, just like maze.c int xopts[4] = {-1,1,0,0}; int yopts[4] = {0,0,-1,1}; int bestopt=0, bestscore=0; int xmag = abs(data->x), ymag = abs(data->y); //app_log(APP_LOG_LEVEL_INFO,"main.c",1337,"mag %i %i",xmag,ymag); for(int i=0; i<4; i++) { int newx = playerX+xopts[i], newy = playerY+yopts[i]; //bounds checking int curscore = (newx>=0 && newy>=0 && newx<mazeWidth && newy < mazeHeight) ? 1 : 0; //wall checking if(i<2) {//x curscore *= 1-maze[getPOS(playerY,(xopts[i]==1?playerX:newx),mazeWidth)].r; curscore *= xmag<50?0:xopts[i]*data->x; } else {//y curscore *= 1-maze[getPOS((yopts[i]==1?playerY:newy),playerX,mazeWidth)].b; curscore *= ymag<50?0:-yopts[i]*data->y; } //app_log(APP_LOG_LEVEL_INFO,"main.c",1338,"score %i %i",i,curscore); if(curscore > bestscore) { bestopt = i; bestscore = curscore; } } if(bestscore>0) { lightup(); playerX += xopts[bestopt]; playerY += yopts[bestopt]; dx -= xopts[bestopt]*(corridorSize-speed); dy -= yopts[bestopt]*(corridorSize-speed); } } free(data); }