.
.
This commit is contained in:
@@ -12,7 +12,7 @@ use crate::std::frame::{Position, Dimensions, RenderError, Frame, ColouredChar};
|
|||||||
use crate::std::io::{Color, ColorCode, KeyStroke, Screen, Stdin};
|
use crate::std::io::{Color, ColorCode, KeyStroke, Screen, Stdin};
|
||||||
use crate::std::random::Random;
|
use crate::std::random::Random;
|
||||||
use crate::user::lib::libgui::cg_core::{CgComponent, Widget};
|
use crate::user::lib::libgui::cg_core::{CgComponent, Widget};
|
||||||
use crate::user::lib::libgui::cg_widgets::{CgContainer, CgIndicatorWidget};
|
use crate::user::lib::libgui::cg_widgets::{CgContainer, CgIndicatorWidget, CgLabel};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
@@ -33,6 +33,9 @@ pub struct Game {
|
|||||||
pub player: Player,
|
pub player: Player,
|
||||||
pub enemies: Vec<Enemy>,
|
pub enemies: Vec<Enemy>,
|
||||||
pub score: u32,
|
pub score: u32,
|
||||||
|
pub hit: bool,
|
||||||
|
pub difficulty_idx: u8,
|
||||||
|
pub gamespeed: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -41,7 +44,10 @@ impl Application for Game {
|
|||||||
Self {
|
Self {
|
||||||
player: Player::new(),
|
player: Player::new(),
|
||||||
enemies: Vec::new(),
|
enemies: Vec::new(),
|
||||||
score: 0
|
score: 0,
|
||||||
|
hit: false,
|
||||||
|
difficulty_idx: 1,
|
||||||
|
gamespeed: 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
@@ -55,23 +61,55 @@ impl Application for Game {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let score_label = Widget::insert(CgLabel::new(
|
||||||
|
String::new(),
|
||||||
|
Position::new(1, 1),
|
||||||
|
78,
|
||||||
|
true,
|
||||||
|
));
|
||||||
|
|
||||||
let self_ref = Widget::insert(self.clone());
|
let self_ref = Widget::insert(self.clone());
|
||||||
container_data.insert("app", self_ref);
|
container_data.insert("app", self_ref);
|
||||||
|
container_data.insert("score_label", score_label);
|
||||||
let self_ref = container_data.fetch("app").unwrap();
|
let self_ref = container_data.fetch("app").unwrap();
|
||||||
|
let score_ref = container_data.fetch("score_label").unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
std::time::wait(0.1);
|
match self.score {
|
||||||
|
0..=9 => { self.gamespeed = 1.0; self.difficulty_idx = 1 },
|
||||||
|
10..=24 => { self.gamespeed = 2.0; self.difficulty_idx = 2 },
|
||||||
|
25..=49 => { self.gamespeed = 3.0; self.difficulty_idx = 3 },
|
||||||
|
50..=99 => { self.gamespeed = 4.0; self.difficulty_idx = 4 },
|
||||||
|
100..=199 => { self.gamespeed = 5.0; self.difficulty_idx = 5 },
|
||||||
|
_ => self.gamespeed = 10.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::time::wait(0.2 / self.gamespeed);
|
||||||
|
|
||||||
spawn_timer += 1;
|
spawn_timer += 1;
|
||||||
|
|
||||||
if spawn_timer >= 8 {
|
if spawn_timer >= 8 {
|
||||||
spawn_timer = 0;
|
spawn_timer = 0;
|
||||||
self.enemies.push(Enemy::new(Random::int(1, 21)));
|
self.new_enemy();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.enemies.retain(|e| {if e.position.x <= 0 {self.score += 1; false } else { true }});
|
self.enemies.iter().for_each(|e| {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
self.enemies.retain(|e| {
|
||||||
|
if e.position.y == self.player.position.y && (0..5).map(|i| e.position.x + i).collect::<Vec<_>>().contains(&self.player.position.x) {
|
||||||
|
self.player.health -= 1;
|
||||||
|
self.hit = true;
|
||||||
|
false
|
||||||
|
} else if e.position.x <= 0 {
|
||||||
|
self.score += 1;
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
self.enemies.iter_mut().for_each(|e| e.position.x -= 1);
|
self.enemies.iter_mut().for_each(|e| e.position.x -= 1);
|
||||||
self.enemies.iter().for_each(|e| { if e.position.x == self.player.position.x && e.position.y == self.player.position.y { self.player.health -= 1; } });
|
|
||||||
|
|
||||||
if self.player.health == 0 {
|
if self.player.health == 0 {
|
||||||
break;
|
break;
|
||||||
@@ -90,9 +128,11 @@ impl Application for Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self_ref.update(self.clone());
|
self_ref.update(self.clone());
|
||||||
|
score_ref.update(CgLabel::new(format!("< Score: {} >", self.score), Position::new(1, 1), 78, true, ));
|
||||||
if let Ok(frame) = container_data.render() {
|
if let Ok(frame) = container_data.render() {
|
||||||
frame.write_to_screen().unwrap();
|
frame.write_to_screen().unwrap();
|
||||||
}
|
}
|
||||||
|
self.hit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut frame = Frame::new(Dimensions::new(0, 0), Dimensions::new(80, 25)).map_err(|_| ApplicationError("idk".to_string()))?;
|
let mut frame = Frame::new(Dimensions::new(0, 0), Dimensions::new(80, 25)).map_err(|_| ApplicationError("idk".to_string()))?;
|
||||||
@@ -117,22 +157,48 @@ impl Application for Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
fn new_enemy(&mut self) {
|
||||||
|
|
||||||
|
let enemy_num = match self.difficulty_idx {
|
||||||
|
1 => 1,
|
||||||
|
2 => 2,
|
||||||
|
3 => 3,
|
||||||
|
4 => 5,
|
||||||
|
_ => 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
for _ in 0..enemy_num {
|
||||||
|
self.enemies.push(Enemy::new(Random::int(1, 21)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CgComponent for Game {
|
impl CgComponent for Game {
|
||||||
fn render(&self) -> Result<Frame, RenderError> {
|
fn render(&self) -> Result<Frame, RenderError> {
|
||||||
let mut frame = Frame::new(Dimensions::new(1, 1), Dimensions::new(78, 23))?;
|
let mut frame = Frame::new(Dimensions::new(1, 2), Dimensions::new(78, 22))?;
|
||||||
|
|
||||||
let pos = self.player.position;
|
let pos = self.player.position;
|
||||||
|
|
||||||
|
let player_colour = match self.hit {
|
||||||
|
true => Color::Red,
|
||||||
|
false => Color::Cyan
|
||||||
|
};
|
||||||
|
|
||||||
frame[pos.y][pos.x] = ColouredChar {
|
frame[pos.y][pos.x] = ColouredChar {
|
||||||
character: '@',
|
character: '@',
|
||||||
colour: ColorCode::new(Color::Cyan, Color::Black),
|
colour: ColorCode::new(player_colour, Color::Black),
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in self.enemies.iter().map(|enemy| enemy.position).collect::<Vec<Position>>() {
|
for i in self.enemies.iter().map(|enemy| enemy.position).collect::<Vec<Position>>() {
|
||||||
frame[i.y][i.x] = ColouredChar {
|
frame[i.y][i.x] = ColouredChar {
|
||||||
character: '*',
|
character: '<',
|
||||||
colour: ColorCode::new(Color::Red, Color::Black),
|
colour: ColorCode::new(Color::LightGray, Color::Black),
|
||||||
}
|
};
|
||||||
|
(1..5).for_each(|offset| if i.x + offset < frame.dimensions.x { frame[i.y][i.x + offset] = ColouredChar {
|
||||||
|
character: '=',
|
||||||
|
colour: ColorCode::new(Color::LightGray, Color::Black),
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(frame)
|
Ok(frame)
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
mod render;
|
pub mod game;
|
||||||
pub(crate) mod game;
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
use crate::println;
|
|
||||||
|
|
||||||
@@ -258,6 +258,7 @@ async fn setup_ui() {
|
|||||||
String::from("test label"),
|
String::from("test label"),
|
||||||
Position::new(1, 1),
|
Position::new(1, 1),
|
||||||
40,
|
40,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
let textbox = Widget::insert(CgTextBox::new(
|
let textbox = Widget::insert(CgTextBox::new(
|
||||||
|
|||||||
@@ -192,14 +192,16 @@ pub struct CgLabel {
|
|||||||
content: String,
|
content: String,
|
||||||
position: Position,
|
position: Position,
|
||||||
dimensions: Dimensions,
|
dimensions: Dimensions,
|
||||||
|
centered: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CgLabel {
|
impl CgLabel {
|
||||||
pub fn new(content: String, position: Position, width: usize) -> CgLabel {
|
pub fn new(content: String, position: Position, width: usize, centered: bool) -> CgLabel {
|
||||||
CgLabel {
|
CgLabel {
|
||||||
content,
|
content,
|
||||||
position: Position::new(position.x, position.y),
|
position: Position::new(position.x, position.y),
|
||||||
dimensions: Dimensions::new(width, 1),
|
dimensions: Dimensions::new(width, 1),
|
||||||
|
centered,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set_text(&mut self, text: String) {
|
pub fn set_text(&mut self, text: String) {
|
||||||
@@ -213,8 +215,22 @@ impl CgComponent for CgLabel {
|
|||||||
|
|
||||||
let shortened_string = self.content.chars().take(self.dimensions.x).collect::<String>();
|
let shortened_string = self.content.chars().take(self.dimensions.x).collect::<String>();
|
||||||
|
|
||||||
|
let left = if self.centered && self.content.len() < self.dimensions.x {
|
||||||
|
let difference = self.dimensions.x - self.content.len();
|
||||||
|
difference / 2
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
for (i, c) in shortened_string.chars().enumerate() {
|
for (i, c) in shortened_string.chars().enumerate() {
|
||||||
result.write(Position::new(i, 0), ColouredChar::new(c));
|
if i + left >= self.dimensions.x {
|
||||||
|
(0..3).for_each(|z| {
|
||||||
|
result.write(Position::new(self.dimensions.x - z + left, self.dimensions.y - 1), ColouredChar::new('.'));
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result.write(Position::new(i + left, 0), ColouredChar::new(c));
|
||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user