use ggez::event::EventHandler; use ggez::graphics::{self, Color, DrawMode, Mesh, MeshBuilder}; use ggez::input::mouse::{self, MouseButton}; use ggez::{Context, GameResult}; use crate::actor; use crate::behaviour; use crate::board; pub struct Apr { board: board::Board, grid: Mesh, should_update_grid: bool, dragging: bool, actors: Vec, #[allow(dead_code)] behaviours: Vec, } pub fn make_grid(ctx: &mut Context, r: u8, c: u8, board: &[Vec]) -> GameResult { let mut builder = MeshBuilder::new(); for row in 0..r { for col in 0..c { builder.rectangle( DrawMode::fill(), graphics::Rect { x: board::START_X + (board::BOARD_SQUARE_SIZE * col as f32), y: board::START_Y + (board::BOARD_SQUARE_SIZE * row as f32), w: board::BOARD_SQUARE_SIZE, h: board::BOARD_SQUARE_SIZE, }, match board[row as usize][col as usize] % 2 { 0 => Color::WHITE, 1 => Color::BLACK, _ => Color::BLACK, //impossible }, )?; } } builder.build(ctx) } impl Apr { pub fn new(_ctx: &mut Context, r: u8, c: u8) -> GameResult { // Load/create resources such as images here. let board = board::make_board(r, c); let mut actors: Vec = Vec::new(); for i in 0..r { // white side actors.push(actor::Actor::new(_ctx, "/pawn.png", i, 1, 0)); } for i in 0..r { // black side actors.push(actor::Actor::new(_ctx, "/pawn2.png", i, c - 2, 0)); } Ok(Apr { grid: make_grid(_ctx, r, c, board.board.as_slice())?, board, should_update_grid: false, actors, dragging: false, behaviours: vec![behaviour::Behaviour { // 4-tile-corner leaper pawn behaviour moves: vec![(1, 1)], dirs: (1, 0, 0, 0), }], //the pawn can go TWO diagonally and to the right and only upwards }) } #[allow(dead_code)] pub fn set_colour(&mut self, r: usize, c: usize, clr: u8) { //You should only modify self.board through this method. self.board.board[r][c] = clr; //Making a getter for self.board would sadly break borrowing in the same way that closest_square_coords does. self.should_update_grid = true; //Similar solutions apply. } } impl EventHandler for Apr { fn update(&mut self, ctx: &mut Context) -> GameResult<()> { let posn = mouse::position(ctx); for actor in self.actors.iter_mut() { match actor.posn { actor::ActorPosn::FloatingPosn { x: _, y: _, held_x, held_y, } => { if !mouse::button_pressed(ctx, MouseButton::Left) { // no long clicking and dragging let (x, y) = self.board.closest_square_coords(posn.x, posn.y); actor.posn = actor::ActorPosn::BoardPosn { x, y }; self.dragging = false; } else { actor.posn = actor::ActorPosn::FloatingPosn { x: posn.x + held_x, y: posn.y + held_y, held_x, held_y, }; } } actor::ActorPosn::BoardPosn { x, y } => { if mouse::button_pressed(ctx, MouseButton::Left) && !self.dragging { let (posx, posy) = self.board.closest_square_coords(posn.x, posn.y); if posx == x && posy == y { let x = board::START_X + board::BOARD_SQUARE_SIZE * (x as f32); let y = board::START_Y + board::BOARD_SQUARE_SIZE * (y as f32); self.dragging = true; actor.posn = actor::ActorPosn::FloatingPosn { x, y, held_x: x - posn.x, held_y: y - posn.y, }; } } } } } Ok(()) } fn draw(&mut self, ctx: &mut Context) -> GameResult<()> { graphics::clear(ctx, Color::new(0.5, 0.5, 0.5, 1.0)); let drawparams = graphics::DrawParam::new(); if self.should_update_grid { self.grid = make_grid( ctx, self.board.row, self.board.col, self.board.board.as_slice(), )?; self.should_update_grid = false; } graphics::draw(ctx, &self.grid, drawparams)?; for actor in &self.actors { match actor.posn { actor::ActorPosn::FloatingPosn { x, y, .. } => { graphics::draw(ctx, &actor.image, drawparams.dest([x, y]))? } actor::ActorPosn::BoardPosn { x, y } => graphics::draw( ctx, &actor.image, drawparams.dest([ board::START_X + board::BOARD_SQUARE_SIZE * (x as f32), board::START_Y + board::BOARD_SQUARE_SIZE * (y as f32), ]), )?, } } // Draw code here... graphics::present(ctx) } }