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 {
|
pub enum GameEvent {
|
||||||
Quit,
|
Quit,
|
||||||
Nop,
|
Nop,
|
||||||
MovePlayer(V2<isize>),
|
PlayerMove(V2<isize>),
|
||||||
|
PlayerDash(V2<isize>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameEvent {
|
impl GameEvent {
|
||||||
@ -26,14 +27,14 @@ impl GameEvent {
|
|||||||
use KeyCode::Char;
|
use KeyCode::Char;
|
||||||
match key_event.code {
|
match key_event.code {
|
||||||
Char('q') => return GameEvent::Quit,
|
Char('q') => return GameEvent::Quit,
|
||||||
Char('j') => return GameEvent::MovePlayer(V2::new(0, 1)),
|
Char('j') => return GameEvent::PlayerMove(V2::new(0, 1)),
|
||||||
Char('k') => return GameEvent::MovePlayer(V2::new(0, -1)),
|
Char('k') => return GameEvent::PlayerMove(V2::new(0, -1)),
|
||||||
Char('h') => return GameEvent::MovePlayer(V2::new(-1, 0)),
|
Char('h') => return GameEvent::PlayerMove(V2::new(-1, 0)),
|
||||||
Char('l') => return GameEvent::MovePlayer(V2::new(1, 0)),
|
Char('l') => return GameEvent::PlayerMove(V2::new(1, 0)),
|
||||||
Char('J') => return GameEvent::MovePlayer(V2::new(0, 2)),
|
Char('J') => return GameEvent::PlayerDash(V2::new(0, 1)),
|
||||||
Char('K') => return GameEvent::MovePlayer(V2::new(0, -2)),
|
Char('K') => return GameEvent::PlayerDash(V2::new(0, -1)),
|
||||||
Char('H') => return GameEvent::MovePlayer(V2::new(-2, 0)),
|
Char('H') => return GameEvent::PlayerDash(V2::new(-1, 0)),
|
||||||
Char('L') => return GameEvent::MovePlayer(V2::new(2, 0)),
|
Char('L') => return GameEvent::PlayerDash(V2::new(1, 0)),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,21 +44,53 @@ impl GameEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Room {
|
struct Room {
|
||||||
size: V2<usize>,
|
tiles: Grid<Tile>,
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
impl Room {}
|
||||||
|
|
||||||
impl GameModel {
|
impl GameModel {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
player_pos: P2::new(1, 1),
|
player_pos: P2::new(1, 1),
|
||||||
room: Room {
|
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) {
|
match GameEvent::from_crossterm(event) {
|
||||||
GameEvent::Quit => None,
|
GameEvent::Quit => None,
|
||||||
GameEvent::Nop => Some(self),
|
GameEvent::Nop => Some(self),
|
||||||
GameEvent::MovePlayer(direction) => {
|
GameEvent::PlayerMove(direction) => {
|
||||||
let player_pos = self.player_pos + 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 })
|
Some(Self { player_pos, ..self })
|
||||||
} else {
|
} else {
|
||||||
Some(self)
|
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> {
|
fn render_tiles(&self) -> Grid<Tile> {
|
||||||
let w = self.room.size.x;
|
let mut tiles = self.room.tiles.clone();
|
||||||
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);
|
|
||||||
|
|
||||||
tiles
|
tiles
|
||||||
.get_mut(self.player_pos)
|
.get_mut(self.player_pos)
|
||||||
@ -133,6 +148,7 @@ impl GameModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
enum Tile {
|
enum Tile {
|
||||||
Floor,
|
Floor,
|
||||||
Ladder,
|
Ladder,
|
||||||
@ -140,17 +156,14 @@ enum Tile {
|
|||||||
Amphora,
|
Amphora,
|
||||||
Frog,
|
Frog,
|
||||||
Water,
|
Water,
|
||||||
Corner,
|
Wall,
|
||||||
VerticalWall,
|
Portal,
|
||||||
HorizontalWall,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tile {
|
impl Tile {
|
||||||
fn render(&self, cell: &mut Cell) {
|
fn render(&self, cell: &mut Cell) {
|
||||||
match self {
|
match self {
|
||||||
Tile::Floor => {
|
Tile::Floor => {}
|
||||||
cell.set_symbol(" ");
|
|
||||||
}
|
|
||||||
Tile::Ladder => {
|
Tile::Ladder => {
|
||||||
cell.set_symbol("Ħ");
|
cell.set_symbol("Ħ");
|
||||||
}
|
}
|
||||||
@ -169,15 +182,29 @@ impl Tile {
|
|||||||
.set_bg(Color::Blue)
|
.set_bg(Color::Blue)
|
||||||
.set_fg(Color::White);
|
.set_fg(Color::White);
|
||||||
}
|
}
|
||||||
Tile::Corner => {
|
Tile::Wall => {
|
||||||
cell.set_symbol("♦");
|
cell.set_bg(Color::DarkGray);
|
||||||
}
|
}
|
||||||
Tile::VerticalWall => {
|
Tile::Portal => {
|
||||||
cell.set_symbol("║");
|
cell.set_symbol("@").set_fg(Color::LightBlue);
|
||||||
},
|
}
|
||||||
Tile::HorizontalWall => {
|
}
|
||||||
cell.set_symbol("═");
|
}
|
||||||
},
|
|
||||||
|
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 struct V2<T> {
|
||||||
pub x: T,
|
pub x: T,
|
||||||
pub y: 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 struct Grid<T> {
|
||||||
pub dims: V2<usize>,
|
pub dims: V2<usize>,
|
||||||
elements: Vec<T>,
|
elements: Vec<T>,
|
||||||
@ -103,4 +104,4 @@ impl<T> Grid<T> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user