├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .vscode ├── settings.json └── spellright.dict ├── Cargo.toml ├── LICENSE ├── README.md ├── bracket-algorithm-traits ├── Cargo.toml ├── LICENSE ├── README.md └── src │ ├── algorithm2d.rs │ ├── algorithm3d.rs │ ├── basemap.rs │ └── lib.rs ├── bracket-bevy ├── Cargo.toml ├── assets │ ├── example_tiles.png │ ├── terminal8x8.png │ ├── vga8x16-color-alpha.png │ └── vga8x16.png ├── examples │ ├── bevy_a_star_mouse.rs │ ├── bevy_alpha.rs │ ├── bevy_batch_z_order.rs │ ├── bevy_benchmark.rs │ ├── bevy_benchmark_scalable.rs │ ├── bevy_colorfont.rs │ ├── bevy_dwarfmap.rs │ ├── bevy_hello_minimal.rs │ ├── bevy_hello_terminal.rs │ ├── bevy_resize_terminal.rs │ ├── bevy_roguelike_tutorial_4 │ │ ├── components.rs │ │ ├── main.rs │ │ ├── map.rs │ │ ├── player.rs │ │ └── rect.rs │ ├── bevy_test.rs │ ├── bevy_textblock.rs │ ├── bevy_tiles.rs │ ├── bevy_two_layers_two_fonts.rs │ └── bevy_walking.rs └── src │ ├── builder │ ├── bterm_builder.rs │ ├── font_builder.rs │ ├── image_fixer.rs │ ├── loader_system.rs │ ├── mod.rs │ └── terminal_layer.rs │ ├── consoles │ ├── common_draw.rs │ ├── draw_batch.rs │ ├── mod.rs │ ├── scaler.rs │ ├── simple_console │ │ ├── back_end │ │ │ ├── mod.rs │ │ │ ├── simple_no_background.rs │ │ │ └── simple_with_background.rs │ │ ├── components.rs │ │ ├── front_end.rs │ │ ├── mod.rs │ │ └── terminal_glyph.rs │ ├── sparse_console │ │ ├── back_end │ │ │ ├── mod.rs │ │ │ ├── sparse_no_background.rs │ │ │ └── sparse_with_background.rs │ │ ├── front_end.rs │ │ └── mod.rs │ ├── text_spans.rs │ ├── update_system.rs │ └── virtual_console.rs │ ├── context.rs │ ├── cp437.rs │ ├── fonts │ ├── font_store.rs │ └── mod.rs │ ├── lib.rs │ ├── random_resource │ └── mod.rs │ └── textblock.rs ├── bracket-color ├── Cargo.toml ├── LICENSE ├── README.md ├── examples │ ├── colors.rs │ ├── lerp.rs │ ├── lerpit.rs │ ├── lerpit_hsv.rs │ ├── named_color.rs │ ├── shades_of_grey.rs │ └── util │ │ └── mod.rs └── src │ ├── color_pair.rs │ ├── hsv.rs │ ├── lerpit.rs │ ├── lib.rs │ ├── named.rs │ ├── palette.rs │ ├── rgb.rs │ ├── rgba.rs │ └── xpcolor.rs ├── bracket-embedding ├── Cargo.toml ├── README.md ├── resources │ ├── terminal8x8.png │ └── vga8x16.png └── src │ ├── embedding.rs │ └── lib.rs ├── bracket-geometry ├── Cargo.toml ├── LICENSE ├── README.md ├── examples │ ├── bresenham_circle.rs │ ├── bresenham_line.rs │ ├── bresenham_sweep.rs │ ├── distance.rs │ └── vector_line.rs └── src │ ├── angle.rs │ ├── angles.rs │ ├── circle_bresenham.rs │ ├── distance.rs │ ├── lib.rs │ ├── line_bresenham.rs │ ├── line_vector.rs │ ├── lines.rs │ ├── point.rs │ ├── point3.rs │ ├── rect.rs │ └── rectf.rs ├── bracket-noise ├── Cargo.toml ├── README.md ├── examples │ ├── cellular.rs │ ├── perlin_fractal.rs │ ├── simplex_billow_quintic.rs │ ├── simplex_fractal.rs │ ├── simplex_rigid_hermite.rs │ ├── value.rs │ ├── value_fractal.rs │ └── whitenoise.rs └── src │ ├── fastnoise.rs │ └── lib.rs ├── bracket-pathfinding ├── Cargo.toml ├── LICENSE ├── README.md ├── benches │ ├── astar_benchmark.rs │ └── fov_benchmark.rs ├── examples │ ├── astar │ │ ├── common.rs │ │ └── main.rs │ ├── astar_manhattan │ │ ├── common.rs │ │ └── main.rs │ ├── dijkstra │ │ ├── common.rs │ │ └── main.rs │ ├── dijkstra_weighted │ │ ├── common.rs │ │ └── main.rs │ └── fov │ │ ├── common.rs │ │ └── main.rs └── src │ ├── astar.rs │ ├── dijkstra.rs │ ├── field_of_view │ ├── mod.rs │ ├── recursive_shadowcasting.rs │ └── symmetric_shadowcasting.rs │ └── lib.rs ├── bracket-random ├── Cargo.toml ├── LICENSE ├── README.md ├── benches │ └── dice.rs ├── examples │ ├── diceroll.rs │ ├── dicestring.rs │ ├── die_iterator.rs │ ├── distribution.rs │ ├── next.rs │ ├── rand.rs │ ├── range.rs │ ├── slice.rs │ └── slice_index.rs └── src │ ├── iterators.rs │ ├── js_seed │ ├── error.rs │ └── mod.rs │ ├── lib.rs │ ├── parsing.rs │ └── random.rs ├── bracket-rex ├── Cargo.toml ├── README.md └── src │ ├── lib.rs │ ├── rex.rs │ └── xpcolor.rs ├── bracket-terminal ├── Cargo.toml ├── LICENSE ├── README.md ├── benches │ └── batching_benchmark.rs ├── examples │ ├── alpha.rs │ ├── astar_mouse.rs │ ├── batch_z_order.rs │ ├── bench_scalable.rs │ ├── benchmark.rs │ ├── colorfont.rs │ ├── dwarfmap.rs │ ├── fancy.rs │ ├── flexible.rs │ ├── fontswitch.rs │ ├── hello_minimal.rs │ ├── hello_terminal.rs │ ├── input_harness.rs │ ├── keyboard.rs │ ├── native_gl.rs │ ├── no_cls.rs │ ├── postprocess.rs │ ├── return_error.rs │ ├── rex.rs │ ├── sparse.rs │ ├── sparse_cls.rs │ ├── sprites.rs │ ├── squishy.rs │ ├── textblock.rs │ ├── textsprites.rs │ ├── tiles.rs │ ├── twelve_by_twelve.rs │ ├── unicode.rs │ ├── virtual_console.rs │ ├── walking.rs │ └── walking_with_is_pressed.rs ├── resources │ ├── cheepicus8x8.png │ ├── example_tiles.png │ ├── example_tiles.xcf │ ├── mkv_curses_6x6.png │ ├── mltest.xp │ ├── nyan.xp │ ├── sprite_dood.png │ ├── terminal8x8.png │ ├── terminal_10x16.png │ ├── terminal_colored_8x8.png │ ├── unicode_16x16.png │ ├── vga8x16-color-alpha.png │ └── vga8x16.png ├── src │ ├── bterm.rs │ ├── consoles │ │ ├── command_buffer.rs │ │ ├── console.rs │ │ ├── flexible_console.rs │ │ ├── mod.rs │ │ ├── simple_console.rs │ │ ├── sparse_console.rs │ │ ├── sprite_console.rs │ │ ├── sprites │ │ │ ├── mod.rs │ │ │ ├── sprite.rs │ │ │ └── spritesheet.rs │ │ ├── text │ │ │ ├── codepage437.rs │ │ │ ├── format_string.rs │ │ │ ├── gui_helpers.rs │ │ │ ├── mod.rs │ │ │ ├── multi_tile_sprite.rs │ │ │ └── textblock.rs │ │ └── virtual_console.rs │ ├── gamestate.rs │ ├── hal │ │ ├── crossterm_be │ │ │ ├── font.rs │ │ │ ├── init.rs │ │ │ ├── main_loop.rs │ │ │ ├── mod.rs │ │ │ ├── scancode_helper.rs │ │ │ └── shader.rs │ │ ├── curses │ │ │ ├── color.rs │ │ │ ├── font.rs │ │ │ ├── init.rs │ │ │ ├── main_loop.rs │ │ │ ├── mod.rs │ │ │ ├── scancode_helper.rs │ │ │ └── shader.rs │ │ ├── dummy │ │ │ ├── keycodes.rs │ │ │ └── mod.rs │ │ ├── gl_common │ │ │ ├── backing │ │ │ │ ├── fancy_console_backing.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── shared_main_loop.rs │ │ │ │ ├── simple_console_backing.rs │ │ │ │ ├── sparse_console_backing.rs │ │ │ │ └── sprite_console_backing.rs │ │ │ ├── font.rs │ │ │ ├── framebuffer.rs │ │ │ ├── glerror.rs │ │ │ ├── mod.rs │ │ │ ├── quadrender.rs │ │ │ ├── shader.rs │ │ │ ├── types_native.rs │ │ │ ├── types_wasm.rs │ │ │ └── vertex_array_helper.rs │ │ ├── mod.rs │ │ ├── native │ │ │ ├── init.rs │ │ │ ├── mainloop.rs │ │ │ ├── mod.rs │ │ │ └── shader_strings.rs │ │ ├── scaler.rs │ │ ├── wasm │ │ │ ├── events │ │ │ │ ├── external.rs │ │ │ │ ├── keyboard.rs │ │ │ │ ├── mod.rs │ │ │ │ └── mouse.rs │ │ │ ├── init.rs │ │ │ ├── mainloop.rs │ │ │ ├── mod.rs │ │ │ └── shader_strings.rs │ │ └── webgpu │ │ │ ├── backend.rs │ │ │ ├── backing │ │ │ ├── fancy_console_backing.rs │ │ │ ├── index_array_helper.rs │ │ │ ├── mod.rs │ │ │ ├── simple_console_backing.rs │ │ │ ├── sparse_console_backing.rs │ │ │ ├── sprite_console_backing.rs │ │ │ └── vertex_array_helper.rs │ │ │ ├── font.rs │ │ │ ├── framebuffer.rs │ │ │ ├── init.rs │ │ │ ├── mainloop.rs │ │ │ ├── mod.rs │ │ │ ├── platform.rs │ │ │ ├── quadrender.rs │ │ │ ├── shader.rs │ │ │ └── shader_source │ │ │ ├── backing_plain.wgsl │ │ │ ├── console_no_bg.wgsl │ │ │ ├── console_with_bg.wgsl │ │ │ ├── fancy.wgsl │ │ │ └── sprites.wgsl │ ├── initializer.rs │ ├── input │ │ ├── event_queue.rs │ │ ├── input_handler.rs │ │ └── mod.rs │ ├── lib.rs │ └── rex.rs ├── wasm_help │ └── index.html └── webglbuild.bat ├── manual ├── book.toml └── src │ ├── SUMMARY.md │ ├── consoles.md │ ├── consoles_print.md │ ├── ex_bt_alpha.gif │ ├── ex_bt_astar_mouse.gif │ ├── ex_bt_colorfont.jpg │ ├── ex_bt_dwarfmap.gif │ ├── ex_bt_flex.gif │ ├── ex_bt_fontswitch.gif │ ├── ex_bt_hello_terminal.gif │ ├── ex_bt_input_harness.jpg │ ├── ex_bt_native_gl.jpg │ ├── ex_bt_post.jpg │ ├── ex_bt_rex.jpg │ ├── ex_bt_sparse.jpg │ ├── ex_bt_sprites.gif │ ├── ex_bt_textblock.jpg │ ├── ex_bt_textsprites.gif │ ├── ex_bt_tiles.jpg │ ├── ex_bt_unicode.jpg │ ├── ex_bt_virtual_console.jpg │ ├── ex_bterm.md │ ├── ex_col_colors.jpg │ ├── ex_col_lerp.jpg │ ├── ex_col_lerpit.jpg │ ├── ex_col_lerpit_hsv.jpg │ ├── ex_col_named.jpg │ ├── ex_col_shades_of_grey.jpg │ ├── ex_color.md │ ├── ex_fancy.gif │ ├── ex_geom_bline.jpg │ ├── ex_geom_bsweep.gif │ ├── ex_geom_circle.jpg │ ├── ex_geometry.md │ ├── ex_noise.md │ ├── ex_noise_cellular.jpg │ ├── ex_noise_perlin_fractal.jpg │ ├── ex_noise_simplex_billow.jpg │ ├── ex_noise_simplex_fractal.jpg │ ├── ex_noise_simplex_rigid.jpg │ ├── ex_noise_value.jpg │ ├── ex_noise_value_fractal.jpg │ ├── ex_noise_white.jpg │ ├── ex_path.md │ ├── ex_path_astar.jpg │ ├── ex_path_astar_manhattan.jpg │ ├── ex_path_dijkstra.jpg │ ├── ex_path_fov.jpg │ ├── ex_rng.md │ ├── examples.md │ ├── fancy.md │ ├── hello_terminal.md │ ├── individual_parts.md │ ├── linking.md │ └── what_is_it.md ├── rltk ├── Cargo.toml ├── LICENSE ├── README.md ├── examples-deprecated │ ├── ex01-helloworld.rs │ ├── ex02-sparse.rs │ ├── ex03-walking.rs │ ├── ex04-fov.rs │ ├── ex05-dijkstra.rs │ ├── ex06-astar-mouse.rs │ ├── ex07-tiles.rs │ ├── ex08-rex.rs │ ├── ex09-offsets.rs │ ├── ex10-postprocess.rs │ ├── ex11-random.rs │ ├── ex12-simplex.rs │ ├── ex13-textblock.rs │ ├── ex14-dwarfmap.rs │ ├── ex15-keyboard.rs │ ├── ex16-wasm-external.rs │ └── ex17-textsprites.rs ├── resources │ ├── example_tiles.png │ ├── mltest.xp │ └── nyan.xp └── src │ └── lib.rs ├── screenshots ├── RLTK_RS_EXAMPLE01.gif ├── RLTK_RS_EXAMPLE02.gif ├── RLTK_RS_EXAMPLE03.gif ├── RLTK_RS_EXAMPLE04.gif ├── RLTK_RS_EXAMPLE05-2.gif ├── RLTK_RS_EXAMPLE06.gif ├── RLTK_RS_EXAMPLE07.gif ├── RLTK_RS_EXAMPLE08.jpg ├── RLTK_RS_EXAMPLE09.jpg ├── RLTK_RS_EXAMPLE10.gif ├── RLTK_RS_EXAMPLE11.gif ├── RLTK_RS_EXAMPLE12.gif ├── RLTK_RS_EXAMPLE13.jpg ├── RLTK_RS_EXAMPLE14.gif ├── RLTK_RS_EXAMPLE15.gif └── RLTK_RS_EXAMPLE18.gif └── src └── lib.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | strategy: 8 | matrix: 9 | os: [ubuntu-latest, macos-latest, windows-latest] 10 | runs-on: ${{ matrix.os }} 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Install alsa and udev 15 | run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev 16 | if: matrix.os == 'ubuntu-latest' 17 | - name: Build 18 | run: cargo build --verbose --all 19 | - name: Run tests 20 | run: 21 | cargo test --verbose --all 22 | - name: Check benchmarks 23 | run: cargo check --benches 24 | - name: Check examples 25 | if: matrix.os != 'windows-latest' 26 | run: | 27 | cargo check --all 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | **/target 5 | **/wasm_help/staging 6 | .vscode/launch.json 7 | manual/book/* 8 | dependency_order.md 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "spellright.language": [ 3 | "en" 4 | ], 5 | "spellright.documentTypes": [ 6 | "markdown", 7 | "latex", 8 | "plaintext" 9 | ] 10 | } -------------------------------------------------------------------------------- /.vscode/spellright.dict: -------------------------------------------------------------------------------- 1 | doryen_rs 2 | XpFile 3 | winit 4 | num 5 | println 6 | desat 7 | serde 8 | to_xp_layer 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-algorithm-traits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-algorithm-traits" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "Traits required for the bracket-* crates. Adapt your maps to the traits with Algorithm2D, Algorithm3D and BaseMap." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = [] 12 | categories = ["game-engines", "graphics"] 13 | license = "MIT" 14 | 15 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 16 | 17 | [dependencies] 18 | bracket-geometry = { path = "../bracket-geometry", version = "~0.8" } 19 | smallvec = "~1" 20 | -------------------------------------------------------------------------------- /bracket-algorithm-traits/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-algorithm-traits/src/basemap.rs: -------------------------------------------------------------------------------- 1 | //! # `BaseMap` 2 | //! 3 | //! `BaseMap` provides map traits required for path-finding and field-of-view operations. Implement these 4 | //! if you want to use these features from `bracket-lib`. 5 | //! 6 | //! `is_opaque` specifies is you can see through a tile, required for field-of-view. 7 | //! 8 | //! `get_available_exits` lists the indices to which one can travel from a given tile, along with a relative 9 | //! cost of each exit. Required for path-finding. 10 | //! 11 | //! `get_pathing_distance` allows you to implement your heuristic for determining remaining distance to a 12 | //! target. 13 | 14 | use smallvec::SmallVec; 15 | 16 | /// Implement this trait to support path-finding functions. 17 | pub trait BaseMap { 18 | /// True is you cannot see through the tile, false otherwise. Default implementation 19 | /// always returns true, and is provided so you don't have to implement it if you 20 | /// aren't using it. 21 | fn is_opaque(&self, _idx: usize) -> bool { 22 | true 23 | } 24 | 25 | /// Return a vector of tile indices to which one can path from the idx. 26 | /// These do NOT have to be contiguous - if you want to support teleport pads, that's awesome. 27 | /// Default implementation is provided that proves an empty list, in case you aren't using 28 | /// it. 29 | /// 30 | /// Note that you should never return the current tile as an exit. The A* implementation 31 | /// really doesn't like that. 32 | fn get_available_exits(&self, _idx: usize) -> SmallVec<[(usize, f32); 10]> { 33 | SmallVec::new() 34 | } 35 | 36 | /// Return the distance you would like to use for path-finding. Generally, Pythagoras distance (implemented in geometry) 37 | /// is fine, but you might use Manhattan or any other heuristic that fits your problem. 38 | /// Default implementation returns 1.0, which isn't what you want but prevents you from 39 | /// having to implement it when not using it. 40 | fn get_pathing_distance(&self, _idx1: usize, _idx2: usize) -> f32 { 41 | 1.0 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bracket-algorithm-traits/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all, clippy::pedantic, clippy::cargo)] 2 | //! This crate is part of the `bracket-lib` family. 3 | //! 4 | //! It provides traits for you to implement on your map (and other geometric constructs), 5 | //! translating them into a format that works with the `bracket-pathfinding` and `bracket-geometry` 6 | //! systems. 7 | //! 8 | //! It is a separate crate so that both can depend upon it. 9 | //! 10 | //! Defaults are provided to get you up and running quickly, but may (should!) be overridden if you 11 | //! don't want to use my default array striding. 12 | //! 13 | //! For example: 14 | //! ```rust 15 | //! use bracket_algorithm_traits::prelude::{BaseMap, Algorithm2D}; 16 | //! use bracket_geometry::prelude::Point; 17 | //! 18 | //! struct TestMap{}; 19 | //! impl BaseMap for TestMap {} 20 | //! impl Algorithm2D for TestMap{ 21 | //! fn dimensions(&self) -> Point { 22 | //! Point::new(2, 2) 23 | //! } 24 | //! } 25 | //! ``` 26 | 27 | mod algorithm2d; 28 | mod algorithm3d; 29 | mod basemap; 30 | 31 | /// Exported traits 32 | pub mod prelude { 33 | /// `Algorithm2D` support 34 | pub use crate::algorithm2d::Algorithm2D; 35 | 36 | /// `Algorithm3D` support 37 | pub use crate::algorithm3d::Algorithm3D; 38 | 39 | /// `BaseMap` support 40 | pub use crate::basemap::BaseMap; 41 | 42 | /// Since we use `SmallVec`, it's only polite to export it so you don't have to have multiple copies. 43 | pub use smallvec::{smallvec, SmallVec}; 44 | } 45 | -------------------------------------------------------------------------------- /bracket-bevy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-bevy" 3 | version = "0.9.0" 4 | edition = "2021" 5 | authors = ["Herbert Wolverson "] 6 | publish = true 7 | description = "ASCII/CP437 Psuedo-terminal for Bevy, based on bracket-lib. Aims to provide everything you need to produce a retro console experience using Bevy for the ECS and rendering." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["roguelike", "gamedev", "RGB", "HSV", "color"] 12 | categories = ["game-engines", "graphics"] 13 | license = "MIT" 14 | 15 | [dependencies] 16 | bevy = "0.9" 17 | parking_lot = "0.12" 18 | lazy_static = "1.4" 19 | bracket-random = { path = "../bracket-random" } 20 | bracket-color = { path = "../bracket-color", features = [ "bevy" ] } 21 | bracket-geometry = { path = "../bracket-geometry", version = "~0.8", features = [ "bevy" ] } 22 | 23 | [dev-dependencies] 24 | bracket-pathfinding = { path = "../bracket-pathfinding", version = "~0.8" } 25 | bracket-noise = { path = "../bracket-noise", version = "~0.8" } -------------------------------------------------------------------------------- /bracket-bevy/assets/example_tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-bevy/assets/example_tiles.png -------------------------------------------------------------------------------- /bracket-bevy/assets/terminal8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-bevy/assets/terminal8x8.png -------------------------------------------------------------------------------- /bracket-bevy/assets/vga8x16-color-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-bevy/assets/vga8x16-color-alpha.png -------------------------------------------------------------------------------- /bracket-bevy/assets/vga8x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-bevy/assets/vga8x16.png -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_batch_z_order.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | App::new() 6 | .add_plugins(DefaultPlugins) 7 | .add_plugin(BTermBuilder::simple_80x50()) 8 | .add_system(tick) 9 | .run(); 10 | } 11 | 12 | fn tick(ctx: Res) { 13 | let mut draw_batch = ctx.new_draw_batch(); 14 | draw_batch.print_color_with_z( 15 | Point::new(10, 10), 16 | "This is at always on top", 17 | ColorPair::new(YELLOW, BLUE), 18 | 1000, 19 | ); 20 | for y in 0..50 { 21 | for x in 0..80 { 22 | draw_batch.set( 23 | Point::new(x, y), 24 | ColorPair::new(DARKGRAY, BLACK), 25 | to_cp437('#'), 26 | ); 27 | } 28 | } 29 | ctx.submit_batch(0, draw_batch); 30 | } 31 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_benchmark.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | let bterm = BTermBuilder::simple_80x50().with_random_number_generator(true); 6 | 7 | App::new() 8 | .add_plugins(DefaultPlugins) 9 | .add_plugin(bterm) 10 | .add_system(tick) 11 | .run(); 12 | } 13 | 14 | fn tick(ctx: Res, rng: Res) { 15 | for y in 0..50 { 16 | for x in 0..80 { 17 | let val = rng.rand::(); 18 | let back = RGB::from_u8( 19 | (val & 0xFF) as u8, 20 | ((val >> 8) & 0x5F) as u8, 21 | ((val >> 16) & 0x3F) as u8, 22 | ); 23 | let fore = RGB::from_u8( 24 | ((val >> 16) & 0xFF) as u8, 25 | ((val >> 24) & 0xFF) as u8, 26 | ((val >> 32) & 0xFF) as u8, 27 | ); 28 | let ascii = ((val >> 40) & 0xFF) as u16; 29 | ctx.set(x, y, fore, back, ascii); 30 | } 31 | } 32 | ctx.draw_box(30, 20, 20, 5, WHITE, BLACK); 33 | ctx.print_centered(22, &format!("{} fps", ctx.fps as u32)); 34 | } 35 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_benchmark_scalable.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | let bterm = BTermBuilder::simple_80x50() 6 | .with_random_number_generator(true) 7 | .with_scaling_mode(TerminalScalingMode::ResizeTerminals); 8 | 9 | App::new() 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(bterm) 12 | .add_system(tick) 13 | .run(); 14 | } 15 | 16 | fn tick(ctx: Res, rng: Res) { 17 | let console_size = ctx.get_char_size(); 18 | for y in 0..console_size.1 { 19 | for x in 0..console_size.0 { 20 | let val = rng.rand::(); 21 | let back = RGB::from_u8( 22 | (val & 0xFF) as u8, 23 | ((val >> 8) & 0x5F) as u8, 24 | ((val >> 16) & 0x3F) as u8, 25 | ); 26 | let fore = RGB::from_u8( 27 | ((val >> 16) & 0xFF) as u8, 28 | ((val >> 24) & 0xFF) as u8, 29 | ((val >> 32) & 0xFF) as u8, 30 | ); 31 | let ascii = ((val >> 40) & 0xFF) as u16; 32 | ctx.set(x, y, fore, back, ascii); 33 | } 34 | } 35 | ctx.draw_box(30, 20, 20, 5, WHITE, BLACK); 36 | ctx.print_centered(22, &format!("{} fps", ctx.fps as u32)); 37 | } 38 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_hello_minimal.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | App::new() 6 | .add_plugins(DefaultPlugins) 7 | .add_plugin(BTermBuilder::simple_80x50()) 8 | .add_system(tick) 9 | .run(); 10 | } 11 | 12 | fn tick(ctx: Res) { 13 | ctx.set_active_console(0); 14 | ctx.cls(); 15 | ctx.print(1, 1, "Hello Bracket-Bevy World ☻"); 16 | } 17 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_hello_terminal.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | let bterm = BTermBuilder::simple_80x50() 6 | .with_named_color("blue", BLUE) 7 | .with_named_color("pink", Color::PINK); 8 | 9 | App::new() 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(bterm) 12 | .insert_resource(State { 13 | y: 0, 14 | going_down: true, 15 | }) 16 | .add_system(tick) 17 | .run(); 18 | } 19 | 20 | #[derive(Resource)] 21 | struct State { 22 | y: i32, 23 | going_down: bool, 24 | } 25 | 26 | fn tick(ctx: Res, mut state: ResMut) { 27 | let col1 = RGB::named(CYAN); 28 | let col2 = RGB::named(YELLOW); 29 | let percent: f32 = state.y as f32 / 50.0; 30 | let fg = col1.lerp(col2, percent); 31 | 32 | ctx.cls(); 33 | ctx.printer( 34 | 40, 35 | 49, 36 | "#[blue]Hello #[pink]Bracket#[] world.", 37 | TextAlign::Center, 38 | Some(RGBA::from_u8(200, 200, 200, 255)), 39 | ); 40 | 41 | ctx.print_color( 42 | 1, 43 | state.y, 44 | "♫ ♪ Hello Bracket World ☺", 45 | fg, 46 | RGB::named(BLACK), 47 | ); 48 | 49 | // Lets make the hello bounce up and down 50 | if state.going_down { 51 | state.y += 1; 52 | if state.y > 48 { 53 | state.going_down = false; 54 | } 55 | } else { 56 | state.y -= 1; 57 | if state.y < 2 { 58 | state.going_down = true; 59 | } 60 | } 61 | 62 | // We'll also show the frame rate, since we generally care about keeping that high. 63 | ctx.draw_box(39, 0, 20, 3, RGB::named(WHITE), RGB::named(BLACK)); 64 | ctx.printer( 65 | 58, 66 | 1, 67 | &format!("#[pink]FPS: #[]{}", ctx.fps as u32), 68 | TextAlign::Right, 69 | None, 70 | ); 71 | ctx.printer( 72 | 58, 73 | 2, 74 | &format!("#[pink]Frame Time: #[]{} ms", ctx.frame_time_ms), 75 | TextAlign::Right, 76 | None, 77 | ); 78 | } 79 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_resize_terminal.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | App::new() 6 | .add_plugins(DefaultPlugins) 7 | .add_plugin( 8 | BTermBuilder::simple_80x50().with_scaling_mode(TerminalScalingMode::ResizeTerminals), 9 | ) 10 | .add_system(tick) 11 | .run(); 12 | } 13 | 14 | fn tick(ctx: Res) { 15 | ctx.set_active_console(0); 16 | ctx.cls(); 17 | let (width, height) = ctx.get_char_size(); 18 | ctx.print(1, 1, "Hello Bracket-Bevy World ☻"); 19 | ctx.print( 20 | 1, 21 | 3, 22 | format!("Console is currently {width}x{height} characters."), 23 | ); 24 | ctx.draw_hollow_box_double(0, 0, width as i32 - 1, height as i32 - 1, WHITE, NAVY); 25 | } 26 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_roguelike_tutorial_4/components.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::RGB; 3 | 4 | #[derive(Component)] 5 | pub struct Position { 6 | pub x: i32, 7 | pub y: i32, 8 | } 9 | 10 | #[derive(Component)] 11 | pub struct Renderable { 12 | pub glyph: u16, 13 | pub fg: RGB, 14 | pub bg: RGB, 15 | } 16 | 17 | #[derive(Component, Debug)] 18 | pub struct Player {} 19 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_roguelike_tutorial_4/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | use std::cmp::{max, min}; 4 | 5 | mod components; 6 | pub use components::*; 7 | mod map; 8 | pub use map::*; 9 | mod player; 10 | pub use player::*; 11 | mod rect; 12 | pub use rect::*; 13 | 14 | fn main() { 15 | App::new() 16 | .add_plugins(DefaultPlugins) 17 | .add_plugin(BTermBuilder::simple_80x50().with_random_number_generator(true)) 18 | .add_startup_system(setup) 19 | .add_system(tick) 20 | .run(); 21 | } 22 | 23 | fn setup(mut commands: Commands, rng: Res) { 24 | let (rooms, map) = new_map_rooms_and_corridors(&rng); 25 | let (player_x, player_y) = rooms[0].center(); 26 | commands.insert_resource(map); 27 | commands 28 | .spawn_empty() 29 | .insert(Position { 30 | x: player_x, 31 | y: player_y, 32 | }) 33 | .insert(Renderable { 34 | glyph: to_cp437('@'), 35 | fg: RGB::named(YELLOW), 36 | bg: RGB::named(BLACK), 37 | }) 38 | .insert(Player {}); 39 | } 40 | 41 | fn tick( 42 | ctx: Res, 43 | map: Res, 44 | keyboard: Res>, 45 | mut queries: ParamSet<( 46 | Query<&mut Position, With>, 47 | Query<(&Position, &Renderable)>, 48 | )>, 49 | ) { 50 | ctx.cls(); 51 | 52 | let delta = player_input(&keyboard); 53 | if delta != (0, 0) { 54 | let mut player_query = queries.p0(); 55 | let mut pos = player_query.single_mut(); 56 | let destination_idx = xy_idx(pos.x + delta.0, pos.y + delta.1); 57 | if map.0[destination_idx] != TileType::Wall { 58 | pos.x = min(79, max(0, pos.x + delta.0)); 59 | pos.y = min(49, max(0, pos.y + delta.1)); 60 | } 61 | } 62 | 63 | draw_map(&map.0, &ctx); 64 | for (pos, render) in queries.p1().iter() { 65 | ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_roguelike_tutorial_4/player.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | pub fn player_input(keyboard: &Input) -> (i32, i32) { 4 | if keyboard.just_pressed(KeyCode::Left) 5 | || keyboard.just_pressed(KeyCode::Numpad4) 6 | || keyboard.just_pressed(KeyCode::H) 7 | { 8 | (-1, 0) 9 | } else if keyboard.just_pressed(KeyCode::Right) 10 | || keyboard.just_pressed(KeyCode::Numpad6) 11 | || keyboard.just_pressed(KeyCode::L) 12 | { 13 | (1, 0) 14 | } else if keyboard.just_pressed(KeyCode::Up) 15 | || keyboard.just_pressed(KeyCode::Numpad8) 16 | || keyboard.just_pressed(KeyCode::K) 17 | { 18 | (0, -1) 19 | } else if keyboard.just_pressed(KeyCode::Down) 20 | || keyboard.just_pressed(KeyCode::Numpad2) 21 | || keyboard.just_pressed(KeyCode::J) 22 | { 23 | (0, 1) 24 | } else { 25 | (0, 0) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_roguelike_tutorial_4/rect.rs: -------------------------------------------------------------------------------- 1 | pub struct Rect { 2 | pub x1: i32, 3 | pub x2: i32, 4 | pub y1: i32, 5 | pub y2: i32, 6 | } 7 | 8 | impl Rect { 9 | pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect { 10 | Rect { 11 | x1: x, 12 | y1: y, 13 | x2: x + w, 14 | y2: y + h, 15 | } 16 | } 17 | 18 | // Returns true if this overlaps with other 19 | pub fn intersect(&self, other: &Rect) -> bool { 20 | self.x1 <= other.x2 && self.x2 >= other.x1 && self.y1 <= other.y2 && self.y2 >= other.y1 21 | } 22 | 23 | pub fn center(&self) -> (i32, i32) { 24 | ((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_test.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | App::new() 6 | .add_plugins(DefaultPlugins) 7 | .add_plugin(BTermBuilder::simple_80x50()) 8 | .add_system(tick) 9 | .run(); 10 | } 11 | 12 | fn tick(ctx: Res) { 13 | ctx.set_active_console(0); 14 | ctx.cls(); 15 | ctx.print(1, 1, "Hello Bracket-Bevy World ☻"); 16 | ctx.print_color(1, 2, "Now in color!", GREEN, NAVY); 17 | 18 | ctx.print_color( 19 | 1, 20 | 4, 21 | format!("Frames per Second: {}", ctx.fps as u32), 22 | YELLOW, 23 | BLACK, 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_textblock.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | App::new() 6 | .add_plugins(DefaultPlugins) 7 | .add_plugin(BTermBuilder::simple_80x50()) 8 | .add_system(tick) 9 | .run(); 10 | } 11 | 12 | fn tick(ctx: Res) { 13 | let mut draw_batch = ctx.new_draw_batch(); 14 | draw_batch.cls(); 15 | let mut block = TextBlock::new(0, 0, 80, 25); 16 | 17 | let mut buf = TextBuilder::empty(); 18 | buf.ln() 19 | .fg(RGB::named(YELLOW)) 20 | .bg(RGB::named(BLUE)) 21 | .centered("Hello World") 22 | .fg(RGB::named(WHITE)) 23 | .bg(RGB::named(BLACK)) 24 | .ln() 25 | .ln() 26 | .line_wrap("The quick brown fox jumped over the lazy dog, and just kept on running in an attempt to exceed the console width.") 27 | .ln() 28 | .ln() 29 | .line_wrap("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") 30 | .ln().ln() 31 | .fg(RGB::named(CYAN)) 32 | .append("FPS: ") 33 | .fg(RGB::named(MAGENTA)) 34 | .append(&format!("{}", ctx.fps)) 35 | .reset(); 36 | 37 | block.print(&buf).expect("Text was too long"); 38 | 39 | block.render_to_draw_batch(&mut draw_batch); 40 | ctx.submit_batch(0, draw_batch); 41 | } 42 | -------------------------------------------------------------------------------- /bracket-bevy/examples/bevy_two_layers_two_fonts.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bracket_bevy::prelude::*; 3 | 4 | fn main() { 5 | let bterm = BTermBuilder::empty() 6 | .with_font("terminal8x8.png", 16, 16, (8.0, 8.0)) 7 | .with_font("vga8x16.png", 16, 16, (8.0, 16.0)) 8 | .with_simple_console(0, 80, 50) 9 | .with_background(true) 10 | .with_sparse_console(1, 80, 25) 11 | .with_background(true); 12 | 13 | App::new() 14 | .add_plugins(DefaultPlugins) 15 | .add_plugin(bterm) 16 | .insert_resource(Bouncer(0)) 17 | .add_system(tick) 18 | .run(); 19 | } 20 | 21 | #[derive(Resource)] 22 | struct Bouncer(i32); 23 | 24 | fn tick(ctx: Res, mut bouncer: ResMut) { 25 | ctx.set_active_console(0); 26 | ctx.cls(); 27 | ctx.print(1, 1, "Hello Bracket-Bevy World ☻"); 28 | ctx.print_color(1, 2, "Now in color!", GREEN, NAVY); 29 | 30 | ctx.set_active_console(1); 31 | ctx.cls(); 32 | ctx.print_color( 33 | 1, 34 | bouncer.0, 35 | format!( 36 | "Frames per Second: {}, {} ms per frame", 37 | ctx.fps, ctx.frame_time_ms 38 | ), 39 | RED, 40 | WHITE, 41 | ); 42 | bouncer.0 += 1; 43 | bouncer.0 %= 25; 44 | } 45 | -------------------------------------------------------------------------------- /bracket-bevy/src/builder/font_builder.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone)] 2 | pub(crate) struct TerminalBuilderFont { 3 | pub(crate) filename: String, 4 | pub(crate) chars_per_row: u16, 5 | pub(crate) n_rows: u16, 6 | pub(crate) font_height_pixels: (f32, f32), 7 | } 8 | 9 | impl TerminalBuilderFont { 10 | pub(crate) fn new( 11 | image_filename: S, 12 | chars_per_row: u16, 13 | n_rows: u16, 14 | font_height_pixels: (f32, f32), 15 | ) -> Self { 16 | Self { 17 | filename: image_filename.to_string(), 18 | chars_per_row, 19 | n_rows, 20 | font_height_pixels, 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bracket-bevy/src/builder/image_fixer.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::*, 3 | render::{render_resource::SamplerDescriptor, texture::ImageSampler}, 4 | }; 5 | 6 | #[derive(Resource)] 7 | pub(crate) struct ImagesToLoad(pub(crate) Vec); 8 | 9 | pub(crate) fn fix_images(mut fonts: ResMut, mut images: ResMut>) { 10 | if fonts.0.is_empty() { 11 | return; 12 | } 13 | 14 | for (handle, img) in images.iter_mut() { 15 | let mut to_remove = Vec::new(); 16 | if let Some(i) = fonts.0.iter().enumerate().find(|(_i, h)| h.id == handle) { 17 | img.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor { 18 | label: Some("LeaveItAlone"), 19 | address_mode_u: bevy::render::render_resource::AddressMode::ClampToEdge, 20 | address_mode_v: bevy::render::render_resource::AddressMode::ClampToEdge, 21 | address_mode_w: bevy::render::render_resource::AddressMode::ClampToEdge, 22 | mag_filter: bevy::render::render_resource::FilterMode::Nearest, 23 | min_filter: bevy::render::render_resource::FilterMode::Nearest, 24 | mipmap_filter: bevy::render::render_resource::FilterMode::Nearest, 25 | ..Default::default() 26 | }); 27 | to_remove.push(i.0); 28 | } 29 | to_remove.iter().for_each(|i| { 30 | fonts.0.remove(*i); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /bracket-bevy/src/builder/mod.rs: -------------------------------------------------------------------------------- 1 | mod font_builder; 2 | pub(crate) use font_builder::TerminalBuilderFont; 3 | mod terminal_layer; 4 | pub(crate) use terminal_layer::*; 5 | mod bterm_builder; 6 | pub use bterm_builder::*; 7 | mod loader_system; 8 | pub(crate) use loader_system::*; 9 | mod image_fixer; 10 | pub(crate) use image_fixer::*; 11 | -------------------------------------------------------------------------------- /bracket-bevy/src/builder/terminal_layer.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | #[derive(Debug, Clone)] 4 | pub enum TerminalLayer { 5 | Simple { 6 | font_index: usize, 7 | width: i32, 8 | height: i32, 9 | features: HashSet, 10 | }, 11 | Sparse { 12 | font_index: usize, 13 | width: i32, 14 | height: i32, 15 | features: HashSet, 16 | }, 17 | } 18 | 19 | #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] 20 | pub enum SimpleConsoleFeatures { 21 | WithoutBackground, 22 | } 23 | 24 | #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] 25 | pub enum SparseConsoleFeatures { 26 | WithoutBackground, 27 | } 28 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/simple_console/back_end/mod.rs: -------------------------------------------------------------------------------- 1 | mod simple_no_background; 2 | mod simple_with_background; 3 | use crate::consoles::ScreenScaler; 4 | 5 | use super::SimpleConsole; 6 | use bevy::{ 7 | prelude::{Assets, Commands, Handle, Mesh}, 8 | sprite::ColorMaterial, 9 | }; 10 | pub(crate) use simple_no_background::*; 11 | pub(crate) use simple_with_background::*; 12 | 13 | pub(crate) trait SimpleConsoleBackend: Sync + Send { 14 | fn new_mesh( 15 | &self, 16 | front_end: &SimpleConsole, 17 | meshes: &mut Assets, 18 | scaler: &ScreenScaler, 19 | ) -> Handle; 20 | fn spawn(&self, commands: &mut Commands, material: Handle, idx: usize); 21 | fn get_pixel_size(&self) -> (f32, f32); 22 | fn resize(&mut self, available_size: &(f32, f32)) -> (i32, i32); 23 | } 24 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/simple_console/components.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Component; 2 | 3 | #[derive(Component)] 4 | pub struct BracketMesh(pub usize); 5 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/simple_console/mod.rs: -------------------------------------------------------------------------------- 1 | mod front_end; 2 | pub(crate) use front_end::*; 3 | mod components; 4 | pub use components::*; 5 | mod terminal_glyph; 6 | pub(crate) use terminal_glyph::*; 7 | mod back_end; 8 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/simple_console/terminal_glyph.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Color; 2 | 3 | #[derive(Clone, Copy)] 4 | pub struct TerminalGlyph { 5 | pub(crate) glyph: u16, 6 | pub(crate) foreground: [f32; 4], 7 | pub(crate) background: [f32; 4], 8 | } 9 | 10 | impl Default for TerminalGlyph { 11 | fn default() -> Self { 12 | Self { 13 | glyph: 32, 14 | foreground: Color::WHITE.as_rgba_f32(), 15 | background: Color::BLACK.as_rgba_f32(), 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/sparse_console/back_end/mod.rs: -------------------------------------------------------------------------------- 1 | mod sparse_no_background; 2 | mod sparse_with_background; 3 | use crate::consoles::ScreenScaler; 4 | 5 | use super::SparseConsole; 6 | use bevy::{ 7 | prelude::{Assets, Commands, Handle, Mesh}, 8 | sprite::ColorMaterial, 9 | }; 10 | pub(crate) use sparse_no_background::*; 11 | pub(crate) use sparse_with_background::*; 12 | 13 | pub(crate) trait SparseConsoleBackend: Sync + Send { 14 | fn new_mesh( 15 | &self, 16 | front_end: &SparseConsole, 17 | meshes: &mut Assets, 18 | scaler: &ScreenScaler, 19 | ) -> Handle; 20 | fn spawn(&self, commands: &mut Commands, material: Handle, idx: usize); 21 | fn get_pixel_size(&self) -> (f32, f32); 22 | fn resize(&mut self, available_size: &(f32, f32)) -> (i32, i32); 23 | } 24 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/sparse_console/mod.rs: -------------------------------------------------------------------------------- 1 | mod front_end; 2 | pub(crate) use front_end::*; 3 | mod back_end; 4 | pub(crate) use back_end::*; 5 | -------------------------------------------------------------------------------- /bracket-bevy/src/consoles/text_spans.rs: -------------------------------------------------------------------------------- 1 | use crate::BracketContext; 2 | use bracket_color::prelude::*; 3 | 4 | #[derive(Debug)] 5 | pub struct ColoredTextSpans { 6 | pub length: usize, 7 | pub spans: Vec<(RGBA, String)>, 8 | } 9 | 10 | impl ColoredTextSpans { 11 | pub fn new(context: &BracketContext, text: &str) -> Self { 12 | let black: RGBA = RGBA::from_u8(0, 0, 0, 255); 13 | let mut result = Self { 14 | length: 0, 15 | spans: Vec::new(), 16 | }; 17 | let mut color_stack: Vec<&RGBA> = Vec::new(); 18 | 19 | for color_span in text.split("#[") { 20 | if color_span.is_empty() { 21 | continue; 22 | } 23 | let mut col_text = color_span.splitn(2, ']'); 24 | let col_name = col_text.next().unwrap(); 25 | if let Some(text_span) = col_text.next() { 26 | if !col_name.is_empty() { 27 | color_stack.push(context.get_named_color(col_name).unwrap_or(&black)); 28 | } else { 29 | color_stack.pop(); 30 | } 31 | result.spans.push(( 32 | **color_stack 33 | .last() 34 | .unwrap_or(&&RGBA::from_u8(255, 255, 255, 255)), 35 | text_span.to_string(), 36 | )); 37 | result.length += text_span.chars().count(); 38 | } 39 | } 40 | 41 | result 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bracket-bevy/src/fonts/font_store.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::{Handle, Image}, 3 | sprite::ColorMaterial, 4 | }; 5 | 6 | /// Stores handles to the components of a font, along with its glyph settings. 7 | pub(crate) struct FontStore { 8 | //pub(crate) texture_handle: Handle, 9 | pub(crate) material_handle: Handle, 10 | pub(crate) chars_per_row: u16, 11 | pub(crate) n_rows: u16, 12 | pub(crate) font_height_pixels: (f32, f32), 13 | } 14 | 15 | impl FontStore { 16 | pub(crate) fn new( 17 | _texture_handle: Handle, 18 | material_handle: Handle, 19 | chars_per_row: u16, 20 | n_rows: u16, 21 | font_height_pixels: (f32, f32), 22 | ) -> Self { 23 | Self { 24 | //texture_handle, 25 | material_handle, 26 | chars_per_row, 27 | n_rows, 28 | font_height_pixels, 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bracket-bevy/src/fonts/mod.rs: -------------------------------------------------------------------------------- 1 | mod font_store; 2 | pub(crate) use font_store::*; 3 | -------------------------------------------------------------------------------- /bracket-bevy/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Provides Bracket-Lib style CP437/ASCII terminal options to Bevy 2 | mod builder; 3 | mod cp437; 4 | mod fonts; 5 | pub use builder::*; 6 | mod context; 7 | pub use context::*; 8 | mod consoles; 9 | use consoles::*; 10 | mod random_resource; 11 | pub use consoles::{DrawBatch, VirtualConsole}; 12 | pub use random_resource::*; 13 | mod textblock; 14 | 15 | pub type FontCharType = u16; 16 | 17 | pub mod prelude { 18 | pub use crate::{ 19 | consoles::TextAlign, cp437::*, textblock::*, BTermBuilder, BracketContext, DrawBatch, 20 | RandomNumbers, TerminalScalingMode, VirtualConsole, 21 | }; 22 | pub use bracket_color::prelude::*; 23 | pub use bracket_geometry::prelude::*; 24 | } 25 | -------------------------------------------------------------------------------- /bracket-color/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-color" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "RGB and HSV color handling and utilities, including lerp and W3C named colors. Part of the bracket-lib family." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["roguelike", "gamedev", "RGB", "HSV", "color"] 12 | categories = ["game-engines", "graphics"] 13 | license = "MIT" 14 | 15 | [features] 16 | palette = [ "lazy_static", "parking_lot" ] 17 | 18 | [dependencies] 19 | serde = { version = "~1.0.110", features = ["derive"], optional = true } 20 | crossterm = { version = "~0.25", optional = true } 21 | lazy_static = { version = "1.4.0", optional = true } 22 | parking_lot = { version = "~0.12", optional = true } 23 | bevy = { version = "~0.9", optional = true } 24 | 25 | [dev-dependencies] 26 | crossterm = "~0.25" 27 | 28 | [[example]] 29 | name = "colors" 30 | required-features = ["crossterm"] 31 | 32 | [[example]] 33 | name = "lerp" 34 | required-features = ["crossterm"] 35 | 36 | [[example]] 37 | name = "lerpit" 38 | required-features = ["crossterm"] 39 | 40 | [[example]] 41 | name = "lerpit_hsv" 42 | required-features = ["crossterm"] 43 | 44 | [[example]] 45 | name = "named_color" 46 | required-features = ["crossterm"] 47 | 48 | [[example]] 49 | name = "shades_of_grey" 50 | required-features = ["crossterm"] 51 | -------------------------------------------------------------------------------- /bracket-color/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-color/examples/colors.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use std::io::{stdout, Write}; 3 | use util::print_color; 4 | 5 | fn main() { 6 | print_color(RGB::named(RED), "Hello RED\n"); 7 | print_color(RGB::from_f32(0.0, 1.0, 0.0), "Hello GREEN\n"); 8 | print_color(RGB::from_u8(0, 0, 255), "Hello BLUE\n"); 9 | print_color( 10 | RGB::from_hex("#FF00FF").expect("Bad hex!"), 11 | "Hello MAGENTA\n", 12 | ); 13 | print_color(RGB::named(WHITE), "And back to white.\n"); 14 | 15 | stdout().flush().expect("Flush Fail"); 16 | } 17 | 18 | mod util; 19 | -------------------------------------------------------------------------------- /bracket-color/examples/lerp.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use std::io::{stdout, Write}; 3 | use util::print_color; 4 | 5 | fn main() { 6 | let red = RGB::named(RED); 7 | let blue = RGB::named(YELLOW); 8 | for i in 1..80 { 9 | let percent = i as f32 / 80.0; 10 | let color = red.lerp(blue, percent); 11 | print_color(color, "*"); 12 | } 13 | print_color(RGB::named(WHITE), "\nAnd back to white.\n"); 14 | 15 | stdout().flush().expect("Flush Fail"); 16 | } 17 | 18 | mod util; 19 | -------------------------------------------------------------------------------- /bracket-color/examples/lerpit.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use std::io::{stdout, Write}; 3 | use util::print_color; 4 | 5 | fn main() { 6 | for color in RgbLerp::new(RGB::named(RED), RGB::named(YELLOW), 20) { 7 | print_color(color, "You've got to lerp it, lerp it.\n"); 8 | } 9 | 10 | print_color(RGB::named(WHITE), "\nAnd back to white.\n"); 11 | 12 | stdout().flush().expect("Flush Fail"); 13 | } 14 | 15 | mod util; 16 | -------------------------------------------------------------------------------- /bracket-color/examples/lerpit_hsv.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use std::io::{stdout, Write}; 3 | use util::print_color; 4 | 5 | fn main() { 6 | for color in HsvLerp::new(RGB::named(GREEN).into(), RGB::named(CHOCOLATE).into(), 20) { 7 | print_color(color.into(), "You've got to lerp it, lerp it.\n"); 8 | } 9 | 10 | print_color(RGB::named(WHITE), "\nAnd back to white.\n"); 11 | 12 | stdout().flush().expect("Flush Fail"); 13 | } 14 | 15 | mod util; 16 | -------------------------------------------------------------------------------- /bracket-color/examples/named_color.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use std::io::{stdout, Write}; 3 | use util::print_color; 4 | 5 | fn main() { 6 | print_color(RGB::named(RED), "Hello RED\n"); 7 | print_color(GREEN.into(), "Hello GREEN\n"); // type inference works too! 8 | print_color(RGB::named(BLUE), "Hello BLUE\n"); 9 | print_color(RGB::named(WHITE), "And back to white.\n"); 10 | 11 | stdout().flush().expect("Flush Fail"); 12 | } 13 | 14 | mod util; 15 | -------------------------------------------------------------------------------- /bracket-color/examples/shades_of_grey.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use std::io::{stdout, Write}; 3 | use util::print_color; 4 | 5 | fn main() { 6 | for color in RgbLerp::new(RGB::named(RED), RGB::named(YELLOW), 20) { 7 | print_color(color.to_greyscale(), "You've got to lerp it, gray it.\n"); 8 | } 9 | for color in RgbLerp::new(RGB::named(GREEN), RGB::named(MAGENTA), 20) { 10 | print_color( 11 | color.desaturate(), 12 | "You've got to lerp it, desaturate it and ruin the joke.\n", 13 | ); 14 | } 15 | 16 | print_color(RGB::named(WHITE), "\nAnd back to white.\n"); 17 | 18 | stdout().flush().expect("Flush Fail"); 19 | } 20 | 21 | mod util; 22 | -------------------------------------------------------------------------------- /bracket-color/examples/util/mod.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use crossterm::queue; 3 | use crossterm::style::{Print, SetForegroundColor}; 4 | use std::convert::TryInto; 5 | use std::io::stdout; 6 | 7 | pub fn print_color(color: RGB, text: &str) { 8 | queue!(stdout(), SetForegroundColor(color.try_into().unwrap())).expect("Command Fail"); 9 | queue!(stdout(), Print(text)).expect("Command fail"); 10 | } 11 | -------------------------------------------------------------------------------- /bracket-color/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all, clippy::pedantic, clippy::cargo)] 2 | 3 | //! This crate is part of the `bracket-lib` family. 4 | //! 5 | //! It provides RGB, HSV and` ColorPair` support for the bracket-lib library. 6 | //! You can construct an RGB with `new`, `from_f32`, `from_u8` or `named`. 7 | //! It exports a large number of named colors (the W3C web named colors) for easy access. 8 | //! It also provides convenience functions such as `to_greyscale`, `desaturate` and `lerp`. 9 | //! 10 | //! For example: 11 | //! ```rust 12 | //! use bracket_color::prelude::*; 13 | //! 14 | //! let red = RGB::named(RED); 15 | //! let blue = RGB::named(BLUE); 16 | //! for lerp in 0 .. 100 { 17 | //! let lerp_by = lerp as f32 / 100.0; 18 | //! let color = red.lerp(blue, lerp_by); 19 | //! println!("{:?}", color); 20 | //! let gray = color.to_greyscale(); 21 | //! println!("{:?}", gray); 22 | //! let desat = color.desaturate(); 23 | //! println!("{:?}", desat); 24 | //! } 25 | //! ``` 26 | //! 27 | //! If you use the `serde` feature flag, the exposed types are serializable/de-serializable. 28 | 29 | #[cfg(feature = "palette")] 30 | #[macro_use] 31 | extern crate lazy_static; 32 | 33 | /// Import color pair support 34 | pub mod color_pair; 35 | /// Import HSV color support 36 | pub mod hsv; 37 | /// Import Lerp as an iterator 38 | pub mod lerpit; 39 | /// Import library of named colors 40 | pub mod named; 41 | /// Import Palette support 42 | #[cfg(feature = "palette")] 43 | pub mod palette; 44 | /// Import RGB color support 45 | pub mod rgb; 46 | /// Import RGBA color support 47 | pub mod rgba; 48 | 49 | /// Exports the color functions/types in the `prelude` namespace. 50 | pub mod prelude { 51 | pub use crate::color_pair::*; 52 | pub use crate::hsv::*; 53 | pub use crate::lerpit::*; 54 | pub use crate::named::*; 55 | #[cfg(feature = "palette")] 56 | pub use crate::palette::*; 57 | pub use crate::rgb::*; 58 | pub use crate::rgba::*; 59 | } 60 | -------------------------------------------------------------------------------- /bracket-color/src/xpcolor.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::RGB; 2 | use byteorder::{ReadBytesExt, WriteBytesExt}; 3 | use std::io; 4 | 5 | /// Structure representing the components of one color 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 7 | pub struct XpColor { 8 | /// Red component 0..255 9 | pub r: u8, 10 | /// Green component 0..255 11 | pub g: u8, 12 | /// Blue component 0..255 13 | pub b: u8, 14 | } 15 | 16 | impl From for XpColor { 17 | fn from(rgb: RGB) -> Self { 18 | rgb.to_xp() 19 | } 20 | } 21 | 22 | impl XpColor { 23 | /// deepest black 24 | pub const BLACK: Self = Self { r: 0, g: 0, b: 0 }; 25 | /// color 0xff00ff (hot pink) is regarded as transparent 26 | pub const TRANSPARENT: Self = Self { 27 | r: 255, 28 | g: 0, 29 | b: 255, 30 | }; 31 | 32 | /// Construct a new color from r,g,b values 33 | #[inline] 34 | #[must_use] 35 | pub const fn new(r: u8, g: u8, b: u8) -> Self { 36 | Self { r, g, b } 37 | } 38 | 39 | /// Return whether this color is considered transparent (if this is the background color of a 40 | /// cell, the layer below it will see through) 41 | #[inline] 42 | #[must_use] 43 | pub fn is_transparent(self) -> bool { 44 | self == Self::TRANSPARENT 45 | } 46 | 47 | /// Read a RGB color from a `ReadBytesExt` 48 | /// 49 | /// # Errors 50 | #[inline] 51 | pub fn read(rdr: &mut T) -> io::Result { 52 | let r = rdr.read_u8()?; 53 | let g = rdr.read_u8()?; 54 | let b = rdr.read_u8()?; 55 | Ok(Self { r, g, b }) 56 | } 57 | 58 | /// Write a RGB color to a `WriteBytesExt` 59 | /// 60 | /// # Errors 61 | #[inline] 62 | pub fn write(self, wr: &mut T) -> io::Result<()> { 63 | wr.write_u8(self.r)?; 64 | wr.write_u8(self.g)?; 65 | wr.write_u8(self.b)?; 66 | Ok(()) 67 | } 68 | } 69 | 70 | impl From for RGB { 71 | fn from(xp: XpColor) -> Self { 72 | RGB::from_xp(xp) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /bracket-embedding/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-embedding" 3 | version = "0.8.7" 4 | edition = "2021" 5 | publish = true 6 | description = "Provides resource embedding services for bracket-lib" 7 | homepage = "https://github.com/thebracket/bracket-lib" 8 | repository = "https://github.com/thebracket/bracket-lib" 9 | readme = "README.md" 10 | keywords = ["roguelike", "gamedev", "terminal", "ascii", "cp437"] 11 | categories = ["game-engines"] 12 | license = "MIT" 13 | 14 | [dependencies] 15 | parking_lot = { version = "~0.12" } 16 | lazy_static = "1.4.0" 17 | -------------------------------------------------------------------------------- /bracket-embedding/README.md: -------------------------------------------------------------------------------- 1 | # Bracket-embedding 2 | 3 | `bracket-lib` includes a system for embedding resources inside your binary (particularly useful for wasm builds). 4 | This crate provides the supporting infrastructure for the embedding. It's not a lot of use on its own. 5 | 6 | ## Example of use 7 | 8 | ```rust 9 | use bracket_embedding::prelude::*; 10 | 11 | embedded_resource!(SOURCE_FILE, "embedding.rs"); 12 | 13 | fn main() { 14 | // This helper macro links the above embedding, allowing it to be accessed as a resource from various parts of the program. 15 | link_resource!(SOURCE_FILE, "embedding.rs"); 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /bracket-embedding/resources/terminal8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-embedding/resources/terminal8x8.png -------------------------------------------------------------------------------- /bracket-embedding/resources/vga8x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-embedding/resources/vga8x16.png -------------------------------------------------------------------------------- /bracket-embedding/src/embedding.rs: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | use parking_lot::Mutex; 3 | use std::collections::HashMap; 4 | 5 | // These are included by default in `bracket-terminal`. 6 | const TERMINAL_8_8_BYTES: &[u8] = 7 | include_bytes!("../resources/terminal8x8.png"); 8 | const TERMINAL_8_16_BYTES: &[u8] = include_bytes!("../resources/vga8x16.png"); 9 | 10 | lazy_static! { 11 | pub static ref EMBED: Mutex = Mutex::new(Dictionary::new()); 12 | } 13 | 14 | /// Stores a dictionary of resources, generally added via `embedded_resource!` and `link_resource!` macros. 15 | #[derive(Default)] 16 | pub struct Dictionary { 17 | entries: HashMap, 18 | } 19 | 20 | impl Dictionary { 21 | /// Create a new, empty dictionary. 22 | #[must_use] 23 | pub fn new() -> Dictionary { 24 | let mut dict = Dictionary { 25 | entries: HashMap::new(), 26 | }; 27 | dict.add_resource("resources/terminal8x8.png".to_string(), TERMINAL_8_8_BYTES); 28 | dict.add_resource("resources/vga8x16.png".to_string(), TERMINAL_8_16_BYTES); 29 | dict 30 | } 31 | 32 | /// Request a resource, returning either a byte array or `None`. 33 | #[must_use] 34 | pub fn get_resource(&self, path: String) -> Option<&'static [u8]> { 35 | let fixed_path = if std::path::MAIN_SEPARATOR == '/' { 36 | path 37 | } else { 38 | path.replace(std::path::MAIN_SEPARATOR, "/") 39 | }; 40 | 41 | if self.entries.contains_key(&fixed_path) { 42 | return Some(self.entries[&fixed_path]); 43 | } 44 | None 45 | } 46 | 47 | /// Insert a resource into the dictionary. 48 | pub fn add_resource(&mut self, path: String, bytes: &'static [u8]) { 49 | self.entries.insert(path, bytes); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /bracket-geometry/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-geometry" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "Geometry utilities. Rect, lines, circles, distance calculations. Part of the bracket-lib family." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["geometry", "gamedev", "bresenham", "circle", "distance"] 12 | categories = ["game-engines", "graphics"] 13 | license = "MIT" 14 | 15 | [dependencies] 16 | serde = { version = "~1.0.139", features = ["derive"], optional = true } 17 | specs = { version = "~0.18.0", optional = true } 18 | bevy = { version = "~0.9", optional = true } 19 | ultraviolet = "~0.9.0" 20 | 21 | [dev-dependencies] 22 | crossterm = "~0.25" 23 | -------------------------------------------------------------------------------- /bracket-geometry/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-geometry/examples/bresenham_circle.rs: -------------------------------------------------------------------------------- 1 | use bracket_geometry::prelude::*; 2 | use crossterm::queue; 3 | use crossterm::style::Print; 4 | use std::io::{stdout, Write}; 5 | 6 | fn main() { 7 | let mut fake_console: Vec = vec!['.'; 100]; 8 | for point in BresenhamCircle::new(Point::new(5, 5), 4) { 9 | let idx = ((point.y * 10) + point.x) as usize; 10 | fake_console[idx] = '*'; 11 | } 12 | 13 | for y in 0..10 { 14 | let mut line = String::from(""); 15 | let idx = y * 10; 16 | for x in 0..10 { 17 | line.push(fake_console[idx + x]); 18 | } 19 | line.push('\n'); 20 | queue!(stdout(), Print(&line)).expect("Command fail"); 21 | } 22 | stdout().flush().expect("Flush Fail"); 23 | } 24 | -------------------------------------------------------------------------------- /bracket-geometry/examples/bresenham_line.rs: -------------------------------------------------------------------------------- 1 | use bracket_geometry::prelude::*; 2 | use crossterm::queue; 3 | use crossterm::style::Print; 4 | use std::io::{stdout, Write}; 5 | 6 | fn main() { 7 | let mut fake_console: Vec = vec!['.'; 100]; 8 | 9 | let line: Vec = Bresenham::new(Point::new(0, 6), Point::new(6, 0)).collect(); 10 | 11 | for (i, point) in line.iter().enumerate() { 12 | let idx = ((point.y * 10) + point.x) as usize; 13 | let character = 48 + i as u8; 14 | fake_console[idx] = character as char; 15 | } 16 | 17 | for y in 0..10 { 18 | let mut line = String::from(""); 19 | let idx = y * 10; 20 | for x in 0..10 { 21 | line.push(fake_console[idx + x]); 22 | } 23 | line.push('\n'); 24 | queue!(stdout(), Print(&line)).expect("Command fail"); 25 | } 26 | stdout().flush().expect("Flush Fail"); 27 | 28 | line.iter().for_each(|p| println!("{:?}", p)); 29 | } 30 | -------------------------------------------------------------------------------- /bracket-geometry/examples/bresenham_sweep.rs: -------------------------------------------------------------------------------- 1 | use bracket_geometry::prelude::*; 2 | use crossterm::style::Print; 3 | use crossterm::{cursor, queue}; 4 | use std::io::{stdout, Write}; 5 | 6 | fn main() { 7 | let mut angle = Degrees::new(0.0); 8 | let start_point = Point::new(10, 10); 9 | while angle.0 < 360.0 { 10 | queue!(stdout(), cursor::MoveTo(0, 0)).expect("Failed to write to stdout"); 11 | let mut fake_console: Vec = vec!['.'; 400]; 12 | 13 | let end_point = project_angle(Point::new(0, 0), 8.0, angle) + start_point; 14 | let line: Vec = Bresenham::new(start_point, end_point).collect(); 15 | 16 | for (i, point) in line.iter().enumerate() { 17 | let idx = ((point.y * 20) + point.x) as usize; 18 | let character = 48 + i as u8; 19 | fake_console[idx] = character as char; 20 | } 21 | 22 | for y in 0..20 { 23 | let mut line = String::from(""); 24 | let idx = y * 20; 25 | for x in 0..20 { 26 | line.push(fake_console[idx + x]); 27 | } 28 | line.push('\n'); 29 | queue!(stdout(), Print(&line)).expect("Command fail"); 30 | } 31 | stdout().flush().expect("Flush Fail"); 32 | angle.0 += 1.0; 33 | std::thread::sleep(std::time::Duration::from_millis(20)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /bracket-geometry/examples/distance.rs: -------------------------------------------------------------------------------- 1 | use bracket_geometry::prelude::*; 2 | 3 | fn main() { 4 | let pt1 = Point::new(0, 0); 5 | let pt2 = Point::new(10, 20); 6 | println!("Given the two points:"); 7 | println!("{:#?}\n{:#?}", pt1, pt2); 8 | println!(); 9 | println!( 10 | "Pythagoras Distance: {}", 11 | DistanceAlg::Pythagoras.distance2d(pt1, pt2) 12 | ); 13 | println!( 14 | "Pythagoras Squared Distance: {}", 15 | DistanceAlg::PythagorasSquared.distance2d(pt1, pt2) 16 | ); 17 | println!( 18 | "Manhattan Distance: {}", 19 | DistanceAlg::Manhattan.distance2d(pt1, pt2) 20 | ); 21 | println!( 22 | "Chebyshev Distance: {}", 23 | DistanceAlg::Chebyshev.distance2d(pt1, pt2) 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /bracket-geometry/examples/vector_line.rs: -------------------------------------------------------------------------------- 1 | use bracket_geometry::prelude::*; 2 | use crossterm::queue; 3 | use crossterm::style::Print; 4 | use std::io::{stdout, Write}; 5 | 6 | fn main() { 7 | let mut fake_console: Vec = vec!['.'; 100]; 8 | for point in VectorLine::new(Point::new(1, 1), Point::new(7, 9)) { 9 | let idx = ((point.y * 10) + point.x) as usize; 10 | fake_console[idx] = '*'; 11 | } 12 | 13 | for y in 0..10 { 14 | let mut line = String::from(""); 15 | let idx = y * 10; 16 | for x in 0..10 { 17 | line.push(fake_console[idx + x]); 18 | } 19 | line.push('\n'); 20 | queue!(stdout(), Print(&line)).expect("Command fail"); 21 | } 22 | stdout().flush().expect("Flush Fail"); 23 | } 24 | -------------------------------------------------------------------------------- /bracket-geometry/src/angle.rs: -------------------------------------------------------------------------------- 1 | /// Convenience type: you can define an angle in Degrees and it is convertible to Radians 2 | /// (and vice versa) 3 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 4 | #[derive(Copy, Clone, Debug)] 5 | pub struct Degrees(pub f32); 6 | 7 | /// Convenience type: you can define an angle in Radians and it is convertible to Degrees 8 | /// (and vice versa) 9 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 10 | #[derive(Copy, Clone, Debug)] 11 | pub struct Radians(pub f32); 12 | 13 | impl Degrees { 14 | /// Creates a new angle in degrees. 15 | /// 16 | /// # Arguments 17 | /// 18 | /// * `angle` - the angle to represent, in degrees. 19 | pub fn new(angle: f32) -> Self { 20 | Self(angle) 21 | } 22 | } 23 | 24 | impl Radians { 25 | /// Creates a new angle in radians. 26 | /// 27 | /// # Arguments 28 | /// 29 | /// * `angle` - the angle to represent, in radians. 30 | pub fn new(angle: f32) -> Self { 31 | Self(angle) 32 | } 33 | } 34 | 35 | impl From for Degrees { 36 | fn from(item: Radians) -> Self { 37 | Self(item.0 * 57.2958) 38 | } 39 | } 40 | 41 | impl From for Radians { 42 | fn from(item: Degrees) -> Self { 43 | Self(item.0 * 0.017_453_3) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /bracket-geometry/src/angles.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::{Point, Radians}; 2 | 3 | /// From a given start point, project forward radius units at an angle of angle_radians degrees. 4 | /// 0 Degrees is north (negative Y), 90 degrees is east (positive X) 5 | pub fn project_angle(start: Point, radius: f32, angle_radians: ANGLE) -> Point 6 | where 7 | ANGLE: Into, 8 | { 9 | let degrees_radians = angle_radians.into().0 + std::f32::consts::PI; 10 | Point::new( 11 | (0.0 - (start.x as f32 + radius * f32::sin(degrees_radians))) as i32, 12 | (start.y as f32 + radius * f32::cos(degrees_radians)) as i32, 13 | ) 14 | } 15 | 16 | #[cfg(test)] 17 | mod tests { 18 | use crate::prelude::{project_angle, Degrees, Point, Radians}; 19 | 20 | #[test] 21 | fn test_project_angle() { 22 | let start = Point::new(0, 0); 23 | let mut dest = project_angle(start, 10.0, Radians::new(0.0)); 24 | assert_eq!(dest, Point::new(0, -10)); 25 | 26 | dest = project_angle(start, 10.0, Radians::new(std::f32::consts::PI)); // 180 degrees 27 | assert_eq!(dest, Point::new(0, 10)); 28 | 29 | dest = project_angle(start, 10.0, Radians::new(std::f32::consts::PI / 2.0)); // 90 degrees, east 30 | assert_eq!(dest, Point::new(10, 0)); 31 | 32 | dest = project_angle( 33 | start, 34 | 10.0, 35 | Radians::new(std::f32::consts::PI + (std::f32::consts::PI / 2.0)), 36 | ); // 270 degrees, west 37 | assert_eq!(dest, Point::new(-10, 0)); 38 | 39 | dest = project_angle(start, 10.0, Radians::new(std::f32::consts::FRAC_PI_4)); // 45 degrees, north-east 40 | assert_eq!(dest, Point::new(7, -7)); 41 | 42 | dest = project_angle(start, 10.0, Degrees::new(135.0)); // 135 degrees, south-east 43 | assert_eq!(dest, Point::new(7, 7)); 44 | 45 | dest = project_angle(start, 10.0, Degrees::new(225.0)); // 225 degrees, south-west 46 | assert_eq!(dest, Point::new(-7, 7)); 47 | 48 | dest = project_angle(start, 10.0, Degrees::new(315.0)); // 315 degrees, north-west 49 | assert_eq!(dest, Point::new(-7, -7)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /bracket-geometry/src/line_vector.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::Point; 2 | use core::iter::Iterator; 3 | use ultraviolet::Vec2; 4 | 5 | /// Define a line using a fast 2D vector. It may not be as pixel-perfect as Bresenham, but with vectorization it is sometimes 6 | /// faster for a quick line solution. 7 | pub struct VectorLine { 8 | end: Point, 9 | current_pos: Vec2, 10 | slope: Vec2, 11 | finished: bool, 12 | really_finished: bool, 13 | } 14 | 15 | impl VectorLine { 16 | /// Define a vector line between two points. 17 | pub fn new(start: Point, end: Point) -> Self { 18 | let current_pos = Vec2::new(start.x as f32 + 0.5, start.y as f32 + 0.5); 19 | let destination = Vec2::new(end.x as f32 + 0.5, end.y as f32 + 0.5); 20 | let slope = (destination - current_pos).normalized(); 21 | 22 | VectorLine { 23 | end, 24 | current_pos, 25 | slope, 26 | finished: false, 27 | really_finished: false, 28 | } 29 | } 30 | } 31 | 32 | impl Iterator for VectorLine { 33 | type Item = Point; 34 | 35 | fn next(&mut self) -> Option { 36 | if self.finished { 37 | if !self.really_finished { 38 | self.really_finished = true; 39 | Some(Point::new( 40 | self.current_pos.x as i32, 41 | self.current_pos.y as i32, 42 | )) 43 | } else { 44 | None 45 | } 46 | } else { 47 | let current_point = Point::new(self.current_pos.x as i32, self.current_pos.y as i32); 48 | self.current_pos += self.slope; 49 | let new_point = Point::new(self.current_pos.x as i32, self.current_pos.y as i32); 50 | if new_point == self.end { 51 | self.finished = true; 52 | } 53 | Some(current_point) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /bracket-noise/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-noise" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "Rust port of Auburn's amazing FastNoise library. Part of the bracket-lib family." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["roguelike", "gamedev", "noise", "perlin", "simplex"] 12 | categories = ["game-engines", "random"] 13 | license = "MIT" 14 | 15 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 16 | 17 | [dependencies] 18 | bracket-random = { path = "../bracket-random", version = "~0.8" } 19 | 20 | [dev-dependencies] 21 | crossterm = "~0.25" 22 | bracket-color = { path = "../bracket-color", version = "~0.8", features = [ "palette" ] } 23 | -------------------------------------------------------------------------------- /bracket-noise/README.md: -------------------------------------------------------------------------------- 1 | # bracket-noise 2 | 3 | [Auburn's FastNoise](https://github.com/Auburns/FastNoise) library is amazing - it's fast, covers all the commonly used types of noise, and has been ported to many systems. This crate ports much of that functionality (more is being ported in each version) to Rust. It is part of the `bracket-lib` family of crates. 4 | 5 | ## Using bracket-noise 6 | 7 | To obtain `bracket-noise`, include the following in your `Cargo.toml` file: 8 | 9 | ```toml 10 | [dependencies] 11 | bracket-noise = "~0.8" 12 | ``` 13 | 14 | ## Examples 15 | 16 | You may run examples with `cargo run --example `. The examples use `crossterm` for easy terminal output. 17 | 18 | * `simplex_fractal` uses Fractal Simplex Noise to make a heightmap, and outputs it to your terminal. 19 | * `perlin_fractal` uses Fractal Perlin Noise to make a heightmap, and outputs it to your terminal. 20 | * `white_noise` outputs a randomized white noise sample to your terminal. 21 | * `value` outputs "value noise" to your terminal. This is a bit like white noise but smoother. 22 | * `value_fractal` outputs "fractal value noise" to your terminal. 23 | * `cellular` provides a dump of cellular noise. Until the functions to look up the base noise layer from another noise generator are implemented, this is of limited utility. 24 | * `simplex_billow_quintic` and `simplex_rigid_hermite` demonstrate some noise tweaking options. 25 | -------------------------------------------------------------------------------- /bracket-noise/examples/cellular.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::Cellular); 26 | noise.set_frequency(0.25); 27 | noise.set_fractal_gain(0.6); 28 | noise.set_cellular_distance_function(CellularDistanceFunction::Natural); 29 | noise.set_cellular_return_type(CellularReturnType::CellValue); 30 | 31 | for y in 0..50 { 32 | for x in 0..80 { 33 | let n = noise.get_noise(x as f32, y as f32); 34 | let col = (n + 1.0) * 0.5; 35 | print_color(RGB::from_f32(col, col, col), "▒"); 36 | } 37 | print_color(RGB::named(WHITE), "\n"); 38 | } 39 | 40 | print_color(RGB::named(WHITE), "\n"); 41 | stdout().flush().expect("Flush Fail"); 42 | } 43 | -------------------------------------------------------------------------------- /bracket-noise/examples/perlin_fractal.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::PerlinFractal); 26 | noise.set_fractal_type(FractalType::FBM); 27 | noise.set_fractal_octaves(5); 28 | noise.set_fractal_gain(0.6); 29 | noise.set_fractal_lacunarity(2.0); 30 | noise.set_frequency(2.0); 31 | 32 | for y in 0..50 { 33 | for x in 0..80 { 34 | let n = noise.get_noise((x as f32) / 160.0, (y as f32) / 100.0); 35 | if n < 0.0 { 36 | print_color(RGB::from_f32(0.0, 0.0, 1.0 - (0.0 - n)), "░"); 37 | } else { 38 | print_color(RGB::from_f32(0.0, n, 0.0), "░"); 39 | } 40 | } 41 | print_color(RGB::named(WHITE), "\n"); 42 | } 43 | 44 | print_color(RGB::named(WHITE), "\n"); 45 | stdout().flush().expect("Flush Fail"); 46 | } 47 | -------------------------------------------------------------------------------- /bracket-noise/examples/simplex_billow_quintic.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::SimplexFractal); 26 | noise.set_fractal_type(FractalType::Billow); 27 | noise.set_interp(Interp::Quintic); 28 | noise.set_fractal_octaves(5); 29 | noise.set_fractal_gain(0.6); 30 | noise.set_fractal_lacunarity(2.0); 31 | noise.set_frequency(2.0); 32 | 33 | for y in 0..50 { 34 | for x in 0..80 { 35 | let n = noise.get_noise((x as f32) / 160.0, (y as f32) / 100.0); 36 | if n < 0.0 { 37 | print_color(RGB::from_f32(0.0, 0.0, 1.0 - (0.0 - n)), "░"); 38 | } else { 39 | print_color(RGB::from_f32(0.0, n, 0.0), "░"); 40 | } 41 | } 42 | print_color(RGB::named(WHITE), "\n"); 43 | } 44 | 45 | print_color(RGB::named(WHITE), "\n"); 46 | stdout().flush().expect("Flush Fail"); 47 | } 48 | -------------------------------------------------------------------------------- /bracket-noise/examples/simplex_fractal.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::SimplexFractal); 26 | noise.set_fractal_type(FractalType::FBM); 27 | noise.set_fractal_octaves(5); 28 | noise.set_fractal_gain(0.6); 29 | noise.set_fractal_lacunarity(2.0); 30 | noise.set_frequency(2.0); 31 | 32 | for y in 0..50 { 33 | for x in 0..80 { 34 | let n = noise.get_noise((x as f32) / 160.0, (y as f32) / 100.0); 35 | if n < 0.0 { 36 | print_color(RGB::from_f32(0.0, 0.0, 1.0 - (0.0 - n)), "░"); 37 | } else { 38 | print_color(RGB::from_f32(0.0, n, 0.0), "░"); 39 | } 40 | } 41 | print_color(RGB::named(WHITE), "\n"); 42 | } 43 | 44 | print_color(RGB::named(WHITE), "\n"); 45 | stdout().flush().expect("Flush Fail"); 46 | } 47 | -------------------------------------------------------------------------------- /bracket-noise/examples/simplex_rigid_hermite.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::SimplexFractal); 26 | noise.set_fractal_type(FractalType::RigidMulti); 27 | noise.set_interp(Interp::Hermite); 28 | noise.set_fractal_octaves(10); 29 | noise.set_fractal_gain(0.6); 30 | noise.set_fractal_lacunarity(2.0); 31 | noise.set_frequency(2.0); 32 | 33 | for y in 0..50 { 34 | for x in 0..80 { 35 | let n = noise.get_noise((x as f32) / 160.0, (y as f32) / 100.0); 36 | if n < 0.0 { 37 | print_color(RGB::from_f32(0.0, 0.0, 1.0 - (0.0 - n)), "░"); 38 | } else { 39 | print_color(RGB::from_f32(0.0, n, 0.0), "░"); 40 | } 41 | } 42 | print_color(RGB::named(WHITE), "\n"); 43 | } 44 | 45 | print_color(RGB::named(WHITE), "\n"); 46 | stdout().flush().expect("Flush Fail"); 47 | } 48 | -------------------------------------------------------------------------------- /bracket-noise/examples/value.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::Value); 26 | noise.set_frequency(0.1); 27 | 28 | for y in 0..50 { 29 | for x in 0..80 { 30 | let n = noise.get_noise(x as f32, y as f32); 31 | let col = (n + 1.0) * 0.5; 32 | print_color(RGB::from_f32(col, col, col), "▒"); 33 | } 34 | print_color(RGB::named(WHITE), "\n"); 35 | } 36 | 37 | print_color(RGB::named(WHITE), "\n"); 38 | stdout().flush().expect("Flush Fail"); 39 | } 40 | -------------------------------------------------------------------------------- /bracket-noise/examples/value_fractal.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::ValueFractal); 26 | noise.set_frequency(0.1); 27 | 28 | for y in 0..50 { 29 | for x in 0..80 { 30 | let n = noise.get_noise(x as f32, y as f32); 31 | let col = (n + 1.0) * 0.5; 32 | print_color(RGB::from_f32(col, col, col), "▒"); 33 | } 34 | print_color(RGB::named(WHITE), "\n"); 35 | } 36 | 37 | print_color(RGB::named(WHITE), "\n"); 38 | stdout().flush().expect("Flush Fail"); 39 | } 40 | -------------------------------------------------------------------------------- /bracket-noise/examples/whitenoise.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use bracket_noise::prelude::*; 3 | use bracket_random::prelude::*; 4 | 5 | use crossterm::queue; 6 | use crossterm::style::{Color::Rgb, Print, SetForegroundColor}; 7 | use std::io::{stdout, Write}; 8 | 9 | fn print_color(color: RGB, text: &str) { 10 | queue!( 11 | stdout(), 12 | SetForegroundColor(Rgb { 13 | r: (color.r * 255.0) as u8, 14 | g: (color.g * 255.0) as u8, 15 | b: (color.b * 255.0) as u8, 16 | }) 17 | ) 18 | .expect("Command Fail"); 19 | queue!(stdout(), Print(text)).expect("Command fail"); 20 | } 21 | 22 | fn main() { 23 | let mut rng = RandomNumberGenerator::new(); 24 | let mut noise = FastNoise::seeded(rng.next_u64()); 25 | noise.set_noise_type(NoiseType::WhiteNoise); 26 | noise.set_frequency(2.0); 27 | 28 | for y in 0..50 { 29 | for x in 0..80 { 30 | let n = noise.get_noise(x as f32, y as f32); 31 | let col = (n + 1.0) * 0.5; 32 | print_color(RGB::from_f32(col, col, col), "▒"); 33 | } 34 | print_color(RGB::named(WHITE), "\n"); 35 | } 36 | 37 | print_color(RGB::named(WHITE), "\n"); 38 | stdout().flush().expect("Flush Fail"); 39 | } 40 | -------------------------------------------------------------------------------- /bracket-noise/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod fastnoise; 2 | 3 | pub mod prelude { 4 | pub use crate::fastnoise::*; 5 | } 6 | -------------------------------------------------------------------------------- /bracket-pathfinding/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-pathfinding" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "Pathfinding and field-of view utilities. A Star, Dijkstra. Part of the bracket-lib family." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["gamedev", "pathfinding", "astar", "dijkstra", "field-of-view"] 12 | categories = ["game-engines", "graphics"] 13 | license = "MIT" 14 | 15 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 16 | 17 | [features] 18 | threaded = ["rayon"] 19 | 20 | [dependencies] 21 | bracket-geometry = { path = "../bracket-geometry", version = "~0.8" } 22 | bracket-algorithm-traits = { path = "../bracket-algorithm-traits", version = "~0.8" } 23 | num-rational = { version = "0.4", default-features = false, features = ["std"] } 24 | rayon = { version = "1.5.0", optional = true } 25 | smallvec = "~1" 26 | 27 | [dev-dependencies] 28 | crossterm = "~0.25" 29 | bracket-random = { path = "../bracket-random", version = "0.8" } 30 | bracket-color = { path = "../bracket-color", version = "~0.8", features = [ "palette" ] } 31 | criterion = "~0.4" 32 | 33 | [[bench]] 34 | name = "fov_benchmark" 35 | harness = false 36 | 37 | [[bench]] 38 | name = "astar_benchmark" 39 | harness = false 40 | -------------------------------------------------------------------------------- /bracket-pathfinding/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-pathfinding/examples/astar/main.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | use bracket_color::prelude::*; 3 | use bracket_pathfinding::prelude::*; 4 | use common::*; 5 | 6 | fn main() { 7 | let mut map = Map::new(); 8 | 9 | // Perform the search 10 | let path = a_star_search( 11 | map.point2d_to_index(START_POINT), 12 | map.point2d_to_index(END_POINT), 13 | &map, 14 | ); 15 | if path.success { 16 | for loc in &path.steps { 17 | map.tiles[*loc] = '*'; 18 | } 19 | } else { 20 | panic!("No path found"); 21 | } 22 | 23 | // Draw the result 24 | for y in 0..MAP_HEIGHT { 25 | let idx = map.point2d_to_index(Point::new(0, y)); 26 | for x in 0..MAP_WIDTH { 27 | match map.tiles[idx + x] { 28 | '#' => print_color(RGB::named(YELLOW), "#"), 29 | '*' => print_color(RGB::named(RED), "*"), 30 | _ => print_color(RGB::named(CHOCOLATE), "."), 31 | } 32 | } 33 | print_color(RGB::named(WHITE), "\n"); 34 | } 35 | flush_console(); 36 | } 37 | -------------------------------------------------------------------------------- /bracket-pathfinding/examples/astar_manhattan/main.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | use bracket_color::prelude::*; 3 | use bracket_pathfinding::prelude::*; 4 | use common::*; 5 | 6 | fn main() { 7 | let mut map = Map::new(); 8 | 9 | // Perform the search 10 | let path = a_star_search( 11 | map.point2d_to_index(START_POINT), 12 | map.point2d_to_index(END_POINT), 13 | &map, 14 | ); 15 | if path.success { 16 | for loc in &path.steps { 17 | map.tiles[*loc] = '*'; 18 | } 19 | } 20 | 21 | // Draw the result 22 | for y in 0..MAP_HEIGHT { 23 | let idx = map.point2d_to_index(Point::new(0, y)); 24 | for x in 0..MAP_WIDTH { 25 | match map.tiles[idx + x] { 26 | '#' => print_color(RGB::named(YELLOW), "#"), 27 | '*' => print_color(RGB::named(RED), "*"), 28 | _ => print_color(RGB::named(CHOCOLATE), "."), 29 | } 30 | } 31 | print_color(RGB::named(WHITE), "\n"); 32 | } 33 | flush_console(); 34 | } 35 | -------------------------------------------------------------------------------- /bracket-pathfinding/examples/dijkstra/main.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | use bracket_color::prelude::*; 3 | use bracket_pathfinding::prelude::*; 4 | use common::*; 5 | 6 | fn main() { 7 | let map = Map::new(); 8 | 9 | // Perform the search 10 | let mut search_targets: Vec = Vec::new(); 11 | search_targets.push(map.point2d_to_index(START_POINT)); 12 | search_targets.push(map.point2d_to_index(END_POINT)); 13 | let flow_map = DijkstraMap::new(MAP_WIDTH, MAP_HEIGHT, &search_targets, &map, 1024.0); 14 | 15 | // Draw the result 16 | for y in 0..MAP_HEIGHT { 17 | let base_idx = map.point2d_to_index(Point::new(0, y)); 18 | for x in 0..MAP_WIDTH { 19 | let idx = base_idx + x; 20 | 21 | let tile = map.tiles[idx]; 22 | let color = match tile { 23 | '#' => RGB::named(YELLOW), 24 | _ => { 25 | if flow_map.map[idx] < std::f32::MAX { 26 | RGB::from_u8( 27 | 0, 28 | 255 - { 29 | let n = flow_map.map[idx] * 6.0; 30 | if n > 255.0 { 31 | 255.0 32 | } else { 33 | n 34 | } 35 | } as u8, 36 | 0, 37 | ) 38 | } else { 39 | RGB::named(CHOCOLATE) 40 | } 41 | } 42 | }; 43 | print_color(color, &tile.to_string()); 44 | } 45 | print_color(RGB::named(WHITE), "\n"); 46 | } 47 | flush_console(); 48 | } 49 | -------------------------------------------------------------------------------- /bracket-pathfinding/examples/dijkstra_weighted/main.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | use bracket_color::prelude::*; 3 | use bracket_pathfinding::prelude::*; 4 | use bracket_random::prelude::RandomNumberGenerator; 5 | use common::*; 6 | 7 | fn main() { 8 | let map = Map::new(); 9 | 10 | // Perform the search 11 | let mut search_targets: Vec<(usize, f32)> = Vec::new(); 12 | let mut rng = RandomNumberGenerator::seeded(3); 13 | for _ in 0..10 { 14 | loop { 15 | let n = rng.range(0, map.tiles.len()); 16 | if map.tiles[n] != '#' { 17 | search_targets.push((n, rng.roll_dice(1, 3) as f32)); 18 | break; 19 | } 20 | } 21 | } 22 | 23 | let flow_map = DijkstraMap::new_weighted(MAP_WIDTH, MAP_HEIGHT, &search_targets, &map, 1024.0); 24 | 25 | // Draw the result 26 | for y in 0..MAP_HEIGHT { 27 | let base_idx = map.point2d_to_index(Point::new(0, y)); 28 | for x in 0..MAP_WIDTH { 29 | let idx = base_idx + x; 30 | 31 | let tile = map.tiles[idx]; 32 | let color = match tile { 33 | '#' => RGB::named(YELLOW), 34 | _ => { 35 | if flow_map.map[idx] < std::f32::MAX { 36 | RGB::from_u8( 37 | 0, 38 | 255 - { 39 | let n = flow_map.map[idx] * 12.0; 40 | if n > 255.0 { 41 | 255.0 42 | } else { 43 | n 44 | } 45 | } as u8, 46 | 0, 47 | ) 48 | } else { 49 | RGB::named(CHOCOLATE) 50 | } 51 | } 52 | }; 53 | print_color(color, &tile.to_string()); 54 | } 55 | print_color(RGB::named(WHITE), "\n"); 56 | } 57 | flush_console(); 58 | } 59 | -------------------------------------------------------------------------------- /bracket-pathfinding/examples/fov/main.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | use bracket_color::prelude::*; 3 | use bracket_pathfinding::prelude::*; 4 | use common::*; 5 | 6 | fn main() { 7 | let map = Map::new(); 8 | 9 | // Field of view 10 | let fov = field_of_view_set(START_POINT, 6, &map); 11 | 12 | // Draw the result 13 | for y in 0..MAP_HEIGHT { 14 | for x in 0..MAP_WIDTH { 15 | let pos = Point::new(x, y); 16 | let idx = map.point2d_to_index(pos); 17 | let tile; 18 | let mut color; 19 | 20 | if pos == START_POINT { 21 | color = RGB::named(GREEN); 22 | tile = '@'; 23 | } else { 24 | match map.tiles[idx] { 25 | '#' => { 26 | tile = '#'; 27 | color = RGB::named(YELLOW); 28 | } 29 | _ => { 30 | tile = '.'; 31 | color = RGB::named(CHOCOLATE); 32 | } 33 | } 34 | } 35 | 36 | if !fov.contains(&pos) { 37 | color = color.to_greyscale(); 38 | } 39 | 40 | print_color(color, &tile.to_string()); 41 | } 42 | print_color(RGB::named(WHITE), "\n"); 43 | } 44 | flush_console(); 45 | } 46 | -------------------------------------------------------------------------------- /bracket-pathfinding/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod astar; 2 | mod dijkstra; 3 | mod field_of_view; 4 | 5 | pub mod prelude { 6 | pub use crate::astar::*; 7 | pub use crate::dijkstra::*; 8 | pub use crate::field_of_view::*; 9 | pub use bracket_algorithm_traits::prelude::*; 10 | pub use bracket_geometry::prelude::*; 11 | 12 | /// Since we use `SmallVec`, it's only polite to export it so you don't have to have multiple copies. 13 | pub use smallvec::{smallvec, SmallVec}; 14 | } 15 | -------------------------------------------------------------------------------- /bracket-random/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-random" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "Random number generator (xorshift based), focused on dice rolling. Optionally includes parsing of RPG-style dice strings (e.g. \"3d6+12\"). Part of the bracket-lib family." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["roguelike", "gamedev", "random", "xorshift", "dice"] 12 | categories = ["game-engines", "random"] 13 | license = "MIT" 14 | 15 | [features] 16 | default = [ "parsing" ] 17 | parsing = [ "regex", "lazy_static" ] 18 | serde = [ "serde_crate", "rand_xorshift/serde1" ] 19 | 20 | [dependencies] 21 | rand_xorshift = { version = "0.3.0" } 22 | regex = { version = "1.3.6", optional = true } 23 | lazy_static = { version = "1.4.0", optional = true } 24 | serde_crate = { version = "~1.0.110", features = ["derive"], optional = true, package = "serde" } 25 | rand = { version = "0.8", default-features = false } 26 | 27 | [target.'cfg(not(any(target_arch = "wasm32")))'.dependencies] 28 | getrandom = { version = "0.2.2" } 29 | 30 | [target.wasm32-unknown-unknown.dependencies] 31 | js-sys = "0.3.48" 32 | wasm-bindgen = "0.2" 33 | 34 | [dev-dependencies] 35 | criterion = "~0.4" 36 | serde_json = "~1.0" 37 | 38 | [[bench]] 39 | name = "dice" 40 | harness = false -------------------------------------------------------------------------------- /bracket-random/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-random/benches/dice.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables)] 2 | 3 | // Benchmark field of geometry calculations 4 | 5 | use criterion::{black_box, criterion_group, criterion_main, Criterion}; 6 | 7 | pub fn criterion_benchmark(c: &mut Criterion) { 8 | use bracket_random::prelude::*; 9 | c.bench_function("next_u64", |b| { 10 | let mut rng = RandomNumberGenerator::new(); 11 | b.iter(|| { 12 | let n = rng.next_u64(); 13 | black_box(n); 14 | }) 15 | }); 16 | 17 | c.bench_function("next_f64", |b| { 18 | let mut rng = RandomNumberGenerator::new(); 19 | b.iter(|| { 20 | let n = rng.rand::(); 21 | black_box(n); 22 | }) 23 | }); 24 | 25 | c.bench_function("next_f32", |b| { 26 | let mut rng = RandomNumberGenerator::new(); 27 | b.iter(|| { 28 | let n = rng.rand::(); 29 | black_box(n); 30 | }) 31 | }); 32 | 33 | c.bench_function("roll_3d6", |b| { 34 | let mut rng = RandomNumberGenerator::new(); 35 | b.iter(|| { 36 | let n = rng.roll_dice(3, 6); 37 | black_box(n); 38 | }) 39 | }); 40 | 41 | c.bench_function("roll_str_3d6+12", |b| { 42 | let mut rng = RandomNumberGenerator::new(); 43 | b.iter(|| { 44 | let n = rng.roll_str("3d6+12").unwrap(); 45 | black_box(n); 46 | }) 47 | }); 48 | 49 | let options = ["Cat", "Dog", "Gerbil", "Hamster", "Dragon"]; 50 | c.bench_function("random_slice_entry", |b| { 51 | let mut rng = RandomNumberGenerator::new(); 52 | b.iter(|| { 53 | let n = rng.random_slice_entry(&options); 54 | black_box(n); 55 | }) 56 | }); 57 | } 58 | 59 | criterion_group!(benches, criterion_benchmark); 60 | criterion_main!(benches); 61 | -------------------------------------------------------------------------------- /bracket-random/examples/diceroll.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | let mut total = 0; 6 | println!("Rolling 3d6, 10 times."); 7 | for _ in 0..10 { 8 | let d6roll = rng.roll_dice(3, 6); 9 | total += d6roll; 10 | println!("3d6 Roll: {}", d6roll); 11 | } 12 | println!("Total of rolls: {}", total); 13 | } 14 | -------------------------------------------------------------------------------- /bracket-random/examples/dicestring.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | let mut total = 0; 6 | println!("Rolling 3d6, 10 times."); 7 | for _ in 0..10 { 8 | let d6roll = rng.roll_str("3d6").expect("Parse fail"); 9 | total += d6roll; 10 | println!("3d6 Roll: {}", d6roll); 11 | } 12 | println!("Total of rolls: {}", total); 13 | } 14 | -------------------------------------------------------------------------------- /bracket-random/examples/die_iterator.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | DiceIterator::new(6, &mut rng) 6 | .take(10) 7 | .for_each(|n| println!("Rolled {}", n)); 8 | } 9 | -------------------------------------------------------------------------------- /bracket-random/examples/distribution.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | let mut rolls: Vec = Vec::new(); 6 | for _ in 0..=18 { 7 | rolls.push(0); 8 | } 9 | 10 | const N_ROLLS: i32 = 200000; 11 | 12 | println!("Rolling 3d6, {} times and counting distribution.", N_ROLLS); 13 | for _ in 0..N_ROLLS { 14 | let d6roll = rng.roll_str("3d6").expect("Parse fail"); 15 | rolls[d6roll as usize] += 1; 16 | } 17 | 18 | let max = rolls.iter().max().unwrap(); 19 | let scale = 70.0 / *max as f32; 20 | 21 | for i in 3..=18 { 22 | //println!("{:02} was rolled {} times.", i, rolls[i]); 23 | print!("{:02} : ", i); 24 | for _ in 0..(rolls[i] as f32 * scale) as i32 { 25 | print!("#"); 26 | } 27 | println!(""); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bracket-random/examples/next.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | println!("Generating the next 10 u64 numbers"); 6 | for _ in 0..10 { 7 | println!("Roll: {}", rng.next_u64()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /bracket-random/examples/rand.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | println!("Generating the next 10 f64 numbers"); 6 | for _ in 0..10 { 7 | println!("Roll: {}", rng.rand::()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /bracket-random/examples/range.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let mut rng = RandomNumberGenerator::new(); 5 | println!("Generating the next 10 numbers in the range 100 - 200"); 6 | for _ in 0..10 { 7 | println!("Roll: {}", rng.range(100, 200)); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /bracket-random/examples/slice.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let options = ["Cat", "Dog", "Gerbil", "Hamster", "Dragon"]; 5 | 6 | let mut rng = RandomNumberGenerator::new(); 7 | for _ in 0..10 { 8 | let option = rng.random_slice_entry(&options); 9 | println!("Randomly chose a: {}", option.unwrap()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /bracket-random/examples/slice_index.rs: -------------------------------------------------------------------------------- 1 | use bracket_random::prelude::*; 2 | 3 | fn main() { 4 | let options = ["Cat", "Dog", "Gerbil", "Hamster", "Dragon"]; 5 | 6 | let mut rng = RandomNumberGenerator::new(); 7 | for _ in 0..10 { 8 | let option = rng.random_slice_index(&options).unwrap(); 9 | println!( 10 | "Randomly chose index: {}, which is a {}", 11 | option, options[option] 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /bracket-random/src/iterators.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::RandomNumberGenerator; 2 | use core::iter::Iterator; 3 | use std::convert::TryInto; 4 | 5 | pub struct DiceIterator<'a> { 6 | die_type: i32, 7 | rng: &'a mut RandomNumberGenerator, 8 | } 9 | 10 | impl<'a> DiceIterator<'a> { 11 | pub fn new(die_type: T, rng: &'a mut RandomNumberGenerator) -> Self 12 | where 13 | T: TryInto, 14 | { 15 | let dt = die_type.try_into().ok().unwrap(); 16 | Self { die_type: dt, rng } 17 | } 18 | } 19 | 20 | impl<'a> Iterator for DiceIterator<'a> { 21 | type Item = i32; 22 | 23 | fn next(&mut self) -> Option { 24 | Some(self.rng.roll_dice(1, self.die_type)) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bracket-random/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "parsing")] 2 | #[macro_use] 3 | extern crate lazy_static; 4 | 5 | mod random; 6 | 7 | #[cfg(feature = "parsing")] 8 | mod parsing; 9 | 10 | #[cfg(target_arch = "wasm32")] 11 | mod js_seed; 12 | 13 | mod iterators; 14 | 15 | pub mod prelude { 16 | pub use crate::random::*; 17 | 18 | #[cfg(feature = "parsing")] 19 | pub use crate::parsing::*; 20 | 21 | pub use crate::iterators::*; 22 | } 23 | 24 | pub mod rand { 25 | pub use rand::*; 26 | } 27 | -------------------------------------------------------------------------------- /bracket-rex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bracket-rex" 3 | version = "0.8.7" 4 | edition = "2021" 5 | publish = true 6 | description = "Load/save REX Paint files and utilize them in bracket-terminal projects." 7 | homepage = "https://github.com/thebracket/bracket-lib" 8 | repository = "https://github.com/thebracket/bracket-lib" 9 | readme = "README.md" 10 | keywords = ["roguelike", "gamedev", "terminal", "ascii", "cp437"] 11 | categories = ["game-engines"] 12 | license = "MIT" 13 | 14 | [dependencies] 15 | byteorder = "1.4.2" 16 | flate2 = "1.0.20" 17 | bracket-color = { path = "../bracket-color", version = "~0.8", features = [ "palette" ] } 18 | bracket-embedding = { path = "../bracket-embedding", version = "~0.8" } -------------------------------------------------------------------------------- /bracket-rex/README.md: -------------------------------------------------------------------------------- 1 | # Bracket-Rex 2 | 3 | This crate separates out `bracket-lib`'s [Rex Paint](https://www.gridsagegames.com/rexpaint/) support. It's primarily used inside `bracket-lib`, but can be used separately. 4 | 5 | -------------------------------------------------------------------------------- /bracket-rex/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod rex; 2 | mod xpcolor; 3 | 4 | pub mod prelude { 5 | pub use crate::rex::*; 6 | pub use crate::xpcolor::*; 7 | } 8 | -------------------------------------------------------------------------------- /bracket-terminal/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /bracket-terminal/benches/batching_benchmark.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables)] 2 | 3 | // Benchmark field of geometry calculations 4 | 5 | use criterion::{criterion_group, criterion_main, Criterion}; 6 | 7 | pub fn criterion_benchmark(c: &mut Criterion) { 8 | use bracket_terminal::prelude::*; 9 | c.bench_function("small_batch", |b| { 10 | b.iter(|| { 11 | let mut draw_batch = DrawBatch::new(); 12 | draw_batch.cls(); 13 | draw_batch.print(Point::new(1, 1), "Hello"); 14 | draw_batch.print(Point::new(1, 2), "World"); 15 | draw_batch.submit(0).expect("Batch error"); 16 | clear_command_buffer().expect("Batch error"); 17 | }) 18 | }); 19 | c.bench_function("large_batch", |b| { 20 | b.iter(|| { 21 | let mut draw_batch = DrawBatch::new(); 22 | draw_batch.cls(); 23 | for i in 0..1000 { 24 | draw_batch.print(Point::new(1, 1), "Hello"); 25 | draw_batch.print(Point::new(1, 2), "World"); 26 | } 27 | draw_batch.submit(0).expect("Batch error"); 28 | clear_command_buffer().expect("Batch error"); 29 | }) 30 | }); 31 | c.bench_function("multi_batch", |b| { 32 | b.iter(|| { 33 | let mut draw_batch = DrawBatch::new(); 34 | draw_batch.cls(); 35 | for j in 0..10 { 36 | for i in 0..1000 { 37 | draw_batch.print(Point::new(1, 1), "Hello"); 38 | draw_batch.print(Point::new(1, 2), "World"); 39 | } 40 | draw_batch.submit(j * 1000).expect("Batch error"); 41 | } 42 | clear_command_buffer().expect("Batch error"); 43 | }) 44 | }); 45 | } 46 | 47 | criterion_group!(benches, criterion_benchmark); 48 | criterion_main!(benches); 49 | -------------------------------------------------------------------------------- /bracket-terminal/examples/batch_z_order.rs: -------------------------------------------------------------------------------- 1 | // This example demonstrates using the "with_z" functionality 2 | // inside batched rendering. 3 | ////////////////////////////////////////////////////////////// 4 | 5 | use bracket_terminal::prelude::*; 6 | bracket_terminal::add_wasm_support!(); 7 | 8 | struct State {} 9 | 10 | impl GameState for State { 11 | fn tick(&mut self, ctx: &mut BTerm) { 12 | let mut draw_batch = DrawBatch::new(); 13 | draw_batch.print_color_with_z( 14 | Point::new(10, 10), 15 | "This is at always on top", 16 | ColorPair::new(YELLOW, BLUE), 17 | 1000, 18 | ); 19 | for y in 0..50 { 20 | for x in 0..80 { 21 | draw_batch.set( 22 | Point::new(x, y), 23 | ColorPair::new(DARKGRAY, BLACK), 24 | to_cp437('#'), 25 | ); 26 | } 27 | } 28 | draw_batch.submit(0).expect("Oops"); 29 | render_draw_buffer(ctx).expect("Render error"); 30 | } 31 | } 32 | 33 | fn main() -> BError { 34 | let context = BTermBuilder::simple80x50() 35 | .with_title("Hello Minimal Bracket World") 36 | .build()?; 37 | 38 | let gs: State = State {}; 39 | main_loop(context, gs) 40 | } 41 | -------------------------------------------------------------------------------- /bracket-terminal/examples/benchmark.rs: -------------------------------------------------------------------------------- 1 | // This example helps checking the performances of differents 2 | // backends and also performance regression from one version 3 | // to another. 4 | // The goal is to test a pathological case (every console cell 5 | // updated every frame) using the fastest game state as possible 6 | // to be as close as possible as measuring only rendering time 7 | ////////////////////////////////////////////////////////////// 8 | 9 | use bracket_random::prelude::*; 10 | use bracket_terminal::prelude::*; 11 | bracket_terminal::add_wasm_support!(); 12 | 13 | struct State { 14 | rng: RandomNumberGenerator, 15 | } 16 | 17 | impl State { 18 | pub fn new() -> Self { 19 | Self { 20 | rng: RandomNumberGenerator::new(), 21 | } 22 | } 23 | } 24 | 25 | impl GameState for State { 26 | fn tick(&mut self, ctx: &mut BTerm) { 27 | for y in 0..45 { 28 | for x in 0..80 { 29 | let val = self.rng.rand::(); 30 | let back = RGB::from_u8( 31 | (val & 0xFF) as u8, 32 | ((val >> 8) & 0x5F) as u8, 33 | ((val >> 16) & 0x3F) as u8, 34 | ); 35 | let fore = RGB::from_u8( 36 | ((val >> 16) & 0xFF) as u8, 37 | ((val >> 24) & 0xFF) as u8, 38 | ((val >> 32) & 0xFF) as u8, 39 | ); 40 | let ascii = ((val >> 40) & 0xFF) as u8; 41 | ctx.set(x, y, fore, back, ascii); 42 | } 43 | } 44 | ctx.draw_box( 45 | 30, 46 | 20, 47 | 20, 48 | 5, 49 | RGB::from_u8(255, 255, 255), 50 | RGB::from_u8(0, 0, 0), 51 | ); 52 | ctx.print_centered(22, &format!("{} fps", ctx.fps as u32)); 53 | } 54 | } 55 | 56 | fn main() -> BError { 57 | let context = BTermBuilder::simple(80, 45) 58 | .unwrap() 59 | .with_title("bracket-lib benchmark") 60 | .with_vsync(false) 61 | .with_fps_cap(120.0) 62 | .build()?; 63 | main_loop(context, State::new()) 64 | } 65 | -------------------------------------------------------------------------------- /bracket-terminal/examples/fancy.rs: -------------------------------------------------------------------------------- 1 | bracket_terminal::add_wasm_support!(); 2 | 3 | use bracket_terminal::prelude::*; 4 | 5 | struct State { 6 | x: f32, 7 | } 8 | 9 | impl GameState for State { 10 | fn tick(&mut self, ctx: &mut BTerm) { 11 | let mut draw_batch = DrawBatch::new(); 12 | 13 | draw_batch.target(1); 14 | draw_batch.cls(); 15 | 16 | let simple_x = self.x as i32; 17 | let fancy_x = self.x + 20.0; 18 | 19 | draw_batch.print(Point::new(0, 0), format!("Simple Console")); 20 | draw_batch.print(Point::new(0, 1), format!("X={}", simple_x)); 21 | draw_batch.print(Point::new(20, 0), format!("Fancy Console")); 22 | draw_batch.print(Point::new(20, 1), format!("X={:2}", fancy_x)); 23 | 24 | draw_batch.print(Point::new(simple_x, 3), "@"); 25 | draw_batch.set_fancy( 26 | PointF::new(fancy_x, 4.0), 27 | 1, 28 | Degrees::new(0.0), 29 | PointF::new(1.0, 1.0), 30 | ColorPair::new(WHITE, BLACK), 31 | to_cp437('@'), 32 | ); 33 | 34 | draw_batch.submit(0).expect("Batch error"); 35 | render_draw_buffer(ctx).expect("Render error"); 36 | 37 | self.x += 0.05; 38 | if self.x > 10.0 { 39 | self.x = 0.0; 40 | } 41 | } 42 | } 43 | 44 | fn main() -> BError { 45 | let context = BTermBuilder::simple80x50() 46 | .with_fancy_console(80, 50, "terminal8x8.png") 47 | .with_title("Bracket Terminal - Fancy Consoles") 48 | .with_fps_cap(30.0) 49 | .build()?; 50 | 51 | let gs = State { x: 0.0 }; 52 | 53 | main_loop(context, gs) 54 | } 55 | -------------------------------------------------------------------------------- /bracket-terminal/examples/flexible.rs: -------------------------------------------------------------------------------- 1 | bracket_terminal::add_wasm_support!(); 2 | 3 | use bracket_terminal::prelude::*; 4 | 5 | struct State { 6 | x: f32, 7 | spin: Radians, 8 | } 9 | 10 | impl GameState for State { 11 | fn tick(&mut self, ctx: &mut BTerm) { 12 | let mut draw_batch = DrawBatch::new(); 13 | 14 | // Show frame rate 15 | draw_batch.target(1); 16 | draw_batch.cls(); 17 | 18 | draw_batch.draw_double_box( 19 | Rect::with_size(39, 0, 20, 3), 20 | ColorPair::new(RGB::named(WHITE), RGB::named(BLACK)), 21 | ); 22 | draw_batch.print_color( 23 | Point::new(40, 1), 24 | &format!("FPS: {}", ctx.fps), 25 | ColorPair::new(RGB::named(YELLOW), RGB::named(BLACK)), 26 | ); 27 | draw_batch.print_color( 28 | Point::new(40, 2), 29 | &format!("Frame Time: {} ms", ctx.frame_time_ms), 30 | ColorPair::new(RGB::named(CYAN), RGB::named(BLACK)), 31 | ); 32 | 33 | let y = 20.0 + (f32::sin(self.x / 2.0) * 5.0); 34 | let scale = f32::cos(self.x / 3.0) + 1.1; 35 | draw_batch.set_fancy( 36 | PointF { x: self.x, y }, 37 | 0, 38 | self.spin, 39 | PointF { x: scale, y: scale }, 40 | ColorPair::new(RGB::named(YELLOW), RGB::named(BLACK)), 41 | to_cp437('@'), 42 | ); 43 | 44 | // Submission 45 | draw_batch.submit(0).expect("Batch error"); 46 | render_draw_buffer(ctx).expect("Render error"); 47 | 48 | // Moving 49 | self.x += 0.1; 50 | if self.x > 80.0 { 51 | self.x = 0.0; 52 | } 53 | self.spin.0 += 0.2; 54 | } 55 | } 56 | 57 | fn main() -> BError { 58 | let mut context = BTermBuilder::simple80x50() 59 | .with_fancy_console(80, 50, "terminal8x8.png") 60 | .with_title("Bracket Terminal - Fancy Consoles") 61 | .with_vsync(false) 62 | .build()?; 63 | 64 | context.with_post_scanlines(true); 65 | 66 | let gs = State { 67 | x: 0.0, 68 | spin: Radians::new(0.0), 69 | }; 70 | 71 | main_loop(context, gs) 72 | } 73 | -------------------------------------------------------------------------------- /bracket-terminal/examples/hello_minimal.rs: -------------------------------------------------------------------------------- 1 | // This is the canonical "Hello World" example for Bracket Terminal. 2 | // It is crammed into one file, and kept as short as possible 3 | ////////////////////////////////////////////////////////////// 4 | 5 | // We're using BTerm (the main context) and GameState (a trait defining what our callback 6 | // looks like), so we need to use that, too.` 7 | use bracket_terminal::prelude::*; 8 | 9 | // We're utilizing functionality from BTerm, so we need to tell it to use the crate. 10 | bracket_terminal::add_wasm_support!(); 11 | 12 | // This is the structure that will store our game state, typically a state machine pointing to 13 | // other structures. This demo is realy simple, so we'll just put the minimum to make it work 14 | // in here. 15 | struct State {} 16 | 17 | // We have to implement the "trait" GameState for our state object. This gives it a callback 18 | // point for the main loop. 19 | impl GameState for State { 20 | // This is called every time the screen refreshes (a "tick") by BTerm's main loop. Since GUIs 21 | // require that you process events every turn - rather than just sequentially like a good old text 22 | // console, you have to run your game as something of a state machine. This will be fleshed out in 23 | // later tutorials. For now, it just shows you the frame rate and says "Hello World". 24 | fn tick(&mut self, ctx: &mut BTerm) { 25 | ctx.print(1, 1, "Hello Bracket World"); 26 | } 27 | } 28 | 29 | // Every program needs a main() function! 30 | fn main() -> BError { 31 | // BTerm's Builder interface offers a number of helpers to get you up and running quickly. 32 | // Here, we are using the `simple80x50()` helper, which builds an 80-wide by 50-tall console, 33 | // with the baked-in 8x8 terminal font. 34 | let context = BTermBuilder::simple80x50() 35 | .with_title("Hello Minimal Bracket World") 36 | .build()?; 37 | 38 | // Now we create an empty state object. 39 | let gs: State = State {}; 40 | 41 | // Call into BTerm to run the main loop. This handles rendering, and calls back into State's tick 42 | // function every cycle. The box is needed to work around lifetime handling. 43 | main_loop(context, gs) 44 | } 45 | -------------------------------------------------------------------------------- /bracket-terminal/examples/input_harness.rs: -------------------------------------------------------------------------------- 1 | use bracket_terminal::prelude::*; 2 | 3 | bracket_terminal::add_wasm_support!(); 4 | 5 | struct State {} 6 | 7 | impl GameState for State { 8 | fn tick(&mut self, ctx: &mut BTerm) { 9 | ctx.cls(); 10 | let mut input = INPUT.lock(); 11 | let mouse_pixels = input.mouse_pixel_pos(); 12 | ctx.print( 13 | 1, 14 | 1, 15 | &format!( 16 | "Mouse pixel position: {}, {}", 17 | mouse_pixels.0, mouse_pixels.1 18 | ), 19 | ); 20 | let mouse_tile = input.mouse_tile(0); 21 | ctx.print( 22 | 1, 23 | 2, 24 | &format!("Mouse tile position: {}, {}", mouse_tile.x, mouse_tile.y), 25 | ); 26 | ctx.print(1, 3, &format!("FPS: {}", ctx.fps)); 27 | ctx.print(1, 4, &format!("Scale factor: {}", input.get_scale_factor())); 28 | 29 | for (i, btn) in input.mouse_button_pressed_set().iter().enumerate() { 30 | ctx.print(1, 5 + i as i32, &format!("Mouse Button {} is pressed", btn)); 31 | } 32 | 33 | for (i, key) in input.scan_code_pressed_set().iter().enumerate() { 34 | ctx.print(50, 5 + i as i32, &format!("Key code: {}", key)); 35 | } 36 | 37 | for (i, key) in input.key_pressed_set().iter().enumerate() { 38 | ctx.print(50, 25 + i as i32, &format!("Key code: {:?}", key)); 39 | } 40 | 41 | input.for_each_message(|event| { 42 | bracket_terminal::console::log(&format!("{:#?}", event)); 43 | if event == BEvent::CloseRequested { 44 | ctx.quitting = true; 45 | } 46 | }); 47 | } 48 | } 49 | 50 | fn main() -> BError { 51 | let context = BTermBuilder::simple80x50() 52 | .with_title("Input Harness - Check Your STDOUT") 53 | .with_vsync(false) 54 | .with_advanced_input(true) 55 | .build()?; 56 | 57 | let gs: State = State {}; 58 | 59 | main_loop(context, gs) 60 | } 61 | -------------------------------------------------------------------------------- /bracket-terminal/examples/keyboard.rs: -------------------------------------------------------------------------------- 1 | bracket_terminal::add_wasm_support!(); 2 | 3 | use bracket_terminal::prelude::*; 4 | 5 | struct State { 6 | display_lines: Vec, 7 | } 8 | 9 | impl GameState for State { 10 | fn tick(&mut self, ctx: &mut BTerm) { 11 | ctx.cls(); 12 | 13 | for (y, line) in self.display_lines.iter().enumerate() { 14 | ctx.print(0, y as i32, &line); 15 | } 16 | 17 | match ctx.key { 18 | None => {} 19 | Some(key) => { 20 | self.display_lines.push(format!( 21 | "{} pressed, shift: {}, control: {}, alt: {}", 22 | key as i32, ctx.shift, ctx.control, ctx.alt 23 | )); 24 | while self.display_lines.len() > 49 { 25 | self.display_lines.remove(0); 26 | } 27 | } 28 | } 29 | } 30 | } 31 | 32 | fn main() -> BError { 33 | let context = BTermBuilder::simple80x50() 34 | .with_title("RLTK Example 16 - Keyboard Input Visualizer") 35 | .build()?; 36 | 37 | let gs: State = State { 38 | display_lines: vec!["Press keys and modifiers to see code combinations.".to_string()], 39 | }; 40 | 41 | main_loop(context, gs) 42 | } 43 | -------------------------------------------------------------------------------- /bracket-terminal/examples/no_cls.rs: -------------------------------------------------------------------------------- 1 | bracket_terminal::add_wasm_support!(); 2 | use bracket_random::prelude::*; 3 | use bracket_terminal::prelude::*; 4 | 5 | struct State { 6 | rng: RandomNumberGenerator, 7 | } 8 | 9 | impl GameState for State { 10 | fn tick(&mut self, ctx: &mut BTerm) { 11 | if let Some(key) = ctx.key { 12 | if let VirtualKeyCode::C = key { 13 | ctx.cls() 14 | } 15 | } 16 | 17 | let x = self.rng.range(0, 80); 18 | let y = self.rng.range(0, 50); 19 | let chr = self.rng.range(0, 255) as u8; 20 | 21 | let fg = RGB::from_u8( 22 | self.rng.range::(0, 254), 23 | self.rng.range::(0, 254), 24 | self.rng.range::(0, 254), 25 | ); 26 | let bg = RGB::from_u8( 27 | self.rng.range::(0, 254), 28 | self.rng.range::(0, 254), 29 | self.rng.range::(0, 254), 30 | ); 31 | 32 | ctx.set(x, y, fg, bg, chr); 33 | } 34 | } 35 | 36 | fn main() -> BError { 37 | let context = BTermBuilder::simple80x50() 38 | .with_title("Hello Minimal Bracket World") 39 | .build()?; 40 | 41 | let gs: State = State { 42 | rng: RandomNumberGenerator::new(), 43 | }; 44 | 45 | main_loop(context, gs) 46 | } 47 | -------------------------------------------------------------------------------- /bracket-terminal/examples/return_error.rs: -------------------------------------------------------------------------------- 1 | // This example demonstrates error returning. 2 | ////////////////////////////////////////////////////////////// 3 | 4 | use bracket_terminal::prelude::*; 5 | 6 | bracket_terminal::add_wasm_support!(); 7 | 8 | struct State {} 9 | 10 | impl GameState for State { 11 | fn tick(&mut self, ctx: &mut BTerm) { 12 | ctx.print(1, 1, "Hello Bracket World"); 13 | } 14 | } 15 | 16 | fn build_context() -> BResult { 17 | BTermBuilder::simple80x50() 18 | .with_title("Hello Minimal Bracket World") 19 | .build() 20 | } 21 | 22 | fn main() -> BError { 23 | let context = build_context()?; 24 | let gs: State = State {}; 25 | 26 | main_loop(context, gs) 27 | } 28 | -------------------------------------------------------------------------------- /bracket-terminal/examples/rex.rs: -------------------------------------------------------------------------------- 1 | bracket_terminal::add_wasm_support!(); 2 | use bracket_terminal::prelude::*; 3 | 4 | struct State { 5 | nyan: XpFile, 6 | } 7 | 8 | impl GameState for State { 9 | fn tick(&mut self, ctx: &mut BTerm) { 10 | ctx.cls(); 11 | ctx.print_color( 12 | 0, 13 | 0, 14 | RGB::named(YELLOW), 15 | RGB::named(BLACK), 16 | "Hello Nyan Cat!", 17 | ); 18 | ctx.print_color( 19 | 0, 20 | 1, 21 | RGB::named(GREEN), 22 | RGB::named(BLACK), 23 | "Loaded from REX Paint (https://www.gridsagegames.com/rexpaint/)", 24 | ); 25 | ctx.render_xp_sprite(&self.nyan, 2, 4); 26 | } 27 | } 28 | 29 | // This is a helper macro to embed a file in your binary. 30 | bracket_terminal::embedded_resource!(NYAN_CAT, "../resources/nyan.xp"); 31 | 32 | fn main() -> BError { 33 | // This helper macro links the above embedding, allowing it to be accessed as a resource from various parts of the program. 34 | bracket_terminal::link_resource!(NYAN_CAT, "../resources/nyan.xp"); 35 | let xp = XpFile::from_resource("../resources/nyan.xp")?; 36 | 37 | let context = BTermBuilder::simple80x50() 38 | .with_title("Bracket Terminal Example - REX Paint, Hello Nyan Cat") 39 | .build()?; 40 | let gs: State = State { nyan: xp }; 41 | main_loop(context, gs) 42 | } 43 | -------------------------------------------------------------------------------- /bracket-terminal/examples/sparse_cls.rs: -------------------------------------------------------------------------------- 1 | use bracket_terminal::prelude::{main_loop, BTerm, BTermBuilder, GameState, VirtualKeyCode, RGBA}; 2 | 3 | const USE_WORKAROUND: bool = false; 4 | fn main() { 5 | let context = BTermBuilder::simple80x50() 6 | .with_font("vga8x16.png", 8, 16) 7 | .with_tile_dimensions(16, 16) 8 | .with_sparse_console(80, 25, "vga8x16.png") 9 | .build() 10 | .unwrap(); 11 | 12 | main_loop( 13 | context, 14 | Demo { 15 | show_outer_console: false, 16 | }, 17 | ) 18 | .unwrap(); 19 | } 20 | 21 | struct Demo { 22 | show_outer_console: bool, 23 | } 24 | 25 | impl GameState for Demo { 26 | fn tick(&mut self, ctx: &mut BTerm) { 27 | ctx.set_active_console(0); 28 | ctx.cls(); 29 | ctx.print_centered(0, "Main console - overlapping text"); 30 | 31 | if self.show_outer_console { 32 | ctx.set_active_console(1); 33 | ctx.cls(); 34 | ctx.print_centered(0, "Sparse console"); 35 | } 36 | 37 | match ctx.key { 38 | Some(VirtualKeyCode::Space) => { 39 | if self.show_outer_console { 40 | ctx.set_active_console(1); 41 | ctx.cls(); 42 | 43 | if USE_WORKAROUND { 44 | let transparent = RGBA::from_f32(0., 0., 0., 0.); 45 | ctx.set(40, 0, transparent, transparent, ' ' as u16); 46 | } 47 | } 48 | self.show_outer_console = !self.show_outer_console 49 | } 50 | _ => (), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /bracket-terminal/examples/textblock.rs: -------------------------------------------------------------------------------- 1 | bracket_terminal::add_wasm_support!(); 2 | use bracket_terminal::prelude::*; 3 | 4 | struct State {} 5 | 6 | impl GameState for State { 7 | fn tick(&mut self, ctx: &mut BTerm) { 8 | let mut draw_batch = DrawBatch::new(); 9 | draw_batch.cls(); 10 | let mut block = TextBlock::new(0, 0, 80, 25); 11 | 12 | let mut buf = TextBuilder::empty(); 13 | buf.ln() 14 | .fg(RGB::named(YELLOW)) 15 | .bg(RGB::named(BLUE)) 16 | .centered("Hello World") 17 | .fg(RGB::named(WHITE)) 18 | .bg(RGB::named(BLACK)) 19 | .ln() 20 | .ln() 21 | .line_wrap("The quick brown fox jumped over the lazy dog, and just kept on running in an attempt to exceed the console width.") 22 | .ln() 23 | .ln() 24 | .line_wrap("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") 25 | .ln().ln() 26 | .fg(RGB::named(CYAN)) 27 | .append("FPS: ") 28 | .fg(RGB::named(MAGENTA)) 29 | .append(&format!("{}", ctx.fps)) 30 | .reset(); 31 | 32 | block.print(&buf).expect("Text was too long"); 33 | 34 | block.render_to_draw_batch(&mut draw_batch); 35 | draw_batch.submit(0).expect("Batch error"); 36 | render_draw_buffer(ctx).expect("Render error"); 37 | } 38 | } 39 | 40 | fn main() -> BError { 41 | let gs: State = State {}; 42 | 43 | let context = BTermBuilder::simple80x50() 44 | .with_title("Bracket Terminal Example - Text Blocks") 45 | .build()?; 46 | main_loop(context, gs) 47 | } 48 | -------------------------------------------------------------------------------- /bracket-terminal/examples/unicode.rs: -------------------------------------------------------------------------------- 1 | use bracket_terminal::prelude::*; 2 | 3 | bracket_terminal::add_wasm_support!(); 4 | 5 | struct State {} 6 | 7 | impl GameState for State { 8 | fn tick(&mut self, ctx: &mut BTerm) { 9 | ctx.set_translation_mode(0, CharacterTranslationMode::Unicode); 10 | ctx.print(1, 1, "Hello Bracket World"); 11 | 12 | ctx.print(20, 8, "こんにちは!"); 13 | ctx.print(20, 10, "真棒!"); 14 | ctx.print(20, 12, "классно"); 15 | ctx.print(20, 14, "Φοβερός!"); 16 | ctx.print(20, 16, "Ça, c'est énorme!"); 17 | } 18 | } 19 | 20 | bracket_terminal::embedded_resource!(TILE_FONT3, "../resources/unicode_16x16.png"); 21 | 22 | fn main() -> BError { 23 | bracket_terminal::link_resource!(TILE_FONT3, "resources/unicode_16x16.png"); 24 | 25 | let context = BTermBuilder::new() 26 | .with_dimensions(80, 50) 27 | .with_tile_dimensions(16, 16) 28 | .with_title("Hello Minimal Bracket World") 29 | .with_font("unicode_16x16.png", 16, 16) 30 | .with_simple_console(80, 50, "unicode_16x16.png") 31 | .build()?; 32 | 33 | let gs: State = State {}; 34 | 35 | main_loop(context, gs) 36 | } 37 | -------------------------------------------------------------------------------- /bracket-terminal/resources/cheepicus8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/cheepicus8x8.png -------------------------------------------------------------------------------- /bracket-terminal/resources/example_tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/example_tiles.png -------------------------------------------------------------------------------- /bracket-terminal/resources/example_tiles.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/example_tiles.xcf -------------------------------------------------------------------------------- /bracket-terminal/resources/mkv_curses_6x6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/mkv_curses_6x6.png -------------------------------------------------------------------------------- /bracket-terminal/resources/mltest.xp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/mltest.xp -------------------------------------------------------------------------------- /bracket-terminal/resources/nyan.xp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/nyan.xp -------------------------------------------------------------------------------- /bracket-terminal/resources/sprite_dood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/sprite_dood.png -------------------------------------------------------------------------------- /bracket-terminal/resources/terminal8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/terminal8x8.png -------------------------------------------------------------------------------- /bracket-terminal/resources/terminal_10x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/terminal_10x16.png -------------------------------------------------------------------------------- /bracket-terminal/resources/terminal_colored_8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/terminal_colored_8x8.png -------------------------------------------------------------------------------- /bracket-terminal/resources/unicode_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/unicode_16x16.png -------------------------------------------------------------------------------- /bracket-terminal/resources/vga8x16-color-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/vga8x16-color-alpha.png -------------------------------------------------------------------------------- /bracket-terminal/resources/vga8x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/bracket-terminal/resources/vga8x16.png -------------------------------------------------------------------------------- /bracket-terminal/src/consoles/mod.rs: -------------------------------------------------------------------------------- 1 | mod command_buffer; 2 | pub mod console; 3 | mod flexible_console; 4 | mod simple_console; 5 | mod sparse_console; 6 | mod sprite_console; 7 | mod sprites; 8 | mod text; 9 | mod virtual_console; 10 | 11 | pub use command_buffer::*; 12 | pub use console::*; 13 | pub use flexible_console::*; 14 | pub use simple_console::*; 15 | pub use sparse_console::*; 16 | pub use sprite_console::*; 17 | pub use sprites::*; 18 | pub use text::*; 19 | pub use virtual_console::*; 20 | -------------------------------------------------------------------------------- /bracket-terminal/src/consoles/sprites/mod.rs: -------------------------------------------------------------------------------- 1 | mod sprite; 2 | mod spritesheet; 3 | 4 | pub use sprite::*; 5 | pub use spritesheet::*; 6 | -------------------------------------------------------------------------------- /bracket-terminal/src/consoles/sprites/sprite.rs: -------------------------------------------------------------------------------- 1 | use bracket_geometry::prelude::Rect; 2 | 3 | #[derive(Copy, Clone, Debug)] 4 | pub struct Sprite { 5 | pub sheet_location: Rect, 6 | } 7 | 8 | impl Sprite { 9 | pub fn new(sheet_location: Rect) -> Self { 10 | Sprite { sheet_location } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /bracket-terminal/src/consoles/sprites/spritesheet.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::{Font, Sprite}; 2 | use bracket_geometry::prelude::Rect; 3 | use std::rc::Rc; 4 | 5 | #[derive(Clone)] 6 | pub struct SpriteSheet { 7 | pub filename: String, 8 | pub sprites: Vec, 9 | pub backing: Option>>, 10 | } 11 | 12 | impl SpriteSheet { 13 | pub fn new(filename: S) -> Self { 14 | Self { 15 | filename: filename.to_string(), 16 | sprites: Vec::new(), 17 | backing: None, 18 | } 19 | } 20 | 21 | pub fn add_sprite(mut self, location_pixel: Rect) -> Self { 22 | self.sprites.push(Sprite::new(location_pixel)); 23 | self 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /bracket-terminal/src/consoles/text/format_string.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | 3 | #[derive(Debug)] 4 | pub struct ColoredTextSpans { 5 | pub length: usize, 6 | pub spans: Vec<(RGBA, String)>, 7 | } 8 | 9 | fn find_color(col_name: &str) -> RGBA { 10 | if let Some(palette) = palette_color(&col_name) { 11 | palette 12 | } else { 13 | RGBA::from_u8(255, 255, 255, 255) 14 | } 15 | } 16 | 17 | impl ColoredTextSpans { 18 | pub fn new(text: &str) -> Self { 19 | let mut result = Self { 20 | length: 0, 21 | spans: Vec::new(), 22 | }; 23 | let mut color_stack = Vec::new(); 24 | 25 | for color_span in text.to_owned().split("#[") { 26 | if color_span.is_empty() { 27 | continue; 28 | } 29 | let mut col_text = color_span.splitn(2, ']'); 30 | let col_name = col_text.next().unwrap(); 31 | if let Some(text_span) = col_text.next() { 32 | if !col_name.is_empty() { 33 | color_stack.push(find_color(col_name)); 34 | } else { 35 | color_stack.pop(); 36 | } 37 | result.spans.push(( 38 | *color_stack 39 | .last() 40 | .unwrap_or(&RGBA::from_u8(255, 255, 255, 255)), 41 | text_span.to_string(), 42 | )); 43 | result.length += text_span.chars().count(); 44 | } 45 | } 46 | 47 | result 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /bracket-terminal/src/consoles/text/mod.rs: -------------------------------------------------------------------------------- 1 | mod codepage437; 2 | mod format_string; 3 | mod gui_helpers; 4 | mod multi_tile_sprite; 5 | mod textblock; 6 | 7 | pub use codepage437::*; 8 | pub(crate) use format_string::*; 9 | pub use gui_helpers::*; 10 | pub use multi_tile_sprite::*; 11 | pub use textblock::*; 12 | -------------------------------------------------------------------------------- /bracket-terminal/src/gamestate.rs: -------------------------------------------------------------------------------- 1 | pub use crate::prelude::BTerm; 2 | 3 | /// Implement this trait on your state struct, so the engine knows what to call on each tick. 4 | pub trait GameState: 'static { 5 | fn tick(&mut self, ctx: &mut BTerm); 6 | } 7 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/crossterm_be/font.rs: -------------------------------------------------------------------------------- 1 | use crate::BResult; 2 | 3 | #[derive(Clone)] 4 | pub struct Font { 5 | pub tile_size: (u32, u32), 6 | } 7 | 8 | impl Font { 9 | pub fn load( 10 | _filename: S, 11 | _tile_size: (u32, u32), 12 | _explicit_background: Option, 13 | ) -> Font { 14 | Font { tile_size: (0, 0) } 15 | } 16 | 17 | pub fn setup_gl_texture(&mut self, _gl: &crate::hal::BTermPlatform) -> BResult<()> { 18 | Ok(()) 19 | } 20 | 21 | pub fn bind_texture(&self, _gl: &crate::hal::BTermPlatform) {} 22 | } 23 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/crossterm_be/init.rs: -------------------------------------------------------------------------------- 1 | use super::{InitHints, BACKEND}; 2 | use crate::prelude::BTerm; 3 | use crate::BResult; 4 | use crossterm::{ 5 | execute, 6 | terminal::{size, SetSize}, 7 | }; 8 | use std::io::{stdout, Write}; 9 | 10 | pub fn init_raw( 11 | width_pixels: u32, 12 | height_pixels: u32, 13 | _window_title: S, 14 | platform_hints: InitHints, 15 | ) -> BResult { 16 | let old_size = size().expect("Unable to get console size"); 17 | execute!( 18 | stdout(), 19 | SetSize(width_pixels as u16 / 8, height_pixels as u16 / 8), 20 | ) 21 | .expect("Console command fail"); 22 | 23 | execute!(stdout(), crossterm::cursor::Hide).expect("Command fail"); 24 | execute!(stdout(), crossterm::event::EnableMouseCapture).expect("Command fail"); 25 | 26 | let mut be = BACKEND.lock(); 27 | be.old_width = old_size.0; 28 | be.old_height = old_size.1; 29 | be.frame_sleep_time = crate::hal::convert_fps_to_wait(platform_hints.frame_sleep_time); 30 | 31 | let bterm = BTerm { 32 | width_pixels, 33 | height_pixels, 34 | original_width_pixels: width_pixels, 35 | original_height_pixels: height_pixels, 36 | fps: 0.0, 37 | frame_time_ms: 0.0, 38 | active_console: 0, 39 | key: None, 40 | mouse_pos: (0, 0), 41 | left_click: false, 42 | shift: false, 43 | control: false, 44 | alt: false, 45 | web_button: None, 46 | quitting: false, 47 | post_scanlines: false, 48 | post_screenburn: false, 49 | screen_burn_color: bracket_color::prelude::RGB::from_f32(0.0, 1.0, 1.0), 50 | mouse_visible: true, 51 | }; 52 | Ok(bterm) 53 | } 54 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/crossterm_be/mod.rs: -------------------------------------------------------------------------------- 1 | use parking_lot::Mutex; 2 | 3 | pub use winit::event::VirtualKeyCode; 4 | 5 | mod main_loop; 6 | pub use main_loop::*; 7 | 8 | mod font; 9 | pub use font::*; 10 | mod init; 11 | mod shader; 12 | pub use init::*; 13 | pub use shader::*; 14 | mod scancode_helper; 15 | pub use scancode_helper::{keycode_to_key, virtual_key_code_to_scan}; 16 | 17 | pub struct InitHints { 18 | pub vsync: bool, 19 | pub fullscreen: bool, 20 | pub frame_sleep_time: Option, 21 | pub fitscreen: bool, 22 | } 23 | 24 | impl InitHints { 25 | pub fn new() -> Self { 26 | Self { 27 | vsync: true, 28 | fullscreen: false, 29 | frame_sleep_time: None, 30 | fitscreen: false, 31 | } 32 | } 33 | } 34 | 35 | pub struct PlatformGL { 36 | old_width: u16, 37 | old_height: u16, 38 | pub frame_sleep_time: Option, 39 | } 40 | 41 | lazy_static! { 42 | pub static ref BACKEND: Mutex = Mutex::new(PlatformGL { 43 | old_width: 0, 44 | old_height: 0, 45 | frame_sleep_time: None, 46 | }); 47 | } 48 | 49 | unsafe impl Send for PlatformGL {} 50 | unsafe impl Sync for PlatformGL {} 51 | 52 | pub fn log(s: &str) { 53 | println!("{}", s); 54 | } 55 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/crossterm_be/shader.rs: -------------------------------------------------------------------------------- 1 | pub struct Shader {} 2 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/curses/color.rs: -------------------------------------------------------------------------------- 1 | use bracket_color::prelude::*; 2 | use parking_lot::Mutex; 3 | use std::collections::HashMap; 4 | 5 | pub struct CursesColor { 6 | rf: f32, 7 | gf: f32, 8 | bf: f32, 9 | } 10 | 11 | impl CursesColor { 12 | pub fn new(red: i16, green: i16, blue: i16) -> CursesColor { 13 | CursesColor { 14 | rf: red as f32 / 1000.0, 15 | gf: green as f32 / 1000.0, 16 | bf: blue as f32 / 1000.0, 17 | } 18 | } 19 | } 20 | 21 | lazy_static! { 22 | static ref COLOR_CACHE: Mutex> = Mutex::new(HashMap::new()); 23 | } 24 | 25 | pub fn find_nearest_color(color: RGBA, map: &[CursesColor]) -> i16 { 26 | let key = (color.r * 255.0) as u32 27 | + (((color.g * 255.0) as u32) << 8u32) 28 | + (((color.b * 255.0) as u32) << 16u32) 29 | + (((color.a * 255.0) as u32) << 24u32); 30 | { 31 | let cache = COLOR_CACHE.lock(); 32 | if let Some(col) = cache.get(&key) { 33 | return *col; 34 | } 35 | } 36 | 37 | let mut result = -1; 38 | let mut best_diff = std::f32::MAX; 39 | 40 | for (i, cc) in map.iter().enumerate() { 41 | let diff_r = f32::abs(color.r - cc.rf); 42 | let diff_g = f32::abs(color.g - cc.gf); 43 | let diff_b = f32::abs(color.b - cc.bf); 44 | let total_diff = diff_r + diff_g + diff_b; 45 | 46 | if total_diff < best_diff { 47 | result = i as i16; 48 | best_diff = total_diff; 49 | } 50 | } 51 | 52 | COLOR_CACHE.lock().insert(key, result); 53 | 54 | result 55 | } 56 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/curses/font.rs: -------------------------------------------------------------------------------- 1 | use crate::BResult; 2 | 3 | #[derive(Clone)] 4 | pub struct Font { 5 | pub tile_size: (u32, u32), 6 | } 7 | 8 | impl Font { 9 | pub fn load( 10 | _filename: S, 11 | _tile_size: (u32, u32), 12 | _explicit_background: Option, 13 | ) -> Font { 14 | Font { tile_size: (1, 1) } 15 | } 16 | 17 | pub fn setup_gl_texture(&mut self, _gl: &crate::hal::BTermPlatform) -> BResult<()> { 18 | Ok(()) 19 | } 20 | 21 | pub fn bind_texture(&self, _gl: &crate::hal::BTermPlatform) {} 22 | } 23 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/curses/init.rs: -------------------------------------------------------------------------------- 1 | pub use super::*; 2 | use pancurses::{initscr, noecho, resize_term}; 3 | 4 | pub fn init_raw( 5 | width_pixels: u32, 6 | height_pixels: u32, 7 | _window_title: S, 8 | platform_hints: InitHints, 9 | ) -> BResult { 10 | let window = initscr(); 11 | resize_term(height_pixels as i32 / 8, width_pixels as i32 / 8); 12 | noecho(); 13 | window.nodelay(true); 14 | window.keypad(true); 15 | pancurses::start_color(); 16 | pancurses::mousemask( 17 | pancurses::ALL_MOUSE_EVENTS | pancurses::REPORT_MOUSE_POSITION, 18 | None, 19 | ); 20 | 21 | // Setup basic color mapping 22 | let mut color_map = Vec::new(); 23 | for i in 0..16 { 24 | let color = pancurses::color_content(i); 25 | color_map.push(CursesColor::new(color.0, color.1, color.2)); 26 | } 27 | 28 | let mut counter = 0; 29 | for bg in 0..16i16 { 30 | for fg in 0..16i16 { 31 | pancurses::init_pair(counter as i16, fg, bg); 32 | counter += 1; 33 | } 34 | } 35 | 36 | let mut be = BACKEND.lock(); 37 | be.window = Some(window); 38 | be.color_map = color_map; 39 | be.frame_sleep_time = crate::hal::convert_fps_to_wait(platform_hints.frame_sleep_time); 40 | 41 | let bterm = BTerm { 42 | width_pixels, 43 | height_pixels, 44 | original_width_pixels: width_pixels, 45 | original_height_pixels: height_pixels, 46 | fps: 0.0, 47 | frame_time_ms: 0.0, 48 | active_console: 0, 49 | key: None, 50 | mouse_pos: (0, 0), 51 | left_click: false, 52 | shift: false, 53 | control: false, 54 | alt: false, 55 | web_button: None, 56 | quitting: false, 57 | post_scanlines: false, 58 | post_screenburn: false, 59 | screen_burn_color: bracket_color::prelude::RGB::from_f32(0.0, 1.0, 1.0), 60 | mouse_visible: true, 61 | }; 62 | Ok(bterm) 63 | } 64 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/curses/mod.rs: -------------------------------------------------------------------------------- 1 | // Dummy platform to let it compile and do nothing. Only useful if you don't want a graphical backend. 2 | use crate::prelude::BTerm; 3 | use crate::BResult; 4 | use parking_lot::Mutex; 5 | 6 | pub use winit::event::VirtualKeyCode; 7 | 8 | use pancurses::Window; 9 | 10 | mod main_loop; 11 | pub use main_loop::main_loop; 12 | 13 | mod font; 14 | pub use font::*; 15 | mod init; 16 | mod shader; 17 | pub use init::init_raw; 18 | pub use shader::*; 19 | mod color; 20 | pub use color::*; 21 | mod scancode_helper; 22 | pub(crate) use scancode_helper::char_to_keycode; 23 | pub use scancode_helper::virtual_key_code_to_scan; 24 | 25 | pub struct InitHints { 26 | pub vsync: bool, 27 | pub fullscreen: bool, 28 | pub frame_sleep_time: Option, 29 | } 30 | 31 | impl InitHints { 32 | pub fn new() -> Self { 33 | Self { 34 | vsync: true, 35 | fullscreen: false, 36 | frame_sleep_time: None, 37 | } 38 | } 39 | } 40 | 41 | pub struct PlatformGL { 42 | window: Option, 43 | color_map: Vec, 44 | pub frame_sleep_time: Option, 45 | } 46 | 47 | lazy_static! { 48 | pub static ref BACKEND: Mutex = Mutex::new(PlatformGL { 49 | window: None, 50 | color_map: Vec::new(), 51 | frame_sleep_time: None 52 | }); 53 | } 54 | 55 | unsafe impl Send for PlatformGL {} 56 | unsafe impl Sync for PlatformGL {} 57 | 58 | pub fn log(s: &str) { 59 | println!("{}", s); 60 | } 61 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/curses/shader.rs: -------------------------------------------------------------------------------- 1 | pub struct Shader {} 2 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/gl_common/backing/mod.rs: -------------------------------------------------------------------------------- 1 | mod simple_console_backing; 2 | pub(crate) use simple_console_backing::*; 3 | mod sparse_console_backing; 4 | pub(crate) use sparse_console_backing::*; 5 | mod fancy_console_backing; 6 | pub(crate) use fancy_console_backing::*; 7 | mod sprite_console_backing; 8 | pub(crate) use sprite_console_backing::*; 9 | mod shared_main_loop; 10 | pub(crate) use shared_main_loop::*; 11 | 12 | pub(crate) enum ConsoleBacking { 13 | Simple { backing: SimpleConsoleBackend }, 14 | Sparse { backing: SparseConsoleBackend }, 15 | Fancy { backing: FancyConsoleBackend }, 16 | Sprite { backing: SpriteConsoleBackend }, 17 | } 18 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/gl_common/glerror.rs: -------------------------------------------------------------------------------- 1 | use glow::HasContext; 2 | 3 | #[macro_export] 4 | macro_rules! gl_error_wrap { 5 | ($gl:expr, $call:expr) => { 6 | $call; 7 | #[cfg(debug_assertions)] 8 | crate::hal::gl_error($gl); 9 | }; 10 | } 11 | 12 | pub fn gl_error(gl: &glow::Context) { 13 | let error; 14 | unsafe { 15 | error = gl.get_error(); 16 | } 17 | if error != glow::NO_ERROR { 18 | match error { 19 | glow::INVALID_ENUM => panic!("[GL] Error: INVALID_ENUM"), 20 | glow::INVALID_VALUE => panic!("[GL] Error: INVALID_ENUM"), 21 | glow::INVALID_OPERATION => panic!("[GL] Error: INVALID_ENUM"), 22 | glow::STACK_OVERFLOW => panic!("[GL] Error: INVALID_ENUM"), 23 | glow::STACK_UNDERFLOW => panic!("[GL] Error: INVALID_ENUM"), 24 | glow::OUT_OF_MEMORY => panic!("[GL] Error: INVALID_ENUM"), 25 | glow::INVALID_FRAMEBUFFER_OPERATION => panic!("[GL] Error: INVALID_ENUM"), 26 | _ => panic!("[GL] Error: {}", error), 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/gl_common/mod.rs: -------------------------------------------------------------------------------- 1 | mod framebuffer; 2 | 3 | pub use framebuffer::*; 4 | mod shader; 5 | pub use shader::*; 6 | mod font; 7 | pub use font::*; 8 | mod quadrender; 9 | pub use quadrender::*; 10 | mod vertex_array_helper; 11 | pub(crate) use vertex_array_helper::*; 12 | mod backing; 13 | pub(crate) use backing::*; 14 | mod glerror; 15 | pub(crate) use glerror::*; 16 | 17 | #[cfg(not(target_arch = "wasm32"))] 18 | mod types_native; 19 | 20 | #[cfg(not(target_arch = "wasm32"))] 21 | pub use types_native::*; 22 | 23 | #[cfg(target_arch = "wasm32")] 24 | mod types_wasm; 25 | 26 | #[cfg(target_arch = "wasm32")] 27 | pub use types_wasm::*; 28 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/gl_common/types_native.rs: -------------------------------------------------------------------------------- 1 | use glow::{NativeTexture, NativeBuffer, NativeVertexArray, NativeProgram, NativeFramebuffer}; 2 | 3 | pub type TextureId = NativeTexture; 4 | pub type BufferId = NativeBuffer; 5 | pub type VertexArrayId = NativeVertexArray; 6 | pub type ShaderId = NativeProgram; 7 | pub type FramebufferId = NativeFramebuffer; 8 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/gl_common/types_wasm.rs: -------------------------------------------------------------------------------- 1 | pub type TextureId = glow::WebTextureKey; 2 | pub type BufferId = glow::WebBufferKey; 3 | pub type VertexArrayId = glow::WebVertexArrayKey; 4 | pub type ShaderId = glow::WebProgramKey; 5 | pub type FramebufferId = glow::WebFramebufferKey; 6 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/wasm/events/external.rs: -------------------------------------------------------------------------------- 1 | /// This module handles binding external web elements, for example movement buttons. 2 | /// Based heavily on Zireael07's pull request, but modified to be significantly more generic. 3 | use wasm_bindgen::prelude::*; 4 | use wasm_bindgen::JsCast; 5 | 6 | pub static mut GLOBAL_BUTTON: Option = None; 7 | 8 | #[allow(dead_code)] 9 | pub fn register_html_button(element_id: S) { 10 | let button = web_sys::window() 11 | .unwrap() 12 | .document() 13 | .unwrap() 14 | .get_element_by_id(&element_id.to_string()) 15 | .unwrap() 16 | .dyn_into::() 17 | .unwrap(); 18 | 19 | let html_callback = Closure::wrap(Box::new(|e: web_sys::Event| { 20 | on_external_element_click(e.clone()); 21 | }) as Box); 22 | 23 | button.set_onclick(Some(html_callback.as_ref().unchecked_ref())); 24 | html_callback.forget(); 25 | } 26 | 27 | #[allow(dead_code)] 28 | pub fn on_external_element_click(event: web_sys::Event) { 29 | //set_command(Command::MoveLeft); 30 | unsafe { 31 | GLOBAL_BUTTON = Some( 32 | event 33 | .target() 34 | .unwrap() 35 | .dyn_into::() 36 | .unwrap() 37 | .id(), 38 | ); 39 | //crate::console::log(format!("{}", GLOBAL_BUTTON.clone().unwrap())); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/wasm/events/mod.rs: -------------------------------------------------------------------------------- 1 | mod keyboard; 2 | pub use keyboard::*; 3 | mod mouse; 4 | pub use mouse::*; 5 | mod external; 6 | pub use external::*; 7 | use wasm_bindgen::prelude::*; 8 | use wasm_bindgen::JsCast; 9 | 10 | pub fn bind_wasm_events(canvas: &web_sys::HtmlCanvasElement) { 11 | // Handle keyboard input 12 | let key_callback = Closure::wrap(Box::new(|e: web_sys::KeyboardEvent| { 13 | on_key(e.clone()); 14 | }) as Box); 15 | 16 | let document = web_sys::window().unwrap(); 17 | document.set_onkeydown(Some(key_callback.as_ref().unchecked_ref())); 18 | key_callback.forget(); 19 | 20 | let keyup_callback = Closure::wrap(Box::new(|e: web_sys::KeyboardEvent| { 21 | on_key_up(e.clone()); 22 | }) as Box); 23 | document.set_onkeyup(Some(keyup_callback.as_ref().unchecked_ref())); 24 | keyup_callback.forget(); 25 | 26 | // Handle mouse moving 27 | let mousemove_callback = Closure::wrap(Box::new(|e: web_sys::MouseEvent| { 28 | on_mouse_move(e.clone()); 29 | }) as Box); 30 | 31 | canvas.set_onmousemove(Some(mousemove_callback.as_ref().unchecked_ref())); 32 | mousemove_callback.forget(); 33 | 34 | // Handle mouse clicking 35 | let mouseclick_callback = Closure::wrap(Box::new(|e: web_sys::MouseEvent| { 36 | on_mouse_down(e.clone()); 37 | }) as Box); 38 | 39 | canvas.set_onmousedown(Some(mouseclick_callback.as_ref().unchecked_ref())); 40 | mouseclick_callback.forget(); 41 | 42 | // Handle mouse release 43 | let mouseunclick_callback = Closure::wrap(Box::new(|e: web_sys::MouseEvent| { 44 | on_mouse_up(e.clone()); 45 | }) as Box); 46 | 47 | canvas.set_onmouseup(Some(mouseunclick_callback.as_ref().unchecked_ref())); 48 | mouseunclick_callback.forget(); 49 | } 50 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/wasm/events/mouse.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::INPUT; 2 | 3 | /// Global variable to store mouse position changes 4 | pub static mut GLOBAL_MOUSE_POS: (i32, i32) = (0, 0); 5 | 6 | /// Event called via the web interface to indicate mouse movement 7 | pub fn on_mouse_move(mouse: web_sys::MouseEvent) { 8 | let off_x = mouse.offset_x(); 9 | let off_y = mouse.offset_y(); 10 | unsafe { 11 | if off_x != GLOBAL_MOUSE_POS.0 || off_y != GLOBAL_MOUSE_POS.1 { 12 | INPUT 13 | .lock() 14 | .on_mouse_pixel_position(off_x as f64, off_y as f64); 15 | GLOBAL_MOUSE_POS = (off_x, off_y); 16 | } 17 | } 18 | } 19 | 20 | /// Global variable to indicate mouse clicking 21 | pub static mut GLOBAL_LEFT_CLICK: bool = false; 22 | 23 | /// Event called via the web interface to indicate mouse clicking 24 | pub fn on_mouse_down(_mouse: web_sys::MouseEvent) { 25 | //super::super::log(&format!("Mouse click {}", mouse.buttons())); 26 | INPUT.lock().on_mouse_button_down(0); 27 | unsafe { 28 | GLOBAL_LEFT_CLICK = true; 29 | } 30 | } 31 | 32 | /// Event called via the web interface to indicate mouse clicking 33 | pub fn on_mouse_up(_mouse: web_sys::MouseEvent) { 34 | //super::super::log(&format!("Mouse unclick {}", mouse.button())); 35 | INPUT.lock().on_mouse_button_up(0); 36 | unsafe { 37 | GLOBAL_LEFT_CLICK = false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/wasm/mod.rs: -------------------------------------------------------------------------------- 1 | pub use winit::event::VirtualKeyCode; 2 | mod init; 3 | pub mod shader_strings; 4 | pub use init::*; 5 | mod events; 6 | pub use events::*; 7 | mod mainloop; 8 | use crate::hal::scaler::{default_gutter_size, ScreenScaler}; 9 | use crate::hal::ConsoleBacking; 10 | pub use mainloop::*; 11 | use parking_lot::Mutex; 12 | use std::any::Any; 13 | 14 | pub type GlCallback = fn(&mut dyn Any, &glow::Context); 15 | 16 | pub struct InitHints { 17 | pub vsync: bool, 18 | pub fullscreen: bool, 19 | pub frame_sleep_time: Option, 20 | pub desired_gutter: u32, 21 | pub fitscreen: bool, 22 | } 23 | 24 | impl InitHints { 25 | pub fn new() -> Self { 26 | Self { 27 | vsync: true, 28 | fullscreen: false, 29 | frame_sleep_time: None, 30 | desired_gutter: 0, 31 | fitscreen: false, 32 | } 33 | } 34 | } 35 | 36 | pub struct PlatformGL { 37 | pub gl: Option, 38 | pub quad_vao: Option, 39 | pub backing_buffer: Option, 40 | pub gl_callback: Option, 41 | pub screen_scaler: ScreenScaler, 42 | } 43 | 44 | lazy_static! { 45 | pub static ref BACKEND: Mutex = Mutex::new(PlatformGL { 46 | gl: None, 47 | quad_vao: None, 48 | gl_callback: None, 49 | backing_buffer: None, 50 | screen_scaler: ScreenScaler::default(), 51 | }); 52 | } 53 | 54 | unsafe impl Send for PlatformGL {} 55 | unsafe impl Sync for PlatformGL {} 56 | 57 | lazy_static! { 58 | pub(crate) static ref CONSOLE_BACKING: Mutex> = Mutex::new(Vec::new()); 59 | } 60 | 61 | use wasm_bindgen::prelude::*; 62 | 63 | #[wasm_bindgen] 64 | extern "C" { 65 | #[wasm_bindgen(js_namespace = console)] 66 | pub fn log(s: &str); 67 | } 68 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/backend.rs: -------------------------------------------------------------------------------- 1 | //! Defines the BACKEND static used by wgpu. 2 | 3 | use crate::hal::{scaler::ScreenScaler, ConsoleBacking, PlatformGL}; 4 | use lazy_static::*; 5 | use parking_lot::Mutex; 6 | 7 | lazy_static! { 8 | pub static ref BACKEND: Mutex = Mutex::new(PlatformGL { 9 | context_wrapper: None, 10 | wgpu: None, 11 | resize_scaling: false, 12 | resize_request: None, 13 | request_screenshot: None, 14 | frame_sleep_time: None, 15 | screen_scaler: ScreenScaler::default() 16 | }); 17 | } 18 | 19 | lazy_static! { 20 | pub(crate) static ref CONSOLE_BACKING: Mutex> = Mutex::new(Vec::new()); 21 | } 22 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/backing/index_array_helper.rs: -------------------------------------------------------------------------------- 1 | //! Helper for generating and maintaining WGPU index buffers. 2 | 3 | use crate::hal::WgpuLink; 4 | use wgpu::util::DeviceExt; 5 | 6 | /// Provides a wgpu index buffer for indexed draw operations. 7 | pub struct IndexBuffer { 8 | /// The actual buffer data. 9 | pub data: Vec, 10 | /// Usage list. Generally wgpu::BufferUsages::INDEX 11 | pub usage: wgpu::BufferUsages, 12 | /// The actual WGPU buffer to which the data is mapped. 13 | pub buffer: Option, 14 | } 15 | 16 | impl IndexBuffer { 17 | /// Create a new index buffer with a given vector capacity. 18 | /// Note that capacity is not the same as zeroing it - it just 19 | /// reserves vector space. 20 | pub fn new(capacity: usize) -> Self { 21 | Self { 22 | data: vec![0; capacity], 23 | usage: wgpu::BufferUsages::INDEX, 24 | buffer: None, 25 | } 26 | } 27 | 28 | /// Calls WGPU's "create_buffer_init" path to copy the index buffer 29 | /// from local memory to GPU memory. 30 | pub fn build(&mut self, wgpu: &WgpuLink) { 31 | if let Some(buf) = &mut self.buffer { 32 | std::mem::drop(buf); 33 | } 34 | self.buffer = Some( 35 | wgpu.device 36 | .create_buffer_init(&wgpu::util::BufferInitDescriptor { 37 | label: None, 38 | contents: bytemuck::cast_slice(&self.data), 39 | usage: self.usage, 40 | }), 41 | ); 42 | } 43 | 44 | /// Returns the length of the index buffer 45 | pub fn len(&self) -> u32 { 46 | self.data.len() as u32 47 | } 48 | 49 | /// Maps the index buffer into a slice, suitable for render submission. 50 | pub fn slice(&self) -> wgpu::BufferSlice { 51 | self.buffer.as_ref().unwrap().slice(..) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/backing/mod.rs: -------------------------------------------------------------------------------- 1 | //! Provides helper-code to map between console representations and wgpu. 2 | 3 | mod simple_console_backing; 4 | pub(crate) use simple_console_backing::*; 5 | mod sparse_console_backing; 6 | pub(crate) use sparse_console_backing::*; 7 | mod fancy_console_backing; 8 | pub(crate) use fancy_console_backing::*; 9 | mod sprite_console_backing; 10 | pub(crate) use sprite_console_backing::*; 11 | pub(crate) mod index_array_helper; 12 | pub(crate) mod vertex_array_helper; 13 | 14 | pub(crate) enum ConsoleBacking { 15 | Simple { backing: SimpleConsoleBackend }, 16 | Sparse { backing: SparseConsoleBackend }, 17 | Fancy { backing: FancyConsoleBackend }, 18 | Sprite { backing: SpriteConsoleBackend }, 19 | } 20 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/framebuffer.rs: -------------------------------------------------------------------------------- 1 | //! Provides a wgpu implementation of a backing buffer. 2 | 3 | use wgpu::{Device, Sampler, Texture, TextureFormat, TextureView}; 4 | 5 | pub struct Framebuffer { 6 | pub texture: Texture, 7 | view: TextureView, 8 | sampler: Sampler, 9 | } 10 | 11 | impl Framebuffer { 12 | pub fn new(device: &Device, format: TextureFormat, width: u32, height: u32) -> Self { 13 | let size = wgpu::Extent3d { 14 | width, 15 | height, 16 | depth_or_array_layers: 1, 17 | }; 18 | let texture = device.create_texture(&wgpu::TextureDescriptor { 19 | label: None, 20 | size, 21 | mip_level_count: 1, 22 | sample_count: 1, 23 | dimension: wgpu::TextureDimension::D2, 24 | format, 25 | usage: wgpu::TextureUsages::TEXTURE_BINDING 26 | | wgpu::TextureUsages::RENDER_ATTACHMENT 27 | | wgpu::TextureUsages::COPY_SRC, 28 | }); 29 | let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); 30 | let sampler = device.create_sampler(&wgpu::SamplerDescriptor { 31 | address_mode_u: wgpu::AddressMode::Repeat, 32 | address_mode_v: wgpu::AddressMode::Repeat, 33 | address_mode_w: wgpu::AddressMode::Repeat, 34 | mag_filter: wgpu::FilterMode::Linear, 35 | min_filter: wgpu::FilterMode::Linear, 36 | mipmap_filter: wgpu::FilterMode::Linear, 37 | lod_min_clamp: -100.0, 38 | lod_max_clamp: 100.0, 39 | compare: None, 40 | label: None, 41 | anisotropy_clamp: None, 42 | ..Default::default() 43 | }); 44 | 45 | Self { 46 | view, 47 | sampler, 48 | texture, 49 | } 50 | } 51 | 52 | pub fn view(&self) -> &TextureView { 53 | &self.view 54 | } 55 | 56 | pub fn sampler(&self) -> &Sampler { 57 | &self.sampler 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/mod.rs: -------------------------------------------------------------------------------- 1 | //! Provides wgpu support back-end. 2 | 3 | mod platform; 4 | pub use platform::*; 5 | mod init; 6 | pub use init::*; 7 | mod font; 8 | pub use font::*; 9 | mod shader; 10 | pub use shader::*; 11 | mod backend; 12 | pub use backend::*; 13 | mod mainloop; 14 | pub use mainloop::*; 15 | pub use winit::event::VirtualKeyCode; 16 | mod backing; 17 | pub(crate) use backing::*; 18 | mod framebuffer; 19 | pub(crate) use framebuffer::*; 20 | mod quadrender; 21 | 22 | pub fn log(s: &str) { 23 | println!("{}", s); 24 | } 25 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/platform.rs: -------------------------------------------------------------------------------- 1 | //! WGPU Platform definition 2 | 3 | use super::Framebuffer; 4 | use crate::hal::scaler::{default_gutter_size, ScreenScaler}; 5 | use wgpu::{Adapter, Device, Instance, Queue, Surface, SurfaceConfiguration}; 6 | use winit::{event_loop::EventLoop, window::Window}; 7 | 8 | /// Defines the WGPU platform 9 | pub struct PlatformGL { 10 | /// Wrapper for the winit context 11 | pub context_wrapper: Option, 12 | /// Contains the WGPU back-end (device, etc.) 13 | pub wgpu: Option, 14 | 15 | /// Target delay per frame 16 | pub frame_sleep_time: Option, 17 | /// Should the back-end resize windows by character (true) or just scale them (false)? 18 | pub resize_scaling: bool, 19 | /// Is there a request to resize the console? 20 | pub resize_request: Option<(u32, u32)>, 21 | /// Are we requesting a screenshot? 22 | pub request_screenshot: Option, 23 | /// Screen scaling system 24 | pub screen_scaler: ScreenScaler, 25 | } 26 | 27 | pub struct WgpuLink { 28 | pub instance: Instance, 29 | pub surface: Surface, 30 | pub adapter: Adapter, 31 | pub device: Device, 32 | pub queue: Queue, 33 | pub config: SurfaceConfiguration, 34 | pub backing_buffer: Framebuffer, 35 | } 36 | 37 | unsafe impl Send for PlatformGL {} 38 | unsafe impl Sync for PlatformGL {} 39 | 40 | pub struct WrappedContext { 41 | pub el: EventLoop<()>, 42 | pub window: Window, 43 | } 44 | 45 | pub struct InitHints { 46 | pub vsync: bool, 47 | pub fullscreen: bool, 48 | pub frame_sleep_time: Option, 49 | pub resize_scaling: bool, 50 | pub desired_gutter: u32, 51 | pub fitscreen: bool, 52 | } 53 | 54 | impl InitHints { 55 | pub fn new() -> Self { 56 | Self { 57 | vsync: true, 58 | fullscreen: false, 59 | frame_sleep_time: None, 60 | resize_scaling: false, 61 | desired_gutter: default_gutter_size(), 62 | fitscreen: false, 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/shader.rs: -------------------------------------------------------------------------------- 1 | //! Helper to load a shader from WGSL 2 | use wgpu::ShaderModule; 3 | 4 | pub struct Shader(pub ShaderModule); 5 | 6 | impl Shader { 7 | pub fn new(device: &wgpu::Device, source: &str) -> Self { 8 | let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { 9 | label: None, 10 | source: wgpu::ShaderSource::Wgsl(source.into()), 11 | }); 12 | 13 | Shader(shader) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/shader_source/console_no_bg.wgsl: -------------------------------------------------------------------------------- 1 | // Vertex shader 2 | 3 | struct VertexInput { 4 | @location(0) position: vec3, 5 | @location(1) fg: vec4, 6 | @location(2) bg: vec4, 7 | @location(3) tex_coords: vec2, 8 | }; 9 | 10 | struct VertexOutput{ 11 | @builtin(position) clip_position: vec4, 12 | @location(0) fg: vec4, 13 | @location(1) bg: vec4, 14 | @location(2) tex_coords: vec2, 15 | }; 16 | 17 | @vertex 18 | fn vs_main( 19 | model: VertexInput, 20 | ) -> VertexOutput { 21 | var out: VertexOutput; 22 | out.fg = model.fg; 23 | out.bg = model.bg; 24 | out.tex_coords = model.tex_coords; 25 | out.clip_position = vec4(model.position, 1.0); 26 | return out; 27 | } 28 | 29 | // Fragment shader 30 | 31 | @group(0) 32 | @binding(0) 33 | var t_font: texture_2d; 34 | @group(0) 35 | @binding(1) 36 | var s_font: sampler; 37 | 38 | @fragment 39 | fn fs_main(in: VertexOutput) -> @location(0) vec4 { 40 | let original : vec4 = textureSample(t_font, s_font, in.tex_coords); 41 | if (original.r < 0.01 && original.g < 0.01 && original.b < 0.01) { 42 | discard; 43 | } 44 | if ((original.r > 0.1 || original.g > 0.1 || original.b > 0.1) || original.a > 0.1) { 45 | return original * in.fg; 46 | } else { 47 | return in.bg; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/shader_source/console_with_bg.wgsl: -------------------------------------------------------------------------------- 1 | // Vertex shader 2 | 3 | struct VertexInput { 4 | @location(0) position: vec3, 5 | @location(1) fg: vec4, 6 | @location(2) bg: vec4, 7 | @location(3) tex_coords: vec2, 8 | }; 9 | 10 | struct VertexOutput{ 11 | @builtin(position) clip_position: vec4, 12 | @location(0) fg: vec4, 13 | @location(1) bg: vec4, 14 | @location(2) tex_coords: vec2, 15 | }; 16 | 17 | @vertex 18 | fn vs_main( 19 | model: VertexInput, 20 | ) -> VertexOutput { 21 | var out: VertexOutput; 22 | out.fg = model.fg; 23 | out.bg = model.bg; 24 | out.tex_coords = model.tex_coords; 25 | out.clip_position = vec4(model.position, 1.0); 26 | return out; 27 | } 28 | 29 | // Fragment shader 30 | 31 | @group(0) 32 | @binding(0) 33 | var t_font: texture_2d; 34 | @group(0) 35 | @binding(1) 36 | var s_font: sampler; 37 | 38 | @fragment 39 | fn fs_main(in: VertexOutput) -> @location(0) vec4 { 40 | let original : vec4 = textureSample(t_font, s_font, in.tex_coords); 41 | if ((original.r > 0.1 || original.g > 0.1 || original.b > 0.1) && original.a > 0.1) { 42 | return original * in.fg; 43 | } else { 44 | return in.bg; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/shader_source/fancy.wgsl: -------------------------------------------------------------------------------- 1 | // Vertex shader 2 | 3 | struct VertexInput { 4 | @location(0) position: vec3, 5 | @location(1) fg: vec4, 6 | @location(2) bg: vec4, 7 | @location(3) tex_coords: vec2, 8 | @location(4) rotate: vec3, 9 | @location(5) scale: vec2, 10 | }; 11 | 12 | struct VertexOutput{ 13 | @builtin(position) clip_position: vec4, 14 | @location(0) fg: vec4, 15 | @location(1) bg: vec4, 16 | @location(2) tex_coords: vec2, 17 | }; 18 | 19 | fn r2d(a:f32) -> mat2x2 { 20 | let c : f32 = cos(a); 21 | let s : f32 = sin(a); 22 | return mat2x2( 23 | vec2(c, s), 24 | vec2(-s, c) 25 | ); 26 | } 27 | 28 | @vertex 29 | fn vs_main( 30 | model: VertexInput, 31 | ) -> VertexOutput { 32 | let rot : f32 = model.rotate.x; 33 | let center_pos : vec2 = model.rotate.yz; 34 | var base_pos : vec2 = model.position.xy - center_pos; 35 | base_pos = base_pos * r2d(rot); 36 | base_pos = base_pos * model.scale; 37 | base_pos = base_pos + center_pos; 38 | 39 | var out: VertexOutput; 40 | out.clip_position = vec4(base_pos, 0.0, 1.0); 41 | out.fg = model.fg; 42 | out.bg = model.bg; 43 | out.tex_coords = vec2(model.tex_coords.x, model.tex_coords.y); 44 | 45 | return out; 46 | } 47 | 48 | // Fragment shader 49 | 50 | @group(0) 51 | @binding(0) 52 | var t_font: texture_2d; 53 | @group(0) 54 | @binding(1) 55 | var s_font: sampler; 56 | 57 | @fragment 58 | fn fs_main(in: VertexOutput) -> @location(0) vec4 { 59 | let original : vec4 = textureSample(t_font, s_font, in.tex_coords); 60 | if ((original.r > 0.1 || original.g > 0.1 || original.b > 0.1) && original.a > 0.1) { 61 | return original * in.fg; 62 | } else { 63 | return in.bg; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /bracket-terminal/src/hal/webgpu/shader_source/sprites.wgsl: -------------------------------------------------------------------------------- 1 | // Vertex shader 2 | 3 | struct VertexInput { 4 | @location(0) relative_pos: vec2, 5 | @location(1) transform: vec2, 6 | @location(2) fg: vec4, 7 | @location(3) tex_coords: vec2, 8 | @location(4) scale: vec2, 9 | }; 10 | 11 | struct VertexOutput{ 12 | @builtin(position) clip_position: vec4, 13 | @location(0) fg: vec4, 14 | @location(1) tex_coords: vec2, 15 | }; 16 | 17 | @vertex 18 | fn vs_main( 19 | model: VertexInput, 20 | ) -> VertexOutput { 21 | var out: VertexOutput; 22 | 23 | let base_pos : vec2 = model.relative_pos; 24 | let scaled : vec2 = base_pos * model.scale; 25 | let translated : vec2 = scaled + model.transform.xy; 26 | 27 | out.clip_position = vec4(translated, 1.0, 1.0); 28 | out.fg = model.fg; 29 | out.tex_coords = model.tex_coords; 30 | 31 | return out; 32 | } 33 | 34 | // Fragment shader 35 | 36 | @group(0) 37 | @binding(0) 38 | var t_font: texture_2d; 39 | @group(0) 40 | @binding(1) 41 | var s_font: sampler; 42 | 43 | @fragment 44 | fn fs_main(in: VertexOutput) -> @location(0) vec4 { 45 | var out: VertexOutput; 46 | let original : vec4 = textureSample(t_font, s_font, in.tex_coords); 47 | let fg = original * in.fg; 48 | return fg; 49 | } 50 | -------------------------------------------------------------------------------- /bracket-terminal/src/input/event_queue.rs: -------------------------------------------------------------------------------- 1 | pub use crate::prelude::VirtualKeyCode; 2 | pub use bracket_geometry::prelude::Point; 3 | 4 | /// Available device events 5 | #[derive(Clone, Debug, PartialEq)] 6 | pub enum BEvent { 7 | /// The window was resized 8 | Resized { 9 | new_size: Point, 10 | dpi_scale_factor: f32, 11 | }, 12 | 13 | /// The window was moved 14 | Moved { new_position: Point }, 15 | 16 | /// The window has requested that it be closed 17 | CloseRequested, 18 | 19 | /// A character was input 20 | Character { c: char }, 21 | 22 | /// The window gained or lost focus 23 | Focused { focused: bool }, 24 | 25 | /// The mouse cursor entered the window 26 | CursorEntered, 27 | 28 | /// The mouse cursor left the window 29 | CursorLeft, 30 | 31 | /// The mouse cursor moved 32 | CursorMoved { position: Point }, 33 | 34 | /// A mouse button was pressed or released 35 | MouseClick { button: usize, pressed: bool }, 36 | 37 | /// Mouse button is down 38 | MouseButtonDown { button: usize }, 39 | 40 | /// Mouse button is up 41 | MouseButtonUp { button: usize }, 42 | 43 | /// A key on the keyboard was pressed or released. 44 | KeyboardInput { 45 | key: VirtualKeyCode, 46 | scan_code: u32, 47 | pressed: bool, 48 | }, 49 | 50 | /// The window's scale factor was changed. You generally don't need to do anything for this, unless you are working with 51 | /// pixel coordinates. 52 | ScaleFactorChanged { 53 | new_size: Point, 54 | dpi_scale_factor: f32, 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /bracket-terminal/src/input/mod.rs: -------------------------------------------------------------------------------- 1 | mod input_handler; 2 | pub use input_handler::*; 3 | mod event_queue; 4 | pub use event_queue::*; 5 | use parking_lot::Mutex; 6 | 7 | lazy_static! { 8 | pub static ref INPUT: Mutex = Mutex::new(Input::new()); 9 | } 10 | -------------------------------------------------------------------------------- /bracket-terminal/src/rex.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::{Console, DrawBatch, FontCharType}; 2 | use bracket_color::prelude::{ColorPair, RGBA}; 3 | use bracket_geometry::prelude::Point; 4 | pub use bracket_rex::prelude::{XpCell, XpColor, XpFile, XpLayer}; 5 | 6 | /// Applies an XpFile to a given console, with 0,0 offset by offset_x and offset-y. 7 | pub fn xp_to_console( 8 | xp: &XpFile, 9 | mut console: impl AsMut, 10 | offset_x: i32, 11 | offset_y: i32, 12 | ) { 13 | for layer in &xp.layers { 14 | for y in 0..layer.height { 15 | for x in 0..layer.width { 16 | let cell = layer.get(x, y).unwrap(); 17 | if !cell.bg.is_transparent() { 18 | console.as_mut().set( 19 | x as i32 + offset_x, 20 | y as i32 + offset_y, 21 | cell.fg.into(), 22 | cell.bg.into(), 23 | cell.ch as FontCharType, 24 | ); 25 | } 26 | } 27 | } 28 | } 29 | } 30 | 31 | /// Applies an XpFile to a given draw batch, with 0,0 offset by offset_x and offset-y. 32 | pub fn xp_to_draw_batch(xp: &XpFile, draw_batch: &mut DrawBatch, offset_x: i32, offset_y: i32) { 33 | for layer in &xp.layers { 34 | for y in 0..layer.height { 35 | for x in 0..layer.width { 36 | let cell = layer.get(x, y).unwrap(); 37 | if !cell.bg.is_transparent() { 38 | draw_batch.set( 39 | Point::new(x as i32 + offset_x, y as i32 + offset_y), 40 | ColorPair::new(RGBA::from(cell.fg), RGBA::from(cell.bg)), 41 | cell.ch as FontCharType, 42 | ); 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /bracket-terminal/wasm_help/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /bracket-terminal/webglbuild.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cargo build --all --target wasm32-unknown-unknown --release --features=opengl 3 | 4 | REM Build the actual WASM files and helpers 5 | CALL :StageExample alpha, alpha 6 | CALL :StageExample astar_mouse, astar_mouse 7 | CALL :StageExample benchmark, benchmark 8 | CALL :StageExample colorfont, colorfont 9 | CALL :StageExample dwarfmap, dwarfmap 10 | CALL :StageExample flexible, flexible 11 | CALL :StageExample fontswitch, fontswitch 12 | CALL :StageExample hello_minimal, hello_minimal 13 | CALL :StageExample hello_terminal, hello_terminal 14 | CALL :StageExample input_harness, input_harness 15 | CALL :StageExample keyboard, keyboard 16 | CALL :StageExample native_gl, native_gl 17 | CALL :StageExample no_cls, no_cls 18 | CALL :StageExample postprocess, postprocess 19 | CALL :StageExample rex, rex 20 | CALL :StageExample sparse, sparse 21 | CALL :StageExample sprites, sprites 22 | CALL :StageExample textblock, textblock 23 | CALL :StageExample textsprites, textsprites 24 | CALL :StageExample tiles, tiles 25 | CALL :StageExample unicode, unicode 26 | CALL :StageExample virtual_console, virtual_console 27 | CALL :StageExample walking, walking 28 | 29 | 30 | REM Submit to server 31 | cd wasm_help\staging 32 | pscp -r * herbert@vps.bracketproductions.com:/var/www/bfnightly/wasmtest 33 | cd ..\.. 34 | 35 | REM Finish 36 | EXIT /B 0 37 | 38 | REM Usage: StageExample EXAMPLE 39 | :StageExample 40 | echo Building example %~1 41 | cargo build --example %~1 --target wasm32-unknown-unknown --release --features=opengl 42 | echo wasm-gc ..\target\wasm32-unknown-unknown\release\examples\%~1.wasm 43 | mkdir .\wasm_help\staging\%~2 44 | wasm-bindgen ..\target\wasm32-unknown-unknown\release\examples\%~1.wasm --out-dir .\wasm_help\staging\%~2 --no-modules --no-typescript 45 | copy .\wasm_help\index.html .\wasm_help\staging\%~2 46 | move .\wasm_help\staging\%~2\%~1_bg.wasm .\wasm_help\staging\%~2\myblob_bg.wasm 47 | move .\wasm_help\staging\%~2\%~1.js .\wasm_help\staging\%~2\myblob.js 48 | EXIT /B 0 49 | -------------------------------------------------------------------------------- /manual/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Herbert Wolverson"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "Bracket-Lib Usage Guide" 7 | -------------------------------------------------------------------------------- /manual/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [What is Bracket-lib](./what_is_it.md) 4 | - [Quick Start](./linking.md) 5 | - [Hello Terminal](./hello_terminal.md) 6 | - [Using Individual Components](./individual_parts.md) 7 | - [Using the Examples](./examples.md) 8 | - [Color Examples](./ex_color.md) 9 | - [Geometry Examples](./ex_geometry.md) 10 | - [Noise Examples](./ex_noise.md) 11 | - [Pathfinding Examples](./ex_path.md) 12 | - [Random Examples](./ex_rng.md) 13 | - [Terminal Examples](./ex_bterm.md) 14 | - [Working with Consoles](./consoles.md) 15 | - [Printing to Consoles](./consoles_print.md) 16 | - [Fancy Consoles](./fancy.md) 17 | 18 | -------------------------------------------------------------------------------- /manual/src/ex_bt_alpha.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_alpha.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_astar_mouse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_astar_mouse.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_colorfont.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_colorfont.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_dwarfmap.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_dwarfmap.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_flex.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_flex.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_fontswitch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_fontswitch.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_hello_terminal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_hello_terminal.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_input_harness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_input_harness.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_native_gl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_native_gl.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_post.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_post.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_rex.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_rex.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_sparse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_sparse.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_sprites.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_sprites.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_textblock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_textblock.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_textsprites.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_textsprites.gif -------------------------------------------------------------------------------- /manual/src/ex_bt_tiles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_tiles.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_unicode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_unicode.jpg -------------------------------------------------------------------------------- /manual/src/ex_bt_virtual_console.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_bt_virtual_console.jpg -------------------------------------------------------------------------------- /manual/src/ex_col_colors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_col_colors.jpg -------------------------------------------------------------------------------- /manual/src/ex_col_lerp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_col_lerp.jpg -------------------------------------------------------------------------------- /manual/src/ex_col_lerpit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_col_lerpit.jpg -------------------------------------------------------------------------------- /manual/src/ex_col_lerpit_hsv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_col_lerpit_hsv.jpg -------------------------------------------------------------------------------- /manual/src/ex_col_named.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_col_named.jpg -------------------------------------------------------------------------------- /manual/src/ex_col_shades_of_grey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_col_shades_of_grey.jpg -------------------------------------------------------------------------------- /manual/src/ex_fancy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_fancy.gif -------------------------------------------------------------------------------- /manual/src/ex_geom_bline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_geom_bline.jpg -------------------------------------------------------------------------------- /manual/src/ex_geom_bsweep.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_geom_bsweep.gif -------------------------------------------------------------------------------- /manual/src/ex_geom_circle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_geom_circle.jpg -------------------------------------------------------------------------------- /manual/src/ex_geometry.md: -------------------------------------------------------------------------------- 1 | ## Bracket-Geometry Examples 2 | 3 | ### bresenham_circle 4 | 5 | [Source Code](https://github.com/amethyst/bracket-lib/tree/master/bracket-geometry/examples) 6 | 7 | This demonstrates the use of `BresenhamCircle` to plot gridded circles, quickly and with compensation for grid locations. 8 | 9 | ![](./ex_geom_circle.jpg) 10 | 11 | ### bresenham_line 12 | 13 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-geometry/examples/bresenham_line.rs) 14 | 15 | This example draws a line and plots it on the console, using Bresenham's Line algorithm. 16 | 17 | ![](./ex_geom_bline.jpg) 18 | 19 | ### bresenham_sweep 20 | 21 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-geometry/examples/bresenham_sweep.rs) 22 | 23 | This example sweeps from 0 to 360 degrees, using `bracket-geometry` angle functions. It then projects a point along that angle, and draws a Bresenham Line to the new point. 24 | 25 | ![](./ex_geom_bsweep.gif) 26 | 27 | ### distance 28 | 29 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-geometry/examples/distance.rs) 30 | 31 | This example calculates the distance between two points using Pythagoras, Pythagoras Squared, Manhattan and Chebyshev distance algorithms. 32 | 33 | ``` 34 | Given the two points: 35 | Point { 36 | x: 0, 37 | y: 0, 38 | } 39 | Point { 40 | x: 10, 41 | y: 20, 42 | } 43 | 44 | Pythagoras Distance: 22.36068 45 | Pythagoras Squared Distance: 500 46 | Manhattan Distance: 30 47 | Chebyshev Distance: 20 48 | ``` 49 | 50 | ### vector_line 51 | 52 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-geometry/examples/vector_line.rs) 53 | 54 | This example uses vector math to plot a line, rather than Bresenham. It can be slightly faster on some CPUs, if you are plotting enough lines (or long enough lines) for the floating-point math to make a difference. Lines aren't quite as nice as their Bresenham brethren. 55 | 56 | ``` 57 | .......... 58 | .*........ 59 | ..*....... 60 | ..**...... 61 | ...*...... 62 | ....*..... 63 | .....*.... 64 | .....**... 65 | ......*... 66 | .......*.. 67 | ``` -------------------------------------------------------------------------------- /manual/src/ex_noise.md: -------------------------------------------------------------------------------- 1 | ## Bracket-Noise Examples 2 | 3 | ### cellular 4 | 5 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/cellular.rs) 6 | 7 | Note that this is *not* cellular automata! Generates *cellular* noise, basically a randomized Voronoi pattern. 8 | 9 | ![](./ex_noise_cellular.jpg) 10 | 11 | ### perlin_fractal 12 | 13 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/perlin_fractal.rs) 14 | 15 | This example uses Perlin Fractal Noise to generate an ASCII height map. 16 | 17 | ![](./ex_noise_perlin_fractal.jpg) 18 | 19 | ### simplex_billow_quintic 20 | 21 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/simplex_billow_quintic.rs) 22 | 23 | This examples uses Simplex noise to make a heightmap, using the Billow and Quintic modes. 24 | 25 | ![](./ex_noise_simplex_billow.jpg) 26 | 27 | ### simplex_fractal 28 | 29 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/simplex_fractal.rs) 30 | 31 | This example uses Simplex noise in Fractal mode to make a heightmap. 32 | 33 | ![](./ex_noise_simplex_fractal.jpg) 34 | 35 | ### simplex_rigid_hermite 36 | 37 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/simplex_rigid_hermite.rs) 38 | 39 | This example uses Simplex noise in Rigit Hermite mode to make a heightmap. 40 | 41 | ![](./ex_noise_simplex_rigid.jpg) 42 | 43 | ### value 44 | 45 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/value.rs) 46 | 47 | This example uses value noise for simple interpolation. 48 | 49 | ![](./ex_noise_value.jpg) 50 | 51 | ### value_fractal 52 | 53 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/value_fractal.rs) 54 | 55 | This example uses value noise in fractal interpolation mode. 56 | 57 | ![](./ex_noise_value_fractal.jpg) 58 | 59 | ### whitenosie 60 | 61 | [Source Code](https://github.com/amethyst/bracket-lib/blob/master/bracket-noise/examples/whitenoise.rs) 62 | 63 | Generates a really random looking field of white noise. Perfect for snow, or for feeding random data to a shader. 64 | 65 | ![](./ex_noise_white.jpg) -------------------------------------------------------------------------------- /manual/src/ex_noise_cellular.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_cellular.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_perlin_fractal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_perlin_fractal.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_simplex_billow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_simplex_billow.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_simplex_fractal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_simplex_fractal.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_simplex_rigid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_simplex_rigid.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_value.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_value.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_value_fractal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_value_fractal.jpg -------------------------------------------------------------------------------- /manual/src/ex_noise_white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_noise_white.jpg -------------------------------------------------------------------------------- /manual/src/ex_path.md: -------------------------------------------------------------------------------- 1 | ## Bracket-Pathfinding Examples 2 | 3 | ### astar 4 | 5 | [Source Code](https://github.com/amethyst/bracket-lib/tree/master/bracket-pathfinding/examples/astar) 6 | 7 | A quick demonstration of A-star pathfinding in action. Demonstrates the minimum required for accurate A-star pathing. 8 | 9 | ![](./ex_path_astar.jpg) 10 | 11 | ### astar_manhattan 12 | 13 | [Source Code](https://github.com/amethyst/bracket-lib/tree/master/bracket-pathfinding/examples/astar_manhattan) 14 | 15 | Demonstrates using Manhattan distances in A-Star, rather than regular Pythagoras. 16 | 17 | ![](./ex_path_astar_manhattan.jpg) 18 | 19 | ### dijkstra 20 | 21 | [Source Code](https://github.com/amethyst/bracket-lib/tree/master/bracket-pathfinding/examples/dijkstra) 22 | 23 | Demonstrates the usage of the Dijkstra maps feature by brightening areas close to starting points, and darkening those further away. 24 | 25 | ![](./ex_path_dijkstra.jpg) 26 | 27 | ### fov 28 | 29 | [Source Code](https://github.com/amethyst/bracket-lib/tree/master/bracket-pathfinding/examples/fov) 30 | 31 | Demonstrates the Field-of-View functionality. 32 | 33 | ![](./ex_path_fov.jpg) -------------------------------------------------------------------------------- /manual/src/ex_path_astar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_path_astar.jpg -------------------------------------------------------------------------------- /manual/src/ex_path_astar_manhattan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_path_astar_manhattan.jpg -------------------------------------------------------------------------------- /manual/src/ex_path_dijkstra.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_path_dijkstra.jpg -------------------------------------------------------------------------------- /manual/src/ex_path_fov.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/manual/src/ex_path_fov.jpg -------------------------------------------------------------------------------- /manual/src/examples.md: -------------------------------------------------------------------------------- 1 | # Using the Examples 2 | 3 | Each of the `bracket-lib` crates comes with a number of examples. These are a great source of inspiration for how the parts of the library fit together, as well as serving as a demonstration of what can be done. 4 | 5 | You can run examples locally by changing directory to the crate you wish to use (e.g. `cd bracket-terminal`), and then running `cargo run --example (name)`. You can get a list of valid example names by omitting `(name)`. 6 | 7 | > Many people find they learn better by reading examples, rather than big manuals. If so, this section is for you! 8 | -------------------------------------------------------------------------------- /manual/src/individual_parts.md: -------------------------------------------------------------------------------- 1 | # Using Individual Bracket-Lib Components 2 | 3 | `bracket-lib` is a collection of libraries. You can depend upon them individually, if you only want part of the `bracket-lib` functionality. The parts are: 4 | 5 | * `bracket-algorithm-traits` defines some traits that are used in other parts of the program. 6 | * `bracket-color` defines how the library handles color, and includes functions for grayscale, RGB/RGBA/HSV conversion, a lot of named colors, and general color management support. 7 | * `bracket-geometry` provides points, lines, rectangles and circle support. 8 | * `bracket-noise` provides Perlin, Simplex, White and other noise functions useful for randomly generating things. 9 | * `bracket-pathfinding` provides an A-Star and a Dijkstra mapping solution. 10 | * `bracket-random` provides an easy-to-use wrapper to a random number generator. 11 | * `bracket-terminal` provides console rendering and support. 12 | 13 | When you link directly to a dependency, the namespace is no longer `bracket_lib::prelude`. Instead, it will be the crate's name, e.g. `bracket_random::prelude`. 14 | 15 | This option is partly provided to help keep development efforts separated, and partly because sometimes you just want a small portion of what the library has to offer---and there's no point in wasting space (and mostly compile time) on the bits you don't need. 16 | -------------------------------------------------------------------------------- /manual/src/linking.md: -------------------------------------------------------------------------------- 1 | # Linking to Bracket-lib 2 | 3 | The quickest and easiest way to use `bracket-lib` in your program is to include the entire library in your project. Open your project's `Cargo.toml` and include: 4 | 5 | ```toml 6 | [dependencies] 7 | bracket-lib = "0.8" 8 | ``` 9 | 10 | You now have the whole `bracket-lib` project linked to your program. 11 | 12 | ## Using the Github Version 13 | 14 | If you'd like to live on the bleeding edge, you can link to the Github version. In your project's `Cargo.toml` file, add the following: 15 | 16 | ```toml 17 | [dependencies] 18 | bracket-lib = { git = "https://github.com/amethyst/bracket-lib.git" } 19 | ``` 20 | 21 | The main reason to do this is to try out new features. The Github version isn't *always* as stable as I'd like, so proceed with caution. -------------------------------------------------------------------------------- /manual/src/what_is_it.md: -------------------------------------------------------------------------------- 1 | # What is Bracket-lib 2 | 3 | `bracket-lib` started out life as RLTK - The RogueLike Toolkit. Initially, I needed a code-page 437 terminal library on which to build roguelikes. The [Rust Roguelike Tutorial](http://bfnightly.bracketproductions.com/rustbook/) grew, and so did the library. Then [Hands-on Rust](https://hands-on-rust.com/) (my book about learning Rust) was born, and `bracket-lib` became the primary library behind the book. 4 | 5 | Bracket-lib is intended to fulfill the following needs: 6 | 7 | * A user-friendly *teaching* library. If I have to choose between performance and a new-user friendly interface, 99% of the time I'll choose the friendly approach. 8 | * Provide virtual consoles on a variety of platforms, from the web to major Operating Systems. 9 | * Provide a number of extensions to allow you to do layering, sprites, and more advanced rendering---without hurting the overall goal of the library. 10 | * Provide a good "on ramp" for moving onto high-performance libraries once you've mastered the basics. 11 | * Remain agnostic about how you write your game. ECS, tick methods, embedded scripting---take the path you want. Bracket-lib is meant to provide the basic tools you need and let you unleash your imagination. 12 | 13 | This "getting started" guide is intended to help you get started with `bracket-lib`. -------------------------------------------------------------------------------- /rltk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rltk" 3 | version = "0.8.7" 4 | authors = ["Herbert Wolverson "] 5 | edition = "2021" 6 | publish = true 7 | description = "A CP437/ASCII terminal library and helpers to make creating roguelike games in Rust easy. Similar to libtcod, but aiming to be Rust-native." 8 | homepage = "https://github.com/thebracket/bracket-lib" 9 | repository = "https://github.com/thebracket/bracket-lib" 10 | readme = "README.md" 11 | keywords = ["roguelike", "cp437", "ascii", "virtual-terminal", "gamedev"] 12 | categories = ["game-engines", "graphics"] 13 | license = "MIT" 14 | resolver = "2" # Enables the new Cargo resolution engine 15 | 16 | [features] 17 | default = ["opengl"] 18 | bevy = ["bracket-lib/bevy"] 19 | specs = ["bracket-lib/specs"] 20 | serde = ["bracket-lib/serde"] 21 | threaded = ["bracket-lib/threaded"] 22 | opengl = ["bracket-lib/opengl"] 23 | curses = ["bracket-lib/curses"] 24 | crossterm = ["bracket-lib/crossterm"] 25 | webgpu = ["bracket-lib/webgpu"] 26 | 27 | [dependencies] 28 | bracket-lib = { path = "../", version = "~0.8", default-features = false } 29 | 30 | [dev-dependencies] 31 | -------------------------------------------------------------------------------- /rltk/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Herbert Wolverson (DBA Bracket Productions) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /rltk/examples-deprecated/ex08-rex.rs: -------------------------------------------------------------------------------- 1 | rltk::add_wasm_support!(); 2 | use rltk::prelude::*; 3 | 4 | struct State { 5 | nyan: XpFile, 6 | } 7 | 8 | impl GameState for State { 9 | fn tick(&mut self, ctx: &mut Rltk) { 10 | ctx.cls(); 11 | ctx.print_color( 12 | 0, 13 | 0, 14 | RGB::named(rltk::YELLOW), 15 | RGB::named(rltk::BLACK), 16 | "Hello Nyan Cat!", 17 | ); 18 | ctx.print_color( 19 | 0, 20 | 1, 21 | RGB::named(rltk::GREEN), 22 | RGB::named(rltk::BLACK), 23 | "Loaded from REX Paint (https://www.gridsagegames.com/rexpaint/)", 24 | ); 25 | ctx.render_xp_sprite(&self.nyan, 2, 4); 26 | } 27 | } 28 | 29 | // This is a helper macro to embed a file in your binary. 30 | rltk::embedded_resource!(NYAN_CAT, "../resources/nyan.xp"); 31 | 32 | fn main() -> RltkError { 33 | // This helper macro links the above embedding, allowing it to be accessed as a resource from various parts of the program. 34 | rltk::link_resource!(NYAN_CAT, "../resources/nyan.xp"); 35 | let xp = XpFile::from_resource("../resources/nyan.xp").unwrap(); 36 | 37 | let context = RltkBuilder::simple80x50() 38 | .with_title("RLTK Example 8 - REX Paint, Hello Nyan Cat") 39 | .build()?; 40 | let gs: State = State { nyan: xp }; 41 | rltk::main_loop(context, gs) 42 | } 43 | -------------------------------------------------------------------------------- /rltk/examples-deprecated/ex10-postprocess.rs: -------------------------------------------------------------------------------- 1 | rltk::add_wasm_support!(); 2 | use rltk::prelude::*; 3 | 4 | struct State { 5 | nyan: XpFile, 6 | burn: bool, 7 | } 8 | 9 | impl GameState for State { 10 | fn tick(&mut self, ctx: &mut Rltk) { 11 | ctx.cls(); 12 | ctx.print_color( 13 | 0, 14 | 0, 15 | RGB::named(rltk::YELLOW), 16 | RGB::named(rltk::BLACK), 17 | "Hello Nyan Cat!", 18 | ); 19 | ctx.print_color( 20 | 0, 21 | 1, 22 | RGB::named(rltk::GREEN), 23 | RGB::named(rltk::BLACK), 24 | "Loaded from REX Paint (https://www.gridsagegames.com/rexpaint/)", 25 | ); 26 | ctx.print_color( 27 | 0, 28 | 2, 29 | RGB::named(rltk::WHITE), 30 | RGB::named(rltk::BLACK), 31 | "Press B to toggle burn.", 32 | ); 33 | ctx.render_xp_sprite(&self.nyan, 2, 4); 34 | 35 | match ctx.key { 36 | None => {} // Nothing happened 37 | Some(key) => { 38 | // A key is pressed or held 39 | if let VirtualKeyCode::B = key { 40 | self.burn = !self.burn; 41 | ctx.with_post_scanlines(self.burn); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | rltk::embedded_resource!(NYAN_CAT, "../resources/nyan.xp"); 49 | 50 | fn main() -> RltkError { 51 | rltk::link_resource!(NYAN_CAT, "../resources/nyan.xp"); 52 | let xp = XpFile::from_resource("../resources/nyan.xp").unwrap(); 53 | 54 | let mut context = RltkBuilder::simple80x50() 55 | .with_title("RLTK Example 10 - Post-Processing Effects") 56 | .build()?; 57 | 58 | context.with_post_scanlines(true); 59 | let gs: State = State { 60 | nyan: xp, 61 | burn: true, 62 | }; 63 | rltk::main_loop(context, gs) 64 | } 65 | -------------------------------------------------------------------------------- /rltk/examples-deprecated/ex11-random.rs: -------------------------------------------------------------------------------- 1 | rltk::add_wasm_support!(); 2 | use rltk::prelude::*; 3 | 4 | struct State { 5 | rng: RandomNumberGenerator, 6 | n_rolls: u32, 7 | rolls: Vec, 8 | } 9 | 10 | impl GameState for State { 11 | fn tick(&mut self, ctx: &mut Rltk) { 12 | self.n_rolls += 1; 13 | 14 | // Handle rollover 15 | if self.n_rolls == std::u32::MAX { 16 | self.n_rolls = 1; 17 | for d in &mut self.rolls { 18 | *d = 0; 19 | } 20 | } 21 | 22 | let roll = self.rng.roll_dice(3, 6) as usize; 23 | self.rolls[roll] += 1; 24 | 25 | let max = self.rolls.iter().max().unwrap(); 26 | 27 | ctx.cls(); 28 | ctx.print(0, 1, "3d6 Distribution"); 29 | for i in 3..19 { 30 | ctx.print(5, i, &format!("{:02} : {}", i, self.rolls[i as usize])); 31 | ctx.draw_bar_horizontal( 32 | 20, 33 | i, 34 | 50, 35 | self.rolls[i as usize] as i32, 36 | *max as i32, 37 | RGB::named(rltk::GREEN), 38 | RGB::named(rltk::BLACK), 39 | ); 40 | } 41 | 42 | ctx.print(5, 22, &format!("Total rolls: {}", self.n_rolls)); 43 | } 44 | } 45 | 46 | fn main() -> RltkError { 47 | let context = RltkBuilder::vga(80, 23) 48 | .with_title("Example 11 - Random Numbers") 49 | .build()?; 50 | let gs: State = State { 51 | rng: RandomNumberGenerator::new(), 52 | n_rolls: 0, 53 | rolls: vec![0; 19], 54 | }; 55 | rltk::main_loop(context, gs) 56 | } 57 | -------------------------------------------------------------------------------- /rltk/examples-deprecated/ex12-simplex.rs: -------------------------------------------------------------------------------- 1 | rltk::add_wasm_support!(); 2 | use rltk::prelude::*; 3 | 4 | struct State { 5 | colors: Vec, 6 | counter: u64, 7 | timer: f32, 8 | } 9 | 10 | impl GameState for State { 11 | fn tick(&mut self, ctx: &mut Rltk) { 12 | self.timer += ctx.frame_time_ms; 13 | if self.timer > 500.0 { 14 | self.timer = 0.0; 15 | self.rebuild_noise(); 16 | } 17 | ctx.cls(); 18 | 19 | for y in 0..50 { 20 | for x in 0..80 { 21 | let idx = ((y * 80) + x) as usize; 22 | ctx.set(x, y, self.colors[idx], RGB::from_f32(0.0, 0.0, 0.0), 219); 23 | } 24 | } 25 | } 26 | } 27 | 28 | impl State { 29 | pub fn rebuild_noise(&mut self) { 30 | let mut noise = FastNoise::seeded(self.counter); 31 | noise.set_noise_type(NoiseType::SimplexFractal); 32 | noise.set_fractal_type(FractalType::FBM); 33 | noise.set_fractal_octaves(5); 34 | noise.set_fractal_gain(0.6); 35 | noise.set_fractal_lacunarity(2.0); 36 | noise.set_frequency(2.0); 37 | 38 | for y in 0..50 { 39 | for x in 0..80 { 40 | let n = noise.get_noise((x as f32) / 160.0, (y as f32) / 100.0); 41 | let idx = ((y * 80) + x) as usize; 42 | if n < 0.0 { 43 | self.colors[idx] = RGB::from_f32(0.0, 0.0, 1.0 - (0.0 - n)); 44 | } else { 45 | self.colors[idx] = RGB::from_f32(0.0, n, 0.0); 46 | } 47 | } 48 | } 49 | self.counter += 1; 50 | } 51 | } 52 | 53 | fn main() -> RltkError { 54 | let mut gs: State = State { 55 | colors: vec![RGB::from_f32(0., 0., 0.); 80 * 50], 56 | counter: 0, 57 | timer: 0.0, 58 | }; 59 | gs.rebuild_noise(); 60 | 61 | let context = RltkBuilder::simple80x50() 62 | .with_title("RLTK Example 12 - Perlin Noise") 63 | .build()?; 64 | rltk::main_loop(context, gs) 65 | } 66 | -------------------------------------------------------------------------------- /rltk/examples-deprecated/ex13-textblock.rs: -------------------------------------------------------------------------------- 1 | rltk::add_wasm_support!(); 2 | use rltk::prelude::*; 3 | 4 | struct State {} 5 | 6 | impl GameState for State { 7 | fn tick(&mut self, ctx: &mut Rltk) { 8 | let mut draw_batch = DrawBatch::new(); 9 | draw_batch.cls(); 10 | let mut block = TextBlock::new(0, 0, 80, 25); 11 | 12 | let mut buf = TextBuilder::empty(); 13 | buf.ln() 14 | .fg(RGB::named(rltk::YELLOW)) 15 | .bg(RGB::named(rltk::BLUE)) 16 | .centered("Hello World") 17 | .fg(RGB::named(rltk::WHITE)) 18 | .bg(RGB::named(rltk::BLACK)) 19 | .ln() 20 | .ln() 21 | .line_wrap("The quick brown fox jumped over the lazy dog, and just kept on running in an attempt to exceed the console width.") 22 | .ln() 23 | .ln() 24 | .line_wrap("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") 25 | .ln().ln() 26 | .fg(RGB::named(rltk::CYAN)) 27 | .append("FPS: ") 28 | .fg(RGB::named(rltk::MAGENTA)) 29 | .append(&format!("{}", ctx.fps)) 30 | .reset(); 31 | 32 | block.print(&buf).expect("Too much text"); 33 | 34 | block.render_to_draw_batch(&mut draw_batch); 35 | draw_batch.submit(0).expect("Batch error"); 36 | render_draw_buffer(ctx).expect("Render error"); 37 | } 38 | } 39 | 40 | fn main() -> RltkError { 41 | let gs: State = State {}; 42 | 43 | let context = RltkBuilder::simple80x50() 44 | .with_title("RLTK Example 13 - Text Blocks") 45 | .build()?; 46 | rltk::main_loop(context, gs) 47 | } 48 | -------------------------------------------------------------------------------- /rltk/resources/example_tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/rltk/resources/example_tiles.png -------------------------------------------------------------------------------- /rltk/resources/mltest.xp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/rltk/resources/mltest.xp -------------------------------------------------------------------------------- /rltk/resources/nyan.xp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/rltk/resources/nyan.xp -------------------------------------------------------------------------------- /rltk/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use bracket_lib::prelude::rex; 2 | pub use bracket_lib::prelude::BError as RltkError; 3 | pub use bracket_lib::prelude::BTerm as Rltk; 4 | pub use bracket_lib::prelude::BTermBuilder as RltkBuilder; 5 | pub use bracket_lib::prelude::*; 6 | 7 | #[macro_export] 8 | macro_rules! link_resource { 9 | ($resource_name : ident, $filename : expr) => { 10 | rltk::EMBED 11 | .lock() 12 | .add_resource($filename.to_string(), $resource_name); 13 | }; 14 | } 15 | 16 | pub mod prelude { 17 | pub use crate::link_resource; 18 | pub use crate::*; 19 | } 20 | 21 | pub mod embedding { 22 | pub use bracket_lib::prelude::EMBED; 23 | } 24 | -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE01.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE02.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE03.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE04.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE05-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE05-2.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE06.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE06.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE07.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE08.jpg -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE09.jpg -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE10.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE11.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE12.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE13.jpg -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE14.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE15.gif -------------------------------------------------------------------------------- /screenshots/RLTK_RS_EXAMPLE18.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amethyst/bracket-lib/0d2d5e6a9a8e7c7ae3710cfef85be4cab0109a27/screenshots/RLTK_RS_EXAMPLE18.gif -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! bracket-lib is a wrapper of the bracket- set of crates designed initally 2 | //! for roguelike development (as RLTK) and later transitioned into a general 3 | //! use crate. 4 | 5 | /// prelude 6 | pub mod prelude { 7 | pub use bracket_algorithm_traits::prelude::*; 8 | pub use bracket_color::prelude::*; 9 | pub use bracket_geometry::prelude::*; 10 | pub use bracket_noise::prelude::*; 11 | pub use bracket_pathfinding::prelude::*; 12 | pub use bracket_random::prelude::*; 13 | pub use bracket_terminal::prelude::*; 14 | pub use bracket_terminal::{add_wasm_support, embedded_resource, link_resource}; 15 | } 16 | 17 | /// bracket-algorithm-traits provides traits for use in the bracket-pathfinding 18 | /// and bracket-geometry 19 | pub mod algorithm_traits { 20 | pub use bracket_algorithm_traits::prelude::*; 21 | } 22 | 23 | /// bracket-color provides a color system for use in the bracket-terminal 24 | pub mod color { 25 | pub use bracket_color::prelude::*; 26 | } 27 | /// bracket-geometry provides some geometric primitives (Point, Point3D, Rect), 28 | /// support functions and distance calculations. It also includes Bresenham's 29 | /// line algorithm, a vector line algorithm, and Bresenham's Circle algorithm. 30 | pub mod geometry { 31 | pub use bracket_geometry::prelude::*; 32 | } 33 | 34 | /// bracket-noise covers all the commonly used types of noise, 35 | pub mod noise { 36 | pub use bracket_noise::prelude::*; 37 | } 38 | /// bracket-pathfinding (in conjunction with bracket-algorithm-traits) provides 39 | /// pathfinding functionality. A-Star (A*) and Dijkstra are supported. It also 40 | // provides field of view (FOV) functionality. 41 | pub mod pathfinding { 42 | pub use bracket_pathfinding::prelude::*; 43 | } 44 | 45 | /// bracket-random provides a dice-oriented random number generation 46 | pub mod random { 47 | pub use bracket_random::prelude::*; 48 | } 49 | 50 | /// bracket-terminal provides a virtual ASCII/Codepage-437 terminal (with 51 | /// optional tile graphic support and layers), and a game loop 52 | pub mod terminal { 53 | pub use bracket_terminal::prelude::*; 54 | } 55 | --------------------------------------------------------------------------------