Exemple #1
0
static void setup_game() {
    playing = true;
    Layer *window_layer = window_get_root_layer(window);
    layer_add_child(window_layer, s_bg_layer);
    layer_add_child(window_layer, s_left_pane_layer);
    layer_remove_from_parent(s_title_pane_layer);
    layer_remove_from_parent(text_layer_get_layer(new_game_label_layer));
    layer_remove_from_parent(text_layer_get_layer(load_game_label_layer));
    layer_remove_from_parent(text_layer_get_layer(high_score_layer));
    layer_remove_from_parent(text_layer_get_layer(option_shadows_layer));
    layer_add_child(window_layer, text_layer_get_layer(score_label_layer));
    layer_add_child(window_layer, text_layer_get_layer(score_layer));
    layer_add_child(window_layer, text_layer_get_layer(level_label_layer));
    layer_add_child(window_layer, text_layer_get_layer(level_layer));
    level = 0;
    lines_cleared = 0;
    text_layer_set_text(title_layer, "");
    text_layer_set_text(score_label_layer, "Score");
    update_num_layer(lines_cleared, scoreStr, score_layer);
    text_layer_set_text(level_label_layer, "Level");
    update_num_layer(level, levelStr, level_layer);
    tick_time = max_tick;
    rotation = 0;
    nextBlockType = rand() % 7;
    drop_block();
    layer_mark_dirty(s_bg_layer);
    layer_mark_dirty(s_left_pane_layer);
}
Exemple #2
0
/*
 * Controls the game gravity, and (attempts to)remove lines when a block
 * reaches the bottom. Indirectly creates new blocks, and updates points,
 * level, etc.
 *
 * Game is over when this function returns.
 */
void *blocks_loop(void *vp)
{
	(void) vp; /* unused*/

	int hit;
	struct timespec ts;

	ts.tv_sec = 0;
	ts.tv_nsec = 0;

	/* When we read in from the database, it sets the current level
	 * for the game. Update the tick delay so we resume at proper
	 * difficulty.
	 */
	update_tick_speed();

	while (1) {
		ts.tv_nsec = pgame->nsec;
		nanosleep(&ts, NULL);

		if (pgame->lose || pgame->quit)
			break;

		pthread_mutex_lock(&pgame->lock);

		if (pgame->pause && pgame->pause_ticks) {
			pgame->pause_ticks--;
			goto draw_game;
		}

		/* Unpause the game if we're out of pause ticks */
		pgame->pause = (pgame->pause && pgame->pause_ticks);

		unwrite_cur_block();
		hit = drop_block(CURRENT_BLOCK());
		write_cur_block();

		if (hit == 0) {
			destroy_lines();
			update_cur_block();
		} else if (hit < 0) {
			exit(EXIT_FAILURE);
		}

		draw_game:

		screen_draw_game();
		pthread_mutex_unlock(&pgame->lock);
	}

	/* remove the current piece from the board, when we write to the
	 * database it would otherwise save the location of a block in mid-air.
	 * We can't restore from blocks like that, so just remove it.
	 */
	unwrite_cur_block();

	return NULL;
}
Exemple #3
0
static void drop_backlog(pa_memblockq *bq) {
    int64_t boundary;
    pa_assert(bq);

    boundary = bq->read_index - (int64_t) bq->maxrewind;

    while (bq->blocks && (bq->blocks->index + (int64_t) bq->blocks->chunk.length <= boundary))
        drop_block(bq, bq->blocks);
}
Exemple #4
0
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);
}
Exemple #5
0
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;
	}
}
Exemple #6
0
/*!
 * @brief ゲームのメインループ
 * @param [in] sock  送信先ソケットのディスクリプタ
 */
