temporary commit

This commit is contained in:
2025-06-27 07:54:23 +08:00
parent c11ab13f42
commit d326c615cd
3 changed files with 278 additions and 45 deletions

View File

@@ -63,10 +63,12 @@ fn draw_piece(
piece: Piece,
crown_red: &SvgHandle,
crown_white: &SvgHandle,
current_player: Player,
) -> Result<(), Error> {
if let Piece::NoPiece = piece {
Ok(())
} else {
cr.save()?;
let center = square.center();
let outer_radius = square.width() * 0.3;
let vertical_scale_factor = 0.8;
@@ -79,8 +81,7 @@ fn draw_piece(
m3.translate(0.0, center.y() - outer_radius * vertical_scale_factor);
Matrix::multiply(&Matrix::multiply(&m1, &m2), &m3)
};
cr.save()?;
cr.set_matrix(matrix);
cr.set_matrix(Matrix::multiply(&matrix, &cr.matrix()));
cr.set_source_rgb(0.0, 0.0, 0.0);
let thickness = outer_radius * 0.3;
cr.arc(
@@ -115,12 +116,16 @@ fn draw_piece(
cr.set_source_rgb(color.0, color.1, color.2);
cr.arc(
center.x(),
center.y() - thickness / 2.0,
match current_player {
Player::White => center.y() + thickness / 2.0,
Player::Red => center.y() - thickness / 2.0,
},
radius,
0.0,
2.0 * PI,
);
cr.fill()?;
cr.restore()?;
if crowned {
let renderer = match piece.player() {
Some(Player::Red) => rsvg::CairoRenderer::new(crown_red),
@@ -129,14 +134,27 @@ fn draw_piece(
};
let m4 = {
let mut m1 = Matrix::identity();
m1.translate(-center.x(), -(center.y() - thickness / 1.0));
match current_player {
Player::Red => m1.translate(-center.x(), -(center.y() - thickness / 1.0)),
Player::White => m1.translate(-center.x(), -(center.y() + thickness / 2.0)),
}
let mut m2 = Matrix::identity();
m2.scale(0.5, 0.5);
if Player::White == current_player {
let m = Matrix::new(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
m2 = Matrix::multiply(&m2, &m);
}
let mut m3 = Matrix::identity();
m3.translate(center.x(), center.y() - thickness / 1.0);
match current_player {
Player::Red => m3.translate(center.x(), center.y() - thickness / 1.0),
Player::White => m3.translate(center.x(), center.y() + thickness / 2.0),
}
Matrix::multiply(&Matrix::multiply(&m1, &m2), &m3)
};
cr.set_matrix(Matrix::multiply(&matrix, &m4));
cr.set_matrix(Matrix::multiply(
&Matrix::multiply(&matrix, &m4),
&cr.matrix(),
));
renderer
.render_document(
cr,
@@ -149,11 +167,54 @@ fn draw_piece(
)
.unwrap();
}
cr.restore()?;
Ok(())
}
}
fn draw_score_bar(
cr: &CairoContext,
board: &Rectangle,
draughts_game: &DraughtsGame,
xform: &Matrix,
) {
let score_bar = Rectangle::new(
board.tl().x() - board.width() / 10.0,
board.tl().y(),
board.width() / 16.0,
board.height(),
);
let score_percentage = draughts_game.relative_score(Player::White) as f64;
let tl = score_bar.tl();
let br = score_bar.br();
{
let (tlx, tly) = xform.transform_point(tl.x(), tl.y());
let (brx, bry) = xform.transform_point(br.x(), br.y());
println!(
"tl: ({}, {}), br: ({}, {}), score: {}",
tlx, tly, brx, bry, score_percentage
);
}
cr.save().unwrap();
//cr.set_matrix(*xform);
cr.set_source_rgb(1.0, 1.0, 1.0);
cr.rectangle(
score_bar.tl().x(),
score_bar.tl().y(),
score_bar.width(),
score_bar.height() * score_percentage,
);
cr.fill().unwrap();
cr.set_source_rgb(1.0, 0.0, 0.0);
cr.rectangle(
tl.x(),
tl.y() + score_bar.height() * score_percentage,
score_bar.width(),
score_bar.height(),
);
cr.fill().unwrap();
cr.restore().unwrap();
}
fn on_activate(application: &gtk::Application) {
// Initialize GTK before using any GTK functions.
if gtk::init().is_err() {
@@ -202,6 +263,7 @@ fn on_activate(application: &gtk::Application) {
)
.unwrap()
};
let current_player = Rc::<Player>::new(Player::White);
let xform = Rc::<RefCell<Matrix>>::new(RefCell::new(Matrix::identity()));
// Set the "draw" function of the drawing area. This callback is called
// whenever GTK needs to redraw this widget (for example, on first display or when resized).
@@ -209,26 +271,8 @@ fn on_activate(application: &gtk::Application) {
let draughts_game = draughts_game.clone();
let xform = xform.clone();
let selected_piece = selected_piece.clone();
let board_clone = board;
let available_moves = available_moves.clone();
let get_square_for_position = move |position: &Position, xform: &Matrix| -> Rectangle {
let square_size = SQUARE_SIZE;
let p1 = Point::new(
(position.col() as f64) * square_size,
((8 - 1 - position.row()) as f64) * square_size,
);
let p2 = &p1 + &Point::new(square_size, square_size);
let square = Rectangle::from_points(&board_clone.tl() + &p1, &board_clone.tl() + &p2);
let tl = transform_point(&square.tl(), xform);
let br = transform_point(&square.br(), xform);
Rectangle::new(
f64::min(tl.x(), br.x()),
f64::min(tl.y(), br.y()),
f64::abs(tl.x() - br.x()),
f64::abs(tl.y() - br.y()),
)
};
let current_player = current_player.clone();
drawing_area
.borrow_mut()
.set_draw_func(move |_widget, cr, width, height| {
@@ -245,17 +289,30 @@ fn on_activate(application: &gtk::Application) {
let mut xform = xform.borrow_mut();
*xform = Matrix::multiply(
&Matrix::multiply(
&Matrix::new(1.0, 0.0, 0.0, 1.0, -board_center.x(), -board_center.y()),
&Matrix::multiply(
&Matrix::new(1.0, 0.0, 0.0, 1.0, -board_center.x(), -board_center.y()),
&(match *current_player {
Player::White => Matrix::new(1.0, 0.0, 0.0, -1.0, 0.0, 0.0),
Player::Red => Matrix::new(1.0, 0.0, 0.0, 1.0, 0.0, 0.0),
}),
),
&Matrix::new(f, 0.0, 0.0, f, 0.0, 0.0),
),
&Matrix::new(1.0, 0.0, 0.0, 1.0, screen_center.x(), screen_center.y()),
);
cr.set_matrix(*xform);
// Loop over rows and columns to draw each chessboard cell.
for row in 0..DraughtsBoard::rows() {
for col in 0..DraughtsBoard::columns() {
let position = Position::new((8 - row - 1) as u8, col as u8);
let square = get_square_for_position(&position, &xform);
let square = Rectangle::new(
position.col() as f64 * SQUARE_SIZE,
position.row() as f64 * SQUARE_SIZE,
SQUARE_SIZE,
SQUARE_SIZE,
);
cr.save().unwrap();
// Alternate colors based on the sum of row and column indices.
if (row + col) % 2 == 0 {
cr.set_source_rgb(0.8, 0.8, 0.6);
@@ -277,12 +334,19 @@ fn on_activate(application: &gtk::Application) {
draughts_game.borrow().piece_at(position),
&crown_red_handle,
&crown_white_handle,
*current_player,
)
.unwrap();
cr.restore().unwrap();
}
}
if let Some(selected_postion) = selected_piece.get() {
let square = get_square_for_position(&selected_postion, &xform);
if let Some(selected_position) = selected_piece.get() {
let square = Rectangle::new(
selected_position.col() as f64 * SQUARE_SIZE,
selected_position.row() as f64 * SQUARE_SIZE,
SQUARE_SIZE,
SQUARE_SIZE,
);
cr.save().unwrap();
cr.new_path();
cr.move_to(square.tl().x(), square.tl().y());
@@ -306,7 +370,13 @@ fn on_activate(application: &gtk::Application) {
let am = available_moves.borrow();
if !am.is_empty() {
for mv in am.iter() {
let square = get_square_for_position(&mv.get_end_position(), &xform);
let end_pos = mv.get_end_position();
let square = Rectangle::new(
end_pos.col() as f64 * SQUARE_SIZE,
end_pos.row() as f64 * SQUARE_SIZE,
SQUARE_SIZE,
SQUARE_SIZE,
);
cr.save().unwrap();
cr.new_path();
cr.move_to(square.tl().x(), square.tl().y());
@@ -327,6 +397,7 @@ fn on_activate(application: &gtk::Application) {
cr.restore().unwrap();
}
}
draw_score_bar(&cr, &board, &draughts_game.borrow(), &xform);
});
}
let gesture = gtk::GestureClick::new();
@@ -350,19 +421,21 @@ fn on_activate(application: &gtk::Application) {
if board_clone.contains(&p) {
let p = &p - &board_clone.tl();
// println!("Point: {:?}", p);
let position = Position::new(
8 - 1 - (p.y() / SQUARE_SIZE) as u8,
(p.x() / SQUARE_SIZE) as u8,
);
let position =
Position::new((p.y() / SQUARE_SIZE) as u8, (p.x() / SQUARE_SIZE) as u8);
// println!("Selected position: {:?}", position);
let mut draughts_game = draughts_game.borrow_mut();
let piece = draughts_game.piece_at(position);
// println!("Selected piece: {:?}", piece);
let mut am = available_moves.borrow_mut();
let mut move_applied = false;
if !am.is_empty() {
for mv in am.iter() {
if mv.get_end_position() == position {
draughts_game.apply_move(mv).unwrap();
if let Some(mv) = draughts_game.get_best_move(10) {
println!("Next best move: {:?}", mv);
}
move_applied = true;
break;
}