Exemple #1
0
int do_test_rectangles(const char *test_parm)
{
    (void) test_parm;

    rect_t out1, out2, oldw, neww;

    oldw.x = 1;
    oldw.y = 1;
    oldw.xsize = 10;
    oldw.ysize = 10;

    neww.x = 2;
    neww.y = 2;
    neww.xsize = 10;
    neww.ysize = 10;

    //int o2 =
    rect_sub( &out1, &out2, &oldw, &neww );

    //rect_dump( &out1 );
    //rect_dump( &out2 );

    test_check_eq(out1.x,1);
    test_check_eq(out1.y,1);
    test_check_eq(out1.xsize,1);
    test_check_eq(out1.ysize,10);

    test_check_eq(out2.x,1);
    test_check_eq(out2.y,1);
    test_check_eq(out2.xsize,10);
    test_check_eq(out2.ysize,1);

    rect_t a, b;

    a.x     = 10; a.y     = 10;
    a.xsize = 10; a.ysize = 10;

    b.x     = 15; b.y     = 15;
    b.xsize = 10; b.ysize = 10;

    test_check_false( rect_includes( &a, &b ) );
    test_check_true( rect_intersects( &a, &b ) );

    b.xsize = 2;  b.ysize = 2;

    test_check_true( rect_includes( &a, &b ) );
    test_check_true( rect_intersects( &a, &b ) );

    b.x     = 35; b.y     = 35;

    test_check_false( rect_includes( &a, &b ) );
    test_check_false( rect_intersects( &a, &b ) );

    return 0;
}
// Subtract rectangle from q
void paint_q_sub( rect_t *r )
{
    pqel_t *pqel;

    ASSERT_LOCKED_MUTEX( &rect_list_lock );

again:
    queue_iterate( &rect_list, pqel, pqel_t *, chain )
    {

        // r includes qe - delete qe
        if( rect_includes( r, &pqel->r ) )
        {
            queue_remove( &rect_list, pqel, pqel_t *, chain );
            goto again;
        }

        // r intersects w qe - divide in two
        if( rect_intersects( r, &pqel->r ) )
        {
            rect_t out1, out2;

            rect_sub( &out1, &out2, r, &pqel->r );

            if( !rect_empty( &out1 ) )
            {
                pqel_t *new1 = mkel( &out1 );  if( !new1 ) return;
                queue_enter(&rect_list, new1, pqel_t *, chain);
            }
void paint_q_add( rect_t *r )
{
    hal_mutex_lock( &rect_list_lock );

    pqel_t *new_el = mkel( r );

    // Don't die, just let some garbage onscreen?
    if(0 == new_el)        return;

    hal_sem_release( &painter_sem );

    if(paint_q_empty())
    {
        queue_enter(&rect_list, new_el, pqel_t *, chain);
        goto finish;
    }

    pqel_t *pqel;

again:
    queue_iterate( &rect_list, pqel, pqel_t *, chain )
    {
        // r includes qe - delete qe
        if( rect_includes( r, &pqel->r ) )
        {
            queue_remove( &rect_list, pqel, pqel_t *, chain );
            goto again;
        }


        // qe includes r - skip addition
        if( rect_includes( &pqel->r, r ) )
        {
            free( new_el );
            goto finish;
        }
    }
int main(int argc, char **argv) {
	int return_status = 1;

	#define MAIN_SDL_CHECK(expression, error_prefix) { \
		if (!(expression)) { \
			log_error(error_prefix, SDL_GetError()); \
			goto exit; \
		} \
	}

	MAIN_SDL_CHECK(SDL_Init(SDL_INIT_VIDEO) == 0, "SDL_Init");
	if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) {
		log_error("IMG_Init", IMG_GetError());
		goto exit;
	}

	MAIN_SDL_CHECK(SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"), "SDL_SetHint SDL_HINT_RENDER_SCALE_QUALITY");

	startup_info_t info = startup(argc, argv);
	if (!info.success)
		goto exit;

	net_mode_t net_mode = info.net_mode;
	network = info.network;

	char wtitle[256];
	if (net_mode == NET_SERVER) {
		snprintf(wtitle, sizeof(wtitle), "NetCheckers - server (%s)", info.port);
	} else {
		snprintf(wtitle, sizeof(wtitle), "NetCheckers - client (%s:%s)", info.host, info.port);
	}
	window = SDL_CreateWindow(
		wtitle,
#if 1
		SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
#else
		(net_mode == NET_SERVER ? 10 : window_width + 20), SDL_WINDOWPOS_CENTERED,
#endif
		window_width, window_height,
		SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI
	);
	MAIN_SDL_CHECK(window, "SDL_CreateWindow");

	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	MAIN_SDL_CHECK(renderer, "SDL_CreateRenderer");
	MAIN_SDL_CHECK(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND) == 0, "SDL_SetRenderDrawBlendMode SDL_BLENDMODE_BLEND");

	char *error = 0;
	char path[1024];
	#define LOAD_TEXTURE_CHECKED(var, file) { \
		sprintf(path, "%s/" file, info.assets_path); \
		var = load_png_texture(path, &error); \
		if (error) { \
			log_error("load_png_texture " file, error); \
			goto exit; \
		} \
	}
	LOAD_TEXTURE_CHECKED(tex.textures.board, "board.png");
	LOAD_TEXTURE_CHECKED(tex.textures.red_piece, "piece_red.png");
	LOAD_TEXTURE_CHECKED(tex.textures.red_piece_king, "piece_red_king.png");
	LOAD_TEXTURE_CHECKED(tex.textures.white_piece, "piece_white.png");
	LOAD_TEXTURE_CHECKED(tex.textures.white_piece_king, "piece_white_king.png");
	LOAD_TEXTURE_CHECKED(tex.textures.highlight, "highlight.png");
	LOAD_TEXTURE_CHECKED(tex.textures.player_turn, "player_turn.png");
	LOAD_TEXTURE_CHECKED(tex.textures.opponent_turn, "opponent_turn.png");
	LOAD_TEXTURE_CHECKED(tex.textures.victory, "victory.png");
	LOAD_TEXTURE_CHECKED(tex.textures.defeat, "defeat.png");

	window_resized(window_width, window_height);

// Put the pieces on the board
#if 0
	// Game over testing
	for (int i = 0; i < 24; i++) {
		piece_t *piece = pieces + i;
		piece->color = (i >= 12) ? PIECE_BLACK : PIECE_WHITE;
		piece->captured = true;
	}
	pieces[0].captured = false;
	pieces[0].king = true;
	pieces[0].pos = cell_pos(1, 3);
	board[1][3] = &pieces[0];

	pieces[12].captured = false;
	pieces[12].king = true;
	pieces[12].pos = cell_pos(5, 3);
	board[5][3] = &pieces[12];
#else
	int fill_row = 0;
	int fill_col = 0;

	for (int i = 0; i < 12; i++) {
		piece_t *piece = pieces + i;
		piece->color = PIECE_WHITE;
		piece->pos = cell_pos(fill_row, fill_col);
		board[fill_row][fill_col] = piece;
		advance_board_row_col(&fill_row, &fill_col);
	}

	fill_row = 5;
	fill_col = 1;
	for (int i = 12; i < 24; i++) {
		piece_t *piece = pieces + i;
		piece->color = PIECE_BLACK;
		piece->pos = cell_pos(fill_row, fill_col);
		board[fill_row][fill_col] = piece;
		advance_board_row_col(&fill_row, &fill_col);
	}
#endif

	game_over = false;
	current_turn = PIECE_BLACK;
	local_color = (net_mode == NET_SERVER) ? PIECE_BLACK : PIECE_WHITE;

	bool running = true;
	int last_time = SDL_GetTicks();
	while (running) {
		int current_time = SDL_GetTicks();
		int ellapsed_ms = current_time - last_time;
		last_time = current_time;
		float delta_time = (float)ellapsed_ms / 1000.0f;

		SDL_Event event = {0};
		while (SDL_PollEvent(&event)) {
			switch (event.type) {
				case SDL_QUIT: {
					running = false;
				} break;
				case SDL_WINDOWEVENT: {
					if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
						window_resized(event.window.data1, event.window.data2);
					}
				} break;
				case SDL_MOUSEBUTTONDOWN: {
					#if 1
					if (event.button.state == SDL_PRESSED && event.button.button == SDL_BUTTON_RIGHT) {
						message_t net_msg = {0};
						net_msg.move_piece = cell_pos(5, 1);
						net_msg.move_target = cell_pos(4, 0);
						net_send_message(network, &net_msg);
					}
					#endif
					if (event.button.state == SDL_PRESSED && event.button.button == SDL_BUTTON_LEFT) {
						if (!game_over && !animating_piece && current_turn == local_color) {
							int click_x = event.button.x * dpi_rate;
							int click_y = event.button.y * dpi_rate;
							if (rect_includes(&board_rect, click_x, click_y)) {
								cell_pos_t clicked_cell = point_to_cell(click_x, click_y);
								piece_t *clicked_piece = board[clicked_cell.row][clicked_cell.col];
								if (clicked_piece && clicked_piece->color == current_turn) {
									piece_moves_t moves = find_valid_moves(clicked_piece);
									if (moves.count) {
										selected_piece = clicked_piece;
										available_moves = moves;
									}
								} else if (selected_piece) {
									cell_pos_t from_cell = selected_piece->pos;

									move_result_t res = perform_move(selected_piece, clicked_cell);
									if (res != MOVE_INVALID) {
										if (res == MOVE_END_TURN) {
											selected_piece = 0;
										} else {
											available_moves = find_valid_moves(selected_piece);
										}

										message_t net_msg = {0};
										net_msg.move_piece = from_cell;
										net_msg.move_target = clicked_cell;
										if (!net_send_message(network, &net_msg)) {
											int err = SDL_ShowSimpleMessageBox(
												SDL_MESSAGEBOX_ERROR,
												"Erro - Falha de comunicação",
												"Falha ao enviar movimento para o adversário.",
												window
											);
											if (err) {
												log_error("SDL_ShowSimpleMessageBox invalid movement", SDL_GetError());
											}
											goto exit;
										}
									}
								}
							}
						}
					}
				} break;
			}
		}

		if (net_get_state(network) != NET_RUNNING) {
			int err = SDL_ShowSimpleMessageBox(
				SDL_MESSAGEBOX_ERROR,
				"Erro - Conexão Interrompida",
				"A conexão foi interrompida pelo adversário",
				window
			);
			if (err) {
				log_error("SDL_ShowSimpleMessageBox invalid movement", SDL_GetError());
			}
			goto exit;
		}

		message_t net_msg;
		if (net_poll_message(network, &net_msg)) {
			bool valid_move = false;

			piece_t *piece = board[net_msg.move_piece.row][net_msg.move_piece.col];
			if (piece && current_turn != local_color && piece->color != local_color) {
				move_result_t res = perform_move(piece, net_msg.move_target);
				if (res != MOVE_INVALID)
					valid_move = true;
			}

			if (!valid_move) {
				int err = SDL_ShowSimpleMessageBox(
					SDL_MESSAGEBOX_ERROR,
					"Erro - Movimento inválido",
					"Seu adversário enviou um movimento inválido.",
					window
				);
				if (err) {
					log_error("SDL_ShowSimpleMessageBox invalid movement", SDL_GetError());
				}
				goto exit;
			}
		}

		render(delta_time);
	}

	return_status = 0;
exit:
	if (network)
		net_destroy(network);
	for (int i = 0; i < ARRAY_SIZE(tex.array); i++) {
		if (tex.array[i])
			SDL_DestroyTexture(tex.array[i]);
	}
	if (renderer)
		SDL_DestroyRenderer(renderer);
	if (window)
		SDL_DestroyWindow(window);
	IMG_Quit();
	SDL_Quit();
	return return_status;
}