it's like minifb but at home
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

124 líneas
3.5 KiB

  1. #![allow(dead_code)]
  2. // modules
  3. pub mod color;
  4. pub mod prelude;
  5. // namespacing
  6. use color::Color;
  7. pub use minifb::{Key, MouseButton};
  8. use minifb::{Window, WindowOptions};
  9. // error type
  10. #[derive(Debug, thiserror::Error)]
  11. pub enum Error {
  12. #[error(transparent)]
  13. MiniFb(#[from] minifb::Error),
  14. }
  15. // result type
  16. pub type Result<T> = std::result::Result<T, Error>;
  17. // pixel buffer for internal use
  18. struct PixelBuffer {
  19. data: Vec<u32>,
  20. width: usize,
  21. height: usize,
  22. }
  23. impl PixelBuffer {
  24. // create a new pixel buffer
  25. fn new(width: usize, height: usize) -> PixelBuffer {
  26. PixelBuffer { width, height, data: vec![0; height * width] }
  27. }
  28. // index pixel buffer !! will panic if given x/y are out of bounds
  29. fn at(&self, x: usize, y: usize) -> &u32 {
  30. assert!(x < self.width);
  31. assert!(y < self.height);
  32. &self.data[y * self.width + x]
  33. }
  34. // index pixel buffer mut !! will panic if given x/y are out of bounds
  35. fn at_mut(&mut self, x: usize, y: usize) -> &mut u32 {
  36. assert!(x < self.width);
  37. assert!(y < self.height);
  38. &mut self.data[y * self.width + x]
  39. }
  40. // returns the buffer as a slice
  41. fn as_ref(&self) -> &[u32] {
  42. &self.data
  43. }
  44. // returns a mutable reference to a slice
  45. fn as_mut_ref(&mut self) -> &mut [u32] {
  46. &mut self.data
  47. }
  48. }
  49. /// context data
  50. pub struct Context {
  51. pixel_buffer: PixelBuffer,
  52. height: usize,
  53. width: usize,
  54. window: Window,
  55. }
  56. impl Context {
  57. /// create a new context
  58. pub fn new(width: usize, height: usize, title: String) -> Result<Context> {
  59. let pixel_buffer = PixelBuffer::new(height, width);
  60. let mut window = Window::new(&title, width, height, WindowOptions::default())?;
  61. window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
  62. Ok(Context { pixel_buffer, window, height, width })
  63. }
  64. /// render the internal buffer to the screen
  65. pub fn present(&mut self) -> Result<()> {
  66. self.window.update_with_buffer(&self.pixel_buffer.as_ref(), self.width, self.height)?;
  67. Ok(())
  68. }
  69. /// clears the pixel buffer
  70. pub fn clear(&mut self, color: Option<color::Color>) {
  71. let color = color.unwrap_or(color::BLACK);
  72. self.pixel_buffer.as_mut_ref().iter_mut().for_each(|pixel| *pixel = color.as_u32());
  73. }
  74. /// checks if window is open
  75. pub fn is_open(&self) -> bool {
  76. self.window.is_open()
  77. }
  78. /// set a pixel
  79. pub fn insert_pixel(&mut self, x: usize, y: usize, color: Color) {
  80. if x < self.pixel_buffer.width && y < self.pixel_buffer.height {
  81. *self.pixel_buffer.at_mut(x, y) = color.as_u32();
  82. }
  83. }
  84. /// insert a slice into the pixel buffer x/y are offsets w/h are the dimensions of the slice
  85. /// !! this method can panic if the given buffer dimensions don't match the buffer length
  86. pub fn insert_slice(&mut self, x: usize, y: usize, w: usize, h: usize, slice: &[Color]) {
  87. assert!(w * h == slice.len());
  88. for i in x..(x + w) {
  89. for j in y..(y + h) {
  90. let color = slice[w * (i - x) + (j - y)];
  91. self.insert_pixel(i, j, color);
  92. }
  93. }
  94. }
  95. /// get mouse position
  96. pub fn get_mouse_pos(&self) -> Option<(f32, f32)> {
  97. self.window.get_mouse_pos(minifb::MouseMode::Discard)
  98. }
  99. /// get mouse down
  100. pub fn get_mouse_down(&self, button: MouseButton) -> bool {
  101. self.window.get_mouse_down(button)
  102. }
  103. }