render some tiles
This commit is contained in:
parent
bea146d439
commit
d506a25716
8 changed files with 129 additions and 60 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
use crate::tiles::{self, *};
|
use crate::tiles::{self, *};
|
||||||
|
|
||||||
|
|
@ -11,8 +12,7 @@ impl Plugin for Riichi {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<Compass>()
|
app.init_resource::<Compass>()
|
||||||
.add_systems(Startup, init_match)
|
.add_systems(Startup, init_match)
|
||||||
.add_systems(Startup, tiles::init_tiles)
|
.add_systems(Startup, (tiles::init_tiles, wall::build_wall).chain())
|
||||||
.add_systems(Update, wall::build_wall)
|
|
||||||
// semicolon stopper
|
// semicolon stopper
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,22 @@ use crate::game::InWall;
|
||||||
use crate::tiles::Tile;
|
use crate::tiles::Tile;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
#[relationship_target(relationship = InWall)]
|
#[relationship_target(relationship = InWall, linked_spawn)]
|
||||||
pub struct Wall(Vec<Entity>);
|
pub struct WallTiles(Vec<Entity>);
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Wall;
|
||||||
|
|
||||||
#[instrument(level = "trace", skip_all)]
|
|
||||||
pub(crate) fn build_wall(mut commands: Commands, tiles: Query<Entity, With<Tile>>) -> Result {
|
pub(crate) fn build_wall(mut commands: Commands, tiles: Query<Entity, With<Tile>>) -> Result {
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
let mut wall = commands.spawn(Wall(vec![]));
|
let mut shuffled = tiles
|
||||||
|
.iter()
|
||||||
let mut shuffled = tiles.iter().collect::<Vec<_>>();
|
.inspect(|e| debug!("{e:?}"))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
shuffled.shuffle(&mut rng);
|
shuffled.shuffle(&mut rng);
|
||||||
|
|
||||||
wall.replace_children(&shuffled);
|
let mut wall = commands.spawn((Wall, WallTiles(shuffled)));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/main.rs
17
src/main.rs
|
|
@ -1,7 +1,8 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::{log::LogPlugin, prelude::*};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use tracing::Level;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
mod gui;
|
mod gui;
|
||||||
|
|
@ -19,18 +20,28 @@ enum Mode {
|
||||||
RunTui,
|
RunTui,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FILTERSTRING: &str = "warn,jong=trace";
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
let app = match args.mode {
|
let app = match args.mode {
|
||||||
Mode::RunGui => app.add_plugins(DefaultPlugins),
|
Mode::RunGui => {
|
||||||
|
app.add_plugins(DefaultPlugins.set(LogPlugin {
|
||||||
|
filter: FILTERSTRING.into(),
|
||||||
|
level: Level::TRACE,
|
||||||
|
// custom_layer: todo!(),
|
||||||
|
// fmt_layer: todo!(),
|
||||||
|
..Default::default()
|
||||||
|
}))
|
||||||
|
}
|
||||||
Mode::RunTui => {
|
Mode::RunTui => {
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(tui_logger::TuiTracingSubscriberLayer)
|
.with(tui_logger::TuiTracingSubscriberLayer)
|
||||||
.init();
|
.init();
|
||||||
tui_logger::init_logger(tui_logger::LevelFilter::Trace).unwrap();
|
tui_logger::init_logger(tui_logger::LevelFilter::Trace).unwrap();
|
||||||
tui_logger::set_env_filter_from_string("warn,jong=trace");
|
tui_logger::set_env_filter_from_string(FILTERSTRING);
|
||||||
|
|
||||||
app.add_plugins(tui::RiichiTui)
|
app.add_plugins(tui::RiichiTui)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
use bevy::{ecs::entity::MapEntities, prelude::*};
|
use bevy::{ecs::entity::MapEntities, prelude::*};
|
||||||
use strum::FromRepr;
|
use strum::FromRepr;
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
use crate::game::wall::Wall;
|
use crate::game::wall::WallTiles;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
#[relationship(relationship_target = Wall)]
|
#[relationship(relationship_target = WallTiles)]
|
||||||
pub struct InWall(pub Entity);
|
pub struct InWall(pub Entity);
|
||||||
|
|
||||||
// #[derive(Component)]
|
// #[derive(Component)]
|
||||||
|
|
@ -13,7 +14,7 @@ pub struct InWall(pub Entity);
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Tile {
|
pub struct Tile {
|
||||||
suit: Suit,
|
pub suit: Suit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(MapEntities, Debug)]
|
#[derive(MapEntities, Debug)]
|
||||||
|
|
@ -26,7 +27,7 @@ pub enum Suit {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deref, DerefMut, Debug)]
|
#[derive(Deref, DerefMut, Debug)]
|
||||||
pub struct Rank(u8);
|
pub struct Rank(pub u8);
|
||||||
|
|
||||||
#[derive(FromRepr, Debug)]
|
#[derive(FromRepr, Debug)]
|
||||||
pub enum Wind {
|
pub enum Wind {
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ use tui_logger::TuiLoggerWidget;
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
|
||||||
pub(crate) enum ConsoleState {
|
pub(crate) enum ConsoleState {
|
||||||
#[default]
|
#[default]
|
||||||
Open,
|
|
||||||
Closed,
|
Closed,
|
||||||
|
Open,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Not for ConsoleState {
|
impl std::ops::Not for ConsoleState {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use bevy::{app::ScheduleRunnerPlugin, prelude::*, state::app::StatesPlugin};
|
use bevy::{app::ScheduleRunnerPlugin, prelude::*, state::app::StatesPlugin};
|
||||||
use bevy_ratatui::{RatatuiContext, RatatuiPlugins};
|
use bevy_ratatui::RatatuiPlugins;
|
||||||
use jong::{game::wall::Wall, tiles::Tile};
|
use jong::tiles::InWall;
|
||||||
use ratatui::widgets::Paragraph;
|
use ratatui::{text::ToSpan, widgets::Paragraph};
|
||||||
|
|
||||||
mod console;
|
mod console;
|
||||||
mod input;
|
mod input;
|
||||||
|
mod render;
|
||||||
|
|
||||||
pub struct RiichiTui;
|
pub struct RiichiTui;
|
||||||
|
|
||||||
|
|
@ -26,50 +28,17 @@ impl Plugin for RiichiTui {
|
||||||
.init_state::<console::ConsoleState>()
|
.init_state::<console::ConsoleState>()
|
||||||
.add_systems(Update, console::toggle_console)
|
.add_systems(Update, console::toggle_console)
|
||||||
.add_systems(Update, console::draw_console.run_if(in_state(console::ConsoleState::Open)))
|
.add_systems(Update, console::draw_console.run_if(in_state(console::ConsoleState::Open)))
|
||||||
|
.init_state::<TuiState>()
|
||||||
.add_systems(Update, input::keyboard_input_system)
|
.add_systems(Update, input::keyboard_input_system)
|
||||||
.add_systems(Update, draw_system)
|
.add_systems(Update, render::draw_ingame.run_if(in_state(TuiState::InGame)))
|
||||||
// semicolon stopper
|
// semicolon stopper
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default)]
|
||||||
// enum TuiState {
|
enum TuiState {
|
||||||
// MainMenu,
|
MainMenu,
|
||||||
// InGame,
|
#[default]
|
||||||
// }
|
InGame,
|
||||||
|
|
||||||
pub(crate) fn draw_system(
|
|
||||||
// mut commands: Commands,
|
|
||||||
wall: Option<Single<&Wall>>,
|
|
||||||
tiles: Option<Populated<&Tile>>,
|
|
||||||
mut tui_ctx: ResMut<RatatuiContext>,
|
|
||||||
) -> Result {
|
|
||||||
let title = ratatui::text::Text::raw("tiny riichi");
|
|
||||||
let wall = if let Some(wall) = wall {
|
|
||||||
let text = (*wall)
|
|
||||||
.iter()
|
|
||||||
.map(|c| {
|
|
||||||
tiles
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get(c)
|
|
||||||
.map(|tile| format!("{tile:?}"))
|
|
||||||
})
|
|
||||||
.collect::<Result<String, _>>()?;
|
|
||||||
|
|
||||||
Some(Paragraph::new(text))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
tui_ctx.draw(|frame| {
|
|
||||||
frame.render_widget(title, frame.area());
|
|
||||||
|
|
||||||
if let Some(wall) = wall {
|
|
||||||
frame.render_widget(wall, frame.area());
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
55
src/tui/render.rs
Normal file
55
src/tui/render.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use bevy::ecs::system::SystemParam;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_ratatui::RatatuiContext;
|
||||||
|
use ratatui::widgets::Paragraph;
|
||||||
|
|
||||||
|
use jong::game::wall::Wall;
|
||||||
|
use jong::game::wall::WallTiles;
|
||||||
|
use jong::tiles::Tile;
|
||||||
|
|
||||||
|
mod tiles;
|
||||||
|
|
||||||
|
pub(crate) fn draw_ingame(
|
||||||
|
tiles: Query<&Tile>,
|
||||||
|
wall: Option<Single<&WallTiles, With<Wall>>>,
|
||||||
|
mut tui_ctx: ResMut<RatatuiContext>,
|
||||||
|
) -> Result {
|
||||||
|
use ratatui::layout::Flex;
|
||||||
|
use ratatui::prelude::*;
|
||||||
|
|
||||||
|
let title = ratatui::text::Text::raw("tiny riichi");
|
||||||
|
|
||||||
|
let wall = if let Some(wall) = wall {
|
||||||
|
let wall = wall
|
||||||
|
.iter()
|
||||||
|
.map(|inwall| -> Result<_> { Ok(tiles.get(inwall).map(tiles::draw_tile)?) })
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
// let paragraph = Paragraph::new(wall.join(", ")).wrap(ratatui::widgets::Wrap { trim: true });
|
||||||
|
Some(wall)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
tui_ctx.draw(|frame| {
|
||||||
|
// frame.render_widget(title, frame.area());
|
||||||
|
debug!("{}", frame.area());
|
||||||
|
|
||||||
|
if let Some(wall) = wall {
|
||||||
|
// let tile_area = Rect::new(0, 0, 5, 4);
|
||||||
|
let layout = Layout::horizontal(vec![Constraint::Max(5); 13]).flex(Flex::Start);
|
||||||
|
let mut area = frame.area();
|
||||||
|
area.height = 4;
|
||||||
|
let areas = layout.areas::<13>(area);
|
||||||
|
// debug!("wall.len(): {}, areas.len(): {}", wall.len(), areas.len());
|
||||||
|
for (tile, rect) in wall.iter().zip(areas.iter()) {
|
||||||
|
// debug!("{rect:?}");
|
||||||
|
frame.render_widget(tile, *rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
30
src/tui/render/tiles.rs
Normal file
30
src/tui/render/tiles.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
use ratatui::widgets::Paragraph;
|
||||||
|
|
||||||
|
use jong::tiles::Tile;
|
||||||
|
|
||||||
|
pub(crate) fn draw_tile(tile: &Tile) -> Paragraph<'_> {
|
||||||
|
use ratatui::prelude::*;
|
||||||
|
|
||||||
|
let block = ratatui::widgets::Block::bordered();
|
||||||
|
|
||||||
|
Paragraph::new(match &tile.suit {
|
||||||
|
jong::tiles::Suit::Pin(rank) => format!("{}\np", rank.0),
|
||||||
|
jong::tiles::Suit::Sou(rank) => format!("{}\ns", rank.0),
|
||||||
|
jong::tiles::Suit::Man(rank) => format!("{}\nm", rank.0),
|
||||||
|
jong::tiles::Suit::Wind(wind) => (match wind {
|
||||||
|
jong::tiles::Wind::Ton => "e\nw",
|
||||||
|
jong::tiles::Wind::Nan => "s\nw",
|
||||||
|
jong::tiles::Wind::Shaa => "w\nw",
|
||||||
|
jong::tiles::Wind::Pei => "n\nw",
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
jong::tiles::Suit::Dragon(dragon) => (match dragon {
|
||||||
|
jong::tiles::Dragon::Haku => "w\nd",
|
||||||
|
jong::tiles::Dragon::Hatsu => "g\nd",
|
||||||
|
jong::tiles::Dragon::Chun => "r\nd",
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
})
|
||||||
|
.block(block)
|
||||||
|
.centered()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue