use ggez::event::EventHandler; use ggez::graphics::{self, Color, DrawMode, Mesh, MeshBuilder}; use ggez::input::mouse::{self, MouseButton}; use ggez::{Context, GameResult}; #[path = "actor.rs"] mod actor; #[path = "behaviour.rs"] mod behaviour; #[path = "board.rs"] mod board; pub struct Apr { board: board::Board, grid: Mesh, should_update_grid: bool, actors: Vec, 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 { actors.push(Apr::make_actor(_ctx, "/pawn.png", i, 0, 0)); } for i in 0..r { actors.push(Apr::make_actor(_ctx, "/pawn2.png", i, c - 1, 0)); } Ok(Apr { grid: make_grid(_ctx, r, c, board.board.as_slice())?, board, should_update_grid: false, actors, behaviours: vec![behaviour::Behaviour { moves: vec![(0, 1)], }], //the pawn can go ONE forwards }) } pub fn make_actor(ctx: &mut Context, img_path: &str, _x: u8, _y: u8, b: u8) -> actor::Actor { actor::Actor { image: graphics::Image::new(ctx, img_path).unwrap(), posn: actor::ActorPosn::BoardPosn { x: _x, y: _y }, behaviour: b, } } pub fn set_colour(&mut self, r: usize, c: usize, col: u8) { //You should only modify self.board through this method. self.board.board[r][c] = col; //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 }; } 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) { 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); 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) } }