5 changed files with 237 additions and 214 deletions
@ -0,0 +1,30 @@ |
|||||
|
use ggez::graphics; |
||||
|
|
||||
|
#[path = "board.rs"] |
||||
|
mod board; |
||||
|
|
||||
|
struct BoardPosnStruct { |
||||
|
x: u8, |
||||
|
y: u8, |
||||
|
} |
||||
|
|
||||
|
pub enum ActorPosn { |
||||
|
BoardPosn { |
||||
|
x: u8, |
||||
|
y: u8, |
||||
|
}, |
||||
|
FloatingPosn { |
||||
|
//This probably needs some `previous position on board' fields
|
||||
|
x: f32, |
||||
|
y: f32, |
||||
|
held_x: f32, |
||||
|
held_y: f32, |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
pub struct Actor { |
||||
|
pub image: graphics::Image, |
||||
|
|
||||
|
pub posn: ActorPosn, |
||||
|
pub behaviour: u8, //index into the behaviours array
|
||||
|
} |
@ -0,0 +1,153 @@ |
|||||
|
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
|
||||
|
/* 2 => Color::RED,
|
||||
|
3 => Color::CYAN, |
||||
|
4 => Color::YELLOW, |
||||
|
5 => Color::GREEN, |
||||
|
6 => Color::BLUE, |
||||
|
7 => Color::MAGENTA, |
||||
|
_ => Color::BLACK,*/ |
||||
|
}, |
||||
|
)?; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
Ok(Apr { |
||||
|
grid: make_grid(_ctx, r, c, board.board.as_slice())?, |
||||
|
board: board, |
||||
|
should_update_grid: false, |
||||
|
|
||||
|
actors: vec![actor::Actor { |
||||
|
image: graphics::Image::new(_ctx, "/pawn.png")?, |
||||
|
posn: actor::ActorPosn::BoardPosn { x: 0, y: 0 }, |
||||
|
behaviour: 0, |
||||
|
}], |
||||
|
behaviours: vec![behaviour::Behaviour { |
||||
|
moves: vec![(0, 1)], |
||||
|
}], //the pawn can go ONE forwards
|
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
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) |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
pub struct Behaviour { |
||||
|
pub moves: Vec<(u8, u8)>, //this is a placeholder
|
||||
|
} |
@ -0,0 +1,47 @@ |
|||||
|
pub const START_X: f32 = 20.0; |
||||
|
pub const START_Y: f32 = 20.0; |
||||
|
pub const BOARD_SQUARE_SIZE: f32 = 20.0; |
||||
|
|
||||
|
pub struct Board { |
||||
|
pub board: Vec<Vec<u8>>, |
||||
|
pub row: u8, |
||||
|
pub col: u8, |
||||
|
} |
||||
|
|
||||
|
pub fn make_board(r: u8, c: u8) -> Board { |
||||
|
let mut init: Vec<Vec<u8>> = vec![vec![0u8; r as usize]; c as usize]; |
||||
|
for (row, rowa) in init.iter_mut().enumerate() { |
||||
|
for (col, item) in rowa.iter_mut().enumerate() { |
||||
|
*item = (row + col) as u8 % 8; |
||||
|
} |
||||
|
} |
||||
|
Board { |
||||
|
board: init, |
||||
|
row: r, |
||||
|
col: c, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
impl Board { |
||||
|
pub fn closest_square_coords(&mut self, x: f32, y: f32) -> (u8, u8) { |
||||
|
//First, normalise to within the grid.
|
||||
|
let mut x = x; |
||||
|
x = x.max(START_X); |
||||
|
x = x.min(START_X + (BOARD_SQUARE_SIZE * self.col as f32) - 1.0); |
||||
|
|
||||
|
let mut y = y; |
||||
|
y = y.max(START_Y); |
||||
|
y = y.min(START_Y + (BOARD_SQUARE_SIZE * self.row as f32) - 1.0); |
||||
|
|
||||
|
//Then, remove the start x and y
|
||||
|
x -= START_X; |
||||
|
y -= START_Y; |
||||
|
|
||||
|
//Then, snap to board coords.
|
||||
|
|
||||
|
let x = (x / BOARD_SQUARE_SIZE) as u8; |
||||
|
let y = (y / BOARD_SQUARE_SIZE) as u8; |
||||
|
|
||||
|
(x, y) |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue