问题描述
我一直在跟随 Roguelike Tutorial 来玩 Rust,并开始扩展一些希望创建某种自然模拟。
在我的简单 POC 中,我试图让多个“生物”在地图上徘徊,寻找具有 ProvidesHealth
组件的实体(例如植物或灌木或被吃掉的东西)。
在 Roguelike 教程中,怪物可以随时轻松定位玩家,因为玩家作为资源在世界各地共享,但就我而言,我无法在我的规范中找出模拟这种行为的最佳方法系统。
生物实体有一个视域组件作为它们的视觉。我原本以为我可以遍历视域的 visible_tiles
并检查是否存在带有 ProvidesHealth
实体的实体,但我无法完成这项工作。
对此的任何想法将不胜感激!我不确定我的方法是否完全偏离,或者我遗漏了一些简单的东西。
谢谢!
// [dependencies]
// bracket-lib = { git = "https://github.com/thebracket/bracket-lib.git",rev = "927d229" }
// specs = "0.16.1"
// specs-derive = "0.4.1"
use bracket_lib::prelude::*;
use specs::prelude::*;
use specs_derive::*;
use std::{thread,time};
#[derive(Component)]
struct Position {
x: i32,y: i32,}
#[derive(Component)]
struct Renderable {
glyph: FontCharType,fg: RGB,bg: RGB,}
#[derive(Component)]
struct Creature {}
#[derive(Component)]
struct ProvidesHealth {
pub hp_gain: i32
}
#[derive(Component)]
pub struct Viewshed {
pub visible_tiles: Vec<Point>,pub range: i32,pub dirty: bool
}
struct State {
ecs: World
}
impl State {
fn run_systems(&mut self) {
let mut vis = VisSystem {};
vis.run_Now(&self.ecs);
let mut ai = CreatureAI {};
ai.run_Now(&self.ecs);
self.ecs.maintain();
}
}
impl GameState for State {
fn tick(&mut self,ctx: &mut BTerm) {
ctx.cls();
self.run_systems();
// map defined in separate file,but isn't really
// important for this question
// draw_map(&self.ecs,ctx);
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();
for (pos,ren) in (&positions,&renderables).join() {
ctx.set(pos.x,pos.y,ren.fg,ren.bg,ren.glyph);
}
let sleep = time::Duration::from_millis(200);
thread::sleep(sleep);
}
}
fn main() -> BError {
let mut context = BTermBuilder::simple80x50()
.build()?;
let mut gs = State {
ecs: World::new(),};
gs.ecs.register::<Position>();
gs.ecs.register::<Renderable>();
gs.ecs.register::<Creature>();
gs.ecs.register::<ProvidesHealth>();
gs.ecs.register::<Viewshed>();
// add one Creature
gs.ecs
.create_entity()
.with(Position {x: 10,y: 20})
.with(Renderable {
glyph: to_cp437('@'),fg: RGB::named(WHITE),bg: RGB::named(BLACK)
})
.with(Creature {})
.with(Viewshed { visible_tiles : Vec::new(),range: 6,dirty: true })
.with(HealthStats { max_hp: 100,hp: 100 })
.build();
// add one "food" item
gs.ecs
.create_entity()
.with(Position {x: 35,y: 35})
.with(Renderable {
glyph: to_cp437('*'),bg: RGB::named(BLACK),})
.with(ProvidesHealth { hp_gain: 10 })
.build();
// map defined in separate file,but isn't really
// important for this question
let mut map = Map::new_map();
gs.ecs.insert(map);
main_loop(context,gs)
}
struct VisSystem {}
impl<'a> System<'a> for VisSystem {
type SystemData = (
WriteExpect<'a,Map>,Entities<'a>,WriteStorage<'a,Viewshed>,ReadStorage<'a,Position>,);
fn run(&mut self,data: Self::SystemData) {
let (map,entities,mut viewshed,pos) = data;
for (_ent,viewshed,pos) in (&entities,&mut viewshed,&pos).join() {
if viewshed.dirty {
viewshed.visible_tiles = field_of_view(
Point::new(pos.x,pos.y),viewshed.range,&*map,)
}
}
}
}
struct CreatureAI {}
impl<'a> System<'a> for CreatureAI {
#[allow(clippy::type_complexity)]
type SystemData = (
// ...
);
fn run(&mut self,data: Self::SystemData) {
// ... not sure what to do here\
//
// by doing a join on (viewshed,position),// i'd be able to iterate thru viewshed.visible_tiles,// but i can't figure out how I Could check if a given
// entity located at the Point has the "ProvidesHealth"
// component or not
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)