⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntetris.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
{
	if(will_collide(state, state->current_shape.x,
				(state->current_shape.y + 1),
				state->current_shape.orientation)) {
		block_reached_bottom(state);
		return 1;
	}

	draw_shape(state, state->current_shape.x, state->current_shape.y, 1);
	state->current_shape.y++;
	draw_shape(state, state->current_shape.x, state->current_shape.y, 0);

	draw_well(state, 0);

	return 0;
}

static void drop_block(nstate *state)
{
	while(!drop_block_1(state)) msleep(DROP_BLOCK_DELAY);
}

static void handle_exposure_event(nstate *state)
{
	GR_EVENT_EXPOSURE *event = &state->event.exposure;

	if(event->wid == state->score_window) {
		draw_score(state);
		return;
	}
	if(event->wid == state->next_shape_window) {
		draw_next_shape(state);
		return;
	}
	if(event->wid == state->new_game_button) {
		draw_new_game_button(state);
		return;
	}
	if(event->wid == state->pause_continue_button) {
		draw_pause_continue_button(state);
		return;
	}
	if(event->wid == state->anticlockwise_button) {
		draw_anticlockwise_button(state);
		return;
	}
	if(event->wid == state->clockwise_button) {
		draw_clockwise_button(state);
		return;
	}
	if(event->wid == state->left_button) {
		draw_left_button(state);
		return;
	}
	if(event->wid == state->right_button) {
		draw_right_button(state);
		return;
	}
	if(event->wid == state->drop_button) {
		draw_drop_button(state);
		return;
	}
	if(event->wid == state->well_window) {
		draw_well(state, 1);
		return;
	}
}

static 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;
	}
}

static 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;
	}
}

static void handle_event(nstate *state)
{
	switch(state->event.type) {
		case GR_EVENT_TYPE_EXPOSURE:
			handle_exposure_event(state);
			break;
		case GR_EVENT_TYPE_BUTTON_DOWN:
			handle_mouse_event(state);
			break;
		case GR_EVENT_TYPE_KEY_DOWN:
			handle_keyboard_event(state);
			break;
		case GR_EVENT_TYPE_CLOSE_REQ:
			state->state = STATE_EXIT;
			break;
		case GR_EVENT_TYPE_TIMEOUT:
			break;
		default:
			fprintf(stderr, "Unhandled event type %d\n",
							state->event.type);
			break;
	}
}

static void clear_well(nstate *state)
{
	int x, y;

	for(y = 0; y < WELL_HEIGHT; y++)
		for(x = 0; x < WELL_WIDTH; x++) {
			state->blocks[0][y][x] = 0;
			state->blocks[1][y][x] = 0;
		}
}

/* Dirty hack alert- this is to avoid using any floating point math */
static int random8(int limit)
{
	int ret;

	do { ret = random() & 7; } while(ret > limit);

	return ret;
}

static void choose_new_shape(nstate *state)
{
	state->current_shape.type = state->next_shape.type;
	state->current_shape.orientation = state->next_shape.orientation;
	state->current_shape.colour = state->next_shape.colour;
	state->current_shape.x = (WELL_WIDTH / 2) - 2;
	state->current_shape.y = WELL_NOTVISIBLE -
			shape_sizes[state->next_shape.type]
				[state->next_shape.orientation][1] - 1;
	state->next_shape.type = random8(MAXSHAPES - 1);
	state->next_shape.orientation = random8(MAXORIENTATIONS - 1);
	state->next_shape.colour = block_colours[random8(MAX_BLOCK_COLOUR)];
}

static void new_game(nstate *state)
{
	clear_well(state);
	if(state->score > state->hiscore) state->hiscore = state->score;
	state->score = 0;
	state->level = 0;
	draw_score(state);
	choose_new_shape(state);
	draw_next_shape(state);
	draw_well(state, 1);
	if(state->state == STATE_NEWGAME) state->state = STATE_RUNNING;
}

static void init_game(nstate *state)
{
	GR_WM_PROPERTIES props;

	if(GrOpen() < 0) {
		fprintf(stderr, "Couldn't connect to Nano-X server\n");
		exit(1);
	}

	state->main_window = GrNewWindow(GR_ROOT_WINDOW_ID,
					MAIN_WINDOW_X_POSITION,
					MAIN_WINDOW_Y_POSITION,
					MAIN_WINDOW_WIDTH,
					MAIN_WINDOW_HEIGHT, 0,
					MAIN_WINDOW_BACKGROUND_COLOUR, 0);
	/* set title */
	props.flags = GR_WM_FLAGS_TITLE | GR_WM_FLAGS_PROPS;
	props.props = GR_WM_PROPS_BORDER | GR_WM_PROPS_CAPTION;
	props.title = "Nano-Tetris";
	GrSetWMProperties(state->main_window, &props);
	GrSelectEvents(state->main_window, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_CLOSE_REQ |
					GR_EVENT_MASK_KEY_DOWN |
					GR_EVENT_MASK_TIMEOUT);

	state->score_window = GrNewWindow(state->main_window,
					SCORE_WINDOW_X_POSITION,
					SCORE_WINDOW_Y_POSITION,
					SCORE_WINDOW_WIDTH,
					SCORE_WINDOW_HEIGHT, 0,
					SCORE_WINDOW_BACKGROUND_COLOUR, 0);
	GrSelectEvents(state->score_window, GR_EVENT_MASK_EXPOSURE);
	GrMapWindow(state->score_window);
	state->scoregcf = GrNewGC();
	GrSetGCForeground(state->scoregcf, SCORE_WINDOW_FOREGROUND_COLOUR);
	GrSetGCBackground(state->scoregcf, SCORE_WINDOW_BACKGROUND_COLOUR);
	state->scoregcb = GrNewGC();
	GrSetGCForeground(state->scoregcb, SCORE_WINDOW_BACKGROUND_COLOUR);

	state->next_shape_window = GrNewWindow(state->main_window,
					NEXT_SHAPE_WINDOW_X_POSITION,
					NEXT_SHAPE_WINDOW_Y_POSITION,
					NEXT_SHAPE_WINDOW_WIDTH,
					NEXT_SHAPE_WINDOW_HEIGHT, 0,
					NEXT_SHAPE_WINDOW_BACKGROUND_COLOUR, 0);
	GrSelectEvents(state->next_shape_window, GR_EVENT_MASK_EXPOSURE);
	GrMapWindow(state->next_shape_window);
	state->nextshapegcf = GrNewGC();
	state->nextshapegcb = GrNewGC();
	GrSetGCForeground(state->nextshapegcb,
				NEXT_SHAPE_WINDOW_BACKGROUND_COLOUR);

	state->new_game_button = GrNewWindow(state->main_window,
					NEW_GAME_BUTTON_X_POSITION,
					NEW_GAME_BUTTON_Y_POSITION,
					NEW_GAME_BUTTON_WIDTH,
					NEW_GAME_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR, 0);
	GrSelectEvents(state->new_game_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);
	GrMapWindow(state->new_game_button);
	state->buttongcf = GrNewGC();
	GrSetGCForeground(state->buttongcf, BUTTON_FOREGROUND_COLOUR);
	GrSetGCBackground(state->buttongcf, BUTTON_BACKGROUND_COLOUR);
	state->buttongcb = GrNewGC();
	GrSetGCForeground(state->buttongcb, BUTTON_BACKGROUND_COLOUR);

	state->pause_continue_button = GrNewWindow(state->main_window,
					PAUSE_CONTINUE_BUTTON_X_POSITION,
					PAUSE_CONTINUE_BUTTON_Y_POSITION,
					PAUSE_CONTINUE_BUTTON_WIDTH,
					PAUSE_CONTINUE_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR, 0);
	GrSelectEvents(state->pause_continue_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);

	state->anticlockwise_button = GrNewWindow(state->main_window,
					ANTICLOCKWISE_BUTTON_X_POSITION,
					ANTICLOCKWISE_BUTTON_Y_POSITION,
					ANTICLOCKWISE_BUTTON_WIDTH,
					ANTICLOCKWISE_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR,
					0);
	GrSelectEvents(state->anticlockwise_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);

	state->clockwise_button = GrNewWindow(state->main_window,
					CLOCKWISE_BUTTON_X_POSITION,
					CLOCKWISE_BUTTON_Y_POSITION,
					CLOCKWISE_BUTTON_WIDTH,
					CLOCKWISE_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR,
					0);
	GrSelectEvents(state->clockwise_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);

	state->left_button = GrNewWindow(state->main_window,
					LEFT_BUTTON_X_POSITION,
					LEFT_BUTTON_Y_POSITION,
					LEFT_BUTTON_WIDTH,
					LEFT_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR,
					0);
	GrSelectEvents(state->left_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);

	state->right_button = GrNewWindow(state->main_window,
					RIGHT_BUTTON_X_POSITION,
					RIGHT_BUTTON_Y_POSITION,
					RIGHT_BUTTON_WIDTH,
					RIGHT_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR,
					0);
	GrSelectEvents(state->right_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);

	state->drop_button = GrNewWindow(state->main_window,
					DROP_BUTTON_X_POSITION,
					DROP_BUTTON_Y_POSITION,
					DROP_BUTTON_WIDTH,
					DROP_BUTTON_HEIGHT, 0,
					BUTTON_BACKGROUND_COLOUR,
					0);
	GrSelectEvents(state->drop_button, GR_EVENT_MASK_EXPOSURE |
					GR_EVENT_MASK_BUTTON_DOWN);

	state->well_window = GrNewWindow(state->main_window,
					WELL_WINDOW_X_POSITION,
					WELL_WINDOW_Y_POSITION,
					WELL_WINDOW_WIDTH,
					WELL_WINDOW_HEIGHT, 0,
					WELL_WINDOW_BACKGROUND_COLOUR, 0);
	GrSelectEvents(state->well_window, GR_EVENT_MASK_EXPOSURE);
	GrMapWindow(state->well_window);
	state->wellgc = GrNewGC();

	GrMapWindow(state->main_window);

	state->state = STATE_STOPPED;
	state->score = 0;
	read_hiscore(state);
	state->level = 0;
	state->running_buttons_mapped = 0;

	srandom(time(0));

	choose_new_shape(state);
	new_game(state);
}

