Compare commits
2 Commits
ba785f8525
...
f0ad2726f8
Author | SHA1 | Date |
---|---|---|
dani | f0ad2726f8 | |
dani | f77b66ecc9 |
|
@ -1,5 +1,6 @@
|
|||
# 0.3.0
|
||||
- added size to backgrounds
|
||||
- added rotation to backgrounds
|
||||
- refactored api, background functions are now methods to background rather than gsa
|
||||
|
||||
# 0.2.1 - 2023-07-27
|
||||
|
|
|
@ -24,7 +24,8 @@ 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"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[profile.release-dani]
|
||||
inherits = "release"
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -1,14 +1,26 @@
|
|||
use glam::IVec2;
|
||||
use gsa::{run, Gsa, FACE_DOWN};
|
||||
use gsa::{run, Gsa, FACE_DOWN, FACE_LEFT, FACE_RIGHT, SCREEN_HEIGHT, SCREEN_MIDDLE, SCREEN_WIDTH};
|
||||
|
||||
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);
|
||||
|
|
Binary file not shown.
|
@ -7,6 +7,10 @@ pub struct Background {
|
|||
pub tiles: Vec<Vec<u16>>,
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@ use crate::rgb::Rgb;
|
|||
use crate::sprite::Sprite;
|
||||
use crate::tilemap::Tilemap;
|
||||
use crate::{
|
||||
Buttons, BACKGROUND_MAX_SIZE, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, EMPTY_TILE,
|
||||
MAX_BACKGROUNDS, MAX_SPRITES,
|
||||
Buttons, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, EMPTY_TILE, MAX_BACKGROUNDS, MAX_SPRITES,
|
||||
};
|
||||
use ascii::{AsciiChar, AsciiStr};
|
||||
use glam::IVec2;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::usize;
|
||||
use std::{f32::consts::PI, usize};
|
||||
//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(
|
||||
|
@ -33,71 +33,94 @@ fn draw_tile(
|
|||
}
|
||||
}
|
||||
|
||||
fn render_bg(target: &mut [u8], map: &Background, tileset: &[u8], screen_size: IVec2) {
|
||||
let tcmult = if map.half_tile { 2 } else { 1 };
|
||||
let tilesize = if map.half_tile {
|
||||
HALF_TILE_SIZE
|
||||
} else {
|
||||
TILE_SIZE
|
||||
} as i32;
|
||||
let mut startx = map.scroll.x / tilesize;
|
||||
let mut starty = map.scroll.y / tilesize;
|
||||
let endx = map
|
||||
.size
|
||||
.x
|
||||
.min(startx + (screen_size.x / TILE_SIZE as i32 + 1) * tcmult);
|
||||
let endy = map
|
||||
.size
|
||||
.y
|
||||
.min(starty + (screen_size.y / TILE_SIZE as i32 + 1) * tcmult);
|
||||
startx = 0.max(startx);
|
||||
starty = 0.max(starty);
|
||||
for x in startx..endx {
|
||||
for y in starty..endy {
|
||||
let tile = map.tiles[x as usize][y as usize];
|
||||
if tile != EMPTY_TILE {
|
||||
draw_tile(
|
||||
target,
|
||||
IVec2 {
|
||||
x: x * tilesize - map.scroll.x,
|
||||
y: y * tilesize - map.scroll.y,
|
||||
},
|
||||
tile,
|
||||
tileset,
|
||||
map.half_tile,
|
||||
screen_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fn render_bg(target: &mut [u8], map: &Background, tileset: &[u8], screen_size: IVec2) {
|
||||
// let tcmult = if map.half_tile { 2 } else { 1 };
|
||||
// let tilesize = if map.half_tile {
|
||||
// HALF_TILE_SIZE
|
||||
// } else {
|
||||
// TILE_SIZE
|
||||
// } as i32;
|
||||
// let mut startx = map.scroll.x / tilesize;
|
||||
// let mut starty = map.scroll.y / tilesize;
|
||||
// let endx = map
|
||||
// .size
|
||||
// .x
|
||||
// .min(startx + (screen_size.x / TILE_SIZE as i32 + 1) * tcmult);
|
||||
// let endy = map
|
||||
// .size
|
||||
// .y
|
||||
// .min(starty + (screen_size.y / TILE_SIZE as i32 + 1) * tcmult);
|
||||
// startx = 0.max(startx);
|
||||
// starty = 0.max(starty);
|
||||
// for x in startx..endx {
|
||||
// for y in starty..endy {
|
||||
// let tile = map.tiles[x as usize][y as usize];
|
||||
// if tile != EMPTY_TILE {
|
||||
// draw_tile(
|
||||
// target,
|
||||
// IVec2 {
|
||||
// x: x * tilesize - map.scroll.x,
|
||||
// y: y * tilesize - map.scroll.y,
|
||||
// },
|
||||
// tile,
|
||||
// tileset,
|
||||
// map.half_tile,
|
||||
// screen_size,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn render_bg2(target: &mut [u8], map: &Background, tileset: &[u8], screen_size: IVec2) {
|
||||
fn render_bg(target: &mut [u8], map: &Background, tileset: &[u8], screen_size: IVec2) {
|
||||
let tilesize = if map.half_tile {
|
||||
HALF_TILE_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)|
|
||||
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 {
|
||||
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 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)];
|
||||
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[x as usize] = p;
|
||||
row[screenx as usize] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +130,7 @@ fn render_bg2(target: &mut [u8], map: &Background, tileset: &[u8], screen_size:
|
|||
pub(crate) fn render_to_screen(target: &mut [u8], gsa: &Gsa, tileset: &[u8], screen_size: IVec2) {
|
||||
for i in 0..MAX_BACKGROUNDS {
|
||||
if gsa.bg[i].active {
|
||||
render_bg2(target, &gsa.bg[i], tileset, screen_size);
|
||||
render_bg(target, &gsa.bg[i], tileset, screen_size);
|
||||
}
|
||||
for sprite in &gsa.sprite {
|
||||
if sprite.tile != EMPTY_TILE && sprite.priority == i as u8 {
|
||||
|
|
14
src/lib.rs
14
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,18 @@ 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;
|
||||
|
||||
|
|
730
src/mapedit.rs
730
src/mapedit.rs
|
@ -1,730 +0,0 @@
|
|||
use std::fs;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::gsa::Gsa;
|
||||
use crate::gsa_render_to_screen::render_to_screen;
|
||||
use crate::gsa_render_to_screen::render_to_window;
|
||||
use crate::maps::Maps;
|
||||
use crate::sprite::Sprite;
|
||||
use crate::tilemap::Tilemap;
|
||||
use crate::tileset::*;
|
||||
use crate::*;
|
||||
use clap::crate_version;
|
||||
use glam::IVec2;
|
||||
use winit::event::ElementState;
|
||||
use winit::{
|
||||
dpi::LogicalSize,
|
||||
event::{Event, VirtualKeyCode, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
};
|
||||
|
||||
const SPR_CURSOR: usize = 0x01;
|
||||
const TILE_CURSOR: u16 = 0x7110;
|
||||
const TILE_MARKER: u16 = 0x7210;
|
||||
const TILE_FRT: u16 = 0x7018;
|
||||
const TILE_FRB: u16 = 0x7118;
|
||||
const TILE_FRL: u16 = 0x7218;
|
||||
const TILE_FRR: u16 = 0x7219;
|
||||
const TILE_FRTL: u16 = 0x7019;
|
||||
const TILE_FRTR: u16 = 0x701A;
|
||||
const TILE_FRBL: u16 = 0x7119;
|
||||
const TILE_FRBR: u16 = 0x711A;
|
||||
const TILE_FRBG: u16 = 0x721A;
|
||||
const TILE_INPUT: u16 = 0x7318;
|
||||
|
||||
const TILE_BUT_YES: u16 = 0x7311;
|
||||
const TILE_BUT_NO: u16 = 0x7312;
|
||||
const TILE_BUT_CREATE: u16 = 0x7213;
|
||||
|
||||
const BUT_SAVE: usize = 0;
|
||||
const BUT_CREATE: usize = 1;
|
||||
const BUT_LAYER1: usize = 3;
|
||||
const BUT_LAYER2: usize = 4;
|
||||
const BUT_LAYER3: usize = 5;
|
||||
const BUT_LAYERS: usize = 6;
|
||||
const BUT_EXIT: usize = 8;
|
||||
|
||||
struct Surface<'a> {
|
||||
pub data: &'a mut [u8],
|
||||
pub size: IVec2,
|
||||
}
|
||||
|
||||
impl<'a> Surface<'a> {
|
||||
fn draw_vline(&mut self, pos: IVec2, len: i32, color: u8) {
|
||||
for i in 0..len {
|
||||
self.data[(pos.x + (pos.y + i) * self.size.x) as usize] = color;
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_hline(&mut self, pos: IVec2, len: i32, color: u8) {
|
||||
for i in 0..len {
|
||||
self.data[(pos.x + i + pos.y * self.size.x) as usize] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum State {
|
||||
Edit,
|
||||
SelectTile,
|
||||
NewMapDialog,
|
||||
}
|
||||
|
||||
fn key_to_num(key: VirtualKeyCode) -> u16 {
|
||||
match key {
|
||||
VirtualKeyCode::Key0 => 0x0,
|
||||
VirtualKeyCode::Key1 => 0x1,
|
||||
VirtualKeyCode::Key2 => 0x2,
|
||||
VirtualKeyCode::Key3 => 0x3,
|
||||
VirtualKeyCode::Key4 => 0x4,
|
||||
VirtualKeyCode::Key5 => 0x5,
|
||||
VirtualKeyCode::Key6 => 0x6,
|
||||
VirtualKeyCode::Key7 => 0x7,
|
||||
VirtualKeyCode::Key8 => 0x8,
|
||||
VirtualKeyCode::Key9 => 0x9,
|
||||
VirtualKeyCode::A => 0xa,
|
||||
VirtualKeyCode::B => 0xb,
|
||||
VirtualKeyCode::C => 0xc,
|
||||
VirtualKeyCode::D => 0xd,
|
||||
VirtualKeyCode::E => 0xe,
|
||||
VirtualKeyCode::F => 0xf,
|
||||
_ => 0x0,
|
||||
}
|
||||
}
|
||||
|
||||
impl Background {
|
||||
fn draw_frame(&mut self, pos: IVec2, size: IVec2) {
|
||||
let px1 = pos.x as usize;
|
||||
let py1 = pos.y as usize;
|
||||
let sx = size.x as usize;
|
||||
let sy = size.y as usize;
|
||||
let px2 = px1 + sx - 1;
|
||||
let py2 = py1 + sy - 1;
|
||||
|
||||
self.tiles[px1][py1] = TILE_FRTL;
|
||||
self.tiles[px1][py2] = TILE_FRBL;
|
||||
self.tiles[px2][py1] = TILE_FRTR;
|
||||
self.tiles[px2][py2] = TILE_FRBR;
|
||||
|
||||
for x in (px1 + 1)..px2 {
|
||||
self.tiles[x][py1] = TILE_FRT;
|
||||
self.tiles[x][py2] = TILE_FRB;
|
||||
}
|
||||
|
||||
for y in (py1 + 1)..py2 {
|
||||
self.tiles[px1][y] = TILE_FRL;
|
||||
self.tiles[px2][y] = TILE_FRR;
|
||||
}
|
||||
for x in (px1 + 1)..px2 {
|
||||
for y in (py1 + 1)..py2 {
|
||||
self.tiles[x][y] = TILE_FRBG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_input_window(gsa: &mut Gsa, pos: IVec2, caption: &str) {
|
||||
gsa.bg[2].draw_frame(pos, IVec2 { x: 7, y: 5 });
|
||||
gsa.bg[2].tiles[pos.x as usize + 3][pos.y as usize + 1] = TILE_INPUT;
|
||||
gsa.bg[2].tiles[pos.x as usize + 4][pos.y as usize + 1] = TILE_INPUT;
|
||||
gsa.bg[2].tiles[pos.x as usize + 1][pos.y as usize + 3] = TILE_BUT_YES;
|
||||
gsa.bg[2].tiles[pos.x as usize + 5][pos.y as usize + 3] = TILE_BUT_NO;
|
||||
gsa.write_string(
|
||||
IVec2 {
|
||||
x: pos.x * 2 + 2,
|
||||
y: pos.y * 2 + 1,
|
||||
},
|
||||
caption,
|
||||
);
|
||||
gsa.write_string(
|
||||
IVec2 {
|
||||
x: pos.x * 2 + 3,
|
||||
y: pos.y * 2 + 3,
|
||||
},
|
||||
"ID:0000",
|
||||
);
|
||||
}
|
||||
|
||||
fn update_input_window(gsa: &mut Gsa, pos: IVec2, val: u16) {
|
||||
gsa.write_string(
|
||||
IVec2 {
|
||||
x: pos.x * 2 + 6,
|
||||
y: pos.y * 2 + 3,
|
||||
},
|
||||
&format!("{:04x}", val),
|
||||
);
|
||||
}
|
||||
|
||||
fn set_state(
|
||||
state: State,
|
||||
gsa1: &mut Gsa,
|
||||
gsa2: &mut Gsa,
|
||||
current_layer: usize,
|
||||
all_layers: bool,
|
||||
current_map: u16,
|
||||
) {
|
||||
match state {
|
||||
State::Edit => {
|
||||
//update editing layers
|
||||
if all_layers {
|
||||
gsa1.bg[0].active = true;
|
||||
gsa1.bg[1].active = true;
|
||||
gsa1.bg[2].active = true;
|
||||
} else {
|
||||
gsa1.bg[0].active = current_layer == 0;
|
||||
gsa1.bg[1].active = current_layer == 1;
|
||||
gsa1.bg[2].active = current_layer == 2;
|
||||
}
|
||||
gsa2.bg[2].clear();
|
||||
gsa2.bg[2].clear();
|
||||
draw_toolbar(gsa1, gsa2, current_layer, all_layers, current_map);
|
||||
|
||||
gsa2.bg[0].active = false;
|
||||
gsa2.bg[1].active = false;
|
||||
gsa1.sprite[SPR_CURSOR].priority = 3;
|
||||
gsa1.sprite[SPR_CURSOR].tile = TILE_CURSOR;
|
||||
gsa2.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
}
|
||||
State::SelectTile => {
|
||||
draw_toolbar(gsa1, gsa2, current_layer, all_layers, current_map);
|
||||
gsa1.bg[0].active = false;
|
||||
gsa1.bg[1].active = false;
|
||||
gsa1.bg[2].active = false;
|
||||
gsa2.bg[0].active = true;
|
||||
gsa2.bg[1].active = true;
|
||||
gsa1.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
gsa2.sprite[SPR_CURSOR].tile = TILE_CURSOR;
|
||||
}
|
||||
State::NewMapDialog => {
|
||||
gsa1.bg[0].active = false;
|
||||
gsa1.bg[1].active = false;
|
||||
gsa1.bg[2].active = false;
|
||||
gsa2.bg[0].active = false;
|
||||
gsa2.bg[1].active = false;
|
||||
gsa1.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
gsa2.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
draw_input_window(gsa2, IVec2 { x: 15, y: 9 }, "Create Map");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_toolbar(
|
||||
gsa1: &mut Gsa,
|
||||
gsa2: &mut Gsa,
|
||||
current_layer: usize,
|
||||
all_layers: bool,
|
||||
current_map: u16,
|
||||
) {
|
||||
for y in 0..BACKGROUND_MAX_SIZE {
|
||||
gsa2.bg[2].tiles[0][y] = 0x7010;
|
||||
}
|
||||
gsa2.bg[2].tiles[0][BUT_SAVE] = 0x7211;
|
||||
gsa2.bg[2].tiles[0][BUT_CREATE] = TILE_BUT_CREATE;
|
||||
gsa2.bg[2].tiles[0][BUT_EXIT] = 0x7212;
|
||||
|
||||
//layer buttons
|
||||
gsa2.bg[2].tiles[0][BUT_LAYER1] = if current_layer == 0 { 0x7111 } else { 0x7011 };
|
||||
gsa2.bg[2].tiles[0][BUT_LAYER2] = if current_layer == 1 { 0x7112 } else { 0x7012 };
|
||||
gsa2.bg[2].tiles[0][BUT_LAYER3] = if current_layer == 2 { 0x7113 } else { 0x7013 };
|
||||
gsa2.bg[2].tiles[0][BUT_LAYERS] = if all_layers { 0x7114 } else { 0x7014 };
|
||||
|
||||
gsa2.bg[2].size = IVec2 { x: 120, y: 68 }; //enough to cover 4k monitors? <_<
|
||||
gsa2.bg[3].size = IVec2 { x: 240, y: 136 };
|
||||
|
||||
gsa2.write_string_vertical(
|
||||
IVec2 {
|
||||
x: 0,
|
||||
y: BUT_EXIT as i32 * 2 + 3,
|
||||
},
|
||||
&format!("MAP-{:04X}", current_map),
|
||||
);
|
||||
|
||||
gsa2.write_string_vertical(
|
||||
IVec2 {
|
||||
x: 0,
|
||||
y: BUT_EXIT as i32 * 2 + 12,
|
||||
},
|
||||
&format!("W-{}", gsa1.bg[0].size.x),
|
||||
);
|
||||
|
||||
gsa2.write_string_vertical(
|
||||
IVec2 {
|
||||
x: 1,
|
||||
y: BUT_EXIT as i32 * 2 + 12,
|
||||
},
|
||||
&format!("H-{}", gsa1.bg[0].size.y),
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn run_mapedit() {
|
||||
println!("running map edit");
|
||||
|
||||
let tileset_path = "examples/basic/gfx.gif";
|
||||
let (tileset, palette) = load_tileset(&fs::read(tileset_path).unwrap());
|
||||
|
||||
let maps_path = "examples/basic/maps.dat";
|
||||
let maps = if Path::new(maps_path).exists() {
|
||||
postcard::from_bytes(&fs::read(maps_path).unwrap()).unwrap()
|
||||
} else {
|
||||
Maps::default()
|
||||
};
|
||||
|
||||
let mut gsa1 = Gsa {
|
||||
sprite: [Sprite::default(); MAX_SPRITES],
|
||||
palette,
|
||||
bg: Default::default(),
|
||||
font: FONT_BOLD,
|
||||
pressed: 0,
|
||||
released: 0,
|
||||
down: 0,
|
||||
maps,
|
||||
str_bg: 3,
|
||||
};
|
||||
|
||||
gsa1.reset_bgs();
|
||||
gsa1.reset_sprites();
|
||||
|
||||
if gsa1.map_exists(0) {
|
||||
gsa1.load_map(0);
|
||||
}
|
||||
|
||||
for i in 0..3 {
|
||||
gsa1.bg[i].scroll = IVec2 {
|
||||
x: -16 - 32,
|
||||
y: -32,
|
||||
};
|
||||
}
|
||||
|
||||
let mut gsa2 = Gsa {
|
||||
sprite: [Sprite::default(); MAX_SPRITES],
|
||||
palette,
|
||||
bg: Default::default(),
|
||||
font: FONT_BOLD,
|
||||
pressed: 0,
|
||||
released: 0,
|
||||
down: 0,
|
||||
maps: Maps::default(),
|
||||
str_bg: 3,
|
||||
};
|
||||
gsa2.reset_bgs();
|
||||
gsa2.reset_sprites();
|
||||
for i in 0..2 {
|
||||
gsa2.bg[i].scroll = IVec2 {
|
||||
x: -16 - 32,
|
||||
y: -32,
|
||||
};
|
||||
}
|
||||
|
||||
for y in 0..TILESET_SIZE {
|
||||
for x in 0..TILESET_SIZE {
|
||||
gsa2.bg[0].tiles[x][y] = (x + (y << 8)) as u16;
|
||||
}
|
||||
}
|
||||
//draw_input_window(&mut gsa2, IVec2 { x: 5, y: 3 }, "Create Map");
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let size = LogicalSize::new(1280, 720);
|
||||
let window = WindowBuilder::new()
|
||||
.with_title(format!(
|
||||
"Game Skunk Advance Map Editor v{}",
|
||||
crate_version!()
|
||||
))
|
||||
.with_inner_size(size)
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
|
||||
let mut surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
|
||||
window.request_redraw();
|
||||
let mut mouse_pos = IVec2::ZERO;
|
||||
let mut tile_pos = IVec2::ZERO;
|
||||
let mut tile_pos2 = IVec2::ZERO;
|
||||
let mut left_down = false;
|
||||
let mut middle_down = false;
|
||||
let mut right_down = false;
|
||||
let mut selected_tile = IVec2::ZERO;
|
||||
gsa2.bg[1].tiles[0][0] = TILE_MARKER;
|
||||
let mut current_layer = 0usize;
|
||||
let mut all_layers = true;
|
||||
let mut state = State::Edit;
|
||||
let mut input_buf = 0u16;
|
||||
let mut current_map = 0;
|
||||
set_state(
|
||||
State::Edit,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
current_layer,
|
||||
all_layers,
|
||||
current_map,
|
||||
);
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
let mouse_pos = &mut mouse_pos;
|
||||
let tile_pos = &mut tile_pos;
|
||||
let tile_pos2 = &mut tile_pos2;
|
||||
let left_down = &mut left_down;
|
||||
let middle_down = &mut middle_down;
|
||||
let right_down = &mut right_down;
|
||||
let selected_tile = &mut selected_tile;
|
||||
let state = &mut state;
|
||||
let current_layer = &mut current_layer;
|
||||
let all_layers = &mut all_layers;
|
||||
let input_buf = &mut input_buf;
|
||||
let current_map = &mut current_map;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::KeyboardInput { input, .. } => {
|
||||
let vk = input.virtual_keycode.unwrap_or(VirtualKeyCode::F24);
|
||||
match vk {
|
||||
VirtualKeyCode::Escape => {
|
||||
//*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
VirtualKeyCode::LShift => {
|
||||
if input.state == ElementState::Pressed {
|
||||
*state = State::SelectTile;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
} else {
|
||||
*state = State::Edit;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
}
|
||||
}
|
||||
VirtualKeyCode::Key0
|
||||
| VirtualKeyCode::Key1
|
||||
| VirtualKeyCode::Key2
|
||||
| VirtualKeyCode::Key3
|
||||
| VirtualKeyCode::Key4
|
||||
| VirtualKeyCode::Key5
|
||||
| VirtualKeyCode::Key6
|
||||
| VirtualKeyCode::Key7
|
||||
| VirtualKeyCode::Key8
|
||||
| VirtualKeyCode::Key9
|
||||
| VirtualKeyCode::A
|
||||
| VirtualKeyCode::B
|
||||
| VirtualKeyCode::C
|
||||
| VirtualKeyCode::D
|
||||
| VirtualKeyCode::E
|
||||
| VirtualKeyCode::F => {
|
||||
if input.state == ElementState::Pressed {
|
||||
*input_buf = ((*input_buf & 0xFFF) << 4) | key_to_num(vk);
|
||||
update_input_window(&mut gsa2, IVec2 { x: 15, y: 9 }, *input_buf);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
WindowEvent::MouseInput {
|
||||
state: but_state,
|
||||
button,
|
||||
..
|
||||
} => match (but_state, button) {
|
||||
(winit::event::ElementState::Pressed, winit::event::MouseButton::Left) => {
|
||||
if mouse_pos.x < 16 {
|
||||
match (mouse_pos.y / 16) as usize {
|
||||
BUT_SAVE => {
|
||||
println!("saving");
|
||||
gsa1.store_map(*current_map);
|
||||
fs::write(
|
||||
maps_path,
|
||||
postcard::to_allocvec(&gsa1.maps).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
BUT_CREATE => {
|
||||
*state = State::NewMapDialog;
|
||||
*input_buf = *current_map;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
update_input_window(
|
||||
&mut gsa2,
|
||||
IVec2 { x: 15, y: 9 },
|
||||
*input_buf,
|
||||
);
|
||||
}
|
||||
BUT_LAYER1 => {
|
||||
*current_layer = 0;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
}
|
||||
BUT_LAYER2 => {
|
||||
*current_layer = 1;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
}
|
||||
BUT_LAYER3 => {
|
||||
*current_layer = 2;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
}
|
||||
BUT_LAYERS => {
|
||||
*all_layers = !*all_layers;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
}
|
||||
BUT_EXIT => {
|
||||
println!("exit");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
match *state {
|
||||
State::NewMapDialog => {
|
||||
//todo: not hardcode?
|
||||
if mouse_pos.y / 16 == 12 {
|
||||
if mouse_pos.x / 16 == 16 {
|
||||
println!("yes");
|
||||
gsa1.store_map(*current_map);
|
||||
*current_map = *input_buf;
|
||||
if gsa1.map_exists(*current_map) {
|
||||
gsa1.load_map(*current_map);
|
||||
} else {
|
||||
//todo: not reset scrolling
|
||||
gsa1.reset_bgs();
|
||||
}
|
||||
*state = State::Edit;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
} else if mouse_pos.x / 16 == 20 {
|
||||
println!("no");
|
||||
*state = State::Edit;
|
||||
set_state(
|
||||
*state,
|
||||
&mut gsa1,
|
||||
&mut gsa2,
|
||||
*current_layer,
|
||||
*all_layers,
|
||||
*current_map,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
*left_down = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(winit::event::ElementState::Released, winit::event::MouseButton::Left) => {
|
||||
*left_down = false;
|
||||
}
|
||||
(winit::event::ElementState::Pressed, winit::event::MouseButton::Middle) => {
|
||||
*middle_down = true;
|
||||
}
|
||||
(winit::event::ElementState::Released, winit::event::MouseButton::Middle) => {
|
||||
*middle_down = false;
|
||||
}
|
||||
(winit::event::ElementState::Pressed, winit::event::MouseButton::Right) => {
|
||||
*right_down = true;
|
||||
}
|
||||
(winit::event::ElementState::Released, winit::event::MouseButton::Right) => {
|
||||
*right_down = false;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let new_pos = IVec2 {
|
||||
x: position.x as i32 / 2,
|
||||
y: position.y as i32 / 2,
|
||||
};
|
||||
let delta = new_pos - *mouse_pos;
|
||||
if *middle_down {
|
||||
match *state {
|
||||
State::Edit => {
|
||||
// normal mode
|
||||
gsa1.bg[0].scroll -= delta;
|
||||
gsa1.bg[1].scroll -= delta;
|
||||
gsa1.bg[2].scroll -= delta;
|
||||
}
|
||||
State::SelectTile => {
|
||||
// tile select mode
|
||||
gsa2.bg[0].scroll -= delta;
|
||||
gsa2.bg[1].scroll -= delta;
|
||||
//gsa2.bgs[2].scroll -= delta;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
*mouse_pos = new_pos;
|
||||
*tile_pos = IVec2 {
|
||||
x: (new_pos.x + gsa1.bg[0].scroll.x).div_euclid(TILE_SIZE as i32),
|
||||
y: (new_pos.y + gsa1.bg[0].scroll.y).div_euclid(TILE_SIZE as i32),
|
||||
};
|
||||
*tile_pos2 = IVec2 {
|
||||
x: (new_pos.x + gsa2.bg[0].scroll.x).div_euclid(TILE_SIZE as i32),
|
||||
y: (new_pos.y + gsa2.bg[0].scroll.y).div_euclid(TILE_SIZE as i32),
|
||||
};
|
||||
let cursor_pos = *tile_pos * TILE_SIZE as i32 - gsa1.bg[0].scroll;
|
||||
let cursor_pos2 = *tile_pos2 * TILE_SIZE as i32 - gsa2.bg[0].scroll;
|
||||
gsa1.sprite[SPR_CURSOR].pos = cursor_pos;
|
||||
gsa2.sprite[SPR_CURSOR].pos = cursor_pos2;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
|
||||
Event::MainEventsCleared => {
|
||||
match *state {
|
||||
State::Edit => {
|
||||
if *left_down {
|
||||
if tile_pos.x >= 0
|
||||
&& tile_pos.y >= 0
|
||||
&& tile_pos.x < BACKGROUND_MAX_SIZE as i32
|
||||
&& tile_pos.y < BACKGROUND_MAX_SIZE as i32
|
||||
{
|
||||
let tile = (selected_tile.x + (selected_tile.y << 8)) as u16;
|
||||
gsa1.bg[*current_layer].tiles[tile_pos.x as usize]
|
||||
[tile_pos.y as usize] = tile;
|
||||
}
|
||||
} else if *right_down {
|
||||
if tile_pos.x >= 0
|
||||
&& tile_pos.y >= 0
|
||||
&& tile_pos.x < BACKGROUND_MAX_SIZE as i32
|
||||
&& tile_pos.y < BACKGROUND_MAX_SIZE as i32
|
||||
{
|
||||
gsa1.bg[*current_layer].tiles[tile_pos.x as usize]
|
||||
[tile_pos.y as usize] = EMPTY_TILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
State::SelectTile => {
|
||||
if *left_down {
|
||||
if tile_pos2.x >= 0
|
||||
&& tile_pos2.y >= 0
|
||||
&& tile_pos2.x < BACKGROUND_MAX_SIZE as i32
|
||||
&& tile_pos2.y < BACKGROUND_MAX_SIZE as i32
|
||||
{
|
||||
gsa2.bg[1].tiles[selected_tile.x as usize]
|
||||
[selected_tile.y as usize] = EMPTY_TILE;
|
||||
*selected_tile = *tile_pos2;
|
||||
gsa2.bg[1].tiles[selected_tile.x as usize]
|
||||
[selected_tile.y as usize] = TILE_MARKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// render
|
||||
let size = window.inner_size();
|
||||
surface
|
||||
.resize(
|
||||
NonZeroU32::new(size.width).unwrap(),
|
||||
NonZeroU32::new(size.height).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut screen_buffer =
|
||||
vec![TRANSPARENT; size.width as usize * size.height as usize / 4];
|
||||
let mut window_buffer = surface.buffer_mut().unwrap();
|
||||
let screen_size = IVec2 {
|
||||
x: size.width as i32 / 2,
|
||||
y: size.height as i32 / 2,
|
||||
};
|
||||
render_to_screen(&mut screen_buffer, &gsa1, &tileset, screen_size);
|
||||
render_to_screen(&mut screen_buffer, &gsa2, &tileset, screen_size);
|
||||
let mut screen = Surface {
|
||||
data: &mut screen_buffer,
|
||||
size: screen_size,
|
||||
};
|
||||
match *state {
|
||||
State::Edit => {
|
||||
let xs = -gsa1.bg[0].scroll.x - 1;
|
||||
let ys = -gsa1.bg[0].scroll.y - 1;
|
||||
let xe = xs + gsa1.bg[0].size.x * TILE_SIZE as i32 + 1;
|
||||
let ye = ys + gsa1.bg[0].size.y * TILE_SIZE as i32 + 1;
|
||||
if xs >= 16 && xs < screen_size.x {
|
||||
let starty = (ys + 1).max(0);
|
||||
let len = ye.min(screen_size.y) - starty;
|
||||
screen.draw_vline(IVec2 { x: xs, y: starty }, len, 0xfc);
|
||||
}
|
||||
if xe >= 16 && xe < screen_size.x {
|
||||
let starty = (ys + 1).max(0);
|
||||
let len = ye.min(screen_size.y) - starty;
|
||||
screen.draw_vline(IVec2 { x: xe, y: starty }, len, 0xfc);
|
||||
}
|
||||
if ys >= 0 && ys < screen_size.y {
|
||||
let startx = (xs + 1).max(16);
|
||||
let len = xe.min(screen_size.x) - startx;
|
||||
screen.draw_hline(IVec2 { x: startx, y: ys }, len, 0xfc);
|
||||
}
|
||||
if ye >= 0 && ye < screen_size.y {
|
||||
let startx = (xs + 1).max(16);
|
||||
let len = xe.min(screen_size.x) - startx;
|
||||
screen.draw_hline(IVec2 { x: startx, y: ye }, len, 0xfc);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
render_to_window(
|
||||
&mut window_buffer,
|
||||
&mut screen_buffer,
|
||||
&palette,
|
||||
IVec2 {
|
||||
x: size.width as i32,
|
||||
y: size.height as i32,
|
||||
},
|
||||
IVec2 {
|
||||
x: size.width as i32 / 2,
|
||||
y: size.height as i32 / 2,
|
||||
},
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
window_buffer.present().unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
use crate::mapedit::*;
|
||||
use crate::Background;
|
||||
|
||||
impl Background {
|
||||
pub(crate) fn draw_frame(&mut self, pos: IVec2, size: IVec2) {
|
||||
let px1 = pos.x as usize;
|
||||
let py1 = pos.y as usize;
|
||||
let sx = size.x as usize;
|
||||
let sy = size.y as usize;
|
||||
let px2 = px1 + sx - 1;
|
||||
let py2 = py1 + sy - 1;
|
||||
|
||||
self.tiles[px1][py1] = TILE_FRTL;
|
||||
self.tiles[px1][py2] = TILE_FRBL;
|
||||
self.tiles[px2][py1] = TILE_FRTR;
|
||||
self.tiles[px2][py2] = TILE_FRBR;
|
||||
|
||||
for x in (px1 + 1)..px2 {
|
||||
self.tiles[x][py1] = TILE_FRT;
|
||||
self.tiles[x][py2] = TILE_FRB;
|
||||
}
|
||||
|
||||
for y in (py1 + 1)..py2 {
|
||||
self.tiles[px1][y] = TILE_FRL;
|
||||
self.tiles[px2][y] = TILE_FRR;
|
||||
}
|
||||
for x in (px1 + 1)..px2 {
|
||||
for y in (py1 + 1)..py2 {
|
||||
self.tiles[x][y] = TILE_FRBG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
pub const SPR_CURSOR: usize = 0x01;
|
||||
pub const TILE_CURSOR: u16 = 0x7110;
|
||||
pub const TILE_MARKER: u16 = 0x7210;
|
||||
pub const TILE_FRT: u16 = 0x7018;
|
||||
pub const TILE_FRB: u16 = 0x7118;
|
||||
pub const TILE_FRL: u16 = 0x7218;
|
||||
pub const TILE_FRR: u16 = 0x7219;
|
||||
pub const TILE_FRTL: u16 = 0x7019;
|
||||
pub const TILE_FRTR: u16 = 0x701A;
|
||||
pub const TILE_FRBL: u16 = 0x7119;
|
||||
pub const TILE_FRBR: u16 = 0x711A;
|
||||
pub const TILE_FRBG: u16 = 0x721A;
|
||||
pub const TILE_INPUT: u16 = 0x7318;
|
||||
|
||||
pub const TILE_BUT_YES: u16 = 0x7311;
|
||||
pub const TILE_BUT_NO: u16 = 0x7312;
|
||||
pub const TILE_BUT_CREATE: u16 = 0x7213;
|
||||
|
||||
pub const BUT_SAVE: usize = 0;
|
||||
pub const BUT_CREATE: usize = 1;
|
||||
pub const BUT_LAYER1: usize = 3;
|
||||
pub const BUT_LAYER2: usize = 4;
|
||||
pub const BUT_LAYER3: usize = 5;
|
||||
pub const BUT_LAYERS: usize = 6;
|
||||
pub const BUT_EXIT: usize = 8;
|
|
@ -0,0 +1,449 @@
|
|||
mod background;
|
||||
mod state;
|
||||
use state::State;
|
||||
mod stuff;
|
||||
use stuff::Stuff;
|
||||
mod constants;
|
||||
use constants::*;
|
||||
mod surface;
|
||||
use surface::Surface;
|
||||
mod util;
|
||||
use util::*;
|
||||
|
||||
use std::fs;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::gsa::Gsa;
|
||||
use crate::gsa_render_to_screen::render_to_screen;
|
||||
use crate::gsa_render_to_screen::render_to_window;
|
||||
use crate::maps::Maps;
|
||||
use crate::sprite::Sprite;
|
||||
use crate::tileset::*;
|
||||
use crate::*;
|
||||
use clap::crate_version;
|
||||
use glam::IVec2;
|
||||
use winit::dpi::PhysicalSize;
|
||||
use winit::event::ElementState;
|
||||
use winit::{
|
||||
dpi::LogicalSize,
|
||||
event::{Event, VirtualKeyCode, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
};
|
||||
|
||||
|
||||
pub(crate) fn run_mapedit() {
|
||||
println!("running map edit");
|
||||
|
||||
let tileset_path = "examples/basic/gfx.gif";
|
||||
let (tileset, palette) = load_tileset(&fs::read(tileset_path).unwrap());
|
||||
|
||||
let maps_path = "examples/basic/maps.dat";
|
||||
let maps = if Path::new(maps_path).exists() {
|
||||
postcard::from_bytes(&fs::read(maps_path).unwrap()).unwrap()
|
||||
} else {
|
||||
Maps::default()
|
||||
};
|
||||
|
||||
let mut gsa1 = Gsa {
|
||||
sprite: [Sprite::default(); MAX_SPRITES],
|
||||
palette,
|
||||
bg: Default::default(),
|
||||
font: FONT_BOLD,
|
||||
pressed: 0,
|
||||
released: 0,
|
||||
down: 0,
|
||||
maps,
|
||||
str_bg: 3,
|
||||
};
|
||||
|
||||
gsa1.reset_bgs();
|
||||
gsa1.reset_sprites();
|
||||
|
||||
if gsa1.map_exists(0) {
|
||||
gsa1.load_map(0);
|
||||
}
|
||||
|
||||
for i in 0..3 {
|
||||
gsa1.bg[i].scroll = IVec2 {
|
||||
x: -16 - 32,
|
||||
y: -32,
|
||||
};
|
||||
}
|
||||
|
||||
let mut gsa2 = Gsa {
|
||||
sprite: [Sprite::default(); MAX_SPRITES],
|
||||
palette,
|
||||
bg: Default::default(),
|
||||
font: FONT_BOLD,
|
||||
pressed: 0,
|
||||
released: 0,
|
||||
down: 0,
|
||||
maps: Maps::default(),
|
||||
str_bg: 3,
|
||||
};
|
||||
gsa2.reset_bgs();
|
||||
gsa2.reset_sprites();
|
||||
for i in 0..2 {
|
||||
gsa2.bg[i].scroll = IVec2 {
|
||||
x: -16 - 32,
|
||||
y: -32,
|
||||
};
|
||||
}
|
||||
|
||||
for y in 0..TILESET_SIZE {
|
||||
for x in 0..TILESET_SIZE {
|
||||
gsa2.bg[0].tiles[x][y] = (x + (y << 8)) as u16;
|
||||
}
|
||||
}
|
||||
//draw_input_window(&mut gsa2, IVec2 { x: 5, y: 3 }, "Create Map");
|
||||
|
||||
let mut stuff = Stuff {
|
||||
gsa1,
|
||||
gsa2,
|
||||
mouse_pos: IVec2::ZERO,
|
||||
tile_pos: IVec2::ZERO,
|
||||
tile_pos2: IVec2::ZERO,
|
||||
left_down: false,
|
||||
middle_down: false,
|
||||
right_down: false,
|
||||
selected_tile: IVec2::ZERO,
|
||||
current_layer: 0,
|
||||
all_layers: true,
|
||||
state: State::Edit,
|
||||
input_buf: 0,
|
||||
current_map: 0,
|
||||
window_tile_size: IVec2::new(1280 / 32, 640 / 32),
|
||||
};
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let size = LogicalSize::new(1280, 640);
|
||||
let window = WindowBuilder::new()
|
||||
.with_title(format!(
|
||||
"Game Skunk Advance Map Editor v{}",
|
||||
crate_version!()
|
||||
))
|
||||
.with_inner_size(size)
|
||||
.with_resize_increments(LogicalSize::new(32, 32))
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
|
||||
let mut surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
|
||||
window.request_redraw();
|
||||
|
||||
stuff.gsa2.bg[1].tiles[0][0] = TILE_MARKER;
|
||||
stuff.set_state(State::Edit);
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
//let stuff = &mut stuff;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::Resized(size) => {
|
||||
if size.width % 32 != 0 || size.height % 32 != 0 {
|
||||
let tw = (size.width as f32 / 32.0).round();
|
||||
let th = (size.height as f32 / 32.0).round();
|
||||
let w = (tw * 32.0) as u32;
|
||||
let h = (th * 32.0) as u32;
|
||||
stuff.window_tile_size.x = tw as i32;
|
||||
stuff.window_tile_size.y = th as i32;
|
||||
stuff.draw_toolbar();
|
||||
let pos = window.outer_position().unwrap();
|
||||
window.set_inner_size(PhysicalSize::new(w, h));
|
||||
window.set_outer_position(pos);
|
||||
}
|
||||
}
|
||||
WindowEvent::KeyboardInput { input, .. } => {
|
||||
let vk = input.virtual_keycode.unwrap_or(VirtualKeyCode::F24);
|
||||
match vk {
|
||||
VirtualKeyCode::Escape => {
|
||||
//*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
VirtualKeyCode::LShift => {
|
||||
if input.state == ElementState::Pressed {
|
||||
stuff.set_state(State::SelectTile);
|
||||
} else {
|
||||
stuff.set_state(State::Edit);
|
||||
}
|
||||
}
|
||||
VirtualKeyCode::Key0
|
||||
| VirtualKeyCode::Key1
|
||||
| VirtualKeyCode::Key2
|
||||
| VirtualKeyCode::Key3
|
||||
| VirtualKeyCode::Key4
|
||||
| VirtualKeyCode::Key5
|
||||
| VirtualKeyCode::Key6
|
||||
| VirtualKeyCode::Key7
|
||||
| VirtualKeyCode::Key8
|
||||
| VirtualKeyCode::Key9
|
||||
| VirtualKeyCode::A
|
||||
| VirtualKeyCode::B
|
||||
| VirtualKeyCode::C
|
||||
| VirtualKeyCode::D
|
||||
| VirtualKeyCode::E
|
||||
| VirtualKeyCode::F => {
|
||||
if input.state == ElementState::Pressed {
|
||||
stuff.input_buf = ((stuff.input_buf & 0xFFF) << 4) | key_to_num(vk);
|
||||
stuff.update_input_window(IVec2 { x: 15, y: 9 }, stuff.input_buf);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
WindowEvent::MouseInput {
|
||||
state: but_state,
|
||||
button,
|
||||
..
|
||||
} => match (but_state, button) {
|
||||
(winit::event::ElementState::Pressed, winit::event::MouseButton::Left) => {
|
||||
if stuff.mouse_pos.x < 16 {
|
||||
match (stuff.mouse_pos.y / 16) as usize {
|
||||
BUT_SAVE => {
|
||||
println!("saving");
|
||||
stuff.gsa1.store_map(stuff.current_map);
|
||||
fs::write(
|
||||
maps_path,
|
||||
postcard::to_allocvec(&stuff.gsa1.maps).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
BUT_CREATE => {
|
||||
stuff.input_buf = stuff.current_map;
|
||||
stuff.set_state(State::NewMapDialog);
|
||||
stuff.update_input_window(
|
||||
IVec2 { x: 15, y: 9 },
|
||||
stuff.input_buf,
|
||||
);
|
||||
}
|
||||
BUT_LAYER1 => {
|
||||
stuff.current_layer = 0;
|
||||
stuff.set_state(stuff.state);
|
||||
}
|
||||
BUT_LAYER2 => {
|
||||
stuff.current_layer = 1;
|
||||
stuff.set_state(stuff.state);
|
||||
}
|
||||
BUT_LAYER3 => {
|
||||
stuff.current_layer = 2;
|
||||
stuff.set_state(stuff.state);
|
||||
}
|
||||
BUT_LAYERS => {
|
||||
stuff.all_layers = !stuff.all_layers;
|
||||
stuff.set_state(stuff.state);
|
||||
}
|
||||
BUT_EXIT => {
|
||||
println!("exit");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
match stuff.state {
|
||||
State::NewMapDialog => {
|
||||
//todo: not hardcode?
|
||||
if stuff.mouse_pos.y / 16 == 12 {
|
||||
if stuff.mouse_pos.x / 16 == 16 {
|
||||
println!("yes");
|
||||
stuff.gsa1.store_map(stuff.current_map);
|
||||
stuff.current_map = stuff.input_buf;
|
||||
if stuff.gsa1.map_exists(stuff.current_map) {
|
||||
stuff.gsa1.load_map(stuff.current_map);
|
||||
} else {
|
||||
//todo: not reset scrolling
|
||||
stuff.gsa1.reset_bgs();
|
||||
}
|
||||
stuff.set_state(State::Edit);
|
||||
} else if stuff.mouse_pos.x / 16 == 20 {
|
||||
println!("no");
|
||||
stuff.set_state(State::Edit);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
stuff.left_down = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(winit::event::ElementState::Released, winit::event::MouseButton::Left) => {
|
||||
stuff.left_down = false;
|
||||
}
|
||||
(winit::event::ElementState::Pressed, winit::event::MouseButton::Middle) => {
|
||||
stuff.middle_down = true;
|
||||
}
|
||||
(winit::event::ElementState::Released, winit::event::MouseButton::Middle) => {
|
||||
stuff.middle_down = false;
|
||||
}
|
||||
(winit::event::ElementState::Pressed, winit::event::MouseButton::Right) => {
|
||||
stuff.right_down = true;
|
||||
}
|
||||
(winit::event::ElementState::Released, winit::event::MouseButton::Right) => {
|
||||
stuff.right_down = false;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let new_pos = IVec2 {
|
||||
x: position.x as i32 / 2,
|
||||
y: position.y as i32 / 2,
|
||||
};
|
||||
let delta = new_pos - stuff.mouse_pos;
|
||||
if stuff.middle_down {
|
||||
match stuff.state {
|
||||
State::Edit => {
|
||||
// normal mode
|
||||
stuff.gsa1.bg[0].scroll -= delta;
|
||||
stuff.gsa1.bg[1].scroll -= delta;
|
||||
stuff.gsa1.bg[2].scroll -= delta;
|
||||
}
|
||||
State::SelectTile => {
|
||||
// tile select mode
|
||||
stuff.gsa2.bg[0].scroll -= delta;
|
||||
stuff.gsa2.bg[1].scroll -= delta;
|
||||
//gsa2.bgs[2].scroll -= delta;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
stuff.mouse_pos = new_pos;
|
||||
let new_tile_pos =
|
||||
IVec2 {
|
||||
x: (new_pos.x + stuff.gsa1.bg[0].scroll.x).div_euclid(TILE_SIZE as i32),
|
||||
y: (new_pos.y + stuff.gsa1.bg[0].scroll.y).div_euclid(TILE_SIZE as i32),
|
||||
};
|
||||
let tile_pos_changed = stuff.tile_pos != new_tile_pos;
|
||||
stuff.tile_pos = new_tile_pos;
|
||||
stuff.tile_pos2 = IVec2 {
|
||||
x: (new_pos.x + stuff.gsa2.bg[0].scroll.x).div_euclid(TILE_SIZE as i32),
|
||||
y: (new_pos.y + stuff.gsa2.bg[0].scroll.y).div_euclid(TILE_SIZE as i32),
|
||||
};
|
||||
let cursor_pos = stuff.tile_pos * TILE_SIZE as i32 - stuff.gsa1.bg[0].scroll;
|
||||
let cursor_pos2 = stuff.tile_pos2 * TILE_SIZE as i32 - stuff.gsa2.bg[0].scroll;
|
||||
stuff.gsa1.sprite[SPR_CURSOR].pos = cursor_pos;
|
||||
stuff.gsa2.sprite[SPR_CURSOR].pos = cursor_pos2;
|
||||
if tile_pos_changed {
|
||||
stuff.update_status_bar();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
|
||||
Event::MainEventsCleared => {
|
||||
match stuff.state {
|
||||
State::Edit => {
|
||||
if stuff.left_down {
|
||||
if stuff.tile_pos.x >= 0
|
||||
&& stuff.tile_pos.y >= 0
|
||||
&& stuff.tile_pos.x < BACKGROUND_MAX_SIZE as i32
|
||||
&& stuff.tile_pos.y < BACKGROUND_MAX_SIZE as i32
|
||||
{
|
||||
let tile =
|
||||
(stuff.selected_tile.x + (stuff.selected_tile.y << 8)) as u16;
|
||||
stuff.gsa1.bg[stuff.current_layer].tiles
|
||||
[stuff.tile_pos.x as usize]
|
||||
[stuff.tile_pos.y as usize] = tile;
|
||||
}
|
||||
} else if stuff.right_down {
|
||||
if stuff.tile_pos.x >= 0
|
||||
&& stuff.tile_pos.y >= 0
|
||||
&& stuff.tile_pos.x < BACKGROUND_MAX_SIZE as i32
|
||||
&& stuff.tile_pos.y < BACKGROUND_MAX_SIZE as i32
|
||||
{
|
||||
stuff.gsa1.bg[stuff.current_layer].tiles
|
||||
[stuff.tile_pos.x as usize]
|
||||
[stuff.tile_pos.y as usize] = EMPTY_TILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
State::SelectTile => {
|
||||
if stuff.left_down {
|
||||
if stuff.tile_pos2.x >= 0
|
||||
&& stuff.tile_pos2.y >= 0
|
||||
&& stuff.tile_pos2.x < BACKGROUND_MAX_SIZE as i32
|
||||
&& stuff.tile_pos2.y < BACKGROUND_MAX_SIZE as i32
|
||||
{
|
||||
stuff.gsa2.bg[1].tiles[stuff.selected_tile.x as usize]
|
||||
[stuff.selected_tile.y as usize] = EMPTY_TILE;
|
||||
stuff.selected_tile = stuff.tile_pos2;
|
||||
stuff.gsa2.bg[1].tiles[stuff.selected_tile.x as usize]
|
||||
[stuff.selected_tile.y as usize] = TILE_MARKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// render
|
||||
let size = window.inner_size();
|
||||
surface
|
||||
.resize(
|
||||
NonZeroU32::new(size.width).unwrap(),
|
||||
NonZeroU32::new(size.height).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut screen_buffer =
|
||||
vec![TRANSPARENT; size.width as usize * size.height as usize / 4];
|
||||
let mut window_buffer = surface.buffer_mut().unwrap();
|
||||
let screen_size = IVec2 {
|
||||
x: size.width as i32 / 2,
|
||||
y: size.height as i32 / 2,
|
||||
};
|
||||
render_to_screen(&mut screen_buffer, &stuff.gsa1, &tileset, screen_size);
|
||||
render_to_screen(&mut screen_buffer, &stuff.gsa2, &tileset, screen_size);
|
||||
let mut screen = Surface {
|
||||
data: &mut screen_buffer,
|
||||
size: screen_size,
|
||||
};
|
||||
match stuff.state {
|
||||
State::Edit => {
|
||||
let xs = -stuff.gsa1.bg[0].scroll.x - 1;
|
||||
let ys = -stuff.gsa1.bg[0].scroll.y - 1;
|
||||
let xe = xs + stuff.gsa1.bg[0].size.x * TILE_SIZE as i32 + 1;
|
||||
let ye = ys + stuff.gsa1.bg[0].size.y * TILE_SIZE as i32 + 1;
|
||||
if xs >= 16 && xs < screen_size.x {
|
||||
let starty = (ys + 1).max(0);
|
||||
let len = ye.min(screen_size.y) - starty;
|
||||
screen.draw_vline(IVec2 { x: xs, y: starty }, len, 0xfc);
|
||||
}
|
||||
if xe >= 16 && xe < screen_size.x {
|
||||
let starty = (ys + 1).max(0);
|
||||
let len = ye.min(screen_size.y) - starty;
|
||||
screen.draw_vline(IVec2 { x: xe, y: starty }, len, 0xfc);
|
||||
}
|
||||
if ys >= 0 && ys < screen_size.y {
|
||||
let startx = (xs + 1).max(16);
|
||||
let len = xe.min(screen_size.x) - startx;
|
||||
screen.draw_hline(IVec2 { x: startx, y: ys }, len, 0xfc);
|
||||
}
|
||||
if ye >= 0 && ye < screen_size.y {
|
||||
let startx = (xs + 1).max(16);
|
||||
let len = xe.min(screen_size.x) - startx;
|
||||
screen.draw_hline(IVec2 { x: startx, y: ye }, len, 0xfc);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
render_to_window(
|
||||
&mut window_buffer,
|
||||
&mut screen_buffer,
|
||||
&palette,
|
||||
IVec2 {
|
||||
x: size.width as i32,
|
||||
y: size.height as i32,
|
||||
},
|
||||
IVec2 {
|
||||
x: size.width as i32 / 2,
|
||||
y: size.height as i32 / 2,
|
||||
},
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
window_buffer.present().unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
use super::stuff::Stuff;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum State {
|
||||
Edit,
|
||||
SelectTile,
|
||||
NewMapDialog,
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
use super::constants::*;
|
||||
use super::state::State;
|
||||
use crate::gsa::Gsa;
|
||||
use crate::*;
|
||||
use glam::IVec2;
|
||||
|
||||
pub struct Stuff {
|
||||
pub gsa1: Gsa,
|
||||
pub gsa2: Gsa,
|
||||
pub mouse_pos: IVec2,
|
||||
pub tile_pos: IVec2,
|
||||
pub tile_pos2: IVec2,
|
||||
pub left_down: bool,
|
||||
pub middle_down: bool,
|
||||
pub right_down: bool,
|
||||
pub selected_tile: IVec2,
|
||||
pub current_layer: usize,
|
||||
pub all_layers: bool,
|
||||
pub state: State,
|
||||
pub input_buf: u16,
|
||||
pub current_map: u16,
|
||||
pub window_tile_size: IVec2,
|
||||
}
|
||||
|
||||
impl Stuff {
|
||||
pub fn draw_input_window(&mut self, pos: IVec2, caption: &str) {
|
||||
self.gsa2.bg[2].draw_frame(pos, IVec2 { x: 7, y: 5 });
|
||||
self.gsa2.bg[2].tiles[pos.x as usize + 3][pos.y as usize + 1] = TILE_INPUT;
|
||||
self.gsa2.bg[2].tiles[pos.x as usize + 4][pos.y as usize + 1] = TILE_INPUT;
|
||||
self.gsa2.bg[2].tiles[pos.x as usize + 1][pos.y as usize + 3] = TILE_BUT_YES;
|
||||
self.gsa2.bg[2].tiles[pos.x as usize + 5][pos.y as usize + 3] = TILE_BUT_NO;
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: pos.x * 2 + 2,
|
||||
y: pos.y * 2 + 1,
|
||||
},
|
||||
caption,
|
||||
);
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: pos.x * 2 + 3,
|
||||
y: pos.y * 2 + 3,
|
||||
},
|
||||
"ID:0000",
|
||||
);
|
||||
}
|
||||
|
||||
pub fn draw_toolbar(&mut self) {
|
||||
self.gsa2.bg[2].clear();
|
||||
self.gsa2.bg[3].clear();
|
||||
|
||||
//vertical
|
||||
for y in 0..(self.window_tile_size.y - 1) {
|
||||
self.gsa2.bg[2].tiles[0][y as usize] = 0x7010;
|
||||
}
|
||||
self.gsa2.bg[2].tiles[0][BUT_SAVE] = 0x7211;
|
||||
self.gsa2.bg[2].tiles[0][BUT_CREATE] = TILE_BUT_CREATE;
|
||||
self.gsa2.bg[2].tiles[0][BUT_EXIT] = 0x7212;
|
||||
|
||||
//layer buttons
|
||||
self.gsa2.bg[2].tiles[0][BUT_LAYER1] = if self.current_layer == 0 {
|
||||
0x7111
|
||||
} else {
|
||||
0x7011
|
||||
};
|
||||
self.gsa2.bg[2].tiles[0][BUT_LAYER2] = if self.current_layer == 1 {
|
||||
0x7112
|
||||
} else {
|
||||
0x7012
|
||||
};
|
||||
self.gsa2.bg[2].tiles[0][BUT_LAYER3] = if self.current_layer == 2 {
|
||||
0x7113
|
||||
} else {
|
||||
0x7013
|
||||
};
|
||||
self.gsa2.bg[2].tiles[0][BUT_LAYERS] = if self.all_layers { 0x7114 } else { 0x7014 };
|
||||
|
||||
self.gsa2.bg[2].size = IVec2 { x: 120, y: 68 }; //enough to cover 4k monitors? <_<
|
||||
self.gsa2.bg[3].size = IVec2 { x: 240, y: 136 };
|
||||
|
||||
//horizontal
|
||||
let bottom = self.window_tile_size.y as usize - 1;
|
||||
self.gsa2.bg[2].tiles[0][bottom] = 0x7410;
|
||||
for x in 1..self.window_tile_size.x {
|
||||
self.gsa2.bg[2].tiles[x as usize][bottom] = 0x7310;
|
||||
}
|
||||
self.update_status_bar();
|
||||
}
|
||||
|
||||
pub fn set_state(&mut self, state: State) {
|
||||
self.state = state;
|
||||
match state {
|
||||
State::Edit => {
|
||||
//update editing layers
|
||||
if self.all_layers {
|
||||
self.gsa1.bg[0].active = true;
|
||||
self.gsa1.bg[1].active = true;
|
||||
self.gsa1.bg[2].active = true;
|
||||
} else {
|
||||
self.gsa1.bg[0].active = self.current_layer == 0;
|
||||
self.gsa1.bg[1].active = self.current_layer == 1;
|
||||
self.gsa1.bg[2].active = self.current_layer == 2;
|
||||
}
|
||||
self.draw_toolbar();
|
||||
|
||||
self.gsa2.bg[0].active = false;
|
||||
self.gsa2.bg[1].active = false;
|
||||
self.gsa1.sprite[SPR_CURSOR].priority = 3;
|
||||
self.gsa1.sprite[SPR_CURSOR].tile = TILE_CURSOR;
|
||||
self.gsa2.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
}
|
||||
State::SelectTile => {
|
||||
self.draw_toolbar();
|
||||
self.gsa1.bg[0].active = false;
|
||||
self.gsa1.bg[1].active = false;
|
||||
self.gsa1.bg[2].active = false;
|
||||
self.gsa2.bg[0].active = true;
|
||||
self.gsa2.bg[1].active = true;
|
||||
self.gsa1.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
self.gsa2.sprite[SPR_CURSOR].tile = TILE_CURSOR;
|
||||
}
|
||||
State::NewMapDialog => {
|
||||
self.gsa1.bg[0].active = false;
|
||||
self.gsa1.bg[1].active = false;
|
||||
self.gsa1.bg[2].active = false;
|
||||
self.gsa2.bg[0].active = false;
|
||||
self.gsa2.bg[1].active = false;
|
||||
self.gsa1.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
self.gsa2.sprite[SPR_CURSOR].tile = EMPTY_TILE;
|
||||
self.draw_input_window(IVec2 { x: 15, y: 9 }, "Create Map");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_input_window(&mut self, pos: IVec2, val: u16) {
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: pos.x * 2 + 6,
|
||||
y: pos.y * 2 + 3,
|
||||
},
|
||||
&format!("{:04x}", val),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_status_bar(&mut self) {
|
||||
let bottom = self.window_tile_size.y as usize - 1;
|
||||
let text_bottom = (bottom * 2 + 1) as i32;
|
||||
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: 0,
|
||||
y: text_bottom,
|
||||
},
|
||||
&" ".repeat(self.window_tile_size.x as usize * 2),
|
||||
);
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: 1,
|
||||
y: text_bottom,
|
||||
},
|
||||
&format!("Map:{:04X}", self.current_map),
|
||||
);
|
||||
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: 17,
|
||||
y: text_bottom,
|
||||
},
|
||||
&format!("Size:{}*{}", self.gsa1.bg[0].size.x, self.gsa1.bg[0].size.y),
|
||||
);
|
||||
|
||||
self.gsa2.write_string(
|
||||
IVec2 {
|
||||
x: 33,
|
||||
y: text_bottom,
|
||||
},
|
||||
&format!("Cursor:{}*{}", self.tile_pos.x, self.tile_pos.y),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
use glam::IVec2;
|
||||
|
||||
pub struct Surface<'a> {
|
||||
pub data: &'a mut [u8],
|
||||
pub size: IVec2,
|
||||
}
|
||||
|
||||
impl<'a> Surface<'a> {
|
||||
pub fn draw_vline(&mut self, pos: IVec2, len: i32, color: u8) {
|
||||
for i in 0..len {
|
||||
self.data[(pos.x + (pos.y + i) * self.size.x) as usize] = color;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_hline(&mut self, pos: IVec2, len: i32, color: u8) {
|
||||
for i in 0..len {
|
||||
self.data[(pos.x + i + pos.y * self.size.x) as usize] = color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
use winit::event::VirtualKeyCode;
|
||||
|
||||
pub fn key_to_num(key: VirtualKeyCode) -> u16 {
|
||||
match key {
|
||||
VirtualKeyCode::Key0 => 0x0,
|
||||
VirtualKeyCode::Key1 => 0x1,
|
||||
VirtualKeyCode::Key2 => 0x2,
|
||||
VirtualKeyCode::Key3 => 0x3,
|
||||
VirtualKeyCode::Key4 => 0x4,
|
||||
VirtualKeyCode::Key5 => 0x5,
|
||||
VirtualKeyCode::Key6 => 0x6,
|
||||
VirtualKeyCode::Key7 => 0x7,
|
||||
VirtualKeyCode::Key8 => 0x8,
|
||||
VirtualKeyCode::Key9 => 0x9,
|
||||
VirtualKeyCode::A => 0xa,
|
||||
VirtualKeyCode::B => 0xb,
|
||||
VirtualKeyCode::C => 0xc,
|
||||
VirtualKeyCode::D => 0xd,
|
||||
VirtualKeyCode::E => 0xe,
|
||||
VirtualKeyCode::F => 0xf,
|
||||
_ => 0x0,
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
use crate::buttons::{button_from_gilrs, button_from_scancode};
|
||||
use crate::gsa_render_to_screen::{render_to_screen, render_to_window};
|
||||
use crate::maps::Maps;
|
||||
use crate::tileset::load_tileset;
|
||||
use crate::{
|
||||
Buttons, Gsa, Sprite, FONT_BOLD, MAX_SPRITES, SCREEN_HEIGHT, SCREEN_WIDTH, TRANSPARENT,
|
||||
|
@ -47,7 +46,7 @@ pub fn run<TGame: 'static>(
|
|||
) {
|
||||
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 +99,7 @@ pub fn run<TGame: 'static>(
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue