Make light offset of tiles variable

This commit is contained in:
crumblingstatue 2023-04-08 16:14:59 +02:00
parent 07c7d628ee
commit 79e2ba7b83
7 changed files with 71 additions and 33 deletions

View file

@ -14,7 +14,7 @@ use sfml::{
use crate::{ use crate::{
debug::{self, DebugState}, debug::{self, DebugState},
game::{for_each_tile_on_screen, Biome, GameState}, game::{for_each_tile_on_screen, Biome, GameState},
graphics::{self, ScreenPos, ScreenPosScalar}, graphics::{self, ScreenSc, ScreenVec},
input::Input, input::Input,
math::{center_offset, TILE_SIZE}, math::{center_offset, TILE_SIZE},
res::Res, res::Res,
@ -178,8 +178,8 @@ impl App {
let vco = viewport_center_offset(self.rw.size(), rt_size, self.scale); let vco = viewport_center_offset(self.rw.size(), rt_size, self.scale);
loc.x -= vco.x; loc.x -= vco.x;
loc.y -= vco.y; loc.y -= vco.y;
loc.x /= self.scale as ScreenPosScalar; loc.x /= self.scale as ScreenSc;
loc.y /= self.scale as ScreenPosScalar; loc.y /= self.scale as ScreenSc;
let mut wpos = self.game.camera_offset; let mut wpos = self.game.camera_offset;
wpos.x = wpos.x.saturating_add_signed(loc.x.into()); wpos.x = wpos.x.saturating_add_signed(loc.x.into());
wpos.y = wpos.y.saturating_add_signed(loc.y.into()); wpos.y = wpos.y.saturating_add_signed(loc.y.into());
@ -289,13 +289,13 @@ impl App {
} }
} }
fn viewport_center_offset(rw_size: Vector2u, rt_size: Vector2u, scale: u8) -> ScreenPos { fn viewport_center_offset(rw_size: Vector2u, rt_size: Vector2u, scale: u8) -> ScreenVec {
let rw_size = rw_size; let rw_size = rw_size;
let rt_size = rt_size * scale as u32; let rt_size = rt_size * scale as u32;
let x = center_offset(rt_size.x as i32, rw_size.x as i32); let x = center_offset(rt_size.x as i32, rw_size.x as i32);
let y = center_offset(rt_size.y as i32, rw_size.y as i32); let y = center_offset(rt_size.y as i32, rw_size.y as i32);
ScreenPos { ScreenVec {
x: x as ScreenPosScalar, x: x as ScreenSc,
y: y as ScreenPosScalar, y: y as ScreenSc,
} }
} }

View file

@ -9,8 +9,8 @@ use sfml::{
}; };
use crate::{ use crate::{
graphics::{ScreenPos, ScreenPosScalar}, graphics::{ScreenSc, ScreenVec},
math::{wp_to_tp, WorldPos, TILE_SIZE}, math::{wp_to_tp, WorldPos},
res::Res, res::Res,
tiles::TileDb, tiles::TileDb,
world::{Tile, TileId, TilePos, World}, world::{Tile, TileId, TilePos, World},
@ -41,7 +41,7 @@ pub struct GameState {
#[derive(Debug, Inspect)] #[derive(Debug, Inspect)]
pub struct LightSource { pub struct LightSource {
pub pos: ScreenPos, pub pos: ScreenVec,
} }
#[derive(PartialEq, Eq, Clone, Copy, Debug, Inspect)] #[derive(PartialEq, Eq, Clone, Copy, Debug, Inspect)]
@ -63,11 +63,12 @@ impl GameState {
} }
if tile.mid != Tile::EMPTY { if tile.mid != Tile::EMPTY {
s.set_texture_rect(self.tile_db[tile.mid].atlas_offset.to_sf_rect()); s.set_texture_rect(self.tile_db[tile.mid].atlas_offset.to_sf_rect());
if self.tile_db[tile.mid].emits_light { if let Some(light) = self.tile_db[tile.mid].light {
let mut pos = sp; let pos = ScreenVec {
pos.x += (TILE_SIZE / 2) as i16; x: sp.x + light.x,
pos.y += (TILE_SIZE / 2) as i16; y: sp.y + light.y,
self.light_sources.push(LightSource { pos: sp }); };
self.light_sources.push(LightSource { pos });
} }
rt.draw(&s); rt.draw(&s);
} }
@ -121,7 +122,7 @@ impl GameState {
pub fn for_each_tile_on_screen( pub fn for_each_tile_on_screen(
camera_offset: WorldPos, camera_offset: WorldPos,
rt_size: Vector2u, rt_size: Vector2u,
mut f: impl FnMut(TilePos, ScreenPos), mut f: impl FnMut(TilePos, ScreenVec),
) { ) {
for y in (-32..(rt_size.y as i16) + 32).step_by(32) { for y in (-32..(rt_size.y as i16) + 32).step_by(32) {
for x in (-32..(rt_size.x as i16) + 32).step_by(32) { for x in (-32..(rt_size.x as i16) + 32).step_by(32) {
@ -130,9 +131,9 @@ pub fn for_each_tile_on_screen(
x: wp_to_tp(camera_offset.x.saturating_add(x.try_into().unwrap_or(0))), x: wp_to_tp(camera_offset.x.saturating_add(x.try_into().unwrap_or(0))),
y: wp_to_tp(camera_offset.y.saturating_add(y.try_into().unwrap_or(0))), y: wp_to_tp(camera_offset.y.saturating_add(y.try_into().unwrap_or(0))),
}, },
ScreenPos { ScreenVec {
x: ((x as i64) - ((camera_offset.x as i64) % 32)) as ScreenPosScalar, x: ((x as i64) - ((camera_offset.x as i64) % 32)) as ScreenSc,
y: ((y as i64) - ((camera_offset.y as i64) % 32)) as ScreenPosScalar, y: ((y as i64) - ((camera_offset.y as i64) % 32)) as ScreenSc,
}, },
) )
} }

View file

@ -1,4 +1,5 @@
use egui_inspect::derive::Inspect; use egui_inspect::derive::Inspect;
use serde::{Deserialize, Serialize};
use sfml::{ use sfml::{
graphics::RenderWindow, graphics::RenderWindow,
system::Vector2f, system::Vector2f,
@ -23,16 +24,17 @@ impl ScreenRes {
} }
} }
// We assume this game won't be played above 32767*32767 resolution #[derive(Default, Clone, Copy, Debug, Inspect, Serialize, Deserialize)]
#[derive(Default, Clone, Copy, Debug, Inspect)] pub struct ScreenVec {
pub struct ScreenPos { pub x: ScreenSc,
pub x: ScreenPosScalar, pub y: ScreenSc,
pub y: ScreenPosScalar,
} }
pub type ScreenPosScalar = i16; /// Screen position/offset scalar
/// We assume this game won't be played above 32767*32767 resolution
pub type ScreenSc = i16;
impl ScreenPos { impl ScreenVec {
pub fn to_sf_vec(self) -> Vector2f { pub fn to_sf_vec(self) -> Vector2f {
Vector2f::new(self.x.into(), self.y.into()) Vector2f::new(self.x.into(), self.y.into())
} }

View file

@ -1,7 +1,7 @@
use fnv::FnvHashSet; use fnv::FnvHashSet;
use sfml::window::{mouse, Event, Key}; use sfml::window::{mouse, Event, Key};
use crate::graphics::ScreenPos; use crate::graphics::ScreenVec;
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct Input { pub struct Input {
@ -9,7 +9,7 @@ pub struct Input {
pressed: FnvHashSet<Key>, pressed: FnvHashSet<Key>,
pub lmb_down: bool, pub lmb_down: bool,
pub rmb_down: bool, pub rmb_down: bool,
pub mouse_down_loc: ScreenPos, pub mouse_down_loc: ScreenVec,
pub mid_pressed: bool, pub mid_pressed: bool,
} }
@ -24,7 +24,7 @@ impl Input {
self.down.remove(code); self.down.remove(code);
} }
&Event::MouseButtonPressed { button, x, y } => { &Event::MouseButtonPressed { button, x, y } => {
self.mouse_down_loc = ScreenPos { self.mouse_down_loc = ScreenVec {
x: x as i16, x: x as i16,
y: y as i16, y: y as i16,
}; };

View file

@ -7,12 +7,17 @@ use log::warn;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sfml::graphics::IntRect; use sfml::graphics::IntRect;
use crate::{math::TILE_SIZE, world::TileId}; use crate::{
graphics::{ScreenSc, ScreenVec},
math::TILE_SIZE,
world::TileId,
};
#[derive(Serialize, Deserialize, Default, Debug, Inspect)] #[derive(Serialize, Deserialize, Default, Debug, Inspect)]
pub struct TileDef { pub struct TileDef {
pub solid: bool, pub solid: bool,
pub emits_light: bool, /// Whether the tile emits light, and the light source offset
pub light: Option<ScreenVec>,
pub atlas_offset: AtlasOffset, pub atlas_offset: AtlasOffset,
} }
@ -32,7 +37,7 @@ impl Default for TileDb {
const EMPTY: TileDef = TileDef { const EMPTY: TileDef = TileDef {
solid: false, solid: false,
emits_light: false, light: None,
// Rendering empty tile is actually special cased, and no rendering is done. // Rendering empty tile is actually special cased, and no rendering is done.
// But just in case, put the offset to UNKNOWN // But just in case, put the offset to UNKNOWN
atlas_offset: UNKNOWN_ATLAS_OFF, atlas_offset: UNKNOWN_ATLAS_OFF,
@ -72,7 +77,10 @@ const UNKNOWN_ATLAS_OFF: AtlasOffset = AtlasOffset { x: 320, y: 0 };
static UNKNOWN_TILE: TileDef = TileDef { static UNKNOWN_TILE: TileDef = TileDef {
solid: true, solid: true,
emits_light: true, light: Some(ScreenVec {
x: TILE_SIZE as ScreenSc / 2,
y: TILE_SIZE as ScreenSc / 2,
}),
atlas_offset: UNKNOWN_ATLAS_OFF, atlas_offset: UNKNOWN_ATLAS_OFF,
}; };

View file

@ -1,7 +1,34 @@
use crate::{
graphics::{ScreenSc, ScreenVec},
math::TILE_SIZE,
};
use super::TileDb; use super::TileDb;
pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) { pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) {
egui::Window::new("Tiledb editor").show(ctx, |ui| { egui::Window::new("Tiledb editor").show(ctx, |ui| {
ui.label(format!("Number of tile defs: {}", tile_db.db.len()));
ui.separator();
for (i, def) in tile_db.db.iter_mut().enumerate() {
ui.label(i.to_string());
match &mut def.light {
Some(light) => {
ui.label("x");
ui.add(egui::DragValue::new(&mut light.x));
ui.label("y");
ui.add(egui::DragValue::new(&mut light.y));
}
None => {
if ui.button("Insert light emit").clicked() {
def.light = Some(ScreenVec {
x: TILE_SIZE as ScreenSc / 2,
y: TILE_SIZE as ScreenSc / 2,
});
}
}
}
}
ui.separator();
if ui.button("Add new default").clicked() { if ui.button("Add new default").clicked() {
tile_db.db.push(super::TileDef::default()); tile_db.db.push(super::TileDef::default());
} }

BIN
tiles.dat

Binary file not shown.