Approved.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.6 KiB

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<actor::Actor>,
behaviours: Vec<behaviour::Behaviour>,
}
pub fn make_grid(ctx: &mut Context, r: u8, c: u8, board: &[Vec<u8>]) -> GameResult<Mesh> {
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<Apr> {
// Load/create resources such as images here.
let board = board::make_board(r, c);
let mut actors: Vec<actor::Actor> = 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)
}
}