~saiko/game

1ace5c9a55f45d376e637901a4eae5d26806b366 — 2xsaiko 1 year, 13 days ago 8f9cd7f
Redesign main
3 files changed, 174 insertions(+), 113 deletions(-)

D data/font/terminus.fdef
M src/main.rs
M src/ui/host.rs
D data/font/terminus.fdef => data/font/terminus.fdef +0 -19
@@ 1,19 0,0 @@
bdf terminus/ter-u12n.bdf 12 normal
bdf terminus/ter-u14n.bdf 14 normal
bdf terminus/ter-u16n.bdf 16 normal
bdf terminus/ter-u18n.bdf 18 normal
bdf terminus/ter-u20n.bdf 20 normal
bdf terminus/ter-u22n.bdf 22 normal
bdf terminus/ter-u24n.bdf 24 normal
bdf terminus/ter-u28n.bdf 28 normal
bdf terminus/ter-u32n.bdf 32 normal

bdf terminus/ter-u12b.bdf 12 bold
bdf terminus/ter-u14b.bdf 14 bold
bdf terminus/ter-u16b.bdf 16 bold
bdf terminus/ter-u18b.bdf 18 bold
bdf terminus/ter-u20b.bdf 20 bold
bdf terminus/ter-u22b.bdf 22 bold
bdf terminus/ter-u24b.bdf 24 bold
bdf terminus/ter-u28b.bdf 28 bold
bdf terminus/ter-u32b.bdf 32 bold
\ No newline at end of file

M src/main.rs => src/main.rs +170 -94
@@ 11,6 11,7 @@ use std::fs::{create_dir_all, File};
use std::io::Read;
use std::ops::Sub;
use std::path::PathBuf;
use std::process::exit;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};


@@ 19,12 20,12 @@ use std::time::{Duration, Instant};

use float_pretty_print::PrettyPrintFloat;
use glium::{BackfaceCullingMode, DepthTest, Display, DrawError, DrawParameters, Program, Surface, VertexBuffer};
use glium::backend::glutin::glutin::platform::desktop::EventLoopExtDesktop;
use glium::glutin::{ContextBuilder, GlProfile, GlRequest};
use glium::glutin::Api::OpenGl;
use glium::glutin::dpi::{LogicalPosition, LogicalSize};
use glium::glutin::event::{ElementState, Event, WindowEvent};
use glium::glutin::event_loop::{ControlFlow, EventLoop};
use glium::glutin::platform::desktop::EventLoopExtDesktop;
use glium::glutin::dpi::LogicalSize;
use glium::glutin::event::{Event, WindowEvent};
use glium::glutin::event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget};
use glium::glutin::window::WindowBuilder;
use glium::index::IndicesSource::NoIndices;
use glium::index::PrimitiveType;


@@ 34,7 35,7 @@ use log::{info, LevelFilter, warn};
use simplelog::{CombinedLogger, Config, ConfigBuilder, TerminalMode, TermLogger, WriteLogger};

use crate::cam::Camera;
use crate::cmd::{command, CommandDispatcher, ConVar, EngineBuilder, ExecSource, expand_command, SimpleExecutor};
use crate::cmd::{command, CommandDispatcher, ConsoleEngine, ConVar, EngineBuilder, ExecSource, expand_command, SimpleExecutor};
use crate::font::{bdf, FontRenderer};
use crate::font::bdf::draw::BakedFont;
use crate::font::multifont::{Multifont, Selector};


@@ 47,7 48,6 @@ use crate::shader::ShaderManager;
use crate::ui::graphics::{Alignment, Graphics, StringDrawProps};
use crate::ui::host::UiHost;
use crate::util::{AnySurface, Color, LogPipe};
use crate::testui::TestUiController;

mod cam;
mod cmd;


@@ 117,10 117,11 @@ fn main() {
    .map(|p| I18n::parse_from_res(&rl, &format!("strs/{}.str", p)).unwrap())
    .fold(I18n::new(), |acc, a| acc.merge(a));

  start_game(Rc::new(Environment { rl, i18n, data_dir, save_dir, v_sync, init_script }));
  start_game(Environment { rl, i18n, data_dir, save_dir, v_sync, init_script });
}

fn start_game(env: Rc<Environment>) {
fn start_game(env: Environment) -> ! {
  let env = Rc::new(env);
  let title = format!("{} v{} {}", GAME_NAME, GAME_VERSION, if cfg!(debug_assertions) { "Debug" } else { "Release" });

  let mut event_loop = EventLoop::new();


@@ 191,26 192,134 @@ fn start_game(env: Rc<Environment>) {
  let mut kb = Keyboard::new();
  camera.borrow_mut().set_pos(vec3(0.0, 10.0, 0.0));

  let mut current_fps = 0;
  let mut smooth_fps = 0;
  let mut frames_since_last = 0;
  let mut last_smooth_fps = Instant::now();
  let fr = load_fonts(&env.rl, &display, &mut sm);

  let mut gui_mode = true;
  let mut game = Game {
    env: env.clone(),
    ce,
    running,
    display: &display,
    sm,
    window,
    ui_host: UiHost::new(),
    kb,
    fps: FpsCounter::new(),
    camera,
    fr,
  };

  if !gui_mode {
    gl_window.set_cursor_grab(true).unwrap();
    gl_window.set_cursor_visible(false);
  }
  event_loop.run_return(|event, target, cf| game.handle_event(event, target, cf));
  exit(0);
}

  let fr = load_fonts(&env.rl, &display, &mut sm);
pub struct GameContainer<'a> {
  event_loop: EventLoop<()>,
  game: Game<'a>,
}

pub struct Game<'a> {
  env: Rc<Environment>,
  ce: ConsoleEngine<LogPipe<'static>>,
  running: Arc<AtomicBool>,
  display: &'a Display,
  sm: ShaderManager<'a>,
  window: Window,
  ui_host: UiHost,
  kb: Keyboard,
  fps: FpsCounter,
  camera: Rc<RefCell<Camera>>,
  fr: Multifont<(i32, bool, f64), (i32, bool), BakedFont<'a>, SelImpl>,
}

