├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.toml ├── assets ├── basic.rmap └── basic.rsprite ├── examples ├── README.md └── snake │ ├── Cargo.toml │ ├── ast │ └── map.rmap │ └── src │ └── main.rs ├── help ├── oldtutorial.md ├── readme.md └── tutorial.md ├── license ├── readme.md └── src ├── UI └── ui.rs ├── backend ├── a.rs └── b.rs ├── build.rs ├── c └── key.c ├── core.rs ├── lib.rs ├── libs ├── cursor.rs ├── escape │ └── escape.rs ├── keycode.rs ├── keyin.rs ├── sys │ ├── Thanks.md │ ├── sys.rs │ └── windows.rs └── terminal.rs ├── map ├── loader.rs └── sprite.rs ├── misc ├── check.rs └── colour.rs ├── physics ├── collision.rs ├── particle.rs └── physics.rs └── test └── test.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | linux: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | 24 | windows: 25 | runs-on: windows-latest 26 | steps: 27 | - uses: actions/checkout@v2 28 | - name: Build 29 | run: cargo build --verbose 30 | - name: Run tests 31 | run: cargo test --verbose 32 | 33 | 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | /examples/snake/target -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ccdb" 3 | version = "1.6.1" 4 | authors = ["TheSlam <32799244+salmmanfred@users.noreply.github.com>"] 5 | edition = "2018" 6 | links = "./src/c/" 7 | build = "./src/build.rs" 8 | license = "MIT" 9 | repository = "https://github.com/salmmanfred/ccdb" 10 | description = "A small terminal based game engine" 11 | readme = "README.md" 12 | keywords = ["gamedev", "graphics","multithreading","engine","terminal"] 13 | exclude = ["./depric/"] 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | openfile = "1.1.0" 18 | winapi-util = "0.1.5" 19 | 20 | [build-dependencies] 21 | cc = "1.0" -------------------------------------------------------------------------------- /assets/basic.rmap: -------------------------------------------------------------------------------- 1 | ############################ 2 | # @ # 3 | # # 4 | # IIIIIIIIIIII # 5 | # # 6 | # # 7 | # # 8 | ############################ -------------------------------------------------------------------------------- /assets/basic.rsprite: -------------------------------------------------------------------------------- 1 | #### 2 | ### 3 | #### -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Example games 2 | All example code is under the MIT license -------------------------------------------------------------------------------- /examples/snake/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake" 3 | version = "0.1.0" 4 | authors = ["TheSlam <32799244+salmmanfred@users.noreply.github.com>"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | ccdb = "1.6.0" 11 | rand = "0.8.3" -------------------------------------------------------------------------------- /examples/snake/ast/map.rmap: -------------------------------------------------------------------------------- 1 | ############################## 2 | # # 3 | # # 4 | # # 5 | # # 6 | # # 7 | # # 8 | # # 9 | # # 10 | ############################## -------------------------------------------------------------------------------- /examples/snake/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate ccdb; 2 | use ccdb::core::{Core, Screen,backend}; // there are 2 diffrent Cores there is Core and there is banana both work the same way when talking to them 3 | use ccdb::collision; // for collision 4 | use ccdb::cursor; // for moving the cursor 5 | use ccdb::keycode; // For key input 6 | use ccdb::keyin; // For key input 7 | use ccdb::loader; 8 | use ccdb::loader::to_map; // this is the loader which makes it so you can load a map from file or load a map from string 9 | use ccdb::terminal; 10 | use ccdb::ui; // ui library 11 | use rand::prelude::*; 12 | 13 | pub fn main() { 14 | cursor::clear(); // clears the Screen 15 | cursor::hide_cursor(); // hides the cursor 16 | 17 | // not really needed here but its so you understand how to use it 18 | let assets = loader::load_from_folder( 19 | "./ast/".to_string(), 20 | ".rmap".to_string(), 21 | ".rsprite".to_string(), 22 | ); // get a folder of maps and sprites 23 | let map1 = assets.load_asset_map("map").unwrap(); //load an assets from the folder struct 24 | 25 | let x = Core { 26 | // set up the Core 27 | name: "Snake".to_string(), //name 28 | desc: " - Snake example game".to_string(), // descirption 29 | line_lenght: 40, // ammount of chars per line 30 | lines: 10, //amount of lines 31 | debug: false, //debug 32 | threads: 2, // ammount of threads 33 | output_string: false, // if you want the output in string form or it just to printed out to the console directly 34 | backend: backend::a, 35 | }; 36 | // if the map is not loaded properly it will just say error 37 | let mut f = Screen { 38 | // Screen is where everything will be stored and how it should be renderd 39 | chars: vec!["Error".to_string()], 40 | x: vec![1], 41 | y: vec![1], 42 | delay: 10, // delay between each frame 43 | sprite: Vec::new(), // this is where all sprites go 44 | orgin: map1.clone(), 45 | }; 46 | 47 | let mut a = x.setup(); // setup the Core 48 | 49 | // set terminal size so that the window is not huge 50 | terminal::set_terminal_size(60, 20); // change terminal size 51 | 52 | // create 2 buttons and add them to the ui component 53 | // get the ui started 54 | let mut ui = ui::UI::new(); 55 | 56 | let mut button = ui::Button::new(0, "Play again"); 57 | let mut button2 = ui::Button::new(1, "Quit"); 58 | 59 | ui.buttons.push(button); 60 | ui.buttons.push(button2); 61 | 62 | // some variables 63 | let mut rendui = false; 64 | let mut change_x = 0; 65 | let mut change_y = 0; 66 | let mut cur = 0; 67 | let speed = 10; //lower is faster 68 | let mut snake: Vec<[i64; 2]> = vec![[10, 3]]; 69 | 70 | let mut x = 10; 71 | let mut y = 3; 72 | let mut snek_lenght = 1; 73 | let mut foodpos: [i64; 2] = [3, 4]; 74 | f.load_map(map1.clone()); 75 | 76 | loop { 77 | f.return_to_orgin(); 78 | cur += 1; // keep the speed under check 79 | if cur >= speed + 1 { 80 | cur = 0; 81 | } 82 | 83 | cursor::clear(); // revert back the cursor 84 | cursor::hide_cursor(); 85 | for x in snake.iter() { 86 | // push all snake parts 87 | f.x.push(x[0]); 88 | f.y.push(x[1]); 89 | f.chars.push("@".to_string()); 90 | } 91 | // print out the apple 92 | f.x.push(foodpos[0]); 93 | f.y.push(foodpos[1]); 94 | f.chars.push("A".to_string()); 95 | 96 | if !rendui { 97 | println!("{}", a.render(&mut f)); //render the entire Screen 98 | println!("Score: {} ", snek_lenght - 1); 99 | } 100 | if rendui { 101 | f.load_map(to_map(" \n".to_string())); // clear the vector 102 | a.render(&mut f); 103 | println!("GAME OVER"); 104 | ui.rend(); // render the ui 105 | match ui.buttons[0].get_status() { 106 | // getting if a button is pressed down or hoverd over or not 107 | ui::ButtonAction::Press => { 108 | x = 10; 109 | y = 3; 110 | snake = vec![[10, 3]]; 111 | snek_lenght = 1; 112 | foodpos = [3, 4]; 113 | change_x = 0; 114 | change_y = 0; 115 | rendui = false; 116 | cursor::clear(); // revert back the cursor 117 | a.render_blank(&mut f); 118 | a.render_blank(&mut f); 119 | 120 | } 121 | _ => {} 122 | } 123 | match ui.buttons[1].get_status() { 124 | // getting if a button is pressed down or hoverd over or not 125 | ui::ButtonAction::Press => { 126 | break; 127 | } 128 | _ => {} 129 | } 130 | } 131 | 132 | if cur == speed { 133 | // makes sure its not too fast 134 | x += change_x; 135 | y += change_y; 136 | snake.push([x, y]); 137 | } 138 | // keep it in shape 139 | if snake.len() > snek_lenght { 140 | snake.remove(0); 141 | } 142 | // check if the apple has collided with something aka the snake 143 | let mut apple_col = false; 144 | if collision::get_collision(f.find_X("A".to_string()) as usize, &f.gmap()) { 145 | snek_lenght += 1; // make snake longer 146 | foodpos = new_apple(); // get new apple positions 147 | apple_col = true; 148 | } 149 | // check if the snake has collided with something then makes sure that thing is not the apple 150 | let all_x = f.find_all_of_X("@".to_string()); 151 | let mut len = 0; 152 | if all_x.len() >= 1 { 153 | if all_x.len() > 1 { 154 | len = all_x.len() - 1; 155 | } 156 | if collision::get_collision(all_x[len] as usize, &f.gmap()) && !apple_col { 157 | rendui = true; 158 | } 159 | } 160 | 161 | // keyinput stuff 162 | 163 | match keyin::get_key() { 164 | keycode::A => { 165 | change_x = -1; 166 | change_y = 0; 167 | } 168 | keycode::D => { 169 | change_x = 1; 170 | change_y = 0; 171 | } 172 | keycode::W => { 173 | change_x = 0; 174 | change_y = -1; 175 | } 176 | keycode::S => { 177 | change_y = 1; 178 | change_x = 0; 179 | } 180 | 181 | _ => {} 182 | } 183 | 184 | } 185 | } 186 | fn new_apple() -> [i64; 2] { 187 | let mut rng = thread_rng(); 188 | let x = rng.gen_range(1.0..29.0) as i64; 189 | let y = rng.gen_range(1.0..9.0) as i64; 190 | [x, y] 191 | } 192 | -------------------------------------------------------------------------------- /help/oldtutorial.md: -------------------------------------------------------------------------------- 1 | # THE OLD TUTORIAL THIS NO LONGER WORKS 2 | 3 | ```rust 4 | 5 | extern crate ccdb; 6 | use ccdb::acore::{core,screen}; // there are 2 diffrent Acores there is Acore and there is banana both work the same way when talking to them 7 | use ccdb::loader::{load,toMap};// this is the loader which makes it so you can load a map from file or load a map from string 8 | use ccdb::keyin; // For key input 9 | use ccdb::cursor; // for moving the cursor 10 | use ccdb::keycode; // for key codes (work in progress) 11 | use ccdb::sprite; // for sprites 12 | use ccdb::collision; // for collision 13 | 14 | pub fn main() { 15 | 16 | cursor::clear(); // clears the screen 17 | cursor::hideCursor(); // hides the cursor 18 | let assets = loader::loadFromFolder("./maps/".to_string(),".rmap".to_string(),".rsprite".to_string());//you can load assets using loadFromFolder you will be rewarded with a folder struct 19 | let map1 = assets.loadAssetMap("map");// you can get your map using assets.loadAssetMap for getting the map 20 | let psprite = assets.loadAssetSprite("sprite");// sprite can be found using this 21 | 22 | let x = Acore{ 23 | name: "Test project".to_string(), // name of the project 24 | desc: " - A test project".to_string(), // descirption (short ) 25 | linelenght: 20,// how many charecters per line 26 | lines: 4, // how many lines 27 | debug: true, // This will make it so that CCDB (VERSION) is not shown 28 | threads: 2, // How many threads 29 | output_string: false,// if you want the output to be in string form or if you want it to just print to the console 30 | 31 | }; 32 | 33 | 34 | let mut f = screen{ 35 | chars: vec!("0".to_string(),"1".to_string()), // these are the different ascii "items" that get renderd X and Y are the cordinates 36 | x: vec!(1,2), 37 | y: vec!(1,2), 38 | delay: 10,// delay between each frame for 39 | sprite: Vec::new(),// the sprite vector contains all the sprites that are going to be renderd 40 | 41 | }; 42 | 43 | let mut a = x.setup(); // set up the Acore struct 44 | //! map loading stuff 45 | f.loadmap(load("./maps/map.rmap")); // loads in the map 46 | let player = f.findX("@".to_string()); // gets the player position in the screen.chars section findAllOfX works the same but returns a vector 47 | f.loadmap(toMap("#####\n33333".to_string()));//if you want to make a map out of a string 48 | 49 | //! physics stuff 50 | a.addphysics(player); // adds phycis to an object 51 | a.addphysicsForAllX(&f,"I".to_string());// adds physics to all objects with the correct char 52 | a.removephysics(player); // remove physics form an object 53 | a.changePhysics(-1); // change the gravity constant to make gravity stronger or weaker or upside down 54 | let mut sprite = sprite::load("./maps/sprite.rsprite"); // loads the sprite from a text file 55 | f.sprite.push(sprite);//push the sprite to the sprite vector 56 | f.sprite[0].setxy(2,-2);//sets the position of the sprite 57 | loop { 58 | 59 | cursor::clear();// clear the screen 60 | a.render(&mut f);// renders it all does not work with Bcore 61 | println!("{}",a.render(&mut f););// if you are using Bcore the output gets output in a string ( Does not work with Acore ) 62 | f.sprite[0].movexy(1, 0); // moves the sprite to the side 63 | 64 | if keyin::keydown(){ // checks if there is a keydown 65 | 66 | 67 | match keyin::getkey(){// gets said keycode 68 | 97 =>{ 69 | f.x[player as usize] -= 1; 70 | } 71 | 100 =>{ 72 | f.x[player as usize] += 1; 73 | } 74 | 119 =>{ 75 | f.y[player as usize] -= 1; 76 | } 77 | 115 =>{ 78 | f.y[player as usize] += 1; 79 | } 80 | _ =>{ 81 | 82 | } 83 | } 84 | 85 | 86 | } 87 | 88 | 89 | } 90 | ``` -------------------------------------------------------------------------------- /help/readme.md: -------------------------------------------------------------------------------- 1 | # This folder has the tutorial 2 | 3 | ## Old tutorial is for version below 0.9.0 -------------------------------------------------------------------------------- /help/tutorial.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | 3 | SOME FEATURES ARE ONLY TESTED ON WINDOWS THIS INCLUDES KEYIN AND CURSOR!(these are made in C) 4 | 5 | 6 | ## Learn how to use it by example 7 | 8 | 9 | ```rust 10 | extern crate ccdb; 11 | use ccdb::core::{Core, Screen,backend}; // there are 2 diffrent Cores there is Core and there is banana both work the same way when talking to them 12 | use ccdb::collision; // for collision 13 | use ccdb::cursor; // for moving the cursor 14 | use ccdb::keycode; // For key input 15 | use ccdb::keyin; // For key input 16 | use ccdb::loader; 17 | use ccdb::loader::{load, map, to_map}; // this is the loader which makes it so you can load a map from file or load a map from string 18 | use ccdb::sprite; // for sprites 19 | use ccdb::terminal; 20 | use ccdb::ui; // ui library 21 | use ccdb::particle; 22 | 23 | pub fn main() { 24 | cursor::clear(); // clears the Screen 25 | cursor::hide_cursor(); // hides the cursor 26 | let assets = loader::load_from_folder( 27 | "./maps/".to_string(), 28 | ".rmap".to_string(), 29 | ".rsprite".to_string(), 30 | ); // get a folder of maps and sprites 31 | let map1 = assets.load_asset_map("map").unwrap(); //load an assets from the folder struct 32 | let psprite = assets.load_asset_sprite("sprite").unwrap(); // 33 | 34 | let x = Core { 35 | // set up the Core 36 | name: "Test project".to_string(), //name 37 | desc: " - A test project".to_string(), // descirption 38 | line_lenght: 40, // ammount of chars per line 39 | lines: 8, //amount of lines 40 | debug: true, //debug 41 | threads: 4, // ammount of threads 42 | output_string: false, // if you want the output in string form or it just to printed out to the console directly 43 | backend: backend::A, // there are also backend::B and backend::N (which is null) 44 | }; 45 | 46 | let mut f = Screen { 47 | // Screen is where everything will be stored and how it should be renderd 48 | chars: vec!["0".to_string(), "1".to_string()], 49 | x: vec![1, 2], 50 | y: vec![1, 2], 51 | delay: 10, // delay between each frame 52 | sprite: Vec::new(), // this is where all sprites go 53 | orgin: map::new(), 54 | }; 55 | 56 | let mut water = particle::water{ // create the water struct 57 | droplets: Vec::new(),//leave this empty 58 | chars: "W".to_string(),// the character the water is based of off. 59 | }; 60 | water.collect_drop(f.gmap()); // after you have loaded the map you can get started adding the droplets. 61 | 62 | 63 | let mut a = x.setup(); // setup the Core 64 | f.load_map(map1.clone()); //load a map from a map struct 65 | f.load_map(to_map("#####\n33333".to_string())); //if you want to make a map out of a string 66 | f.load_map(load("./maps/map.rmap")); 67 | let run = true; 68 | let player = f.find_X("@".to_string()); // find a chars position 69 | 70 | a.add_physics(player); // add physics to char position 71 | a.add_physics_for_all_X(&f, "I".to_string()); 72 | a.remove_physics(player); //remove physics for char pos 73 | a.change_physics(1); // change the phycis 74 | 75 | let mut sprite = psprite; // sprite loaded from assets otherwise its sprite::load("./maps/sprite.rsprite"); 76 | f.sprite.push(sprite); //add the sprite to the sprite rendering list 77 | f.sprite[0].set_xy(2, -2); // set the sprites position 78 | f.sprite[0].move_xy(5, 0); // move the sprite 79 | 80 | // let x = terminal::get_terminal_size(); // get the terminal size 81 | terminal::set_terminal_size(50, 20); // change terminal size 82 | 83 | // create 2 buttons and add them to the ui component 84 | let button = ui::Button::new(0, "test"); 85 | let button2 = ui::Button::new(1, "test2"); 86 | 87 | let mut ui = ui::UI::new(); 88 | ui.buttons.push(button); 89 | ui.buttons.push(button2); 90 | f.set_orgin(map1.clone()); // set the orgin 91 | 92 | loop { 93 | f.return_to_orgin(); // use this if you want to return to the orgin 94 | a.render_blank(&mut f); //render a output the same size as the normal rend just with nothing in it 95 | 96 | cursor::clear(); 97 | cursor::hide_cursor(); 98 | 99 | println!("{}", a.render(&mut f)); //render the entire Screen 100 | f.load_map(water.run(f.gmap())); // to render the water just must give it the current map from the screen by doing screen.gmap(); 101 | // then you can load the map that it returns straight into the screen or store it for later use. 102 | ui.rend(); // render the ui 103 | 104 | 105 | 106 | match ui.buttons[0].get_status() { 107 | // getting if a button is pressed down or hoverd over or not 108 | ui::ButtonAction::Press => { 109 | println!("yes"); 110 | } 111 | ui::ButtonAction::Hover => { 112 | println!("maybe"); 113 | } 114 | ui::ButtonAction::Idle => { 115 | println!("no not"); 116 | } 117 | _ => {} 118 | } 119 | 120 | //a.render(&mut f); 121 | 122 | f.sprite[0].move_xy(1, 0); 123 | 124 | //standard key input system 125 | 126 | match keyin::get_key() { 127 | keycode::A => { 128 | f.x[player as usize] -= 1; 129 | if collision::get_collision(player as usize, &f.gmap()) 130 | //how to get the collision must pass in the Screen 131 | { 132 | f.x[player as usize] += 1; 133 | } 134 | } 135 | keycode::D => { 136 | f.x[player as usize] += 1; 137 | if collision::get_collision(player as usize, &f.gmap()) { 138 | f.x[player as usize] -= 1; 139 | } 140 | } 141 | keycode::W => { 142 | f.y[player as usize] -= 1; 143 | if collision::get_collision(player as usize, &f.gmap()) { 144 | f.y[player as usize] += 1; 145 | } 146 | } 147 | keycode::S => { 148 | f.y[player as usize] += 1; 149 | if collision::get_collision(player as usize, &f.gmap()) { 150 | f.y[player as usize] -= 1; 151 | } 152 | } 153 | keycode::SPACE => { 154 | for x in 0..10 { 155 | f.x[player as usize] += 1; 156 | if collision::get_collision(player as usize, &f.gmap()) { 157 | f.x[player as usize] -= 1; 158 | break; 159 | } 160 | } 161 | } 162 | _ => {} 163 | } 164 | 165 | } 166 | } 167 | 168 | 169 | 170 | ``` 171 | 172 | ## Differance between A and B backend 173 | A is Multi threaded while BCore is single threaded 174 | B is the old algorithm for making the text 175 | Their names are A: Banana Backend, B: Olive Backend 176 | 177 | ## UI 178 | There is an issue where the keyboard things get really slow when using the ui 179 | Try to not use them at the same time 180 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Manfred 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ccdb: The cmd game engine 2 | (Thats also multi threaded) 3 | 4 | 5 | # How to use 6 | 7 | [Tutorial](https://github.com/salmmanfred/ccdb/blob/master/help/tutorial.md) 8 | 9 | # Multi threading 10 | If you want to use multi threading you have to use ACore 11 | The amount of threads cannot be odd 12 | If you have more threads than lines the program will crash 13 | 14 | # Contributing 15 | If you have linux it would be nice if you could test the keyin and cursor libraries to see if they will work on linux! 16 | 17 | 18 | 19 | # screenshots / gifs 20 | 21 | ![2021-04-23_18-17-31](https://user-images.githubusercontent.com/32799244/115900503-508a7900-a460-11eb-8bac-21ee4e9658d7.gif) 22 | 23 | ![2021-04-24_14-32-41](https://user-images.githubusercontent.com/32799244/115958979-1970a200-a50a-11eb-8e06-280bfefca134.gif) 24 | 25 | ## Buttons system 26 | ![2021-04-23_18-22-30](https://user-images.githubusercontent.com/32799244/115901069-035ad700-a461-11eb-906b-976c37b09f4a.gif) 27 | 28 | # Releases 29 | [Releases](https://github.com/salmmanfred/ccdb/releases) 30 | 31 | # Upcoming 32 | [ccdb-script](https://github.com/salmmanfred/ccdb-script) 33 | 34 | # Roadmap 35 | v0.2.0: Add a function to find all of a certain character or just the first one DONE 36 | v0.3.0: Being able to get the output in a string instead of the cmd DONE 37 | v0.4.0: Physics and collision DONE 38 | v0.5.0: Loading of ascii sprites from file DONE 39 | v0.6.0: Key input rework DONE (+ some rework to the aCore(IT works allot better)) 40 | v0.7.0: Rework of variable names and function names DONE 41 | v0.8.0: Adding a way to load in a folder DONE 42 | v0.9.0: Getting the code ready for 1.0.0 DONE 43 | v1.0.0: optimization DONE 44 | v1.1.0: Terminal control DONE 45 | v1.2.0: UI DONE 46 | v1.3.0: Quality update DONE 47 | v1.4.0: Fixing linux support DONE 48 | v1.5.0: Water physics DONE 49 | v1.6.0: Change how the core system works DONE 50 | v1.7.0: Smoke physics 51 | -------------------------------------------------------------------------------- /src/UI/ui.rs: -------------------------------------------------------------------------------- 1 | use crate::keyin; 2 | 3 | pub enum ButtonAction { 4 | Press, 5 | Idle, 6 | Hover, 7 | } 8 | 9 | pub struct Button { 10 | pub text: String, 11 | pub pos: i64, 12 | imsel: bool, // if the button is pressed down 13 | pub hover: bool, 14 | } 15 | impl Button { 16 | pub fn new(y: i64, text: &str) -> Button { 17 | Button { 18 | text: text.to_string(), 19 | pos: y, 20 | imsel: false, 21 | hover: false, 22 | } 23 | } 24 | pub fn get_status(&mut self) -> ButtonAction { 25 | //gets the status 26 | 27 | if self.imsel { 28 | self.imsel = false; 29 | return ButtonAction::Press; 30 | } 31 | 32 | if self.hover { 33 | self.hover = false; 34 | 35 | return ButtonAction::Hover; 36 | } 37 | return ButtonAction::Idle; 38 | } 39 | } 40 | 41 | pub struct UI { 42 | pub buttons: Vec