bool updateGame(void) { /* In cas of pausing */ if (state == STATE_PAUSE) { if (arduboy.buttonDown(A_BUTTON | B_BUTTON)) { state = STATE_GAME; ignoreCnt = 30; // 1/2 sec toDraw = true; dprintln("Resume"); } return false; } /* Move objects */ int scrollX = -playerX / 4; int scrollY = -playerY / 4; playerX += scrollX; playerY += scrollY; playerRotate += playerTorque; if (playerJump > -64) { if (--playerJump == 0) { pFloorBlur = NULL; if (state == STATE_CLEAR) { initLevel(false); } } } if (state != STATE_OVER) { moveFloors(scrollX, scrollY, playerJump); } moveChips(scrollX, scrollY, playerJump); /* Player interaction */ if (state == STATE_GAME || state == STATE_OVER) { movePlayer(); if (state == STATE_GAME) { gameFrames++; if (floorAry[floorIdxFirst].z < 0) { state = STATE_OVER; isHiscore = (setLastScore(score, gameFrames) == 0); counter = 480; // 8 secs arduboy.playScore2(soundOver, 1); dprint("Game Over: score="); dprintln(score); } else if (ignoreCnt == 0 && arduboy.buttonDown(A_BUTTON | B_BUTTON)) { state = STATE_PAUSE; dprintln("Pause"); } } else { counter--; if (ignoreCnt == 0 && arduboy.buttonDown(A_BUTTON | B_BUTTON)) { initLevel(true); } } } if (ignoreCnt > 0) ignoreCnt--; toDraw = true; return (state == STATE_OVER && counter == 0); }
void handleMenu(void) { if (arduboy.buttonDown(UP_BUTTON) && menuItemPos > 0) { menuItemPos--; playSoundTick(); isInvalidMenu = true; dprint(F("menuItemPos=")); dprintln(menuItemPos); } if (arduboy.buttonDown(DOWN_BUTTON) && menuItemPos < menuItemCount - 1) { menuItemPos++; playSoundTick(); isInvalidMenu = true; dprint(F("menuItemPos=")); dprintln(menuItemPos); } if (isControlSound && arduboy.buttonDown(A_BUTTON)) { setSound(!arduboy.isAudioEnabled()); playSoundClick(); isInvalidMenu = true; } if (arduboy.buttonDown(B_BUTTON)) { menuItemAry[menuItemPos].func(); } }
static void judgeVanish(int x, int y) { memset(vanishFlg, 0, FIELD_H); OBJ_T die = field[y][x]; if (die.type == OBJ_TYPE_1) { if (judgeHappyOne(x, y)) { int link = vanishHappyOne(); setVanishEffect(OBJ_TYPE_1); score += link; dprint(F("Happy one ")); dprintln(link); } } else { uint16_t chain; int link = judgeLinkedDice(x, y, die.type, &chain); if (link >= die.type) { if (chain < CHAIN_MAX) chain++; vanishLinkedDice(chain); setVanishEffect(die.type); score += (uint32_t) die.type * link * chain; maxChain = max(maxChain, chain); dprint(F("Valnish ")); dprint(die.type * link); dprint(F(" x ")); dprintln(chain); } } score = min(score, SCORE_MAX); }
static bool isGameOver(void) { #ifdef DEBUG if (dbgRecvChar == 'o') { pLargeLabel = F("DEBUG"); return true; } #endif switch (gameMode) { case GAME_MODE_ENDLESS: if (countValidDice >= FIELD_H * FIELD_W) { pLargeLabel = F("GAME OVER"); if (record.endlessHiscore < score) { record.endlessHiscore = score; record.endlessMaxLevel = level; dprintln(F("New record! (Endless)")); } arduboy.playScore2(soundOver, 1); return true; } return false; case GAME_MODE_LIMITED: if (gameFrames >= FRAMES_3MINUTES) { pLargeLabel = F("TIME UP"); if (record.limitedHiscore < score) { record.limitedHiscore = score; record.limitedMaxChain = maxChain; dprintln(F("New record! (Time Limited)")); } arduboy.playScore2(soundOver, 1); return true; } return false; case GAME_MODE_PUZZLE: if (step <= 0 || countValidDice == 0) { if (countValidDice == 0) { pLargeLabel = F("CLEAR"); int idx = issue / 8; uint8_t bit = 1 << issue % 8; if ((record.puzzleClearFlag[idx] & bit) == 0) { record.puzzleClearFlag[idx] |= bit; record.puzzleClearCount++; dprint(F("Clear puzzle issue ")); dprintln(issue); if (issue < COUNT_ISSUES - 1) issue++; } arduboy.playScore2(soundClear, 1); } else { pLargeLabel = F("AGAIN"); arduboy.playScore2(soundAgain, 1); } return true; } return false; } }
static void moveFloors(int scrollX, int scrollY, int scrollZ) { FLOOR *pFloor; for (int i = 0; i < FLOORS_MANAGE; i++) { pFloor = &floorAry[i]; if (pFloor->type != FLRTYPE_NONE) { pFloor->x += scrollX + pFloor->vx; pFloor->y += scrollY + pFloor->vy; pFloor->z += scrollZ; int z = pFloor->z; if (pFloor->type == FLRTYPE_VANISH) { if (z < 0) { pFloor->size = pFloor->sizeBack; } else if (pFloor->size != pFloor->sizeBack && pFloor->size > 0) { pFloor->size--; } } if (scrollZ <= 0 && z >= 0 && z + scrollZ - 1 < 0) { int diff = max(abs(pFloor->x - playerX), abs(pFloor->y - playerY)); if (diff < pFloor->size * 128) { springPlayer(pFloor, diff); dprint("Spring floor "); dprintln(i); } } } } pFloor = &floorAry[floorIdxFirst]; if (pFloor->z > FLOOR_Z_MAX) { pFloor->type = FLRTYPE_NONE; floorIdxFirst = nextFloorIdx(floorIdxFirst); dprint("floorIdxFirst="); dprintln(floorIdxFirst); } pFloor = &floorAry[floorIdxLast]; int z = pFloor->z; if (state == STATE_GAME && z >= 0 && pFloor->type != FLRTYPE_GOAL) { uint8_t pos = pFloor->pos + 1; uint8_t type = (pos == FLOORS_LEVEL) ? FLRTYPE_GOAL : flrTypes[random(flrTypesNum)]; floorIdxLast = nextFloorIdx(floorIdxLast); addFloor(type, pos, rand() * 2, rand() * 2, z - (512 + level * 32)); dprint("floorIdxLast="); dprintln(floorIdxLast); } #ifdef DEBUG if (dbgRecvChar == 'z') { pFloor->type = FLRTYPE_GOAL; springPlayer(pFloor, 0); } #endif }
static void initLevel(bool isStart) { if (isStart) { state = STATE_START; gameFrames = 0; score = 0; level = 0; arduboy.playScore2(soundStart, 0); } else { level++; arduboy.tunes.stopScore(); } dprint("Init Level "); dprintln(level); flrTypesNum = 0; if (level < 6) flrTypes[flrTypesNum++] = FLRTYPE_NORMAL; if (level ==1) flrTypes[flrTypesNum++] = FLRTYPE_NORMAL; if (level & 1) flrTypes[flrTypesNum++] = FLRTYPE_MOVE; if (level & 2) flrTypes[flrTypesNum++] = FLRTYPE_VANISH; if (level & 4 || level == 8) flrTypes[flrTypesNum++] = FLRTYPE_SMALL; for (int i = 0; i < FLOORS_MANAGE; i++) { floorAry[i].type = FLRTYPE_NONE; } floorIdxFirst = 0; floorIdxLast = 0; addFloor(FLRTYPE_NORMAL, 0, playerX, playerY, FLOOR_Z_MAX); }
void setMenuItemPos(int8_t pos) { menuItemPos = pos; isInvalidMenu = true; dprint(F("menuItemPos=")); dprintln(menuItemPos); }
uint8_t matrix_scan(void) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { select_col(col); _delay_us(3); // TODO: Determine the correct value needed here. uint8_t rows = read_rows(); if((col == 0 && !LAYOUT_MINI) || (col == 2 && LAYOUT_MINI) ) { rows |= read_caps(); } for (uint8_t row = 0; row < MATRIX_ROWS; row++) { bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); bool curr_bit = rows & (1<<row); if (prev_bit != curr_bit) { matrix_debouncing[row] ^= ((matrix_row_t)1<<col); if (debouncing) { dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); } debouncing = DEBOUNCE; } } unselect_cols(); } if (debouncing) { if (--debouncing) { _delay_ms(1); } else { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = matrix_debouncing[i]; } } } return 1; }
uint8_t matrix_scan(void) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { // 0-16 select_col(col); _delay_us(30); // without this wait it won't read stable value. uint16_t rows = read_rows(); for (uint8_t row = 0; row < MATRIX_ROWS; row++) { // 0-5 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); bool curr_bit = rows & (1<<row); if (prev_bit != curr_bit) { matrix_debouncing[row] ^= ((matrix_row_t)1<<col); if (debouncing) { dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); } debouncing = DEBOUNCE; } } unselect_cols(); } if (debouncing) { if (--debouncing) { _delay_ms(1); } else { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = matrix_debouncing[i]; } } } return 1; }
static void moveCursor(int8_t vx, int8_t vy) { if (cursorX + vx < 0 || cursorX + vx >= BOARD_W) vx = 0; if (cursorY + vy < 0 || cursorY + vy >= BOARD_H) vy = 0; if (vx != 0 || vy != 0) { cursorX += vx; cursorY += vy; focusPiece(cursorX, cursorY); toDrawAll = true; } if (arduboy.buttonDown(B_BUTTON) && focusPieceIdx >= 0) { arduboy.playScore2(soundPick, 2); state = STATE_PICKED; toDrawAll = true; dprint(F("Pick piece=")); dprintln(focusPieceIdx); } else if (arduboy.buttonDown(A_BUTTON)) { playSoundClick(); if (isDirty && creepFrames >= FRAMES_30SECS) { saveAndResetCreep(); } state = STATE_LEAVE; toDrawAll = true; } }
MODE_T updatePuzzle(void) { handleDPad(); if (state == STATE_FREE) { moveCursor(padX, padY); playFrames++; } else if (state == STATE_PICKED) { movePiece(padX, padY); playFrames++; } else if (state == STATE_CLEAR) { clearEffectCount--; if (clearEffectCount == 0) { arduboy.stopScore2(); state = STATE_FREE; helpY = HEIGHT; toDrawAll = true; } } adjustHelpPosition(); if (creepFrames < FRAMES_2MINS) { creepFrames++; } if (padRepeatCount == 0) { if (quietFrames < FRAMES_5SECS) { quietFrames++; } else if (isDirty && creepFrames >= FRAMES_2MINS) { saveAndResetCreep(); dprintln(F("Auto save")); } } else { quietFrames = 0; } return (state == STATE_LEAVE) ? MODE_MENU : MODE_PUZZLE; }
/** \brief Called to execute an action. * * FIXME: Needs documentation. */ void action_exec(keyevent_t event) { if (!IS_NOEVENT(event)) { dprint("\n---- action_exec: start -----\n"); dprint("EVENT: "); debug_event(event); dprintln(); #ifdef RETRO_TAPPING retro_tapping_counter++; #endif } #ifdef FAUXCLICKY_ENABLE if (IS_PRESSED(event)) { FAUXCLICKY_ACTION_PRESS; } if (IS_RELEASED(event)) { FAUXCLICKY_ACTION_RELEASE; } fauxclicky_check(); #endif #ifdef SWAP_HANDS_ENABLE if (!IS_NOEVENT(event)) { process_hand_swap(&event); } #endif keyrecord_t record = { .event = event }; #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) if (has_oneshot_layer_timed_out()) { clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); } if (has_oneshot_mods_timed_out()) { clear_oneshot_mods(); } #endif #ifndef NO_ACTION_TAPPING action_tapping_process(record); #else process_record(&record); if (!IS_NOEVENT(record.event)) { dprint("processed: "); debug_record(record); dprintln(); } #endif }
static void layer_state_set(uint32_t state) { dprint("layer_state: "); layer_debug(); dprint(" to "); layer_state = state; layer_debug(); dprintln(); clear_keyboard_but_mods(); // To avoid stuck keys }
void action_exec(keyevent_t event) { if (!IS_NOEVENT(event)) { dprint("\n---- action_exec: start -----\n"); dprint("EVENT: "); debug_event(event); dprintln(); } keyrecord_t record = { .event = event }; #ifndef NO_ACTION_TAPPING action_tapping_process(record); #else process_action(&record); if (!IS_NOEVENT(record.event)) { dprint("processed: "); debug_record(record); dprintln(); } #endif }
void addMenuItem(const __FlashStringHelper *label, void (*func)(void)) { if (menuItemCount >= MENU_COUNT_MAX) return; ITEM_T *pItem = &menuItemAry[menuItemCount]; pItem->label = label; pItem->func = func; menuItemCount++; dprint(F("Add menu items: ")); dprintln(label); }
static void setLevel(int newLevel) { level = newLevel; if (level == 1) norm = 0; uint8_t grade = level / 5; uint8_t gradeStep = level % 5; countDiceMin = min(12 + grade + gradeStep, 28); countDiceUsual = min(18 + grade * 2, 29) + gradeStep; countDiceMax = 35; intervalDieUsual = max(FPS * 4 - grade * 12 - gradeStep * 16, FPS / 2); intervalDieMax = FPS * 6 - grade * 5; norm += grade * 2 + 6; elaspedFrames = min(FPS * (grade - 10) / 2, 0); if (gradeStep == 0) elaspedFrames -= FPS * 4; blinkFrameFrames = BLINK_FRAME_FRAMES_MAX; blinkLevelFrames = BLINK_LEVEL_FRAMES_MAX; dprint(F("Level ")); dprintln(level); dprintln(countDiceMin); dprintln(countDiceUsual); dprintln(intervalDieUsual); dprintln(intervalDieMax); dprintln(elaspedFrames); }
static void initPuzzleField(void) { countDice = 0; const uint8_t *p = puzzleData + issue * BYTES_PER_ISSUE; #ifdef DEBUG p = puzzleData; #endif uint16_t buffer = 0, bits = 0; for (int y = 0; y < FIELD_H; y++) { for (int x = 0; x < FIELD_W; x++) { if (bits < 5) { buffer += pgm_read_byte(p++) << bits; bits += 8; } OBJ_T *pObj = &field[y][x]; uint16_t data = buffer & 0x1F; if (data < 30) { if (data < 24) { pObj->type = data / 4 + OBJ_TYPE_1; pObj->rotate = data % 4; pObj->mode = OBJ_MODE_NORMAL; } else { pObj->type = data - 24 + OBJ_TYPE_1; pObj->rotate = 0; pObj->mode = OBJ_MODE_FIXED; } pObj->chain = 0; pObj->depth = 0; countDice++; } else { pObj->type = (data == 30) ? OBJ_TYPE_BLANK : OBJ_TYPE_FLOOR; pObj->rotate = 0; pObj->depth = DEPTH_MAX; } buffer >>= 5; bits -= 5; } } for (int y = 1; y < FIELD_H - 1; y++) { for (int x = 1; x < FIELD_W - 1; x++) { if (field[y][x].type == OBJ_TYPE_BLANK && field[y - 1][x].type != OBJ_TYPE_BLANK && field[y + 1][x].type != OBJ_TYPE_BLANK && field[y][x - 1].type != OBJ_TYPE_BLANK && field[y][x + 1].type != OBJ_TYPE_BLANK) { field[y][x].rotate = 1; } } } countValidDice = countDice; step = pgm_read_byte(p); dprint(F("Puzzle initialized ")); dprintln(issue); }
static void layer_state_set(uint32_t state) { dprint("layer_state: "); layer_debug(); dprint(" to "); layer_state = state; layer_debug(); dprintln(); clear_keyboard_but_mods(); // To avoid stuck keys // find highest set bit and set LED color appropriately uint8_t active_layer = 32 - __builtin_clzl(layer_state | default_layer_state) - 1; on_layer_change(active_layer); }
static void encodePieces(CODE_T *pCode) { PIECE_T pieceWorkAry[PIECES]; memcpy(pieceWorkAry, pieceAry, sizeof(PIECE_T) * PIECES); uint8_t rot = pieceWorkAry[0].rot; PIECE_T *p = pieceWorkAry; rotatePieces(p, 0); pieceWorkAry[0].rot = rot; for (int i = 0; i < PIECES; i++, p++, pCode++) { pCode->xy = (p->x - 4) / 2 + p->y / 2 * 5; pCode->rot = p->rot; } dprintln(F("Encoded pieces")); }
static void initTrialField(void) { for (int y = 0; y < FIELD_H; y++) { for (int x = 0; x < FIELD_W; x++) { OBJ_T *pObj = &field[y][x]; pObj->type = OBJ_TYPE_FLOOR; pObj->depth = DEPTH_MAX; } } countDice = countValidDice = 0; for (int i = 0; i < COUNT_DICE_INITIAL; i++) { setDie(pickFloorObject(), OBJ_MODE_NORMAL); } dprintln(F("Field initialized")); }
static uint8_t checkAndRegisterPieces(void) { CODE_T code[PIECES], work[PIECES]; encodePieces(code); dprintln(F("Checking history...")); for (int i = -1; i < clearCount; i++) { uint8_t idx = (i == -1) ? lastPatternIdx : i; if (idx < clearCount && i != lastPatternIdx) { readEncodedPieces(idx, work); if (code[0].xy == work[0].xy && memcmp(code + 1, work + 1, PIECES - 1) == 0) { return idx; } } } writeEncodedPieces(clearCount, code); return clearCount; }
/** \brief Take a key event (key press or key release) and processes it. * * FIXME: Needs documentation. */ void process_record(keyrecord_t *record) { if (IS_NOEVENT(record->event)) { return; } if(!process_record_quantum(record)) return; action_t action = store_or_get_action(record->event.pressed, record->event.key); dprint("ACTION: "); debug_action(action); #ifndef NO_ACTION_LAYER dprint(" layer_state: "); layer_debug(); dprint(" default_layer_state: "); default_layer_debug(); #endif dprintln(); process_action(record, action); }
static void updateGamePlaying(void) { #ifdef DEBUG if (dbgRecvChar == 'a') initTrialField(); if (dbgRecvChar == 'l') norm = 0; if (dbgRecvChar == 'q') field[cursorY][cursorX].chain = CHAIN_MAX; #endif if (vanishFlashFrames > 0) vanishFlashFrames--; if (blinkFrameFrames > 0) blinkFrameFrames--; if (blinkChainFrames > 0) blinkChainFrames--; if (blinkLevelFrames > 0) blinkLevelFrames--; handleDPad(); updateField(); moveCursor(); if (gameMode == GAME_MODE_ENDLESS) { if (level < LEVEL_MAX && norm <= 0) { setLevel(level + 1); arduboy.playScore2(soundLevelUp, 2); } } else if (gameMode == GAME_MODE_LIMITED) { if (isTimeToBlinkFrame()) { arduboy.playScore2(soundTimeToBlink, 2); blinkFrameFrames = BLINK_FRAME_FRAMES_MAX; } } gameFrames++; record.playFrames++; blinkFlg = !blinkFlg; if (isGameOver()) { state = STATE_OVER; writeRecord(); blinkFlg = false; overAnimFrames = OVER_ANIM_FRAMES_MAX; dprintln(F("Game over")); } else if (arduboy.buttonDown(A_BUTTON)) { setupMenu(); } isInvalid = true; }
static void addFloor(uint8_t type, uint8_t pos, int16_t x, int16_t y, int16_t z) { FLOOR *pFloor = &floorAry[floorIdxLast]; pFloor->type = type; pFloor->pos = pos; pFloor->x = x; pFloor->y = y; pFloor->z = z; double vd = random(256) * PI / 128.0; int vr = (type == FLRTYPE_MOVE) ? 256 + level * 16 : 0; pFloor->vx = cos(vd) * vr; pFloor->vy = sin(vd) * vr; uint8_t size = (type == FLRTYPE_SMALL) ? 36 - level : 64 - level * 3; pFloor->size = max(size, 16); pFloor->sizeBack = pFloor->size; dprint("New Floor: type="); dprint(type); dprint(" size="); dprintln(size); }
uint8_t matrix_scan(void) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { select_col(col); _delay_us(3); uint8_t rows = read_rows(); if(col == 0) { rows |= read_fwkey(); } for (uint8_t row = 0; row < MATRIX_ROWS; row++) { bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); bool curr_bit = rows & (1<<row); if (prev_bit != curr_bit) { matrix_debouncing[row] ^= ((matrix_row_t)1<<col); if (debouncing) { dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); } debouncing = DEBOUNCING_DELAY; } } unselect_cols(); } if (debouncing) { if (--debouncing) { _delay_ms(1); } else { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = matrix_debouncing[i]; } } } matrix_scan_quantum(); return 1; }
void initPuzzle(void) { if (state == STATE_INIT) { for (int i = 0; i < PIECES; i++) { pieceOrder[i] = i; } cursorX = 8; cursorY = 4; helpX = HELP_RIGHT_POS; creepFrames = 0; lastPatternIdx = 255; // trick! dprintln(F("Initialize puzzle")); } putPieces(); focusPiece(cursorX, cursorY); state = STATE_FREE; padRepeatCount = 0; helpY = HEIGHT; if (!isDirty) { creepFrames = 0; } quietFrames = 0; }
void decodePieces(CODE_T *pCode) { PIECE_T *p = pieceAry; for (int i = 0; i < PIECES; i++, p++, pCode++) { p->x = pCode->xy % 5 * 2 + 4; p->y = pCode->xy / 5 * 2; p->rot = pCode->rot; if (i <= 1) { // white, green if (p->rot & 1) { p->y++; } else { p->x++; } } else if (i >= 3 && i <= 7) { // orange, red, pink, gray, blue p->x++; p->y++; } } uint8_t rot = pieceAry[0].rot; pieceAry[0].rot = 0; rotatePieces(pieceAry, rot); dprintln(F("Decoded pieces")); }
static inline void bluefruit_trace_footer() { dprintln(); }
void process_action(keyrecord_t *record) { keyevent_t event = record->event; #ifndef NO_ACTION_TAPPING uint8_t tap_count = record->tap.count; #endif if (IS_NOEVENT(event)) { return; } action_t action = layer_switch_get_action(event.key); dprint("ACTION: "); debug_action(action); #ifndef NO_ACTION_LAYER dprint(" layer_state: "); layer_debug(); dprint(" default_layer_state: "); default_layer_debug(); #endif dprintln(); switch (action.kind.id) { /* Key and Mods */ case ACT_LMODS: case ACT_RMODS: { uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods<<4; if (event.pressed) { if (mods) { add_weak_mods(mods); send_keyboard_report(); } register_code(action.key.code); } else { unregister_code(action.key.code); if (mods) { del_weak_mods(mods); send_keyboard_report(); } } } break; #ifndef NO_ACTION_TAPPING case ACT_LMODS_TAP: case ACT_RMODS_TAP: { uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods<<4; switch (action.layer_tap.code) { #ifndef NO_ACTION_ONESHOT case MODS_ONESHOT: // Oneshot modifier if (event.pressed) { if (tap_count == 0) { register_mods(mods); } else if (tap_count == 1) { dprint("MODS_TAP: Oneshot: start\n"); set_oneshot_mods(mods); } else { register_mods(mods); } } else { if (tap_count == 0) { clear_oneshot_mods(); unregister_mods(mods); } else if (tap_count == 1) { // Retain Oneshot mods } else { clear_oneshot_mods(); unregister_mods(mods); } } break; #endif case MODS_TAP_TOGGLE: if (event.pressed) { if (tap_count <= TAPPING_TOGGLE) { register_mods(mods); } } else { if (tap_count < TAPPING_TOGGLE) { unregister_mods(mods); } } break; default: if (event.pressed) { if (tap_count > 0) { if (record->tap.interrupted) { dprint("MODS_TAP: Tap: Cancel: add_mods\n"); // ad hoc: set 0 to cancel tap record->tap.count = 0; register_mods(mods); } else { dprint("MODS_TAP: Tap: register_code\n"); register_code(action.key.code); } } else { dprint("MODS_TAP: No tap: add_mods\n"); register_mods(mods); } } else { if (tap_count > 0) { dprint("MODS_TAP: Tap: unregister_code\n"); unregister_code(action.key.code); } else { dprint("MODS_TAP: No tap: add_mods\n"); unregister_mods(mods); } } break; } } break; #endif #ifdef EXTRAKEY_ENABLE /* other HID usage */ case ACT_USAGE: switch (action.usage.page) { case PAGE_SYSTEM: if (event.pressed) { host_system_send(action.usage.code); } else { host_system_send(0); } break; case PAGE_CONSUMER: if (event.pressed) { host_consumer_send(action.usage.code); } else { host_consumer_send(0); } break; } break; #endif #ifdef MOUSEKEY_ENABLE /* Mouse key */ case ACT_MOUSEKEY: if (event.pressed) { mousekey_on(action.key.code); mousekey_send(); } else { mousekey_off(action.key.code); mousekey_send(); } break; #endif #ifndef NO_ACTION_LAYER case ACT_LAYER: if (action.layer_bitop.on == 0) { /* Default Layer Bitwise Operation */ if (!event.pressed) { uint8_t shift = action.layer_bitop.part*4; uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift; uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0; switch (action.layer_bitop.op) { case OP_BIT_AND: default_layer_and(bits | mask); break; case OP_BIT_OR: default_layer_or(bits | mask); break; case OP_BIT_XOR: default_layer_xor(bits | mask); break; case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break; } } } else { /* Layer Bitwise Operation */ if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { uint8_t shift = action.layer_bitop.part*4; uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift; uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0; switch (action.layer_bitop.op) { case OP_BIT_AND: layer_and(bits | mask); break; case OP_BIT_OR: layer_or(bits | mask); break; case OP_BIT_XOR: layer_xor(bits | mask); break; case OP_BIT_SET: layer_and(mask); layer_or(bits); break; } } } break; #ifndef NO_ACTION_TAPPING case ACT_LAYER_TAP: case ACT_LAYER_TAP_EXT: switch (action.layer_tap.code) { case 0xe0 ... 0xef: /* layer On/Off with modifiers(left only) */ if (event.pressed) { layer_on(action.layer_tap.val); register_mods(action.layer_tap.code & 0x0f); } else { layer_off(action.layer_tap.val); unregister_mods(action.layer_tap.code & 0x0f); } break; case OP_TAP_TOGGLE: /* tap toggle */ if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { layer_invert(action.layer_tap.val); } } else { if (tap_count <= TAPPING_TOGGLE) { layer_invert(action.layer_tap.val); } } break; case OP_ON_OFF: event.pressed ? layer_on(action.layer_tap.val) : layer_off(action.layer_tap.val); break; case OP_OFF_ON: event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val); break; case OP_SET_CLEAR: event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); break; default: /* tap key */ if (event.pressed) { if (tap_count > 0) { dprint("KEYMAP_TAP_KEY: Tap: register_code\n"); register_code(action.layer_tap.code); } else { dprint("KEYMAP_TAP_KEY: No tap: On on press\n"); layer_on(action.layer_tap.val); } } else { if (tap_count > 0) { dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); unregister_code(action.layer_tap.code); } else { dprint("KEYMAP_TAP_KEY: No tap: Off on release\n"); layer_off(action.layer_tap.val); } } break; } break; #endif #endif /* Extentions */ #ifndef NO_ACTION_MACRO case ACT_MACRO: action_macro_play(action_get_macro(record, action.func.id, action.func.opt)); break; #endif #ifdef BACKLIGHT_ENABLE case ACT_BACKLIGHT: if (!event.pressed) { switch (action.backlight.opt) { case BACKLIGHT_INCREASE: backlight_increase(); break; case BACKLIGHT_DECREASE: backlight_decrease(); break; case BACKLIGHT_TOGGLE: backlight_toggle(); break; case BACKLIGHT_STEP: backlight_step(); break; case BACKLIGHT_LEVEL: backlight_level(action.backlight.level); break; } } break; #endif case ACT_COMMAND: break; #ifndef NO_ACTION_FUNCTION case ACT_FUNCTION: action_function(record, action.func.id, action.func.opt); break; #endif default: break; } }
static void movePiece(int8_t vx, int8_t vy) { PIECE_T *p = &pieceAry[focusPieceIdx]; if (arduboy.buttonPressed(A_BUTTON)) { int vr = 0; if (arduboy.buttonDown(LEFT_BUTTON)) vr--; if (arduboy.buttonDown(RIGHT_BUTTON)) vr++; if (vr != 0) { arduboy.playScore2(soundRotate, 3); p->rot = rotatePiece(focusPieceIdx, p->rot, vr); isDirty = true; toDrawAll = true; } else if (arduboy.buttonDown(UP_BUTTON | DOWN_BUTTON)) { arduboy.playScore2(soundFlip, 3); p->rot = flipPiece(focusPieceIdx, p->rot); isDirty = true; toDrawAll = true; } if (toDrawAll) { dprint(F("Rotate rot=")); dprintln(p->rot); } } else { int g = (focusPieceIdx < 3) ? 0 : 1; if (p->x + vx < g || p->x + vx >= BOARD_W - g) vx = 0; if (p->y + vy < g || p->y + vy >= BOARD_H - g) vy = 0; if (vx != 0 || vy != 0) { playSoundTick(); p->x += vx; p->y += vy; isDirty = true; toDrawAll = true; } if (arduboy.buttonDown(B_BUTTON)) { if (putPieces()) { arduboy.playScore2(soundPut, 2); state = STATE_FREE; dprintln(F("Release")); } else { uint8_t idx = checkAndRegisterPieces(); isNew = (idx == clearCount); if (idx == lastPatternIdx) { arduboy.playScore2(soundPut, 2); state = STATE_FREE; } else { lastPatternIdx = idx; if (isNew) { arduboy.playScore2(soundNewPattern, 1); clearCount++; saveAndResetCreep(); setGalleryIndex(idx); clearEffectCount = 120; } else { arduboy.playScore2(soundExistedPattern, 1); clearEffectCount = 60; } state = STATE_CLEAR; } dprint(F("Completed! isNew=")); dprintln(isNew); } cursorX = p->x; cursorY = p->y; if (board[p->y][p->x].idx != focusPieceIdx) { cursorY += (board[p->y - 1][p->x].idx == focusPieceIdx) ? -1 : 1; } toDrawAll = true; } } }