Compare commits

...

3 Commits

Author SHA1 Message Date
dani 3c447c764f added changelog, changed tilemap to background, working on template gfx.gif 2023-07-25 04:36:02 +00:00
dani 8372690bc0 changed tilemap to background 2023-07-24 17:26:09 +00:00
dani d2155a718b removed unnecessary dependency 2023-07-23 04:14:01 +00:00
9 changed files with 56 additions and 37 deletions

6
CHANGLOG.md Normal file
View File

@ -0,0 +1,6 @@
# 0.2.0 -
- added README.md
- renamed tilemaps to backgrounds to make space for... tilemaps
# 0.1.0 - 2023-07-21
initial release

View File

@ -13,7 +13,6 @@ keywords = ["gamedev"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
lazy_static = "1.4.0"
glam = "0.24.0" glam = "0.24.0"
ascii = "1.1.0" ascii = "1.1.0"
gilrs = "0.10.2" gilrs = "0.10.2"

View File

@ -6,8 +6,8 @@ struct Game {}
fn init(gsa: &mut Gsa) -> Game { fn init(gsa: &mut Gsa) -> Game {
gsa.sprites[0].tile = 0x0300; gsa.sprites[0].tile = 0x0300;
gsa.sprites[1].tile = 0x0200; gsa.sprites[1].tile = 0x0200;
gsa.maps[0].tiles[1][1] = 0x0300; gsa.bgs[0].tiles[1][1] = 0x0300;
gsa.maps[1].half_tile = true; gsa.bgs[1].half_tile = true;
gsa.write_string(1, IVec2::ONE, "Hello world nyaa~"); gsa.write_string(1, IVec2::ONE, "Hello world nyaa~");
Game {} Game {}
} }
@ -15,7 +15,7 @@ fn init(gsa: &mut Gsa) -> Game {
fn update(_game: &mut Game, gsa: &mut Gsa) { fn update(_game: &mut Game, gsa: &mut Gsa) {
gsa.sprites[0].pos.x = (gsa.sprites[0].pos.x + 1) % 300; gsa.sprites[0].pos.x = (gsa.sprites[0].pos.x + 1) % 300;
gsa.sprites[1].pos += gsa.input_dir(); gsa.sprites[1].pos += gsa.input_dir();
gsa.maps[1].scroll.x += 1; gsa.bgs[1].scroll.x += 1;
if gsa.button_pressed(FACE_DOWN) { if gsa.button_pressed(FACE_DOWN) {
gsa.sprites[1].tile += 1; gsa.sprites[1].tile += 1;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -1,9 +1,9 @@
use crate::TILEMAP_MAX_SIZE; use crate::BACKGROUND_MAX_SIZE;
use glam::IVec2; use glam::IVec2;
/// Tilemap which will be rendered on screen /// Tilemap which will be rendered on screen
pub struct Tilemap { pub struct Background {
/// Tiles in idx, accessible via \[x\]\[y\], x and y 0..[TILEMAP_MAX_SIZE] /// Tiles in idx, accessible via \[x\]\[y\], x and y 0..[BACKGROUND_MAX_SIZE]
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,
@ -11,10 +11,10 @@ pub struct Tilemap {
pub half_tile: bool, pub half_tile: bool,
} }
impl Default for Tilemap { impl Default for Background {
fn default() -> Self { fn default() -> Self {
let row = vec![0u16; TILEMAP_MAX_SIZE]; let row = vec![0u16; BACKGROUND_MAX_SIZE];
let tiles = vec![row; TILEMAP_MAX_SIZE]; let tiles = vec![row; BACKGROUND_MAX_SIZE];
Self { Self {
tiles, tiles,
scroll: IVec2::ZERO, scroll: IVec2::ZERO,

View File

@ -1,8 +1,9 @@
use crate::background::Background;
use crate::rgb::Rgb; use crate::rgb::Rgb;
use crate::sprite::Sprite; use crate::sprite::Sprite;
use crate::tilemap::Tilemap;
use crate::{ use crate::{
Buttons, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, MAX_SPRITES, MAX_TILEMAPS, TILEMAP_MAX_SIZE, Buttons, BACKGROUND_MAX_SIZE, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, MAX_BACKGROUNDS,
MAX_SPRITES,
}; };
use ascii::{AsciiChar, AsciiStr}; use ascii::{AsciiChar, AsciiStr};
use glam::IVec2; use glam::IVec2;
@ -16,7 +17,7 @@ pub struct Gsa {
pub palette: [Rgb; 256], pub palette: [Rgb; 256],
/// Tilemap layers available /// Tilemap layers available
pub maps: [Tilemap; MAX_TILEMAPS], pub bgs: [Background; MAX_BACKGROUNDS],
/// Currently selected font /// Currently selected font
/// ///
@ -36,9 +37,9 @@ impl Gsa {
/// Sets all tiles of map to val /// Sets all tiles of map to val
pub fn fill_map(&mut self, map: usize, val: u16) { pub fn fill_map(&mut self, map: usize, val: u16) {
for x in 0..TILEMAP_MAX_SIZE { for x in 0..BACKGROUND_MAX_SIZE {
for y in 0..TILEMAP_MAX_SIZE { for y in 0..BACKGROUND_MAX_SIZE {
self.maps[map].tiles[x][y] = val; self.bgs[map].tiles[x][y] = val;
} }
} }
} }
@ -72,7 +73,7 @@ impl Gsa {
pub fn write_string(&mut self, map: usize, pos: IVec2, str: &str) { pub fn write_string(&mut self, map: usize, pos: IVec2, str: &str) {
let str = AsciiStr::from_ascii(str).unwrap(); let str = AsciiStr::from_ascii(str).unwrap();
for (i, ch) in str.into_iter().enumerate() { for (i, ch) in str.into_iter().enumerate() {
self.maps[map].tiles[pos.x as usize + i][pos.y as usize] = self.get_char_tile(*ch); self.bgs[map].tiles[pos.x as usize + i][pos.y as usize] = self.get_char_tile(*ch);
} }
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
Gsa, Rgb, Tilemap, HALF_TILE_SIZE, MAX_TILEMAPS, SCREEN_HEIGHT, SCREEN_WIDTH, TILEMAP_MAX_SIZE, Background, Gsa, Rgb, BACKGROUND_MAX_SIZE, EMPTY_TILE, HALF_TILE_SIZE, MAX_BACKGROUNDS,
TILESET_SIZE, TILE_SIZE, SCREEN_HEIGHT, SCREEN_WIDTH, TILESET_SIZE, TILE_SIZE, TRANSPARENT,
}; };
use glam::IVec2; use glam::IVec2;
use softbuffer::Buffer; use softbuffer::Buffer;
@ -16,7 +16,7 @@ fn draw_tile(target: &mut [u8], pos: IVec2, tile: u16, tileset: &[u8], half: boo
for y in (starty - pos.y)..(endy - pos.y) { for y in (starty - pos.y)..(endy - pos.y) {
for x in (startx - pos.x)..(endx - pos.x) { for x in (startx - pos.x)..(endx - pos.x) {
let p = tileset[(x as usize + tx) + (y as usize + ty) * (TILESET_SIZE * TILE_SIZE)]; let p = tileset[(x as usize + tx) + (y as usize + ty) * (TILESET_SIZE * TILE_SIZE)];
if p > 0 { if p != TRANSPARENT {
target[(x as usize + pos.x as usize) target[(x as usize + pos.x as usize)
+ (y as usize + pos.y as usize) * SCREEN_WIDTH] = p; + (y as usize + pos.y as usize) * SCREEN_WIDTH] = p;
} }
@ -24,7 +24,7 @@ fn draw_tile(target: &mut [u8], pos: IVec2, tile: u16, tileset: &[u8], half: boo
} }
} }
fn render_map(target: &mut [u8], map: &Tilemap, tileset: &[u8]) { fn render_map(target: &mut [u8], map: &Background, tileset: &[u8]) {
let tcmult = if map.half_tile { 2 } else { 1 }; let tcmult = if map.half_tile { 2 } else { 1 };
let tilesize = if map.half_tile { let tilesize = if map.half_tile {
HALF_TILE_SIZE HALF_TILE_SIZE
@ -33,14 +33,14 @@ fn render_map(target: &mut [u8], map: &Tilemap, tileset: &[u8]) {
} as i32; } as i32;
let mut startx = map.scroll.x / tilesize; let mut startx = map.scroll.x / tilesize;
let mut starty = map.scroll.y / tilesize; let mut starty = map.scroll.y / tilesize;
let endx = (TILEMAP_MAX_SIZE as i32).min(startx + 20 * tcmult); let endx = (BACKGROUND_MAX_SIZE as i32).min(startx + 20 * tcmult);
let endy = (TILEMAP_MAX_SIZE as i32).min(starty + 12 * tcmult); let endy = (BACKGROUND_MAX_SIZE as i32).min(starty + 12 * tcmult);
startx = 0.max(startx); startx = 0.max(startx);
starty = 0.max(starty); starty = 0.max(starty);
for x in startx..endx { for x in startx..endx {
for y in starty..endy { for y in starty..endy {
let tile = map.tiles[x as usize][y as usize]; let tile = map.tiles[x as usize][y as usize];
if tile > 0 { if tile > EMPTY_TILE {
draw_tile( draw_tile(
target, target,
IVec2 { IVec2 {
@ -57,8 +57,8 @@ fn render_map(target: &mut [u8], map: &Tilemap, tileset: &[u8]) {
} }
pub(crate) fn render_to_screen(target: &mut [u8], gsa: &Gsa, tileset: &[u8]) { pub(crate) fn render_to_screen(target: &mut [u8], gsa: &Gsa, tileset: &[u8]) {
for i in 0..MAX_TILEMAPS { for i in 0..MAX_BACKGROUNDS {
render_map(target, &gsa.maps[i], tileset); render_map(target, &gsa.bgs[i], tileset);
for sprite in &gsa.sprites { for sprite in &gsa.sprites {
if sprite.tile > 0 && sprite.priority == i as u8 { if sprite.tile > 0 && sprite.priority == i as u8 {
draw_tile(target, sprite.pos, sprite.tile, tileset, false); draw_tile(target, sprite.pos, sprite.tile, tileset, false);

View File

@ -8,11 +8,12 @@
//! - Colors: 256 (indexed out of a possible 24-bit) //! - Colors: 256 (indexed out of a possible 24-bit)
//! - Tilesize: 16x16 (or 8x8 for half-tiles) //! - Tilesize: 16x16 (or 8x8 for half-tiles)
//! - Tileset: 65536 tiles, indexed via 0xYYXX //! - Tileset: 65536 tiles, indexed via 0xYYXX
//! - rectangle(not id range) of 0x7000 to 0x7F7F semi-reserved
//! - Sprites: 256 of size 16x16 (pondering allowing larger sprites) //! - Sprites: 256 of size 16x16 (pondering allowing larger sprites)
//! - Tilemaps: 4 of size 1024x1024, scrollable //! - Backgrounds: 4 of size 1024x1024, scrollable
//! //!
//! ## Features not yet implemented //! ## Features not yet implemented
//! - Tilemap effects //! - Background effects
//! - Rotation? Scaling? //! - Rotation? Scaling?
//! - Mosaic? //! - Mosaic?
//! - Mode7? //! - Mode7?
@ -27,21 +28,21 @@
//! - Gamepad text keyboard input //! - Gamepad text keyboard input
//! - Menus //! - Menus
mod background;
mod buttons; mod buttons;
mod gsa; mod gsa;
mod gsa_render_to_screen; mod gsa_render_to_screen;
mod rgb; mod rgb;
mod run; mod run;
mod sprite; mod sprite;
mod tilemap;
mod tileset; mod tileset;
pub use crate::background::*;
pub use crate::buttons::*; pub use crate::buttons::*;
pub use crate::gsa::*; pub use crate::gsa::*;
pub use crate::rgb::*; pub use crate::rgb::*;
pub use crate::run::run; pub use crate::run::run;
pub use crate::sprite::*; pub use crate::sprite::*;
pub use crate::tilemap::*;
/// Amount of sprites in [Gsa::sprites] /// Amount of sprites in [Gsa::sprites]
pub const MAX_SPRITES: usize = 0xff; pub const MAX_SPRITES: usize = 0xff;
@ -52,8 +53,17 @@ 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;
/// X and y dimensions of maps in [Gsa::maps] /// X and y dimensions of maps in [Gsa::bgs]
pub const TILEMAP_MAX_SIZE: usize = 1024; pub const BACKGROUND_MAX_SIZE: usize = 1024;
/// Tile considered empty (never drawn even if has contents)
pub const EMPTY_TILE: u16 = 0xffff
/// Tile id of bold default font
pub const FONT_BOLD: u16 = 0xf000;
/// Tile id of thin default font
pub const FONT_THIN: u16 = 0xe000;
/// Width and height (in tiles) of tileset /// Width and height (in tiles) of tileset
pub const TILESET_SIZE: usize = 0x100; pub const TILESET_SIZE: usize = 0x100;
@ -61,8 +71,11 @@ pub const TILESET_SIZE: usize = 0x100;
/// Width and height of a tile /// Width and height of a tile
pub const TILE_SIZE: usize = 16; pub const TILE_SIZE: usize = 16;
/// Palette index which is treated as transparent
pub const TRANSPARENT: u8 = 0xff;
/// Width and height of a tile in half-tile mode /// Width and height of a tile in half-tile mode
pub const HALF_TILE_SIZE: usize = 8; pub const HALF_TILE_SIZE: usize = 8;
/// Amount of tile maps in [Gsa::maps] /// Amount of tile maps in [Gsa::bgs]
pub const MAX_TILEMAPS: usize = 4; pub const MAX_BACKGROUNDS: usize = 4;

View File

@ -1,7 +1,7 @@
use crate::buttons::{button_from_gilrs, button_from_scancode}; use crate::buttons::{button_from_gilrs, button_from_scancode};
use crate::gsa_render_to_screen::{render_to_screen, render_to_window}; use crate::gsa_render_to_screen::{render_to_screen, render_to_window};
use crate::tileset::load_tileset; use crate::tileset::load_tileset;
use crate::{Buttons, Gsa, Sprite, MAX_SPRITES, SCREEN_HEIGHT, SCREEN_WIDTH}; use crate::{Buttons, Gsa, Sprite, FONT_BOLD, MAX_SPRITES, SCREEN_HEIGHT, SCREEN_WIDTH};
use gilrs::EventType; use gilrs::EventType;
use glam::IVec2; use glam::IVec2;
use std::cmp::min; use std::cmp::min;
@ -39,9 +39,9 @@ pub fn run<TGame: 'static>(
let mut gsa = Gsa { let mut gsa = Gsa {
sprites: [Sprite::default(); MAX_SPRITES], sprites: [Sprite::default(); MAX_SPRITES],
maps: Default::default(), bgs: Default::default(),
palette, palette,
font: 0x1010, font: FONT_BOLD,
pressed: 0, pressed: 0,
released: 0, released: 0,
down: 0, down: 0,