impl Game<'_> {
  fn handle_event(&mut self, event: Event<()>, target: &EventLoopWindowTarget<()>, cf: &mut ControlFlow) {
    match event {
      Event::WindowEvent { event: WindowEvent::RedrawRequested, .. } => {
        self.cycle(false);
      }
      Event::EventsCleared => {
        if self.ui_host.is_animated() {
          self.cycle(true);
        }
      }
      Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
        self.running.store(false, Ordering::Relaxed);
      }
      Event::WindowEvent { event: WindowEvent::Resized(LogicalSize { width, height }), .. } => {
        self.window.on_resize(width, height);
        self.ui_host.resize(self.window.width(), self.window.height());
      }
      Event::WindowEvent { event: WindowEvent::KeyboardInput { input, .. }, .. } => {
        // self.ui_host.press_key();
      }
      Event::WindowEvent { event: WindowEvent::Focused(state), .. } => {
//          if !gui_mode {
//            gl_window.set_cursor_grab(state).unwrap();
//            gl_window.set_cursor_visible(!state);
//            gl_window.set_cursor_position(center).unwrap();
//          }
      }
      Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => {
//          mdiff = Some((position.x - center.x, position.y - center.y));
      }
      Event::WindowEvent { event: WindowEvent::HiDpiFactorChanged(f), .. } => {
        self.window.on_dpi_changed(f);
        self.ui_host.resize(self.window.width(), self.window.height());
      }
      _ => ()
    }

    if !self.running.load(Ordering::Relaxed) {
      *cf = ControlFlow::Exit;
    }
  }

  let mut ui_host = UiHost::new();
  ui_host.resize(window.width(), window.height());
  fn cycle(&mut self, limit: bool) {
    self.fps.end_frame(if limit { 120 } else { 0 });
    self.draw();

//    let center = LogicalPosition::new(self.window.scaled_width as f64 / 2.0, self.window.scaled_height as f64 / 2.0);
//    let mut mdiff = None;
//
//    if !gui_mode {
//      let mut camera = self.camera.borrow_mut();
//      if let Some((mdiff_x, mdiff_y)) = mdiff {
//        camera.rotate(mdiff_x as f32 * 0.1, -mdiff_y as f32 * 0.1, 0.0);
//        self.gl_window.set_cursor_position(center).unwrap();
//      }
//
//      if self.kb.esc { self.running.store(false, Ordering::Relaxed); }
//
//      let cam_mat = camera.get_matrix().into_mat3();
//      let mut movement = Vec3::origin();
//      if self.kb.fwd { movement += vec3(0.0, 0.0, 1.0); }
//      if self.kb.back { movement += vec3(0.0, 0.0, -1.0); }
//      if self.kb.left { movement += vec3(1.0, 0.0, 0.0); }
//      if self.kb.right { movement += vec3(-1.0, 0.0, 0.0); }
//
//      camera.shift(cam_mat * movement * 0.1);
//    }

    self.ce.dispatcher_mut().resume();
  }

  ui_host.open_ui(TestUiController::new());
  fn draw(&mut self) {
    let Game {
      env,
      ce,
      running,
      sm,
      window,
      ui_host,
      kb,
      camera,
      display,
      fps,
      fr
    } = self;

    let display = *display;

  while running.load(Ordering::Relaxed) {
    let time_start = Instant::now();
    let mut frame = display.draw();
    frame.clear(None, Some((0.0, 0.0, 0.0, 0.0)), false, Some(1.0), None);


@@ 219,18 328,18 @@ fn start_game(env: Rc<Environment>) {
    let gui_mat = Mat4::get_ortho(0.0, window.width() as f32, window.height() as f32, 0.0, -1000.0, 1000.0);

    let mut surface = AnySurface::Frame(&mut frame);
    let mut g = Graphics::new(&display, &mut surface, fr.choose((12, false, window.dpi)), &mut sm, gui_mat);
    let mut g = Graphics::new(display, &mut surface, self.fr.choose((12, false, window.dpi)), &mut self.sm, gui_mat);

    ui_host.draw(&mut g);
    self.ui_host.draw(&mut g);

    let fr = fr.choose((14, false, window.dpi));
    let fr = self.fr.choose((14, false, window.dpi));

    let s = "Press [tab] to switch views";
    let color = Color::white();
    g.push_matrix(|g| {
      g.translatei(0, 0, 100);
      g.draw_string(s, window.width() as i32 - 2, 2, StringDrawProps::default().with_alignment(Alignment::Right));
      g.draw_string(&format!("fps: {} ({} actual)", smooth_fps, current_fps), 2, 2, StringDrawProps::default());
      g.draw_string(&format!("fps: {} ({} actual)", fps.smooth_fps(), fps.current_fps()), 2, 2, StringDrawProps::default());

      let camera = camera.borrow();
      g.draw_string(&format!("pos: {:5.3} {:5.3} {:5.3}",


@@ 246,87 355,54 @@ fn start_game(env: Rc<Environment>) {
    });
    drop(g);
    frame.finish().unwrap();
  }

    let center = LogicalPosition::new(window.scaled_width as f64 / 2.0, window.scaled_height as f64 / 2.0);
    let mut mdiff = None;

    event_loop.run_return(|event, target, cf| {
      *cf = ControlFlow::Exit;
      match event {
        Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
          running.store(false, Ordering::Relaxed);
        }
        Event::WindowEvent { event: WindowEvent::Resized(LogicalSize { width, height }), .. } => {
          window.on_resize(width, height);
          ui_host.resize(window.width(), window.height());
        }
        Event::WindowEvent { event: WindowEvent::KeyboardInput { input, .. }, .. } => {
          if input.scancode == 15 && input.state == ElementState::Pressed {
            gui_mode = !gui_mode;
            gl_window.set_cursor_grab(!gui_mode).unwrap();
            gl_window.set_cursor_visible(gui_mode);
            gl_window.set_cursor_position(center).unwrap();
          } else {
            kb.handle_event(&input);
          }
        }
        Event::WindowEvent { event: WindowEvent::Focused(state), .. } => {
          if !gui_mode {
            gl_window.set_cursor_grab(state).unwrap();
            gl_window.set_cursor_visible(!state);
            gl_window.set_cursor_position(center).unwrap();
          }
        }
        Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. } => {
          mdiff = Some((position.x - center.x, position.y - center.y));
        }
        Event::WindowEvent { event: WindowEvent::HiDpiFactorChanged(f), .. } => {
          window.on_dpi_changed(f);
          ui_host.resize(window.width(), window.height());
        }
        _ => ()
      };
    });

    if !gui_mode {
      let mut camera = camera.borrow_mut();
      if let Some((mdiff_x, mdiff_y)) = mdiff {
        camera.rotate(mdiff_x as f32 * 0.1, -mdiff_y as f32 * 0.1, 0.0);
        gl_window.set_cursor_position(center).unwrap();
      }

      if kb.esc { running.store(false, Ordering::Relaxed); }
  fn mouse_move(&mut self) {}
}

      let cam_mat = camera.get_matrix().into_mat3();
      let mut movement = Vec3::origin();
      if kb.fwd { movement += vec3(0.0, 0.0, 1.0); }
      if kb.back { movement += vec3(0.0, 0.0, -1.0); }
      if kb.left { movement += vec3(1.0, 0.0, 0.0); }
      if kb.right { movement += vec3(-1.0, 0.0, 0.0); }
pub struct FpsCounter {
  last_frame_start: Instant,
  current_fps: u64,
  smooth_fps: u64,
  last_smooth_fps: Instant,
  frames_since_last: u64,
}

      camera.shift(cam_mat * movement * 0.1);
impl FpsCounter {
  pub fn new() -> Self {
    FpsCounter {
      last_frame_start: Instant::now(),
      current_fps: 0,
      smooth_fps: 0,
      last_smooth_fps: Instant::now(),
      frames_since_last: 0,
    }
  }

    ce.dispatcher_mut().resume();

    {
      let fps_max = ce.get_cvar("fps_limit").unwrap().get_int_value().unwrap() as u64;
      let frame_time = Duration::from_micros(1000000 / fps_max);
      let elapsed = time_start.elapsed();
  pub fn end_frame(&mut self, fps_target: u64) {
    if fps_target > 0 {
      let frame_time = Duration::from_micros(1000000 / fps_target);
      let elapsed = self.last_frame_start.elapsed();
      if elapsed < frame_time {
        sleep(frame_time.clone().sub(elapsed));
      }
    }

    current_fps = (1000000000 / time_start.elapsed().as_nanos()) as u32;
    frames_since_last += 1;
    let last_smooth = last_smooth_fps.elapsed();
    self.current_fps = (1000000000 / self.last_frame_start.elapsed().as_nanos()) as u64;
    self.frames_since_last += 1;
    let last_smooth = self.last_smooth_fps.elapsed();
    if last_smooth.as_secs() > 0 {
      smooth_fps = frames_since_last * 1000000000 / last_smooth.as_nanos();
      frames_since_last = 0;
      last_smooth_fps = Instant::now();
      self.smooth_fps = self.frames_since_last * 1000000000 / last_smooth.as_nanos() as u64;
      self.frames_since_last = 0;
      self.last_smooth_fps = Instant::now();
    }

    self.last_frame_start = Instant::now();
  }

  pub fn smooth_fps(&self) -> u64 { self.smooth_fps }

  pub fn current_fps(&self) -> u64 { self.current_fps }
}

fn draw(surface: &mut AnySurface, model: &Model<Vertex>, props: &RenderProperties) {

M src/ui/host.rs => src/ui/host.rs +4 -0
@@ 45,4 45,8 @@ impl UiHost {
      c.draw(g)
    }
  }

  pub fn is_animated(&self) -> bool {
    true
  }
}
\ No newline at end of file