static void calculate_timeout(nstate *state)
{
	struct timeval t;
	long u;

	gettimeofday(&t, NULL);
	u = t.tv_usec + (delays[state->level] * 1000);
	state->timeout.tv_sec = t.tv_sec + (u / 1000000);
	state->timeout.tv_usec = u % 1000000;
}

static unsigned long timeout_delay(nstate *state)
{
	struct timeval t;
	signed long s, m, ret;

	gettimeofday(&t, NULL);

	if((t.tv_sec > state->timeout.tv_sec) ||
			((t.tv_sec == state->timeout.tv_sec) &&
			t.tv_usec >= state->timeout.tv_usec)) return 1;

	s = state->timeout.tv_sec - t.tv_sec;
	m = ((state->timeout.tv_usec - t.tv_usec) / 1000);
	ret = (unsigned long)((1000 * s) + m);
/*
	fprintf(stderr, "t.tv_sec = %ld, t.tv_usec = %ld, timeout.tv_sec = "
		"%ld, timeout.tv_usec = %ld, s = %ld, m = %ld, ret = %ld\n",
		t.tv_sec, t.tv_usec, state->timeout.tv_sec,	
		state->timeout.tv_usec, s, m, ret);
*/
	if(ret <= 0) return 1;
	else return ret;
}

static void do_update(nstate *state)
{
	struct timeval t;

	gettimeofday(&t, NULL);

	if((t.tv_sec > state->timeout.tv_sec) ||
			((t.tv_sec == state->timeout.tv_sec) &&
			(t.tv_usec >= state->timeout.tv_usec))) {
		drop_block_1(state);
		calculate_timeout(state);
	} 
}

static void do_pause(nstate *state)
{
	draw_pause_continue_button(state);
	while(state->state == STATE_PAUSED) {
		GrGetNextEvent(&state->event);
		handle_event(state);
	}
	draw_pause_continue_button(state);
}

static void wait_for_start(nstate *state)
{
	draw_pause_continue_button(state);
	while(state->state == STATE_STOPPED) {
		GrGetNextEvent(&state->event);
		handle_event(state);
	}
	if(state->state == STATE_NEWGAME) state->state = STATE_RUNNING;
	draw_pause_continue_button(state);
	calculate_timeout(state);
}

static void run_game(nstate *state)
{
	while(state->state == STATE_RUNNING) {
		GrGetNextEventTimeout(&state->event, timeout_delay(state));
		handle_event(state);
		if(state->state == STATE_PAUSED) do_pause(state);
		if(state->state == STATE_RUNNING) do_update(state);
	}
}

static void main_game_loop(nstate *state)
{
	wait_for_start(state);
	while(state->state != STATE_EXIT) {
		if(state->state == STATE_RUNNING) run_game(state);
		if(state->state == STATE_STOPPED) wait_for_start(state);
		if(state->state != STATE_EXIT) new_game(state);
	}
}

#ifdef __ECOS
#define main ntetris_main
#endif

int main(int argc, char *argv[])
{
	nstate *state = my_malloc(sizeof(nstate));

        bzero(state, sizeof(*state));
	init_game(state);
	main_game_loop(state);

	write_hiscore(state);

	GrClose();

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -