increase max speed and step counter digits, show microseconds per step, massive simulation optimisation for large worlds (5-100x faster)

This commit is contained in:
Crispy 2024-12-07 16:19:59 +01:00
parent 140a462add
commit c1094980a6
2 changed files with 27 additions and 14 deletions

View file

@ -28,6 +28,8 @@ const FOOTER_HEIGHT: i32 = 95;
const SIDEBAR_WIDTH: i32 = 200 + 32 * 2 + 5 * 4; const SIDEBAR_WIDTH: i32 = 200 + 32 * 2 + 5 * 4;
const MAX_ZOOM_IN: i32 = 3; const MAX_ZOOM_IN: i32 = 3;
const BOARD_MARGIN: isize = 3; const BOARD_MARGIN: isize = 3;
const MAX_SPEED_POWER: u8 = 16;
const SPEED_DIGITS: u8 = 5;
#[derive(Debug)] #[derive(Debug)]
pub struct Editor { pub struct Editor {
@ -58,6 +60,7 @@ pub struct Editor {
blueprints: Vec<Blueprint>, blueprints: Vec<Blueprint>,
selected_blueprint: usize, selected_blueprint: usize,
blueprint_scroll: usize, blueprint_scroll: usize,
step_time: u128,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -133,6 +136,7 @@ impl Editor {
blueprints: get_blueprints(), blueprints: get_blueprints(),
selected_blueprint: usize::MAX, selected_blueprint: usize::MAX,
blueprint_scroll: 0, blueprint_scroll: 0,
step_time: 0,
} }
} }
@ -174,7 +178,10 @@ impl Editor {
} }
fn step(&mut self) { fn step(&mut self) {
let start_time = std::time::Instant::now();
self.machine.step(); self.machine.step();
self.step_time = start_time.elapsed().as_micros();
if self.complete_popup == Popup::Visible { if self.complete_popup == Popup::Visible {
self.complete_popup = Popup::Dismissed; self.complete_popup = Popup::Dismissed;
} }
@ -572,20 +579,21 @@ impl Editor {
} }
draw_scaled_texture(d, textures.get("step"), 332, 4, 2.); draw_scaled_texture(d, textures.get("step"), 332, 4, 2.);
d.draw_text("spd", 368, 6, 10, Color::WHITE); draw_usize(d, textures, 1 << self.sim_speed, 368, 4, SPEED_DIGITS, 1);
draw_usize(d, textures, 1 << self.sim_speed, 388, 4, 3, 1); slider(d, &mut self.sim_speed, 0, MAX_SPEED_POWER, 368, 24, 48, 12);
slider(d, &mut self.sim_speed, 0, 9, 368, 24, 48, 12);
draw_usize(d, textures, self.machine.step_count(), 420, 4, 5, 2); draw_usize(d, textures, self.machine.step_count(), 420, 4, 9, 2);
d.draw_text("input:", 523, 8, 10, Color::WHITE); draw_usize(d, textures, self.step_time as usize, 540, 42, 9, 1);
if simple_button(d, 520, 20, 35, 15) {
d.draw_text("input:", 603, 8, 10, Color::WHITE);
if simple_button(d, 600, 20, 35, 15) {
self.input_as_text = !self.input_as_text self.input_as_text = !self.input_as_text
} }
let input_mode_text = if self.input_as_text { "text" } else { "bytes" }; let input_mode_text = if self.input_as_text { "text" } else { "bytes" };
d.draw_text(input_mode_text, 523, 23, 10, Color::WHITE); d.draw_text(input_mode_text, 603, 23, 10, Color::WHITE);
let input_x = 560; let input_x = 638;
let width = d.get_screen_width(); let width = d.get_screen_width();
if self.input_as_text { if self.input_as_text {
let mut input_text = String::new(); let mut input_text = String::new();

View file

@ -1,3 +1,5 @@
use std::hint::unreachable_unchecked;
use raylib::prelude::*; use raylib::prelude::*;
pub mod board; pub mod board;
@ -13,6 +15,7 @@ use crate::{draw_usize_small, Textures};
pub struct Machine { pub struct Machine {
board: Board, board: Board,
marbles: Vec<Pos>, marbles: Vec<Pos>,
powered: Vec<Pos>,
input: Vec<u8>, input: Vec<u8>,
input_index: usize, input_index: usize,
@ -25,6 +28,7 @@ impl Machine {
Self { Self {
board: Board::new_empty(width, width), board: Board::new_empty(width, width),
marbles: Vec::new(), marbles: Vec::new(),
powered: Vec::new(),
input, input,
input_index: 0, input_index: 0,
output: Vec::new(), output: Vec::new(),
@ -97,13 +101,13 @@ impl Machine {
pub fn step(&mut self) { pub fn step(&mut self) {
self.steps += 1; self.steps += 1;
// reset wires // reset wires
for y in 0..self.board.height() { for &p in &self.powered {
for x in 0..self.board.width() { let Some(Tile::Powerable(_, state)) = self.board.get_mut(p) else {
if let Some(Tile::Powerable(_, state)) = self.board.get_mut((x, y).into()) { unsafe { unreachable_unchecked() }
};
*state = false; *state = false;
} }
} self.powered.clear();
}
if self.marbles.is_empty() { if self.marbles.is_empty() {
return; return;
@ -302,6 +306,7 @@ impl Machine {
} }
let was_powered = *state; let was_powered = *state;
*state = true; *state = true;
self.powered.push(pos);
match tile { match tile {
PTile::Wire(wiretype) => { PTile::Wire(wiretype) => {
if was_powered { if was_powered {