rotation of backgrounds

This commit is contained in:
dani 2023-08-15 00:32:14 +00:00
parent ba785f8525
commit f77b66ecc9
6 changed files with 76 additions and 31 deletions

View File

@ -24,7 +24,7 @@ dunce = "1.0.4"
path-slash = "0.2.1" path-slash = "0.2.1"
serde = {version = "1.0.181", features = ["derive"]} serde = {version = "1.0.181", features = ["derive"]}
postcard = {version = "1.0.6", features = ["alloc"]} postcard = {version = "1.0.6", features = ["alloc"]}
#rayon = "1.7.0" rayon = "1.7.0"
[profile.release-dani] [profile.release-dani]
inherits = "release" inherits = "release"

View File

@ -1,14 +1,26 @@
use glam::IVec2; 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 {} struct Game {}
fn init(gsa: &mut Gsa) -> 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.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 {} 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); run!(init, update);

View File

@ -7,6 +7,10 @@ pub struct Background {
pub tiles: Vec<Vec<u16>>, pub tiles: Vec<Vec<u16>>,
/// Camera scroll (negative draw offset) for rendering /// Camera scroll (negative draw offset) for rendering
pub scroll: IVec2, 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) /// Size (used for rendering)
pub size: IVec2, pub size: IVec2,
/// Are tiles indices half-tile indices? /// Are tiles indices half-tile indices?
@ -25,6 +29,8 @@ impl Default for Background {
half_tile: false, half_tile: false,
active: true, active: true,
size: IVec2 { x: 19, y: 11 }, size: IVec2 { x: 19, y: 11 },
origin: IVec2::ZERO,
rot: 0
} }
} }
} }

View File

@ -1,11 +1,11 @@
use std::usize; use std::{usize, f32::consts::PI};
//use rayon::prelude::*; use rayon::prelude::*;
use crate::{ use crate::{
Background, Gsa, Rgb, EMPTY_TILE, HALF_TILE_SIZE, MAX_BACKGROUNDS, TILESET_SIZE, TILE_SIZE, Background, Gsa, Rgb, EMPTY_TILE, HALF_TILE_SIZE, MAX_BACKGROUNDS, TILESET_SIZE, TILE_SIZE,
TRANSPARENT, TRANSPARENT,
}; };
use glam::IVec2; use glam::{IVec2, Mat2, Vec2};
use softbuffer::Buffer; use softbuffer::Buffer;
fn draw_tile( fn draw_tile(
@ -78,26 +78,45 @@ fn render_bg2(target: &mut [u8], map: &Background, tileset: &[u8], screen_size:
} else { } else {
TILE_SIZE TILE_SIZE
} as i32; } 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.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)| target
.chunks_exact_mut(screen_size.x as usize)
.enumerate()
.for_each({
|(screeny, row)| {
for screenx in 0..screen_size.x { for screenx in 0..screen_size.x {
let x = screenx + map.scroll.x; let screen = duv * Vec2::new(screenx as f32 - map.origin.x as f32, screeny as f32 - map.origin.y as f32);
let y = screeny as i32 + map.scroll.y; let x = screen.x.floor() as i32 + map.scroll.x;
let tilex = x / tilesize; let y = screen.y.floor() as i32 + map.scroll.y;
let tiley = y / tilesize; let tilex = x.div_euclid(tilesize);
let pixx = x % tilesize; let tiley = y.div_euclid(tilesize);
let pixy = y % tilesize; //println!("{},{}", x,tilex);
let tile = if tilex >= 0 && tiley >= 0 && tilex < map.size.x && tiley < map.size.y { //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] map.tiles[tilex as usize][tiley as usize]
} else { } else {
EMPTY_TILE EMPTY_TILE
}; };
if tile != EMPTY_TILE { if tile != EMPTY_TILE {
let tilesetx = tile as usize % 0x100 * tilesize as usize + pixx as usize; let tilesetx = tile as i32 % 0x100 * tilesize + pixx;
let tilesety = tile as usize / 0x100 * tilesize as usize + pixy as usize; let tilesety = tile as i32 / 0x100 * tilesize + pixy;
let p = tileset[tilesetx + tilesety * (TILESET_SIZE * TILE_SIZE)]; let p = tileset[tilesetx as usize + tilesety as usize * (TILESET_SIZE * TILE_SIZE)];
if p != TRANSPARENT { if p != TRANSPARENT {
row[x as usize] = p; row[screenx as usize] = p;
}
} }
} }
} }

View File

@ -50,6 +50,8 @@ mod sprite;
mod tilemap; mod tilemap;
mod tileset; mod tileset;
use glam::IVec2;
pub use crate::background::*; pub use crate::background::*;
pub use crate::buttons::*; pub use crate::buttons::*;
pub use crate::gsa::*; pub use crate::gsa::*;
@ -66,6 +68,12 @@ pub const SCREEN_WIDTH: usize = 304;
/// Screen Height in pixels /// Screen Height in pixels
pub const SCREEN_HEIGHT: usize = 176; 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] /// X and y dimensions of maps in [Gsa::bgs]
pub const BACKGROUND_MAX_SIZE: usize = 1024; pub const BACKGROUND_MAX_SIZE: usize = 1024;

View File

@ -47,7 +47,7 @@ pub fn run<TGame: 'static>(
) { ) {
let (tileset, palette) = load_tileset(image_data); 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 { let mut gsa = Gsa {
sprite: [Sprite::default(); MAX_SPRITES], sprite: [Sprite::default(); MAX_SPRITES],
@ -100,7 +100,7 @@ pub fn run<TGame: 'static>(
let mut last_second = Instant::now(); let mut last_second = Instant::now();
let mut last_frame = last_second; 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 scale = 1usize;
let mut off_x = 0usize; let mut off_x = 0usize;