Skip to content

Commit

Permalink
wip grid
Browse files Browse the repository at this point in the history
  • Loading branch information
aratama committed Feb 11, 2025
1 parent c44661e commit e4dbca5
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod ceil;
pub mod chunk;
pub mod collision;
pub mod entities;
pub mod grid;
pub mod spawn;
pub mod tile;
pub mod world;
82 changes: 80 additions & 2 deletions src/level/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::entities::SpawnEvent;
use super::grid::Grid;
use crate::constant::TILE_HALF;
use crate::constant::TILE_SIZE;
use crate::level::entities::Spawn;
Expand All @@ -12,6 +13,14 @@ use std::collections::HashMap;
use std::collections::HashSet;
use std::sync::LazyLock;

#[derive(Clone, Debug, Default)]
pub enum NavigationTile {
#[default]
Wall,
Floor,
Surface,
}

#[derive(Clone, Debug, Copy)]
pub struct Bounds {
pub min_x: i32,
Expand Down Expand Up @@ -40,6 +49,7 @@ impl Bounds {
pub struct LevelChunk {
pub level: GameLevel,
pub tiles: Vec<Tile>,
pub navigation_grid: Grid<NavigationTile>,
pub loading_index: i32,
pub entities: Vec<SpawnEvent>,
pub bounds: Bounds,
Expand Down Expand Up @@ -69,15 +79,17 @@ impl LevelChunk {
let max_y =
((ldtk_level.world_y + ldtk_level.px_hei) / ldtk.coordinate.default_grid_size) as i32;

let width = max_x - min_x;
let height = max_y - min_y;

// タイル読み込み

let int_grid_layer = ldtk_level.get_layer("Tiles").unwrap();
let map: HashMap<i64, &str> = ldtk.get_tile_mapping("Tiles");
let mut tiles: Vec<Tile> = Vec::new();
let mut navigation_grid: Grid<NavigationTile> = Grid::new(width as usize, height as usize);
for tile_value in int_grid_layer.int_grid_csv.iter() {
tiles.push(if *tile_value == 0 {
let tile = if *tile_value == 0 {
Tile::default()
} else {
match map.get(&tile_value) {
Expand All @@ -87,7 +99,24 @@ impl LevelChunk {
Tile::default()
}
}
});
};

tiles.push(tile);
}

for (i, tile) in tiles.iter().enumerate() {
let x = i % width as usize;
let y = i / width as usize;
let props = registry.get_tile(tile);
navigation_grid.set(
x,
y,
match props.tile_type {
TileType::Wall => NavigationTile::Wall,
TileType::Floor => NavigationTile::Floor,
TileType::Surface => NavigationTile::Surface,
},
);
}

// エンティティ読み込み
Expand Down Expand Up @@ -126,6 +155,30 @@ impl LevelChunk {
}
};

match spawn {
Spawn::Bookshelf => {
let entity_index = position_to_index(Vec2::new(
entity.world_x.unwrap_or_default() as f32 + 8.0,
-entity.world_y.unwrap_or_default() as f32 + 8.0,
));
navigation_grid.set(
(entity_index.0 - min_x) as usize,
(entity_index.1 - min_y) as usize,
NavigationTile::Wall,
);
let entity_index2 = position_to_index(Vec2::new(
entity.world_x.unwrap_or_default() as f32 + 24.0,
-entity.world_y.unwrap_or_default() as f32 + 8.0,
));
navigation_grid.set(
(entity_index2.0 - min_x) as usize,
(entity_index2.1 - min_y) as usize,
NavigationTile::Wall,
);
}
_ => {}
}

entities.push(SpawnEvent {
spawn,
position: Vec2::new(
Expand All @@ -138,6 +191,7 @@ impl LevelChunk {
return Self {
level: level.clone(),
tiles,
navigation_grid,
entities,
bounds: Bounds {
min_x,
Expand Down Expand Up @@ -284,6 +338,30 @@ impl LevelChunk {
let (x, y) = position_to_index(position);
self.contains_by_index(x, y)
}

pub fn set_navigation_tile(&mut self, x: i32, y: i32, tile: NavigationTile) {
if !self.bounds.contains(x, y) {
return;
}
self.navigation_grid.set(
(x - self.bounds.min_x) as usize,
(y - self.bounds.min_y) as usize,
tile,
);
}

pub fn get_navigation_tile(&self, x: i32, y: i32) -> NavigationTile {
if !self.bounds.contains(x, y) {
return NavigationTile::default();
}
self.navigation_grid
.get(
(x - self.bounds.min_x) as usize,
(y - self.bounds.min_y) as usize,
)
.cloned()
.unwrap_or_default()
}
}

pub fn index_to_position((tx, ty): (i32, i32)) -> Vec2 {
Expand Down
38 changes: 38 additions & 0 deletions src/level/grid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#[derive(Debug, Clone)]
pub struct Grid<T> {
pub width: usize,
pub height: usize,
pub cells: Vec<T>,
}

impl<T: Default + Clone> Grid<T> {
pub fn new(width: usize, height: usize) -> Self {
Self {
width,
height,
cells: vec![T::default(); width * height],
}
}

pub fn get(&self, x: usize, y: usize) -> Option<&T> {
if x < self.width && y < self.height {
Some(&self.cells[y * self.width + x])
} else {
None
}
}

pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
if x < self.width && y < self.height {
Some(&mut self.cells[y * self.width + x])
} else {
None
}
}

pub fn set(&mut self, x: usize, y: usize, value: T) {
if x < self.width && y < self.height {
self.cells[y * self.width + x] = value;
}
}
}
33 changes: 16 additions & 17 deletions src/level/world.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet};

use super::chunk::position_to_index;
use super::chunk::{position_to_index, NavigationTile};
use crate::constant::*;
use crate::level::chunk::LevelChunk;
use crate::level::tile::Tile;
Expand Down Expand Up @@ -139,17 +139,23 @@ impl GameWorld {
chunk.is_visible_ceil(x, y, depth, targets)
}

pub fn get_navigation_tile(&self, x: i32, y: i32) -> NavigationTile {
let Some(chunk) = self.find_chunk_by_index(x, y) else {
return NavigationTile::default();
};
chunk.get_navigation_tile(x, y)
}

/// A* アルゴリズムを使って経路を探索します
pub fn find_route(
&self,
registry: &Registry,
start: (i32, i32),
goal: (i32, i32),
max_distance: i32,
) -> Option<Vec<(i32, i32)>> {
// Early return if start or goal is blocked
if self.get_movement_cost(registry, start, start, max_distance) == BLOCKED_PATH_COST
|| self.get_movement_cost(registry, goal, start, max_distance) == BLOCKED_PATH_COST
if self.get_movement_cost(start, start, max_distance) == BLOCKED_PATH_COST
|| self.get_movement_cost(goal, start, max_distance) == BLOCKED_PATH_COST
{
return None;
}
Expand All @@ -171,7 +177,7 @@ impl GameWorld {
open_set.remove(&current);

for neighbor in neighbors(current) {
let cost = self.get_movement_cost(registry, neighbor, start, max_distance);
let cost = self.get_movement_cost(neighbor, start, max_distance);
if cost == BLOCKED_PATH_COST {
continue;
}
Expand All @@ -189,22 +195,15 @@ impl GameWorld {
None
}

fn get_movement_cost(
&self,
registry: &Registry,
pos: (i32, i32),
start: (i32, i32),
max_distance: i32,
) -> i32 {
fn get_movement_cost(&self, pos: (i32, i32), start: (i32, i32), max_distance: i32) -> i32 {
if manhattan_distance(pos, start) >= max_distance {
return BLOCKED_PATH_COST;
}

let tile = self.get_tile(pos.0, pos.1);
let props = registry.get_tile(&tile);
match props.tile_type {
TileType::Wall | TileType::Surface => BLOCKED_PATH_COST,
TileType::Floor => 1,
let tile = self.get_navigation_tile(pos.0, pos.1);
match tile {
NavigationTile::Wall | NavigationTile::Surface => BLOCKED_PATH_COST,
NavigationTile::Floor => 1,
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions src/strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ fn update(

// 現在のアクションを実行する
execute(
&registry,
context,
&map,
entity,
Expand Down Expand Up @@ -185,7 +184,6 @@ fn update(
}

fn execute(
registry: &Registry,
context: &RapierContext,
map: &HashMap<Entity, (Actor, Vec2, f32)>,
entity: Entity,
Expand Down Expand Up @@ -250,7 +248,6 @@ fn execute(
// TODO
// ナビメッシュでルートを検索
let route = world.find_route(
&registry,
position_to_index(origin),
position_to_index(nearest.position),
(*far / TILE_SIZE) as i32,
Expand Down

0 comments on commit e4dbca5

Please sign in to comment.