void handle_keyboard_event(nstate *state) { GR_EVENT_KEYSTROKE *event = &state->event.keystroke; switch(event->ch) { case 'q': case 'Q': case MWKEY_CANCEL: state->state = STATE_EXIT; return; case 'n': case 'N': case MWKEY_APP1: state->state = STATE_NEWGAME; return; } if(state->state == STATE_STOPPED) return; state->state = STATE_RUNNING; switch(event->ch) { case 'p': case 'P': state->state = STATE_PAUSED; break; case 'j': case 'J': case MWKEY_LEFT: move_block(state, 0); break; case 'k': case 'K': case MWKEY_RIGHT: move_block(state, 1); break; case 'd': case 'D': case MWKEY_UP: rotate_block(state, 0); break; case 'f': case 'F': case MWKEY_DOWN: rotate_block(state, 1); break; case ' ': case MWKEY_MENU: drop_block(state); break; } }
// This should probably go in the helper file with the save logic. // But it's late and I want to get saving/loading working. static void load_game() { // We already know that we have valid data (can_load). lines_cleared = persist_read_int(SCORE_KEY); level = (lines_cleared / 10) + 1; if (level > 10) { level = 10; } update_num_layer(lines_cleared, scoreStr, score_layer); update_num_layer(level, levelStr, level_layer); tick_time = max_tick - (tick_interval * level); persist_read_data(GRID_KEY, grid, sizeof(grid)); persist_read_data(GRID_COL_KEY, grid_col, sizeof(grid_col)); blockType = persist_read_int(BLOCK_TYPE_KEY); nextBlockType = persist_read_int(NEXT_BLOCK_TYPE_KEY); blockX = persist_read_int(BLOCK_X_KEY); blockY = persist_read_int(BLOCK_Y_KEY); make_block(block, blockType, blockX, blockY); make_block(nextBlock, nextBlockType, nextBlockX, nextBlockY); rotation = persist_read_int(ROTATION_KEY); if (rotation != 0) { for (int i=0; i<rotation; i++) { GPoint rPoints[4]; rotate_block(rPoints, block, blockType, i); for (int j=0; j<4; j++) { block[j] = rPoints[j]; } } } }
static void select_click_handler(ClickRecognizerRef recognizer, void *context) { if (!playing && lost) { restart_after_loss(); return; } if (!playing && !lost && (load_choice < 2)) { setup_game(); if (can_load && (load_choice == 1)) { load_game(); } if (!s_timer) { drop_block(); s_timer = app_timer_register(tick_time, game_tick, NULL); } return; } if (!playing && (load_choice == 2)) { // kamotswolf - had to modify several things in here to add new option option_shadows_buffer = !option_shadows_buffer; persist_write_bool(OPTION_SHADOWS_KEY, option_shadows_buffer); if(option_shadows_buffer) { text_layer_set_text(option_shadows_layer, "Drop Shadows ON"); } else { text_layer_set_text(option_shadows_layer, "Drop Shadows OFF"); } //layer_mark_dirty(s_title_pane_layer); return; } if (paused) { paused = false; s_timer = app_timer_register(tick_time, game_tick, NULL); layer_remove_from_parent(text_layer_get_layer(paused_label_layer)); return; } if (blockType == -1) { return; } GPoint newPos[4]; rotate_block(newPos, block, blockType, rotation); bool should_rotate = true; for (int i=0; i<4; i++) { if (newPos[i].x < 0 || newPos[i].x > 9) { should_rotate = false; } if (newPos[i].y < 0 || newPos[i].y > 19) { should_rotate = false; } if (grid[newPos[i].x][newPos[i].y]) { should_rotate = false; } } if (!should_rotate) { return; } for (int i=0; i<4; i++) { block[i] = newPos[i]; } rotation = (rotation + 1) % 4; layer_mark_dirty(s_left_pane_layer); }
/* * Tetris Guidlines say wallkicks first try to move left, attempt rotation * again. Then if that fails, we try again but by moving to the right. */ static int try_wall_kick(struct blocks *block, enum blocks_input_cmd cmd) { /* Try to move left and rotate again. */ if (translate_block(block, MOVE_LEFT) == 1) { if (rotate_block(block, cmd) == 1) return 1; } /* undo previous translation */ translate_block(block, MOVE_RIGHT); /* Try to move right and rotate again. */ if (translate_block(block, MOVE_RIGHT) == 1) { if (rotate_block(block, cmd) == 1) return 1; } return 0; }
block create_block(uint8_t max_block_id) { uint8_t block_id = rand() % (max_block_id + 1); block ret; memcpy_P(&ret, &blocks[block_id], sizeof(ret)); for(uint8_t i = 0, rotations = rand() % 4; i != rotations; ++i) ret = rotate_block(ret); return ret; }
void handle_mouse_event(nstate *state) { GR_EVENT_MOUSE *event = &state->event.mouse; if(event->wid == state->new_game_button) { state->state = STATE_NEWGAME; return; } if(event->wid == state->pause_continue_button) { if(state->state == STATE_PAUSED) state->state = STATE_RUNNING; else state->state = STATE_PAUSED; return; } if(event->wid == state->anticlockwise_button) { if(state->state == STATE_PAUSED) state->state = STATE_RUNNING; rotate_block(state, 0); return; } if(event->wid == state->clockwise_button) { if(state->state == STATE_PAUSED) state->state = STATE_RUNNING; rotate_block(state, 1); return; } if(event->wid == state->left_button) { if(state->state == STATE_PAUSED) state->state = STATE_RUNNING; move_block(state, 0); return; } if(event->wid == state->right_button) { if(state->state == STATE_PAUSED) state->state = STATE_RUNNING; move_block(state, 1); return; } if(event->wid == state->drop_button) { if(state->state == STATE_PAUSED) state->state = STATE_RUNNING; drop_block(state); return; } }
Move Game::find_move() { for (int x = 0; x < dimension; x++) { for (int y = 0; y < dimension; y++) { for (int rot = 0; rot < 4; rot++) { for (int i = 0; i < blocks.size(); i++) { block b = blocks[my_number][i]; block bb = rotate_block(b, rot); if (can_place(bb, Point(x, y))) { Move move = {i, rot, x, y}; return move; } } } } } Move move = {0, 0, 0, 0}; return move; }
void GameArea::key_press(QKeyEvent* event) { switch (event->key()) { case Qt::Key_Left: { _start_x -= _step; if (is_left_most()) { _start_x += _step; } else { cur_block_2_map(); drawArea(); } break; } case Qt::Key_Right: { _start_x += _step; if (is_right_most()) { _start_x -= _step; } else { cur_block_2_map(); drawArea(); } break; } case Qt::Key_Up: { rotate_block(); cur_block_2_map(); drawArea(); break; } case Qt::Key_Down: { if (_is_straight_down) { _start_y += _step; if (isMoveFini()) { _start_y -= _step; } else { cur_block_2_map(); drawArea(); } } else { int i = 0; while (!this->isMoveFini()) { _start_y += _step; ++i; } _start_y -= _step; if (i > 0) { cur_block_2_map(); drawArea(); } } break; } default: QFrame::keyPressEvent(event); } }
/* * User input. Hopefully self explanatory. * * Input keys are currently: * F1 pause * F3 quit * * wasdqe * - w hard drops a piece to the bottom. * - a/d move left/right respectively. * - s soft drops one row. * - qe rotate counter clockwise/clockwise repectively. * * - space is used to hold the currently falling block. */ void *blocks_input(void *vp) { (void) vp; /* unused */ int ch; if (!CURRENT_BLOCK()) return NULL; while ((ch = getch())) { /* prevent modification of the game from blocks_loop in the * other thread */ pthread_mutex_lock(&pgame->lock); switch (ch) { case KEY_F(1): pgame->pause = !pgame->pause; goto draw_game; case KEY_F(3): pgame->pause = false; pgame->quit = true; goto draw_game; } /* remove the current piece from the board */ unwrite_cur_block(); /* modify it */ switch (toupper(ch)) { case 'A': translate_block(CURRENT_BLOCK(), MOVE_LEFT); break; case 'D': translate_block(CURRENT_BLOCK(), MOVE_RIGHT); break; case 'S': if (drop_block(CURRENT_BLOCK())) CURRENT_BLOCK()->soft_drop++; else CURRENT_BLOCK()->lock_delay = 1E9 -1; break; case 'W': /* drop the block to the bottom of the game */ while (drop_block(CURRENT_BLOCK())) CURRENT_BLOCK()->hard_drop++; /* XXX */ CURRENT_BLOCK()->lock_delay = 1E9 -1; break; case 'Q': if (!rotate_block(CURRENT_BLOCK(), ROT_LEFT)) { try_wall_kick(CURRENT_BLOCK(), ROT_LEFT); } break; case 'E': if (!rotate_block(CURRENT_BLOCK(), ROT_RIGHT)) { try_wall_kick(CURRENT_BLOCK(), ROT_RIGHT); } break; case ' ': { struct blocks *tmp; /* We can hold each block exactly once */ if (CURRENT_BLOCK()->hold == true) break; tmp = CURRENT_BLOCK(); /* Effectively swap the first and second elements in * the linked list. The "Current Block" is element 2. * And the "Hold Block" is element 1. So we remove the * current block and reinstall it at the head, pushing * the hold block to the current position. */ LIST_REMOVE(tmp, entries); LIST_INSERT_HEAD(&pgame->blocks_head, tmp, entries); reset_block(HOLD_BLOCK()); HOLD_BLOCK()->hold = true; break; } } /* then rewrite it */ write_cur_block(); draw_game: screen_draw_game(); pthread_mutex_unlock(&pgame->lock); } return NULL; }
bool loop(uint32_t& score) { score = 0; const uint8_t max_brightness = options::get_max_brightness(); const bool accelerometer_enabled = options::is_accelerometer_enabled(); block fig; uint8_t block_x = invalid_block_pos, block_y = invalid_block_pos; color::rgb block_color; uint8_t new_x; bool need_redraw = false; uint8_t game_counter = 0; uint8_t game_difficulty; uint8_t multiplier; uint8_t max_block_id; accelerometer::speed_state speed_state(5); accelerometer::direction last_direction = accelerometer::direction_none; init_difficulty(score, multiplier, game_difficulty, max_block_id); while(true) { timer::wait_for_interrupt(); if(block_x == invalid_block_pos) { fig = create_block(max_block_id); game::get_random_color(block_color, max_brightness); block_y = ws2812_matrix::height - 1; bool have_space = get_new_block_pos(fig, block_x); show_block(block_x, block_y, fig, block_color); ws2812_matrix::show(); if(!have_space) break; //No more space } if(++game_counter == game_difficulty) { game_counter = 0; hide_block(block_x, block_y, fig); if(block_y == fig.height - 1 || intersects(fig, block_x, block_y - 1)) { show_block(block_x, block_y, fig, block_color); block_y = invalid_block_pos; block_x = invalid_block_pos; //Force new block creation //Re-initializes difficulty in case of fast drop check_filled_rows(score, multiplier, game_difficulty, max_block_id, max_brightness); continue; } --block_y; need_redraw = true; } auto button_up_status = buttons::get_button_status(buttons::button_up); auto button_down_status = buttons::get_button_status(buttons::button_down); if(button_up_status != buttons::button_status_not_pressed && button_down_status != buttons::button_status_not_pressed) { button_up_status = buttons::button_status_not_pressed; button_down_status = buttons::button_status_not_pressed; hide_block(block_x, block_y, fig); if(!game::pause_with_screen_backup()) { number_display::output_number(score); return true; } show_block(block_x, block_y, fig, block_color); number_display::output_number(score); need_redraw = true; } new_x = block_x; if(button_up_status == buttons::button_status_pressed) { hide_block(block_x, block_y, fig); const block new_fig = rotate_block(fig); uint8_t move_left = 0; bool rotated = true; if(block_y < new_fig.height - 1) { rotated = false; } else { if(new_fig.width + block_x > ws2812_matrix::width) move_left = block_x + new_fig.width - ws2812_matrix::width; while(intersects(new_fig, block_x - move_left, block_y)) { ++move_left; if(move_left == new_fig.width || block_x < move_left) { rotated = false; break; } } } if(rotated) { block_x -= move_left; new_x = block_x; fig = new_fig; need_redraw = true; } else { show_block(block_x, block_y, fig, block_color); } } switch(move_helper::process_speed(&speed_state, nullptr, accelerometer_enabled)) { case move_direction_left: if(new_x < ws2812_matrix::width - fig.width) ++new_x; break; case move_direction_right: if(new_x) --new_x; break; default: break; } if(accelerometer_enabled) { if(game_difficulty != fast_fall_game_difficulty) { auto accel_direction = accelerometer::get_exclusive_direction(); if(accel_direction == accelerometer::direction_down && last_direction == accelerometer::direction_none) { game_difficulty = fast_fall_game_difficulty; game_counter = game_difficulty - 1; } last_direction = accel_direction; } } else { if(button_down_status == buttons::button_status_pressed && game_difficulty != fast_fall_game_difficulty) { game_difficulty = fast_fall_game_difficulty; game_counter = game_difficulty - 1; } } if(new_x != block_x) { hide_block(block_x, block_y, fig); if(!intersects(fig, new_x, block_y)) { block_x = new_x; need_redraw = true; } else { show_block(block_x, block_y, fig, block_color); } } if(need_redraw) { show_block(block_x, block_y, fig, block_color); ws2812_matrix::show(); need_redraw = false; } } return false; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int block_idx = (int) (mxGetScalar(prhs[1])); int translation = (int) (mxGetScalar(prhs[2])); int rotation = (int) (mxGetScalar(prhs[3])); double* map0 = mxGetPr(prhs[0]); int block[4][2]; int block_pos[2]; int new_block_pos[2]; int map_2D[19][12]; double* game_over; double* map1; int i; plhs[0] =mxCreateDoubleMatrix(19,12, mxREAL); /*resulting board*/ plhs[1] =mxCreateDoubleMatrix(1,1, mxREAL); /*game over or not*/ map1 = mxGetPr(plhs[0]); game_over = mxGetPr(plhs[1]); /* // default outcomes: */ game_over[0] = 1; copy_map(map1, map0); if(block_idx <1 || block_idx > 7){ printf("illegal block_idx: %d\n", block_idx); return; } if(translation > 10 || translation < 1){ if(translation>10) translation = 10; if(translation < 1) translation = 1; } if(rotation < 0 || rotation > 3){ while(rotation < 0) rotation+=4; while(rotation > 3) rotation -= 4; } build_2D_map(map0, map_2D); /* // printf("printing before block placement\n"); */ /* // print_2D_map(map_2D); */ copy_block(blocks[block_idx-1], block); game_over[0] = 0; block_pos[1] = BoxY-3; block_pos[0] = (int) (floor(BoxX/2)); /*% rotate action*/ for (i=1; i<=rotation; ++i){ rotate_block(block); } /* check if game over*/ if(collision(map_2D, block_pos, block)){ copy_map(map1, map0); game_over[0] = 1; return; } /*% translate action*/ while( translation < block_pos[0]){ new_block_pos[0] = block_pos[0]-1; new_block_pos[1] = block_pos[1]; if (!collision(map_2D, new_block_pos, block)){ block_pos[0] = new_block_pos[0]; } else { break; } } while( translation > block_pos[0]){ new_block_pos[0] = block_pos[0]+1; new_block_pos[1] = block_pos[1]; if (!collision(map_2D, new_block_pos, block)){ block_pos[0] = new_block_pos[0]; } else { break; } } /*%drop shape:*/ new_block_pos[0] = block_pos[0]; new_block_pos[1] = block_pos[1]; while(!collision(map_2D, new_block_pos, block)){ new_block_pos[1] = new_block_pos[1] - 1; } block_pos[1] = new_block_pos[1]+1; place_block_in_map(map_2D, block_pos, block); /* // printf("printing after block placement\n"); */ /* // print_2D_map(map_2D); */ /* % check for filled rows */ check_map_for_filled_rows(map_2D); /* // printf("printing after row clearing\n"); */ /* // print_2D_map(map_2D); */ write_2D_map_to_1D(map_2D, map1); game_over[0] = 0; }