diff --git a/Cargo.toml b/Cargo.toml index 20db143..e7e9311 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ dunce = "1.0.4" path-slash = "0.2.1" serde = {version = "1.0.181", features = ["derive"]} postcard = {version = "1.0.6", features = ["alloc"]} -#rayon = "1.7.0" +rayon = "1.7.0" [profile.release-dani] inherits = "release" diff --git a/examples/basic/main.rs b/examples/basic/main.rs index 78c0579..cf54a37 100644 --- a/examples/basic/main.rs +++ b/examples/basic/main.rs @@ -1,14 +1,26 @@ use glam::IVec2; -use gsa::{run, Gsa, FACE_DOWN}; +use gsa::{run, Gsa, FACE_DOWN, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_MIDDLE, FACE_LEFT, FACE_RIGHT}; struct Game {} fn init(gsa: &mut Gsa) -> Game { - gsa.bg[0].fill(0x0101); + gsa.bg[0].fill(0x7101); //gsa.write_string(IVec2::ONE, "Hello world nyaa~"); + gsa.bg[0].rot = 10; + gsa.bg[0].origin = SCREEN_MIDDLE; + gsa.bg[0].scroll = SCREEN_MIDDLE; Game {} } -fn update(_game: &mut Game, gsa: &mut Gsa) {} +fn update(_game: &mut Game, gsa: &mut Gsa) { + if gsa.button_down(FACE_LEFT) { + gsa.bg[0].rot = gsa.bg[0].rot.wrapping_add(1); + } + if gsa.button_down(FACE_RIGHT) { + gsa.bg[0].rot = gsa.bg[0].rot.wrapping_sub(1); + } + //gsa.bg[0].scroll.x = (gsa.bg[0].scroll.x + 10) % 300; + gsa.bg[0].scroll += gsa.input_dir(); +} run!(init, update); diff --git a/src/background.rs b/src/background.rs index ed37da0..3492a3d 100644 --- a/src/background.rs +++ b/src/background.rs @@ -7,6 +7,10 @@ pub struct Background { pub tiles: Vec>, /// Camera scroll (negative draw offset) for rendering pub scroll: IVec2, + /// Rotation, 0-255 equals one full turn + pub rot: u8, + /// Origin (used for rotation and scroll and such) + pub origin: IVec2, /// Size (used for rendering) pub size: IVec2, /// Are tiles indices half-tile indices? @@ -25,6 +29,8 @@ impl Default for Background { half_tile: false, active: true, size: IVec2 { x: 19, y: 11 }, + origin: IVec2::ZERO, + rot: 0 } } } diff --git a/src/gsa_render_to_screen.rs b/src/gsa_render_to_screen.rs index 0cf95e4..6da798a 100644 --- a/src/gsa_render_to_screen.rs +++ b/src/gsa_render_to_screen.rs @@ -1,11 +1,11 @@ -use std::usize; -//use rayon::prelude::*; +use std::{usize, f32::consts::PI}; +use rayon::prelude::*; use crate::{ Background, Gsa, Rgb, EMPTY_TILE, HALF_TILE_SIZE, MAX_BACKGROUNDS, TILESET_SIZE, TILE_SIZE, TRANSPARENT, }; -use glam::IVec2; +use glam::{IVec2, Mat2, Vec2}; use softbuffer::Buffer; fn draw_tile( @@ -78,30 +78,49 @@ fn render_bg2(target: &mut [u8], map: &Background, tileset: &[u8], screen_size: } else { TILE_SIZE } as i32; + + let a = map.rot as f32 / 256.0 * PI * 2.0; + + + let du = glam::Vec2::new(a.cos(), a.sin()); + let dv = glam::Vec2::new(-a.sin(), a.cos()); + let duv = Mat2::from_cols(du, dv); + //target.par_chunks_exact_mut(screen_size.x as usize).enumerate().for_each({|(screeny, row)| - target.chunks_exact_mut(screen_size.x as usize).enumerate().for_each({|(screeny, row)| - for screenx in 0..screen_size.x { - let x = screenx + map.scroll.x; - let y = screeny as i32 + map.scroll.y; - let tilex = x / tilesize; - let tiley = y / tilesize; - let pixx = x % tilesize; - let pixy = y % tilesize; - let tile = if tilex >= 0 && tiley >= 0 && tilex < map.size.x && tiley < map.size.y { - map.tiles[tilex as usize][tiley as usize] - } else { - EMPTY_TILE - }; - if tile != EMPTY_TILE { - let tilesetx = tile as usize % 0x100 * tilesize as usize + pixx as usize; - let tilesety = tile as usize / 0x100 * tilesize as usize + pixy as usize; - let p = tileset[tilesetx + tilesety * (TILESET_SIZE * TILE_SIZE)]; - if p != TRANSPARENT { - row[x as usize] = p; - } + target + .chunks_exact_mut(screen_size.x as usize) + .enumerate() + .for_each({ + |(screeny, row)| { + for screenx in 0..screen_size.x { + let screen = duv * Vec2::new(screenx as f32 - map.origin.x as f32, screeny as f32 - map.origin.y as f32); + let x = screen.x.floor() as i32 + map.scroll.x; + let y = screen.y.floor() as i32 + map.scroll.y; + let tilex = x.div_euclid(tilesize); + let tiley = y.div_euclid(tilesize); + //println!("{},{}", x,tilex); + //assert!(tilex >= 0); + // the addition is there because otherwise x might be below 0 + // which messes with the modulo + let pixx = (x+tilesize) % tilesize; + let pixy = (y+tilesize) % tilesize; + let tile = + if tilex >= 0 && tiley >= 0 && tilex < map.size.x && tiley < map.size.y { + map.tiles[tilex as usize][tiley as usize] + } else { + EMPTY_TILE + }; + if tile != EMPTY_TILE { + let tilesetx = tile as i32 % 0x100 * tilesize + pixx; + let tilesety = tile as i32 / 0x100 * tilesize + pixy; + let p = tileset[tilesetx as usize + tilesety as usize * (TILESET_SIZE * TILE_SIZE)]; + if p != TRANSPARENT { + row[screenx as usize] = p; + } + } + } } - } - }); + }); } pub(crate) fn render_to_screen(target: &mut [u8], gsa: &Gsa, tileset: &[u8], screen_size: IVec2) { diff --git a/src/lib.rs b/src/lib.rs index ab0784a..0ceead4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,6 +50,8 @@ mod sprite; mod tilemap; mod tileset; +use glam::IVec2; + pub use crate::background::*; pub use crate::buttons::*; pub use crate::gsa::*; @@ -66,6 +68,12 @@ pub const SCREEN_WIDTH: usize = 304; /// Screen Height in pixels pub const SCREEN_HEIGHT: usize = 176; +/// Screen size as vector (SCREEN_WIDTH,SCREEN_HEIGHT) +pub const SCREEN_SIZE: IVec2 = IVec2{x: SCREEN_WIDTH as i32, y: SCREEN_HEIGHT as i32}; + +/// Center of screen as vector +pub const SCREEN_MIDDLE: IVec2 = IVec2{x: SCREEN_WIDTH as i32 / 2, y: SCREEN_HEIGHT as i32 / 2}; + /// X and y dimensions of maps in [Gsa::bgs] pub const BACKGROUND_MAX_SIZE: usize = 1024; diff --git a/src/run.rs b/src/run.rs index 668966c..cc0599f 100644 --- a/src/run.rs +++ b/src/run.rs @@ -47,7 +47,7 @@ pub fn run( ) { let (tileset, palette) = load_tileset(image_data); - //rayon::ThreadPoolBuilder::new().num_threads(32).build_global().unwrap(); + //rayon::ThreadPoolBuilder::new().num_threads(2).build_global().unwrap(); let mut gsa = Gsa { sprite: [Sprite::default(); MAX_SPRITES], @@ -100,7 +100,7 @@ pub fn run( let mut last_second = Instant::now(); let mut last_frame = last_second; - let target_frame_duration = Duration::from_secs(1).div_f64(60000.0); + let target_frame_duration = Duration::from_secs(1).div_f64(60.0); let mut scale = 1usize; let mut off_x = 0usize;