split image into image8 and image32, also made run work on screens of both
This commit is contained in:
parent
588797c4b7
commit
6afa8bafdf
|
@ -0,0 +1,21 @@
|
||||||
|
use skunk2d::{run, Event, Game, Image32, WindowState};
|
||||||
|
|
||||||
|
struct World {}
|
||||||
|
|
||||||
|
impl Game<Image32> for World {
|
||||||
|
fn new(window_state: &mut WindowState) -> Self {
|
||||||
|
World {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, window_state: &mut WindowState) {}
|
||||||
|
|
||||||
|
fn on_event(&mut self, window_state: &mut WindowState, event: Event) {}
|
||||||
|
|
||||||
|
fn draw(&self, target: &mut Image32) {
|
||||||
|
target.fill([0xc0, 0xf0, 0xd0, 0xff]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
run::<Image32, World>(1920 / 3, 1080 / 3, 60);
|
||||||
|
}
|
|
@ -12,10 +12,10 @@ struct World {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
rand::thread_rng().gen::<Direction>();
|
rand::thread_rng().gen::<Direction>();
|
||||||
run::<World>(WIDTH, HEIGHT, 10000);
|
run::<Image8, World>(WIDTH, HEIGHT, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Game for World {
|
impl Game<Image8> for World {
|
||||||
fn new(window_state: &mut WindowState) -> Self {
|
fn new(window_state: &mut WindowState) -> Self {
|
||||||
window_state.set_palette(0, 0xc0, 0xf0, 0xd0);
|
window_state.set_palette(0, 0xc0, 0xf0, 0xd0);
|
||||||
window_state.scramble_palette();
|
window_state.scramble_palette();
|
||||||
|
@ -48,7 +48,7 @@ impl Game for World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, target: &mut Image) {
|
fn draw(&self, target: &mut Image8) {
|
||||||
target.clear();
|
target.clear();
|
||||||
target.draw_hexmap(IVec2 { x: 0, y: 0 }, &self.map);
|
target.draw_hexmap(IVec2 { x: 0, y: 0 }, &self.map);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{IRect, Image, Tileset};
|
use crate::{IRect, Image8, Tileset};
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ impl Console {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn draw_to_image(&self, target: &mut Image, pos: IVec2, font: &Tileset) {
|
pub(crate) fn draw_to_image(&self, target: &mut Image8, pos: IVec2, font: &Tileset) {
|
||||||
let height = self.max_lines as i32 * font.tile_size().y;
|
let height = self.max_lines as i32 * font.tile_size().y;
|
||||||
let width = self.max_line_length as i32 * font.tile_size().x;
|
let width = self.max_line_length as i32 * font.tile_size().x;
|
||||||
target.fill_rect(
|
target.fill_rect(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::vec_util::IVec2Helper;
|
use crate::vec_util::IVec2Helper;
|
||||||
use crate::{Image, Tileset};
|
use crate::{Image8, Tileset};
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use rand::distributions::Standard;
|
use rand::distributions::Standard;
|
||||||
use rand::prelude::Distribution;
|
use rand::prelude::Distribution;
|
||||||
|
@ -121,7 +121,7 @@ impl HexMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
//pubcrate
|
//pubcrate
|
||||||
pub(crate) fn draw_tile_to_image(&self, target: &mut Image, coord: IVec2, offset: IVec2) {
|
pub(crate) fn draw_tile_to_image(&self, target: &mut Image8, coord: IVec2, offset: IVec2) {
|
||||||
target.draw_image(
|
target.draw_image(
|
||||||
self.coord_to_pixel(coord) + offset,
|
self.coord_to_pixel(coord) + offset,
|
||||||
self.tileset.get(self.data[self.coord_to_idx(coord)]),
|
self.tileset.get(self.data[self.coord_to_idx(coord)]),
|
||||||
|
|
158
src/image.rs
158
src/image.rs
|
@ -1,151 +1,13 @@
|
||||||
use crate::vec_util::IVec2Helper;
|
|
||||||
use crate::{HexMap, IRect, Tileset};
|
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use std::fs;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
//todo: make dynamically different bitdepths
|
pub trait Image {
|
||||||
pub struct Image {
|
fn new(size: IVec2) -> Self;
|
||||||
data: Vec<u8>,
|
|
||||||
size: IVec2,
|
fn clear(&mut self);
|
||||||
}
|
|
||||||
|
fn data_mut(&mut self) -> &mut [u8];
|
||||||
impl Image {
|
|
||||||
pub fn new(size: IVec2) -> Self {
|
fn data(&self) -> &[u8];
|
||||||
Image {
|
|
||||||
data: vec![0u8; (size.x * size.y) as usize],
|
fn size(&self) -> IVec2;
|
||||||
size,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load(path: &str) -> Rc<Self> {
|
|
||||||
Self::load_data(fs::read(path).unwrap().as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_data(data: &[u8]) -> Rc<Self> {
|
|
||||||
let mut options = gif::DecodeOptions::new();
|
|
||||||
options.set_color_output(gif::ColorOutput::Indexed);
|
|
||||||
let mut decoder = options.read_info(data).unwrap();
|
|
||||||
|
|
||||||
let x = decoder.width();
|
|
||||||
let y = decoder.height();
|
|
||||||
|
|
||||||
let mut data = vec![0u8; (x * y) as usize];
|
|
||||||
decoder.next_frame_info().unwrap();
|
|
||||||
decoder.read_into_buffer(&mut data).unwrap();
|
|
||||||
Image {
|
|
||||||
data,
|
|
||||||
size: IVec2 {
|
|
||||||
x: x as i32,
|
|
||||||
y: y as i32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.fill(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data_mut(&mut self) -> &mut [u8] {
|
|
||||||
self.data.as_mut_slice()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data(&self) -> &[u8] {
|
|
||||||
self.data.as_slice()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_hexmap(&mut self, pos: IVec2, hexmap: &HexMap) {
|
|
||||||
for i in hexmap.size().to_rect().iter() {
|
|
||||||
hexmap.draw_tile_to_image(self, i, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_image(&mut self, pos: IVec2, image: &Image) {
|
|
||||||
self.draw_image_partial(
|
|
||||||
pos,
|
|
||||||
image,
|
|
||||||
IRect {
|
|
||||||
pos: IVec2::ZERO,
|
|
||||||
size: image.size,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_image_partial(&mut self, pos: IVec2, image: &Image, src_rect: IRect) {
|
|
||||||
//todo: write proper implementation later
|
|
||||||
for i in IVec2::ZERO.iter_to(src_rect.size) {
|
|
||||||
//todo: implement better(very stupid to do per pixel)
|
|
||||||
if self.size.to_rect().contains(i + pos) {
|
|
||||||
let p = image.get_pixel(i + src_rect.pos);
|
|
||||||
if p > 0 {
|
|
||||||
self.set_pixel(i + pos, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_line(&mut self, pos1: IVec2, pos2: IVec2, color: u8) {
|
|
||||||
let (x1, y1, x2, y2) = (pos1.x, pos1.y, pos2.x, pos2.y);
|
|
||||||
|
|
||||||
let mut x = x1 as f32;
|
|
||||||
let mut y = y1 as f32;
|
|
||||||
let xdiff = (x2 - x1) as f32;
|
|
||||||
let ydiff = (y2 - y1) as f32;
|
|
||||||
let step = if xdiff.abs() > ydiff.abs() {
|
|
||||||
xdiff.abs()
|
|
||||||
} else {
|
|
||||||
ydiff.abs()
|
|
||||||
};
|
|
||||||
let xs = xdiff / step;
|
|
||||||
let ys = ydiff / step;
|
|
||||||
for _ in 1..=(step as i32) {
|
|
||||||
self.set_pixel(
|
|
||||||
IVec2 {
|
|
||||||
x: x as i32,
|
|
||||||
y: y as i32,
|
|
||||||
},
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
x += xs;
|
|
||||||
y += ys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_string(&mut self, pos: IVec2, str: &str, font: &Tileset) {
|
|
||||||
assert!(str.is_ascii());
|
|
||||||
let array = str.as_bytes();
|
|
||||||
//for i in 0..array.len()
|
|
||||||
for (i, idx) in array.iter().enumerate() {
|
|
||||||
self.draw_image(
|
|
||||||
IVec2 {
|
|
||||||
x: pos.x + font.tile_size().x * i as i32,
|
|
||||||
y: pos.y,
|
|
||||||
},
|
|
||||||
font.get(*idx as i32),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fill(&mut self, color: u8) {
|
|
||||||
self.data.fill(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fill_rect(&mut self, rect: IRect, color: u8) {
|
|
||||||
for pos in rect.iter() {
|
|
||||||
self.set_pixel(pos, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pixel(&self, pos: IVec2) -> u8 {
|
|
||||||
self.data[(pos.x + self.size.x * pos.y) as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_pixel(&mut self, pos: IVec2, color: u8) {
|
|
||||||
self.data[(pos.x + self.size.x * pos.y) as usize] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> IVec2 {
|
|
||||||
self.size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
use crate::image::Image;
|
||||||
|
use crate::vec_util::IVec2Helper;
|
||||||
|
use crate::IRect;
|
||||||
|
use glam::IVec2;
|
||||||
|
|
||||||
|
pub type Pixel32 = [u8; 4];
|
||||||
|
|
||||||
|
pub struct Image32 {
|
||||||
|
data: Vec<u8>,
|
||||||
|
size: IVec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image32 {
|
||||||
|
pub fn fill(&mut self, color: Pixel32) {
|
||||||
|
//todo: performance
|
||||||
|
for i in (0..self.size.size() * 4).step_by(4) {
|
||||||
|
self.data[i..i + 4].copy_from_slice(&color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_rect(&mut self, rect: IRect, color: Pixel32) {
|
||||||
|
for pos in rect.iter() {
|
||||||
|
self.set_pixel(pos, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pixel(&self, pos: IVec2) -> Pixel32 {
|
||||||
|
//todo: check if performance?
|
||||||
|
let i = (pos.x + self.size.x * pos.y * 4) as usize;
|
||||||
|
let mut a = [0u8; 4];
|
||||||
|
a.copy_from_slice(&self.data[i..i + 4]);
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pixel(&mut self, pos: IVec2, color: Pixel32) {
|
||||||
|
let i = (pos.x + self.size.x * pos.y * 4) as usize;
|
||||||
|
self.data[i..i + 4].copy_from_slice(&color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image for Image32 {
|
||||||
|
fn new(size: IVec2) -> Self {
|
||||||
|
Image32 {
|
||||||
|
data: vec![0u8; (size.x * size.y) as usize * 4],
|
||||||
|
size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.data.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_mut(&mut self) -> &mut [u8] {
|
||||||
|
self.data.as_mut_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data(&self) -> &[u8] {
|
||||||
|
self.data.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> IVec2 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
use crate::image::Image;
|
||||||
|
use crate::vec_util::IVec2Helper;
|
||||||
|
use crate::{HexMap, IRect, Tileset};
|
||||||
|
use glam::IVec2;
|
||||||
|
use std::fs;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
//todo: make dynamically different bitdepths
|
||||||
|
pub struct Image8 {
|
||||||
|
data: Vec<u8>,
|
||||||
|
size: IVec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image8 {
|
||||||
|
pub fn new(size: IVec2) -> Self {
|
||||||
|
Image8 {
|
||||||
|
data: vec![0u8; (size.x * size.y) as usize],
|
||||||
|
size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(path: &str) -> Rc<Self> {
|
||||||
|
Self::load_data(fs::read(path).unwrap().as_slice())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_data(data: &[u8]) -> Rc<Self> {
|
||||||
|
let mut options = gif::DecodeOptions::new();
|
||||||
|
options.set_color_output(gif::ColorOutput::Indexed);
|
||||||
|
let mut decoder = options.read_info(data).unwrap();
|
||||||
|
|
||||||
|
let x = decoder.width();
|
||||||
|
let y = decoder.height();
|
||||||
|
|
||||||
|
let mut data = vec![0u8; (x * y) as usize];
|
||||||
|
decoder.next_frame_info().unwrap();
|
||||||
|
decoder.read_into_buffer(&mut data).unwrap();
|
||||||
|
Image8 {
|
||||||
|
data,
|
||||||
|
size: IVec2 {
|
||||||
|
x: x as i32,
|
||||||
|
y: y as i32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_mut(&mut self) -> &mut [u8] {
|
||||||
|
self.data.as_mut_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data(&self) -> &[u8] {
|
||||||
|
self.data.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_hexmap(&mut self, pos: IVec2, hexmap: &HexMap) {
|
||||||
|
for i in hexmap.size().to_rect().iter() {
|
||||||
|
hexmap.draw_tile_to_image(self, i, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_image(&mut self, pos: IVec2, image: &Image8) {
|
||||||
|
self.draw_image_partial(
|
||||||
|
pos,
|
||||||
|
image,
|
||||||
|
IRect {
|
||||||
|
pos: IVec2::ZERO,
|
||||||
|
size: image.size,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_image_partial(&mut self, pos: IVec2, image: &Image8, src_rect: IRect) {
|
||||||
|
//todo: write proper implementation later
|
||||||
|
for i in IVec2::ZERO.iter_to(src_rect.size) {
|
||||||
|
//todo: implement better(very stupid to do per pixel)
|
||||||
|
if self.size.to_rect().contains(i + pos) {
|
||||||
|
let p = image.get_pixel(i + src_rect.pos);
|
||||||
|
if p > 0 {
|
||||||
|
self.set_pixel(i + pos, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_line(&mut self, pos1: IVec2, pos2: IVec2, color: u8) {
|
||||||
|
let (x1, y1, x2, y2) = (pos1.x, pos1.y, pos2.x, pos2.y);
|
||||||
|
|
||||||
|
let mut x = x1 as f32;
|
||||||
|
let mut y = y1 as f32;
|
||||||
|
let xdiff = (x2 - x1) as f32;
|
||||||
|
let ydiff = (y2 - y1) as f32;
|
||||||
|
let step = if xdiff.abs() > ydiff.abs() {
|
||||||
|
xdiff.abs()
|
||||||
|
} else {
|
||||||
|
ydiff.abs()
|
||||||
|
};
|
||||||
|
let xs = xdiff / step;
|
||||||
|
let ys = ydiff / step;
|
||||||
|
for _ in 1..=(step as i32) {
|
||||||
|
self.set_pixel(
|
||||||
|
IVec2 {
|
||||||
|
x: x as i32,
|
||||||
|
y: y as i32,
|
||||||
|
},
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
x += xs;
|
||||||
|
y += ys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_string(&mut self, pos: IVec2, str: &str, font: &Tileset) {
|
||||||
|
assert!(str.is_ascii());
|
||||||
|
let array = str.as_bytes();
|
||||||
|
//for i in 0..array.len()
|
||||||
|
for (i, idx) in array.iter().enumerate() {
|
||||||
|
self.draw_image(
|
||||||
|
IVec2 {
|
||||||
|
x: pos.x + font.tile_size().x * i as i32,
|
||||||
|
y: pos.y,
|
||||||
|
},
|
||||||
|
font.get(*idx as i32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill(&mut self, color: u8) {
|
||||||
|
self.data.fill(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_rect(&mut self, rect: IRect, color: u8) {
|
||||||
|
for pos in rect.iter() {
|
||||||
|
self.set_pixel(pos, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pixel(&self, pos: IVec2) -> u8 {
|
||||||
|
self.data[(pos.x + self.size.x * pos.y) as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pixel(&mut self, pos: IVec2, color: u8) {
|
||||||
|
self.data[(pos.x + self.size.x * pos.y) as usize] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image for Image8 {
|
||||||
|
fn new(size: IVec2) -> Self {
|
||||||
|
Image8 {
|
||||||
|
data: vec![0u8; (size.x * size.y) as usize],
|
||||||
|
size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_mut(&mut self) -> &mut [u8] {
|
||||||
|
self.data.as_mut_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data(&self) -> &[u8] {
|
||||||
|
self.data.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> IVec2 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,16 @@
|
||||||
mod console;
|
mod console;
|
||||||
mod hexmap;
|
mod hexmap;
|
||||||
mod image;
|
mod image;
|
||||||
|
mod image32;
|
||||||
|
mod image8;
|
||||||
mod rect;
|
mod rect;
|
||||||
mod tileset;
|
mod tileset;
|
||||||
mod vec_util;
|
mod vec_util;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
pub use hexmap::*;
|
pub use hexmap::*;
|
||||||
pub use image::*;
|
pub use image32::*;
|
||||||
|
pub use image8::*;
|
||||||
pub use rect::*;
|
pub use rect::*;
|
||||||
pub use tileset::*;
|
pub use tileset::*;
|
||||||
pub use window::*;
|
pub use window::*;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
use crate::image::Image;
|
||||||
use crate::vec_util::IVec2Helper;
|
use crate::vec_util::IVec2Helper;
|
||||||
use crate::{IRect, Image};
|
use crate::{IRect, Image8};
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -7,7 +8,7 @@ use std::rc::Rc;
|
||||||
pub struct Tileset {
|
pub struct Tileset {
|
||||||
count: i32,
|
count: i32,
|
||||||
size: IVec2,
|
size: IVec2,
|
||||||
images: Vec<Image>,
|
images: Vec<Image8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tileset {
|
impl Tileset {
|
||||||
|
@ -16,14 +17,14 @@ impl Tileset {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_data(data: &[u8], tile_count: IVec2) -> Rc<Self> {
|
pub fn load_data(data: &[u8], tile_count: IVec2) -> Rc<Self> {
|
||||||
let img = Image::load_data(data);
|
let img = Image8::load_data(data);
|
||||||
let mut images: Vec<Image> = vec![];
|
let mut images: Vec<Image8> = vec![];
|
||||||
let size = IVec2 {
|
let size = IVec2 {
|
||||||
x: img.size().x / tile_count.x,
|
x: img.size().x / tile_count.x,
|
||||||
y: img.size().y / tile_count.y,
|
y: img.size().y / tile_count.y,
|
||||||
};
|
};
|
||||||
for tile in tile_count.to_rect().iter() {
|
for tile in tile_count.to_rect().iter() {
|
||||||
let mut image = Image::new(size);
|
let mut image = Image8::new(size);
|
||||||
image.draw_image_partial(
|
image.draw_image_partial(
|
||||||
IVec2::ZERO,
|
IVec2::ZERO,
|
||||||
&img,
|
&img,
|
||||||
|
@ -45,7 +46,7 @@ impl Tileset {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, idx: i32) -> &Image {
|
pub fn get(&self, idx: i32) -> &Image8 {
|
||||||
&self.images[idx as usize]
|
&self.images[idx as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
120
src/window.rs
120
src/window.rs
|
@ -1,8 +1,10 @@
|
||||||
use crate::console::Console;
|
use crate::console::Console;
|
||||||
use crate::image::Image;
|
use crate::image::Image;
|
||||||
use crate::Tileset;
|
use crate::image8::Image8;
|
||||||
|
use crate::{Image32, Tileset};
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use softbuffer::Buffer;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
@ -30,7 +32,7 @@ pub enum Event {
|
||||||
MouseClick(MouseButton, IVec2),
|
MouseClick(MouseButton, IVec2),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Game {
|
pub trait Game<Image> {
|
||||||
fn new(window_state: &mut WindowState) -> Self;
|
fn new(window_state: &mut WindowState) -> Self;
|
||||||
fn update(&mut self, window_state: &mut WindowState);
|
fn update(&mut self, window_state: &mut WindowState);
|
||||||
fn on_event(&mut self, window_state: &mut WindowState, event: Event);
|
fn on_event(&mut self, window_state: &mut WindowState, event: Event);
|
||||||
|
@ -75,7 +77,84 @@ impl WindowState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<T: Game + 'static>(width: i32, height: i32, target_fps: u32) {
|
pub trait RenderToScreen {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn render_to_screen(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buffer,
|
||||||
|
palette: &[u32; 256],
|
||||||
|
width: usize,
|
||||||
|
window_width: usize,
|
||||||
|
scale: usize,
|
||||||
|
chunk_size: usize,
|
||||||
|
screen_data: &[u8],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderToScreen for Image8 {
|
||||||
|
fn render_to_screen(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buffer,
|
||||||
|
palette: &[u32; 256],
|
||||||
|
width: usize,
|
||||||
|
window_width: usize,
|
||||||
|
scale: usize,
|
||||||
|
chunk_size: usize,
|
||||||
|
screen_data: &[u8],
|
||||||
|
) {
|
||||||
|
buf.chunks_exact_mut(chunk_size)
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(y, chunk)| {
|
||||||
|
for x in 0..width {
|
||||||
|
let p = palette[screen_data[x + y * width] as usize];
|
||||||
|
for scaley in 0..scale {
|
||||||
|
for scalex in 0..scale {
|
||||||
|
let sx = x * scale + scalex;
|
||||||
|
chunk[sx + scaley * window_width] = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderToScreen for Image32 {
|
||||||
|
fn render_to_screen(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buffer,
|
||||||
|
_palette: &[u32; 256],
|
||||||
|
width: usize,
|
||||||
|
window_width: usize,
|
||||||
|
scale: usize,
|
||||||
|
chunk_size: usize,
|
||||||
|
screen_data: &[u8],
|
||||||
|
) {
|
||||||
|
let screen_data32 = unsafe {
|
||||||
|
let (_, middle, _) = screen_data.align_to::<u32>();
|
||||||
|
//todo: add assert?
|
||||||
|
middle
|
||||||
|
};
|
||||||
|
buf.chunks_exact_mut(chunk_size)
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(y, chunk)| {
|
||||||
|
for x in 0..width {
|
||||||
|
let p = screen_data32[x + y * width];
|
||||||
|
for scaley in 0..scale {
|
||||||
|
for scalex in 0..scale {
|
||||||
|
let sx = x * scale + scalex;
|
||||||
|
chunk[sx + scaley * window_width] = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run<TImage: Image + RenderToScreen, TGame: Game<TImage> + 'static>(
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
target_fps: u32,
|
||||||
|
) {
|
||||||
let mut event_loop = EventLoop::new();
|
let mut event_loop = EventLoop::new();
|
||||||
let window = {
|
let window = {
|
||||||
let size = LogicalSize::new(width as f64, height as f64);
|
let size = LogicalSize::new(width as f64, height as f64);
|
||||||
|
@ -89,10 +168,10 @@ pub fn run<T: Game + 'static>(width: i32, height: i32, target_fps: u32) {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
//todo: replace Pixels with custom thingie (startup time slow because wgpu?)
|
|
||||||
let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
|
let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
|
||||||
let mut surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
|
let mut surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
|
||||||
let mut screen = Image::new(IVec2 {
|
|
||||||
|
let mut screen = TImage::new(IVec2 {
|
||||||
x: width,
|
x: width,
|
||||||
y: height,
|
y: height,
|
||||||
});
|
});
|
||||||
|
@ -101,7 +180,7 @@ pub fn run<T: Game + 'static>(width: i32, height: i32, target_fps: u32) {
|
||||||
x: width / internal_font.tile_size().x,
|
x: width / internal_font.tile_size().x,
|
||||||
y: height / internal_font.tile_size().y / 3,
|
y: height / internal_font.tile_size().y / 3,
|
||||||
});
|
});
|
||||||
let mut game = T::new(&mut window_state);
|
let mut game = TGame::new(&mut window_state);
|
||||||
window_state.console.add("Initialising Skunk2d");
|
window_state.console.add("Initialising Skunk2d");
|
||||||
|
|
||||||
let mut display_console = true;
|
let mut display_console = true;
|
||||||
|
@ -200,13 +279,15 @@ pub fn run<T: Game + 'static>(width: i32, height: i32, target_fps: u32) {
|
||||||
if Instant::now() - last_frame >= target_frame_duration {
|
if Instant::now() - last_frame >= target_frame_duration {
|
||||||
game.update(&mut window_state);
|
game.update(&mut window_state);
|
||||||
game.draw(&mut screen);
|
game.draw(&mut screen);
|
||||||
|
//todo: make this work again
|
||||||
|
/*
|
||||||
if display_console {
|
if display_console {
|
||||||
window_state.console.draw_to_image(
|
window_state.console.draw_to_image(
|
||||||
&mut screen,
|
&mut screen,
|
||||||
IVec2::ZERO,
|
IVec2::ZERO,
|
||||||
&internal_font,
|
&internal_font,
|
||||||
);
|
);
|
||||||
}
|
} */
|
||||||
|
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
surface
|
surface
|
||||||
|
@ -221,7 +302,6 @@ pub fn run<T: Game + 'static>(width: i32, height: i32, target_fps: u32) {
|
||||||
*off_y = (size.height as usize - height as usize * *scale) / 2;
|
*off_y = (size.height as usize - height as usize * *scale) / 2;
|
||||||
|
|
||||||
let mut buf = surface.buffer_mut().unwrap();
|
let mut buf = surface.buffer_mut().unwrap();
|
||||||
//for y in 0..height as usize {
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let width = width as usize;
|
let width = width as usize;
|
||||||
|
@ -229,21 +309,15 @@ pub fn run<T: Game + 'static>(width: i32, height: i32, target_fps: u32) {
|
||||||
let scale = *scale;
|
let scale = *scale;
|
||||||
let chunk_size = scale * window_width;
|
let chunk_size = scale * window_width;
|
||||||
let screen_data = screen.data();
|
let screen_data = screen.data();
|
||||||
buf.chunks_exact_mut(chunk_size)
|
screen.render_to_screen(
|
||||||
.enumerate()
|
&mut buf,
|
||||||
.for_each(|(y, chunk)| {
|
&window_state.palette,
|
||||||
for x in 0..width {
|
width,
|
||||||
let p =
|
window_width,
|
||||||
window_state.palette[screen_data[x + y * width] as usize];
|
scale,
|
||||||
//let p = 0;
|
chunk_size,
|
||||||
for scaley in 0..scale {
|
&screen_data,
|
||||||
for scalex in 0..scale {
|
);
|
||||||
let sx = x * scale + scalex;
|
|
||||||
chunk[sx + scaley * window_width] = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.present().unwrap();
|
buf.present().unwrap();
|
||||||
|
|
Loading…
Reference in New Issue