initial commit
This commit is contained in:
commit
5817fea9ad
10 changed files with 465 additions and 0 deletions
73
src/bar.rs
Normal file
73
src/bar.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
use crate::command_queue::PacketQueue;
|
||||
use crate::{Currency, GenerateCommands, Progressable};
|
||||
use servicepoint::{Bitmap, BitmapCommand, Grid, Origin, TILE_SIZE, TILE_WIDTH, Tiles};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Bar {
|
||||
progress: f64,
|
||||
speed: f64,
|
||||
factor: f64,
|
||||
origin: Origin<Tiles>,
|
||||
width_tiles: usize,
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
pub(crate) fn new(factor: f64, origin: Origin<Tiles>) -> Bar {
|
||||
Self {
|
||||
factor,
|
||||
progress: 0f64,
|
||||
speed: 0.01f64,
|
||||
origin,
|
||||
width_tiles: TILE_WIDTH / 2, // TODO: param
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Progressable for Bar {
|
||||
fn progress(&self, delta: Duration) -> (Self, Currency) {
|
||||
let extra_progress = delta.as_secs_f64() * self.speed;
|
||||
let progress = self.progress + extra_progress;
|
||||
let completions = progress.floor();
|
||||
let progress = progress - completions;
|
||||
let currency = completions * self.factor;
|
||||
|
||||
(Self { progress, ..*self }, currency)
|
||||
}
|
||||
}
|
||||
|
||||
impl GenerateCommands for Bar {
|
||||
fn generate_commands(&self, q: &mut impl PacketQueue) {
|
||||
let mut bitmap = Bitmap::new(self.width_tiles * TILE_SIZE, TILE_SIZE).unwrap();
|
||||
|
||||
// border top
|
||||
let last_row = bitmap.height() - 1;
|
||||
for x in 0..bitmap.width() {
|
||||
bitmap.set(x, 0, true);
|
||||
bitmap.set(x, last_row, true);
|
||||
}
|
||||
|
||||
// border bottom
|
||||
let last_col = bitmap.width() - 1;
|
||||
for y in 0..bitmap.height() {
|
||||
bitmap.set(0, y, true);
|
||||
bitmap.set(last_col, y, true);
|
||||
}
|
||||
|
||||
// progress fill
|
||||
let fill_to = (bitmap.width() as f64 * self.progress) as usize;
|
||||
for y in 0..bitmap.height() {
|
||||
for x in 0..fill_to {
|
||||
bitmap.set(x, y, true);
|
||||
}
|
||||
}
|
||||
|
||||
// to command
|
||||
q.enqueue_command(BitmapCommand {
|
||||
bitmap,
|
||||
origin: Origin::from(&self.origin),
|
||||
compression: Default::default(),
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
20
src/command_queue.rs
Normal file
20
src/command_queue.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use servicepoint::{Packet, UdpSocketExt};
|
||||
use std::net::UdpSocket;
|
||||
|
||||
pub(crate) trait PacketQueue {
|
||||
fn enqueue_command<P: TryInto<Packet>>(&mut self, packet: P) -> Result<bool, P::Error>;
|
||||
}
|
||||
|
||||
impl PacketQueue for Vec<Packet> {
|
||||
fn enqueue_command<P: TryInto<Packet>>(&mut self, packet: P) -> Result<bool, P::Error> {
|
||||
self.push(packet.try_into()?);
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketQueue for UdpSocket {
|
||||
fn enqueue_command<P: TryInto<Packet>>(&mut self, packet: P) -> Result<bool, P::Error> {
|
||||
let packet = packet.try_into()?;
|
||||
Ok(self.send_command(packet).is_some())
|
||||
}
|
||||
}
|
||||
39
src/game_state.rs
Normal file
39
src/game_state.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use crate::bar::Bar;
|
||||
use crate::command_queue::PacketQueue;
|
||||
use crate::label::Label;
|
||||
use crate::{Currency, GenerateCommands, Progressable};
|
||||
use servicepoint::{Origin, TILE_WIDTH};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GameState {
|
||||
pub(crate) currency: Currency,
|
||||
pub(crate) first_step: Bar,
|
||||
}
|
||||
|
||||
impl Progressable for GameState {
|
||||
fn progress(&self, delta: Duration) -> (Self, Currency) {
|
||||
let (first_step, first_currency) = self.first_step.progress(delta);
|
||||
|
||||
let currency = self.currency + first_currency;
|
||||
|
||||
(
|
||||
Self {
|
||||
currency,
|
||||
first_step,
|
||||
},
|
||||
0f64,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl GenerateCommands for GameState {
|
||||
fn generate_commands(&self, queue: &mut impl PacketQueue) {
|
||||
Label::new(Origin::ZERO, TILE_WIDTH, "Discordia Boot Procedure").generate_commands(queue);
|
||||
|
||||
self.first_step.generate_commands(queue);
|
||||
Label::new(Origin::new(TILE_WIDTH / 2 + 1, 1), TILE_WIDTH / 2 - 1, "Power infrastructure")
|
||||
.generate_commands(queue);
|
||||
|
||||
}
|
||||
}
|
||||
35
src/label.rs
Normal file
35
src/label.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use crate::GenerateCommands;
|
||||
use crate::command_queue::PacketQueue;
|
||||
use servicepoint::{CharGrid, CharGridCommand, Origin, Tiles};
|
||||
|
||||
pub(crate) struct Label<S: AsRef<str>> {
|
||||
position: Origin<Tiles>,
|
||||
text: S,
|
||||
width_tiles: usize,
|
||||
}
|
||||
|
||||
impl Label<String> {
|
||||
pub(crate) fn new<S: AsRef<str>>(position: Origin<Tiles>, width_tiles: usize, text: S) -> Self {
|
||||
// TODO: those should be grapheme clusters
|
||||
let text = text.as_ref().chars().take(width_tiles).collect::<String>();
|
||||
Self {
|
||||
position,
|
||||
text,
|
||||
width_tiles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: AsRef<str>> GenerateCommands for Label<S> {
|
||||
fn generate_commands(&self, queue: &mut impl PacketQueue) {
|
||||
let mut grid = CharGrid::new(self.width_tiles, 1);
|
||||
grid.set_row_str(0, self.text.as_ref()).unwrap();
|
||||
|
||||
queue
|
||||
.enqueue_command(CharGridCommand {
|
||||
grid: CharGrid::from(self.text.as_ref()),
|
||||
origin: self.position,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
43
src/main.rs
Normal file
43
src/main.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use crate::command_queue::PacketQueue;
|
||||
use bar::Bar;
|
||||
use game_state::GameState;
|
||||
use servicepoint::{ClearCommand, Origin, UdpSocketExt};
|
||||
use std::net::UdpSocket;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
mod bar;
|
||||
mod command_queue;
|
||||
mod game_state;
|
||||
mod label;
|
||||
|
||||
type Currency = f64;
|
||||
|
||||
trait Progressable: Sized {
|
||||
#[must_use]
|
||||
fn progress(&self, delta: Duration) -> (Self, Currency);
|
||||
}
|
||||
|
||||
trait GenerateCommands {
|
||||
fn generate_commands(&self, queue: &mut impl PacketQueue);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut state = GameState {
|
||||
currency: 0f64,
|
||||
first_step: Bar::new(1f64, Origin::new(0, 1)),
|
||||
};
|
||||
|
||||
let mut connection = UdpSocket::bind_connect("127.0.0.1:2342").unwrap();
|
||||
|
||||
let mut last_refresh = Instant::now();
|
||||
loop {
|
||||
let current_time = Instant::now();
|
||||
let delta = current_time - last_refresh;
|
||||
last_refresh = current_time;
|
||||
|
||||
(state, _) = state.progress(delta);
|
||||
|
||||
connection.send_command(ClearCommand);
|
||||
state.generate_commands(&mut connection);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue