Add dash
This commit is contained in:
parent
c7194cf2bc
commit
966582e0c2
167
src/game.rs
167
src/game.rs
@ -17,7 +17,8 @@ pub struct GameModel {
|
||||
pub enum GameEvent {
|
||||
Quit,
|
||||
Nop,
|
||||
MovePlayer(V2<isize>),
|
||||
PlayerMove(V2<isize>),
|
||||
PlayerDash(V2<isize>),
|
||||
}
|
||||
|
||||
impl GameEvent {
|
||||
@ -26,14 +27,14 @@ impl GameEvent {
|
||||
use KeyCode::Char;
|
||||
match key_event.code {
|
||||
Char('q') => return GameEvent::Quit,
|
||||
Char('j') => return GameEvent::MovePlayer(V2::new(0, 1)),
|
||||
Char('k') => return GameEvent::MovePlayer(V2::new(0, -1)),
|
||||
Char('h') => return GameEvent::MovePlayer(V2::new(-1, 0)),
|
||||
Char('l') => return GameEvent::MovePlayer(V2::new(1, 0)),
|
||||
Char('J') => return GameEvent::MovePlayer(V2::new(0, 2)),
|
||||
Char('K') => return GameEvent::MovePlayer(V2::new(0, -2)),
|
||||
Char('H') => return GameEvent::MovePlayer(V2::new(-2, 0)),
|
||||
Char('L') => return GameEvent::MovePlayer(V2::new(2, 0)),
|
||||
Char('j') => return GameEvent::PlayerMove(V2::new(0, 1)),
|
||||
Char('k') => return GameEvent::PlayerMove(V2::new(0, -1)),
|
||||
Char('h') => return GameEvent::PlayerMove(V2::new(-1, 0)),
|
||||
Char('l') => return GameEvent::PlayerMove(V2::new(1, 0)),
|
||||
Char('J') => return GameEvent::PlayerDash(V2::new(0, 1)),
|
||||
Char('K') => return GameEvent::PlayerDash(V2::new(0, -1)),
|
||||
Char('H') => return GameEvent::PlayerDash(V2::new(-1, 0)),
|
||||
Char('L') => return GameEvent::PlayerDash(V2::new(1, 0)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -43,21 +44,53 @@ impl GameEvent {
|
||||
}
|
||||
|
||||
struct Room {
|
||||
size: V2<usize>,
|
||||
}
|
||||
impl Room {
|
||||
fn in_bounds(&self, player_pos: P2<isize>) -> bool {
|
||||
(0..self.size.x as isize).contains(&player_pos.x)
|
||||
&& (0..self.size.y as isize).contains(&player_pos.y)
|
||||
}
|
||||
tiles: Grid<Tile>,
|
||||
}
|
||||
impl Room {}
|
||||
|
||||
impl GameModel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
player_pos: P2::new(1, 1),
|
||||
room: Room {
|
||||
size: V2::new(20, 10),
|
||||
tiles: {
|
||||
let w = 30;
|
||||
let h = 12;
|
||||
let mut tiles = Grid::from_fn(w, h, |x, y| {
|
||||
let is_vertical_boundary = [0, w - 1].contains(&x);
|
||||
let is_horizontal_boundary = [0, h - 1].contains(&y);
|
||||
|
||||
if is_vertical_boundary || is_horizontal_boundary {
|
||||
Tile::Wall
|
||||
} else {
|
||||
Tile::Floor
|
||||
}
|
||||
});
|
||||
|
||||
tiles
|
||||
.get_mut(P2::new(1, 1))
|
||||
.map(|tile| *tile = Tile::Ladder);
|
||||
|
||||
tiles
|
||||
.get_mut(P2::new(5, 2))
|
||||
.map(|tile| *tile = Tile::Amphora);
|
||||
|
||||
tiles.get_mut(P2::new(8, 5)).map(|tile| *tile = Tile::Frog);
|
||||
|
||||
tiles.get_mut(P2::new(7, 6)).map(|tile| *tile = Tile::Water);
|
||||
tiles.get_mut(P2::new(8, 6)).map(|tile| *tile = Tile::Water);
|
||||
tiles.get_mut(P2::new(9, 6)).map(|tile| *tile = Tile::Water);
|
||||
|
||||
tiles.get_mut(P2::new(8, 7)).map(|tile| *tile = Tile::Wall);
|
||||
tiles.get_mut(P2::new(9, 7)).map(|tile| *tile = Tile::Wall);
|
||||
|
||||
tiles.get_mut(P2::new(10, 2)).map(|tile| *tile = Tile::Portal);
|
||||
tiles.get_mut(P2::new(18, 2)).map(|tile| *tile = Tile::Portal);
|
||||
tiles.get_mut(P2::new(10, 8)).map(|tile| *tile = Tile::Portal);
|
||||
tiles.get_mut(P2::new(18, 8)).map(|tile| *tile = Tile::Portal);
|
||||
|
||||
tiles
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -66,14 +99,32 @@ impl GameModel {
|
||||
match GameEvent::from_crossterm(event) {
|
||||
GameEvent::Quit => None,
|
||||
GameEvent::Nop => Some(self),
|
||||
GameEvent::MovePlayer(direction) => {
|
||||
GameEvent::PlayerMove(direction) => {
|
||||
let player_pos = self.player_pos + direction;
|
||||
if self.room.in_bounds(player_pos) {
|
||||
if let Some(target_tile) = self.room.tiles.get(player_pos)
|
||||
&& target_tile.may_enter()
|
||||
{
|
||||
Some(Self { player_pos, ..self })
|
||||
} else {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
GameEvent::PlayerDash(direction) => {
|
||||
let max_dash_tiles = 10;
|
||||
let mut player_pos = self.player_pos;
|
||||
for _ in 0..max_dash_tiles {
|
||||
let next_pos = player_pos + direction;
|
||||
if let Some(target_tile) = self.room.tiles.get(next_pos) && target_tile.may_enter() {
|
||||
player_pos = next_pos;
|
||||
if target_tile.may_interact() {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(Self { player_pos, ..self })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,43 +138,7 @@ impl GameModel {
|
||||
}
|
||||
|
||||
fn render_tiles(&self) -> Grid<Tile> {
|
||||
let w = self.room.size.x;
|
||||
let h = self.room.size.y;
|
||||
let mut tiles = Grid::from_fn(w, h, |x, y| {
|
||||
let is_vertical_boundary = [0, w - 1].contains(&x);
|
||||
let is_horizontal_boundary = [0, h - 1].contains(&y);
|
||||
let is_corner = is_vertical_boundary && is_horizontal_boundary;
|
||||
|
||||
if is_corner {
|
||||
Tile::Corner
|
||||
} else if is_vertical_boundary {
|
||||
Tile::VerticalWall
|
||||
} else if is_horizontal_boundary {
|
||||
Tile::HorizontalWall
|
||||
} else {
|
||||
Tile::Floor
|
||||
}
|
||||
});
|
||||
|
||||
tiles
|
||||
.get_mut(P2::new(1, 1))
|
||||
.map(|tile| *tile = Tile::Ladder);
|
||||
|
||||
tiles
|
||||
.get_mut(P2::new(5, 2))
|
||||
.map(|tile| *tile = Tile::Amphora);
|
||||
|
||||
tiles.get_mut(P2::new(8, 5)).map(|tile| *tile = Tile::Frog);
|
||||
|
||||
tiles.get_mut(P2::new(7, 6)).map(|tile| *tile = Tile::Water);
|
||||
|
||||
tiles.get_mut(P2::new(8, 6)).map(|tile| *tile = Tile::Water);
|
||||
|
||||
tiles.get_mut(P2::new(9, 6)).map(|tile| *tile = Tile::Water);
|
||||
|
||||
tiles.get_mut(P2::new(8, 7)).map(|tile| *tile = Tile::Water);
|
||||
|
||||
tiles.get_mut(P2::new(9, 7)).map(|tile| *tile = Tile::Water);
|
||||
let mut tiles = self.room.tiles.clone();
|
||||
|
||||
tiles
|
||||
.get_mut(self.player_pos)
|
||||
@ -133,6 +148,7 @@ impl GameModel {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Tile {
|
||||
Floor,
|
||||
Ladder,
|
||||
@ -140,17 +156,14 @@ enum Tile {
|
||||
Amphora,
|
||||
Frog,
|
||||
Water,
|
||||
Corner,
|
||||
VerticalWall,
|
||||
HorizontalWall,
|
||||
Wall,
|
||||
Portal,
|
||||
}
|
||||
|
||||
impl Tile {
|
||||
fn render(&self, cell: &mut Cell) {
|
||||
match self {
|
||||
Tile::Floor => {
|
||||
cell.set_symbol(" ");
|
||||
}
|
||||
Tile::Floor => {}
|
||||
Tile::Ladder => {
|
||||
cell.set_symbol("Ħ");
|
||||
}
|
||||
@ -169,15 +182,29 @@ impl Tile {
|
||||
.set_bg(Color::Blue)
|
||||
.set_fg(Color::White);
|
||||
}
|
||||
Tile::Corner => {
|
||||
cell.set_symbol("♦");
|
||||
Tile::Wall => {
|
||||
cell.set_bg(Color::DarkGray);
|
||||
}
|
||||
Tile::VerticalWall => {
|
||||
cell.set_symbol("║");
|
||||
},
|
||||
Tile::HorizontalWall => {
|
||||
cell.set_symbol("═");
|
||||
},
|
||||
Tile::Portal => {
|
||||
cell.set_symbol("@").set_fg(Color::LightBlue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn may_enter(&self) -> bool {
|
||||
match self {
|
||||
Tile::Wall => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn may_interact(&self) -> bool {
|
||||
match self {
|
||||
Tile::Amphora => true,
|
||||
Tile::Frog => true,
|
||||
Tile::Ladder => true,
|
||||
Tile::Portal => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ impl<T: Copy + Div<T>> Div<T> for P2<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct V2<T> {
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
@ -64,6 +64,7 @@ impl<T: Copy + Div<T>> Div<T> for V2<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Grid<T> {
|
||||
pub dims: V2<usize>,
|
||||
elements: Vec<T>,
|
||||
@ -103,4 +104,4 @@ impl<T> Grid<T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user