int play_tetris(int sock) {
  static const uchar FLAG = GAMEOVER;  /* ゲームオーバ時に送信する値 */
  uint   cnt = 1;                 /* カウンタ */
  time_t base_time = time(NULL);  /* ゲーム開始時刻を記憶 */

  initialize(sock); /* 初期化 */
  while (!gameover) {  /* ゲームオーバーになるまでゲーム続行 */
    static uchar enemy_field[STAGE_HEIGHT][STAGE_WIDTH];  /* 相手のフィールドデータを格納する2次元配列 */
    time_t game_time;        /* ゲームを開始してから、何秒経過したかを保持する */

    /* キー入力があればそれに応じて操作 */
    control_block();
    /* 32回ループをしたら、ブロックを1マス落とす */
    if ((cnt = (cnt + 1) % 32) == 0) {
      drop_block();
    }

    write(sock,  field, sizeof(field));             /* 自分のフィールドデータを送信 */
    write(sock, &score, sizeof(score));             /* 自分のスコアを送信 */
    read(sock,  enemy_field, sizeof(enemy_field));  /* 相手のフィールドデータを受信 */
    read(sock, &enemy_score, sizeof(enemy_score));  /* 相手のスコアを受信 */
    show_field(enemy_field, ENEMY_FIELD_X);  /* 相手のフィールドを描画する */

    if (read_protocol(enemy_field[0][0])) {  /* 特別な値を受信していないかチェックする */
      sleep(1);
      return EXIT_SUCCESS;  /* ゲーム終了 */
    }

    print_score(ENEMY_SCORE_X, ENEMY_SCORE_Y, enemy_score);  /* 相手のスコアを描画 */

    if ((game_time = GAME_TIME - (time(NULL) - base_time)) == 0) {
      timeup(sock);
      sleep(1);
      return EXIT_SUCCESS;  /* ゲーム終了 */
    }
    print_time(game_time);  /* ゲーム時間を表示する */

    usleep(20000);                   /* 20000マイクロ秒停止する(この間、CPUに負荷をかけない) */
  }
  write(sock, &FLAG, sizeof(FLAG));  /* 自分がゲームオーバになったことを相手に知らせる */

  clear();
  mvprintw(RESULT_STR_Y, RESULT_STR_X, "You lose!");
  refresh();
  sleep(2);
  endwin();  /* curses終了 */

  puts("\nYou lose!");
  sleep(1);
  return EXIT_SUCCESS;
}
Exemple #7
0
static void key_cb(SDL_Keycode k, int shift, struct game_state *gs)
{
	switch (k)
	{
	case SDLK_r: init_game_state(gs); break;
	case SDLK_q: if (shift) end_cb(gs); break;
	case SDLK_j:
	case SDLK_s: drop_block(gs); break;
	case SDLK_h:
	case SDLK_a: move_x(gs, -1); break;
	case SDLK_l:
	case SDLK_d: move_x(gs, 1); break;
	case SDLK_k:
	case SDLK_w: rot_block(gs); break;
	}

	draw_cb(gs);
}
Exemple #8
0
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;
	}
}
Exemple #9
0
/*
 * 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;
}
Exemple #10
0
int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
    struct list_item *q, *n;
    pa_memchunk chunk;
    int64_t old;

    pa_assert(bq);
    pa_assert(uchunk);
    pa_assert(uchunk->memblock);
    pa_assert(uchunk->length > 0);
    pa_assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock));

    pa_assert(uchunk->length % bq->base == 0);
    pa_assert(uchunk->index % bq->base == 0);

    if (!can_push(bq, uchunk->length))
        return -1;

    old = bq->write_index;
    chunk = *uchunk;

    fix_current_write(bq);
    q = bq->current_write;

    /* First we advance the q pointer right of where we want to
     * write to */

    if (q) {
        while (bq->write_index + (int64_t) chunk.length > q->index)
            if (q->next)
                q = q->next;
            else
                break;
    }

    if (!q)
        q = bq->blocks_tail;

    /* We go from back to front to look for the right place to add
     * this new entry. Drop data we will overwrite on the way */

    while (q) {

        if (bq->write_index >= q->index + (int64_t) q->chunk.length)
            /* We found the entry where we need to place the new entry immediately after */
            break;
        else if (bq->write_index + (int64_t) chunk.length <= q->index) {
            /* This entry isn't touched at all, let's skip it */
            q = q->prev;
        } else if (bq->write_index <= q->index &&
                   bq->write_index + (int64_t) chunk.length >= q->index + (int64_t) q->chunk.length) {

            /* This entry is fully replaced by the new entry, so let's drop it */

            struct list_item *p;
            p = q;
            q = q->prev;
            drop_block(bq, p);
        } else if (bq->write_index >= q->index) {
            /* The write index points into this memblock, so let's
             * truncate or split it */

            if (bq->write_index + (int64_t) chunk.length < q->index + (int64_t) q->chunk.length) {

                /* We need to save the end of this memchunk */
                struct list_item *p;
                size_t d;

                /* Create a new list entry for the end of the memchunk */
                if (!(p = pa_flist_pop(PA_STATIC_FLIST_GET(list_items))))
                    p = pa_xnew(struct list_item, 1);

                p->chunk = q->chunk;
                pa_memblock_ref(p->chunk.memblock);

                /* Calculate offset */
                d = (size_t) (bq->write_index + (int64_t) chunk.length - q->index);
                pa_assert(d > 0);

                /* Drop it from the new entry */
                p->index = q->index + (int64_t) d;
                p->chunk.length -= d;

                /* Add it to the list */
                p->prev = q;
                if ((p->next = q->next))
                    q->next->prev = p;
                else
                    bq->blocks_tail = p;
                q->next = p;

                bq->n_blocks++;
            }

            /* Truncate the chunk */
            if (!(q->chunk.length = (size_t) (bq->write_index - q->index))) {
                struct list_item *p;
                p = q;
                q = q->prev;
                drop_block(bq, p);
            }

            /* We had to truncate this block, hence we're now at the right position */
            break;
        } else {
            size_t d;

            pa_assert(bq->write_index + (int64_t)chunk.length > q->index &&
                      bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length &&
                      bq->write_index < q->index);

            /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */

            d = (size_t) (bq->write_index + (int64_t) chunk.length - q->index);
            q->index += (int64_t) d;
            q->chunk.index += d;
            q->chunk.length -= d;

            q = q->prev;
        }
    }
Exemple #11
0
static void game_tick(void *data) {
  if (paused || !playing || lost) { return; }

  drop_block();
  s_timer = app_timer_register(tick_time, game_tick, NULL);
}