diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f994030 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "CrystalPy"] + path = CrystalPy + url = git@github.com:FantasyPvP/CrystalPy.git diff --git a/.idea/CrystalOS-Restructured.iml b/.idea/CrystalOS-Restructured.iml index bbe0a70..da70464 100644 --- a/.idea/CrystalOS-Restructured.iml +++ b/.idea/CrystalOS-Restructured.iml @@ -4,6 +4,8 @@ + + diff --git a/CrystalPy b/CrystalPy new file mode 160000 index 0000000..0dfd92e --- /dev/null +++ b/CrystalPy @@ -0,0 +1 @@ +Subproject commit 0dfd92eca7f5fa9aa6b6d7c85a0678220863c0b6 diff --git a/src/system/std/mod.rs b/src/system/std/mod.rs index 6caf058..0b52d52 100644 --- a/src/system/std/mod.rs +++ b/src/system/std/mod.rs @@ -3,7 +3,7 @@ pub mod random; pub mod application; pub mod tasks; pub mod os; -pub mod frame; +pub mod render; pub mod time; pub mod syscall; diff --git a/src/system/std/frame.rs b/src/system/std/render.rs similarity index 80% rename from src/system/std/frame.rs rename to src/system/std/render.rs index 1437ca5..147dfc2 100644 --- a/src/system/std/frame.rs +++ b/src/system/std/render.rs @@ -3,6 +3,7 @@ use alloc::vec; use alloc::vec::Vec; use crate::system::kernel::render::{RENDERER, ScreenChar}; use crate::std::io::Color; +use num_traits::{Num, ToPrimitive}; /// TODO: get a working implementation for CLI apps /// elements can be created using their from_str() method @@ -61,30 +62,50 @@ impl ColouredChar { #[derive(Copy, Clone, Debug)] -pub struct Position { - pub x: usize, - pub y: usize, +pub struct Position { + pub x: T, + pub y: T, } -impl Position { - pub fn new(x: usize, y: usize) -> Position { +impl Position { + pub fn new(x: T, y: T) -> Position { Position { x, y } } + + pub fn into_usize(self) -> Result, ()> { + Ok(Position { + x: self.x.to_usize().ok_or(())?, + y: self.y.to_usize().ok_or(())?, + }) + } + pub fn into_i32(self) -> Result, ()> { + Ok(Position { + x: self.x.to_i32().ok_or(())?, + y: self.y.to_i32().ok_or(())?, + }) + } + + pub fn into_f32(self) -> Result, ()> { + Ok(Position { + x: self.x.to_f32().ok_or(())?, + y: self.y.to_f32().ok_or(())?, + }) + } } -pub type Dimensions = Position; +pub type Dimensions = Position; #[derive(Clone, Debug)] pub struct Frame { - pub position: Position, - pub dimensions: Dimensions, + pub position: Position, + pub dimensions: Dimensions, pub frame: Vec>, } impl Frame { - pub fn new(position: Position, dimensions: Dimensions) -> Result { + pub fn new(position: Position, dimensions: Dimensions) -> Result { Ok(Frame { position, dimensions, @@ -126,16 +147,16 @@ impl Frame { RENDERER.lock().render_frame(frame); Ok(()) } - pub fn get_position(&self) -> Position { + pub fn get_position(&self) -> Position { self.position } - pub fn set_position(&mut self, position: Position) { + pub fn set_position(&mut self, position: Position) { self.position = position } - pub fn dimensions(&self) -> Dimensions { + pub fn dimensions(&self) -> Dimensions { self.dimensions } - pub fn write(&mut self, position: Position, char: ColouredChar) -> Result<(), RenderError> { + pub fn write(&mut self, position: Position, char: ColouredChar) -> Result<(), RenderError> { if position.x >= self.dimensions.x || position.y >= self.dimensions.y { return Err(RenderError::OutOfBounds( position.x >= self.dimensions.x, diff --git a/src/user/bin/asteroids.rs b/src/user/bin/games/asteroids.rs similarity index 94% rename from src/user/bin/asteroids.rs rename to src/user/bin/games/asteroids.rs index 95add4c..fd2be50 100644 --- a/src/user/bin/asteroids.rs +++ b/src/user/bin/games/asteroids.rs @@ -1,6 +1,6 @@ use crate::std::application::Error; use crate::std::application::Error::ApplicationError; -use crate::std::frame::{ColouredChar, Dimensions, Frame, Position, RenderError}; +use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError}; use crate::std::io::{Color, ColorCode, Display, KeyStroke, Screen, Stdin}; use crate::std::random::Random; use crate::system::std::application::Application; @@ -17,7 +17,7 @@ use core::any::Any; #[derive(Clone)] pub struct Player { pub health: i32, - pub position: Position, + pub position: Position, } impl Player { pub fn new() -> Player { @@ -195,9 +195,9 @@ impl Game { if let Some(input_key) = Stdin::try_keystroke() { match input_key { - KeyStroke::Char('q') => return true, - KeyStroke::Char('w') => self.player.position.y -= 1, - KeyStroke::Char('s') => self.player.position.y += 1, + KeyStroke::Char('`') => return true, + KeyStroke::Char('w') => { if self.player.position.y > 0 { self.player.position.y -= 1 }}, + KeyStroke::Char('s') => { if self.player.position.y < 21 { self.player.position.y += 1 }}, _ => (), } } @@ -219,7 +219,7 @@ impl Game { frame.write_to_screen().unwrap(); while let KeyStroke::Char(c) = Stdin::keystroke().await { - if c == 'q' { + if c == '`' { break; } } @@ -251,13 +251,13 @@ impl CgComponent for Game { .collect::>() { frame[i.1 as usize][i.0 as usize] = ColouredChar { - character: '<', + character: '«', colour: ColorCode::new(Color::LightGray, Color::Black), }; (1..5).for_each(|offset| { if i.0 + offset < frame.dimensions.x as i16 { frame[i.1 as usize][(i.0 + offset) as usize] = ColouredChar { - character: '=', + character: '═', colour: ColorCode::new(Color::LightGray, Color::Black), } } diff --git a/src/user/bin/crystalrpg/entity.rs b/src/user/bin/games/crystalrpg/entity.rs similarity index 100% rename from src/user/bin/crystalrpg/entity.rs rename to src/user/bin/games/crystalrpg/entity.rs diff --git a/src/user/bin/crystalrpg/mod.rs b/src/user/bin/games/crystalrpg/mod.rs similarity index 100% rename from src/user/bin/crystalrpg/mod.rs rename to src/user/bin/games/crystalrpg/mod.rs diff --git a/src/user/bin/gameoflife.rs b/src/user/bin/games/gameoflife.rs similarity index 97% rename from src/user/bin/gameoflife.rs rename to src/user/bin/games/gameoflife.rs index dee0b73..ecf781e 100644 --- a/src/user/bin/gameoflife.rs +++ b/src/user/bin/games/gameoflife.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use alloc::boxed::Box; use crate::std::application::{Application, Error}; use async_trait::async_trait; -use crate::std::frame::{ColouredChar, Frame, Position, Dimensions, RenderError}; +use crate::std::render::{ColouredChar, Frame, Position, Dimensions, RenderError}; use crate::std::io::{KeyStroke, Stdin, Color, ColorCode, Display}; use crate::std::time::wait; diff --git a/src/user/bin/games/mod.rs b/src/user/bin/games/mod.rs new file mode 100644 index 0000000..456c80c --- /dev/null +++ b/src/user/bin/games/mod.rs @@ -0,0 +1,5 @@ +pub mod asteroids; +pub mod gameoflife; +pub mod crystalrpg; +pub mod pong; +pub mod snake; diff --git a/src/user/bin/pong.rs b/src/user/bin/games/pong.rs similarity index 63% rename from src/user/bin/pong.rs rename to src/user/bin/games/pong.rs index e5e2ea5..7f1345a 100644 --- a/src/user/bin/pong.rs +++ b/src/user/bin/games/pong.rs @@ -5,7 +5,7 @@ use core::any::Any; use async_trait::async_trait; use crate::std::application::{Application, Error}; use crate::std; -use crate::std::frame::{BUFFER_HEIGHT, BUFFER_WIDTH, ColorCode, ColouredChar, Dimensions, Frame, Position, RenderError}; +use crate::std::render::{BUFFER_HEIGHT, BUFFER_WIDTH, ColorCode, ColouredChar, Dimensions, Frame, Position, RenderError}; use crate::std::io::{Color, Display, KeyStroke, Stdin}; use crate::std::time::Timer; use crate::user::lib::libgui::cg_core::CgComponent; @@ -59,7 +59,7 @@ impl Application for Game { } if update_time.is_done() { updated = true; - self.ball.update(&mut self.player1, &mut self.player2); + self.update_ball(); update_time.reset() } @@ -68,12 +68,58 @@ impl Application for Game { frame.write_to_screen().unwrap(); } } - // self.ball.update(&self.player1, &self.player2); } Ok(()) } } +impl Game { + fn update_ball(&mut self) { + let pos_next_f32 = Position::new( // invert x direction on collision with player + self.ball.pos.x + self.ball.vx, + self.ball.pos.y + self.ball.vy, + ); + + if pos_next_f32.y < 0.0 || pos_next_f32.y >= BUFFER_HEIGHT as f32 { // if the move is outside the screen, then invert the direction + self.ball.vy = -self.ball.vy; + } + + if pos_next_f32.x < 0.0 { + self.player2.score += 1; + self.ball.pos = Position::new(40.0, 12.0); + self.ball.vx = 1.0; + self.ball.vy = 0.3; + } + + if pos_next_f32.x >= BUFFER_WIDTH as f32 { + self.player1.score += 1; + self.ball.pos = Position::new(40.0, 12.0); + self.ball.vx = -1.0; + self.ball.vy = 0.3; + } + + let pos_next = Position::new( + pos_next_f32.x as usize, + pos_next_f32.y as usize, + ); + + for i in 0..5 { + if self.player1.pos.y + i - 2 == pos_next.y && self.player1.pos.x == pos_next.x { + self.ball.vx = -self.ball.vx; + break; + } else if self.player2.pos.y + i - 2 == pos_next.y && self.player2.pos.x == pos_next.x { + self.ball.vx = -self.ball.vx; + break; + } + }; + + self.ball.pos = Position::new( + self.ball.pos.x + self.ball.vx, + self.ball.pos.y + self.ball.vy + ) + } +} + impl CgComponent for Game { fn render(&self) -> Result { let mut frame = Frame::new(Dimensions::new(0, 0), Dimensions::new(80, 25))?; @@ -82,7 +128,7 @@ impl CgComponent for Game { frame.write(Position::new(self.player1.pos.x, self.player1.pos.y + y -2), ColouredChar::coloured('▓', ColorCode::new(Color::Cyan, Color::Black))).unwrap(); frame.write(Position::new(self.player2.pos.x, self.player2.pos.y + y -2), ColouredChar::coloured('▓', ColorCode::new(Color::Cyan, Color::Black))).unwrap(); } - frame.write(self.ball.pos, ColouredChar::coloured('O', ColorCode::new(Color::Green, Color::Black))).unwrap(); + frame.write(self.ball.pos.into_usize().unwrap(), ColouredChar::coloured('O', ColorCode::new(Color::Green, Color::Black))).unwrap(); Ok(frame) } @@ -93,7 +139,7 @@ impl CgComponent for Game { } struct Player { - pos: Position, + pos: Position, score: i32, } @@ -115,52 +161,13 @@ impl Player { } struct Ball { - pos: Position, - vx: i32, - vy: i32, + pos: Position, + vx: f32, + vy: f32, } impl Ball { fn new() -> Self { - Ball { pos: Position::new(40, 12), vx: 1, vy: 1 } - } - - fn update(&mut self, player1: &mut Player, player2: &mut Player) { - let pos_next = Position::new( // invert x direction on collision with player - (self.pos.x as i32 + self.vx) as usize, - (self.pos.y as i32 + self.vy) as usize - ); - for i in 0..5 { - if player1.pos.y + i - 2 == pos_next.y && player1.pos.x == pos_next.x { - self.vx = -self.vx; - break; - } else if player2.pos.y + i - 2 == pos_next.y && player2.pos.x == pos_next.x { - self.vx = -self.vx; - break; - } - }; - - if pos_next.y < 0 || pos_next.y >= BUFFER_HEIGHT { // if the move is outside the screen, then invert the direction - self.vy = -self.vy; - } - - if pos_next.x < 0 { - player2.score += 1; - self.pos = Position::new(40, 12); - self.vx = 1; - self.vy = 1; - } - - if pos_next.x >= BUFFER_WIDTH { - player1.score += 1; - self.pos = Position::new(40, 12); - self.vx = -1; - self.vy = 1; - } - - self.pos = Position::new( - (self.pos.x as i32 + self.vx) as usize, - (self.pos.y as i32 + self.vy) as usize - ) + Ball { pos: Position::new(40.0, 12.0), vx: 1.0, vy: 0.3 } } } diff --git a/src/user/bin/snake.rs b/src/user/bin/games/snake.rs similarity index 97% rename from src/user/bin/snake.rs rename to src/user/bin/games/snake.rs index 6a92b55..6f094fa 100644 --- a/src/user/bin/snake.rs +++ b/src/user/bin/games/snake.rs @@ -4,10 +4,10 @@ use async_trait::async_trait; use crate::std::io::{Color, Display, KeyStroke, Stdin}; use crate::std::time; use crate::std::application::{Application, Error}; -use crate::std::frame::{ColouredChar, Dimensions, Frame, RenderError, ColorCode}; +use crate::std::render::{ColouredChar, Dimensions, Frame, RenderError, ColorCode}; use crate::std::random::Random; -use crate::system::std::frame; -use super::super::lib::coords::{Position, Direction}; +use crate::system::std::render; +use super::super::super::lib::coords::{Position, Direction}; #[derive(PartialEq)] enum Gamemode { @@ -164,7 +164,7 @@ impl Game { fn render(&mut self) -> Result<(), RenderError> { - let mut frame = Frame::new(frame::Position::new(0, 0), Dimensions::new(80, 25))?; + let mut frame = Frame::new(render::Position::new(0, 0), Dimensions::new(80, 25))?; let mut curr_colour = ColorCode::new(Color::LightBlue, Color::Black); for s in self.snakes.clone() { @@ -205,7 +205,7 @@ impl Game { } fn render_end_screen(&mut self) -> Result<(), RenderError> { - let mut frame = Frame::new(frame::Position::new(0, 0), Dimensions::new(80, 25))?; + let mut frame = Frame::new(render::Position::new(0, 0), Dimensions::new(80, 25))?; frame[10] = Game::centre_text(80, String::from("u lost")).chars().map(|c| ColouredChar::coloured(c, ColorCode::new(Color::Red, Color::Black))).collect(); frame[12] = Game::centre_text(80, String::from(format!("ur score was {}", self.score))).chars().map(|c| ColouredChar::coloured(c, ColorCode::new(Color::LightGreen, Color::Black))).collect(); diff --git a/src/user/bin/grapher.rs b/src/user/bin/grapher.rs index 5034e50..8997fd5 100644 --- a/src/user/bin/grapher.rs +++ b/src/user/bin/grapher.rs @@ -5,7 +5,7 @@ use alloc::boxed::Box; use core::any::Any; use async_trait::async_trait; use crate::std::application::{Application, Error}; -use crate::std::frame::{Frame, Position, Dimensions, ColouredChar, RenderError}; +use crate::std::render::{Frame, Position, Dimensions, ColouredChar, RenderError}; use crate::std::io::{Display, KeyStroke, Screen, Stdin}; use crate::user::lib::libgui::{ diff --git a/src/user/bin/mod.rs b/src/user/bin/mod.rs index b809b9c..b6ce62a 100644 --- a/src/user/bin/mod.rs +++ b/src/user/bin/mod.rs @@ -1,15 +1,13 @@ + pub mod calc; pub mod crystalfetch; pub mod rickroll; pub mod shell; -//pub mod shellrewrite; pub mod tasks; mod gigachad_detector; + //mod shellrewrite; -mod snake; + mod grapher; -mod gameoflife; -mod tetris; -mod asteroids; -mod crystalrpg; -mod pong; + +mod games; \ No newline at end of file diff --git a/src/user/bin/shell.rs b/src/user/bin/shell.rs index 7dfe8ed..8999bd5 100644 --- a/src/user/bin/shell.rs +++ b/src/user/bin/shell.rs @@ -24,6 +24,7 @@ use crate::user::{ cg_widgets::CgDialog, }, bin::*, + bin::games::*, }; lazy_static! { @@ -122,30 +123,30 @@ async fn exec() -> Result<(), Error> { let mode = Graphics640x480x16::new(); mode.set_mode(); mode.clear_screen(Color16::Black); - mode.draw_line((80, 60), (80, 420), Color16::Cyan); + mode.draw_line((80, 60), (120, 420), Color16::Cyan); } "graph" => { grapher::Grapher::new().run(args).await?; } - "snake" => { + "games/snake" => { snake::Game::new().run(args).await?; } - "asteroids" => { + "games/asteroids" => { let mut asteroid_game = asteroids::Game::new(); asteroid_game.run(args).await?; } - "pong" => { + "games/pong" => { pong::Game::new().run(args).await?; } "serial" => { let c = Serial::reply_char('e'); println!("{}", c); } - "gameoflife" => { + "games/gameoflife" => { let mut game = gameoflife::GameOfLife::new(); game.run(Vec::new()).await?; } - "tetris" => { + "games/tetris" => { // let mut game = tetris::TetrisEngine::new(); // game.run(Vec::new()).await?; } diff --git a/src/user/lib/libgui/cg_core.rs b/src/user/lib/libgui/cg_core.rs index aa4d4bc..fee4b1c 100644 --- a/src/user/lib/libgui/cg_core.rs +++ b/src/user/lib/libgui/cg_core.rs @@ -1,6 +1,6 @@ use hashbrown::HashMap; use spin::{Mutex}; -use crate::std::frame::{Frame, RenderError}; +use crate::std::render::{Frame, RenderError}; use alloc::{ boxed::Box, diff --git a/src/user/lib/libgui/cg_inputs.rs b/src/user/lib/libgui/cg_inputs.rs index 2734bad..d8940f3 100644 --- a/src/user/lib/libgui/cg_inputs.rs +++ b/src/user/lib/libgui/cg_inputs.rs @@ -4,21 +4,21 @@ use alloc::boxed::Box; use core::any::Any; use async_trait::async_trait; use crate::std::application::Exit; -use crate::std::frame::{ColouredChar, Dimensions, Frame, Position, RenderError}; +use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError}; use crate::std::io::{KeyStroke, Stdin}; use crate::user::lib::libgui::cg_core::{CgComponent, CgTextEdit, CgTextInput, Widget}; #[derive(Debug, Clone)] pub struct CgLineEdit { - pub position: Position, - pub dimensions: Dimensions, + pub position: Position, + pub dimensions: Dimensions, pub prompt: String, pub text: Vec, pub ptr: usize, // cursor position } impl CgLineEdit { - pub fn new(position: Position, width: usize, prompt: String) -> CgLineEdit { + pub fn new(position: Position, width: usize, prompt: String) -> CgLineEdit { CgLineEdit { position, dimensions: Dimensions::new(width, 1), @@ -131,15 +131,15 @@ impl CgTextInput for CgLineEdit { #[derive(Debug, Clone)] pub struct CgBoxEdit { - pub position: Position, - pub dimensions: Dimensions, + pub position: Position, + pub dimensions: Dimensions, pub prompt: String, pub text: Vec, - pub ptr: Position, + pub ptr: Position, } impl CgBoxEdit { - pub fn new(position: Position, dimensions: Dimensions, prompt: String) -> CgBoxEdit { + pub fn new(position: Position, dimensions: Dimensions, prompt: String) -> CgBoxEdit { CgBoxEdit { position, dimensions, diff --git a/src/user/lib/libgui/cg_utils.rs b/src/user/lib/libgui/cg_utils.rs index 0a8709c..83ce076 100644 --- a/src/user/lib/libgui/cg_utils.rs +++ b/src/user/lib/libgui/cg_utils.rs @@ -1,6 +1,6 @@ -use crate::std::frame::{ColouredChar, Dimensions, Frame, Position, RenderError}; +use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError}; -pub(crate) fn render_outline(frame: &mut Frame, dimensions: Dimensions) -> Result<(), RenderError> { +pub(crate) fn render_outline(frame: &mut Frame, dimensions: Dimensions) -> Result<(), RenderError> { // draws the sides of the container for i in 0..frame.dimensions.x { frame.write(Position::new(i, 0), ColouredChar::new('─'))?; diff --git a/src/user/lib/libgui/cg_widgets.rs b/src/user/lib/libgui/cg_widgets.rs index 4326edd..feff9b7 100644 --- a/src/user/lib/libgui/cg_widgets.rs +++ b/src/user/lib/libgui/cg_widgets.rs @@ -7,19 +7,19 @@ use hashbrown::HashMap; use crate::std::application::Exit; use super::cg_core::{CgComponent, CgKeyboardCapture, Widget}; use super::cg_utils::render_outline; -use crate::std::frame::{ColouredChar, Dimensions, Position, Frame, RenderError, ColorCode, BUFFER_WIDTH, BUFFER_HEIGHT}; +use crate::std::render::{ColouredChar, Dimensions, Position, Frame, RenderError, ColorCode, BUFFER_WIDTH, BUFFER_HEIGHT}; use crate::std::io::{Color, KeyStroke, Stdin}; #[derive(Debug, Clone)] pub struct CgContainer { pub elements: HashMap<&'static str, Widget>, - pub position: Position, - pub dimensions: Dimensions, + pub position: Position, + pub dimensions: Dimensions, pub outlined: bool, } impl CgContainer { - pub fn new(position: Position, dimensions: Dimensions, outlined: bool) -> CgContainer { + pub fn new(position: Position, dimensions: Dimensions, outlined: bool) -> CgContainer { CgContainer { elements: HashMap::new(), position, @@ -60,14 +60,14 @@ impl CgComponent for CgContainer { pub struct CgTextBox { title: String, pub content: String, - pub position: Position, - pub dimensions: Dimensions, + pub position: Position, + pub dimensions: Dimensions, outlined: bool, wrap_words: bool // if false then will not wrap until the end of a word if possible } impl CgTextBox { - pub fn new(title: String, content: String, position: Position, dimensions: Dimensions, outlined: bool) -> CgTextBox { + pub fn new(title: String, content: String, position: Position, dimensions: Dimensions, outlined: bool) -> CgTextBox { CgTextBox { title, content, position, dimensions, outlined, wrap_words: true } } @@ -143,13 +143,13 @@ impl CgComponent for CgTextBox { #[derive(Debug, Clone)] pub struct CgLabel { content: String, - position: Position, - dimensions: Dimensions, + position: Position, + dimensions: Dimensions, centered: bool, } impl CgLabel { - pub fn new(content: String, position: Position, width: usize, centered: bool) -> CgLabel { + pub fn new(content: String, position: Position, width: usize, centered: bool) -> CgLabel { CgLabel { content, position: Position::new(position.x, position.y), @@ -247,12 +247,12 @@ impl CgComponent for CgIndicatorWidget { #[derive(Debug, Clone)] pub struct CgIndicatorBar { pub fields: Vec, - position: Position, - dimensions: Dimensions, + position: Position, + dimensions: Dimensions, } impl CgIndicatorBar { - pub fn new(position: Position, width: usize) -> CgIndicatorBar { + pub fn new(position: Position, width: usize) -> CgIndicatorBar { CgIndicatorBar { fields: Vec::new(), position: Position::new(position.x, position.y), @@ -291,8 +291,8 @@ impl CgComponent for CgIndicatorBar { #[derive(Debug, Clone)] pub struct CgStatusBar { - position: Position, - dimensions: Dimensions, + position: Position, + dimensions: Dimensions, window_title: CgIndicatorWidget, screen_mode: CgIndicatorWidget, @@ -325,7 +325,7 @@ impl CgComponent for CgStatusBar { } impl CgStatusBar { - pub fn new(position: Position, dimensions: Dimensions) -> CgStatusBar { + pub fn new(position: Position, dimensions: Dimensions) -> CgStatusBar { let mut widget = CgStatusBar { position, dimensions,