Browse Source

Refactored, moved row/col into Board, moved closest_square__coords into

Board
master
iamsosmart19 4 years ago
parent
commit
17cbdd12bd
  1. 30
      src/actor.rs
  2. 153
      src/apr.rs
  3. 3
      src/behaviour.rs
  4. 47
      src/board.rs
  5. 218
      src/main.rs

30
src/actor.rs

@ -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
}

153
src/apr.rs

@ -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)
}
}

3
src/behaviour.rs

@ -0,0 +1,3 @@
pub struct Behaviour {
pub moves: Vec<(u8, u8)>, //this is a placeholder
}

47
src/board.rs

@ -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)
}
}

218
src/main.rs

@ -1,220 +1,10 @@
use ggez::event::{self, EventHandler};
use ggez::graphics::{self, Color, DrawMode, Mesh, MeshBuilder};
use ggez::input::mouse::{self, MouseButton};
use ggez::{Context, ContextBuilder, GameResult};
use ggez::event;
use ggez::{ContextBuilder, GameResult};
use std::env;
use std::path;
const START_X: f32 = 20.0;
const START_Y: f32 = 20.0;
const BOARD_SQUARE_SIZE: f32 = 20.0;
struct Apr {
row: i32,
col: i32,
board: Vec<Vec<u8>>,
grid: Mesh,
should_update_grid: bool,
actors: Vec<Actor>,
behaviours: Vec<Behaviour>,
}
struct Behaviour {
moves: Vec<(u8, u8)>, //this is a placeholder
}
enum ActorPosn {
Board {
x: u8,
y: u8,
},
Floating { //This probably needs some `previous position on board' fields
x: f32,
y: f32,
held_x: f32,
held_y: f32,
},
}
use crate::ActorPosn::{Board, Floating};
struct Actor {
image: graphics::Image,
posn: ActorPosn,
behaviour: u8, //index into the behaviours array
}
fn make_grid(ctx: &mut Context, r: i32, c: i32, 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: START_X + (BOARD_SQUARE_SIZE * col as f32),
y: START_Y + (BOARD_SQUARE_SIZE * row as f32),
w: BOARD_SQUARE_SIZE,
h: 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)
}
fn make_board(r: i32, c: i32) -> Vec<Vec<u8>> {
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;
}
}
init
}
//I have moved this function out of the impl block for borrow checking reasons.
//This should really only borrow self.col and self.row, but as a method it borrows everything.
//As a result, I couldn't use this while iterating through actors.
//Possible solution: Wrap `col' and `row' up as some kind of Dimensions struct, then make this a method on that struct.
//Would then only borrow the dimensions.
//http://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/
fn closest_square_coords(x: f32, y: f32, col: i32, row: i32) -> (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 * col as f32) - 1.0);
let mut y = y;
y = y.max(START_Y);
y = y.min(START_Y + (BOARD_SQUARE_SIZE * 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)
}
impl Apr {
pub fn new(_ctx: &mut Context, r: i32, c: i32) -> GameResult<Apr> {
// Load/create resources such as images here.
let board = make_board(r, c);
Ok(Apr {
row: r,
col: c,
grid: make_grid(_ctx, r, c, board.as_slice())?,
board,
should_update_grid: false,
actors: vec![Actor {
image: graphics::Image::new(_ctx, "/pawn.png")?,
posn: Board { x: 0, y: 0 },
behaviour: 0,
}],
behaviours: vec![Behaviour {
moves: vec![(0, 1)],
}], //the pawn can go ONE forwards
})
}
fn set_colour(&mut self, r: usize, c: usize, col: u8) { //You should only modify self.board through this method.
self.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 {
Floating {
x: _,
y: _,
held_x,
held_y,
} => {
if !mouse::button_pressed(ctx, MouseButton::Left) {
// no long clicking and dragging
let (x, y) = closest_square_coords(posn.x, posn.y, self.col, self.row);
actor.posn = Board { x, y };
} else {
actor.posn = Floating {
x: posn.x + held_x,
y: posn.y + held_y,
held_x,
held_y,
};
}
}
Board { x, y } => {
if mouse::button_pressed(ctx, MouseButton::Left) {
let (posx, posy) =
closest_square_coords(posn.x, posn.y, self.col, self.row);
if posx == x && posy == y {
let x = START_X + BOARD_SQUARE_SIZE * (x as f32);
let y = START_Y + BOARD_SQUARE_SIZE * (y as f32);
actor.posn = Floating {
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.row, self.col, self.board.as_slice())?;
self.should_update_grid = false;
}
graphics::draw(ctx, &self.grid, drawparams)?;
for actor in &self.actors {
match actor.posn {
Floating { x, y, .. } => graphics::draw(ctx, &actor.image, drawparams.dest([x, y]))?,
Board { x, y } => graphics::draw(
ctx,
&actor.image,
drawparams.dest([
START_X + BOARD_SQUARE_SIZE * (x as f32),
START_Y + BOARD_SQUARE_SIZE * (y as f32),
]),
)?,
}
}
// Draw code here...
graphics::present(ctx)
}
}
mod apr;
fn main() -> GameResult<()> {
let mut cb = ContextBuilder::new("apruebo", "s1m7u and e-dt");
@ -232,7 +22,7 @@ fn main() -> GameResult<()> {
// Create an instance of your event handler.
// Usually, you should provide it with the Context object to
// use when setting your game up.
let apr = Apr::new(&mut ctx, 8, 8)?;
let apr = apr::Apr::new(&mut ctx, 8, 8)?;
// Run!
event::run(ctx, event_loop, apr);

Loading…
Cancel
Save