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::{
debug::{self, DebugState},
game::{for_each_tile_on_screen, Biome, GameState},
graphics::{self, ScreenPos, ScreenPosScalar},
graphics::{self, ScreenSc, ScreenVec},
input::Input,
math::{center_offset, TILE_SIZE},
res::Res,
@ -178,8 +178,8 @@ impl App {
let vco = viewport_center_offset(self.rw.size(), rt_size, self.scale);
loc.x -= vco.x;
loc.y -= vco.y;
loc.x /= self.scale as ScreenPosScalar;
loc.y /= self.scale as ScreenPosScalar;
loc.x /= self.scale as ScreenSc;
loc.y /= self.scale as ScreenSc;
let mut wpos = self.game.camera_offset;
wpos.x = wpos.x.saturating_add_signed(loc.x.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 rt_size = rt_size * scale as u32;
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);
ScreenPos {
x: x as ScreenPosScalar,
y: y as ScreenPosScalar,
ScreenVec {
x: x as ScreenSc,
y: y as ScreenSc,
}
}

View file

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

View file

@ -1,4 +1,5 @@
use egui_inspect::derive::Inspect;
use serde::{Deserialize, Serialize};
use sfml::{
graphics::RenderWindow,
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)]
pub struct ScreenPos {
pub x: ScreenPosScalar,
pub y: ScreenPosScalar,
#[derive(Default, Clone, Copy, Debug, Inspect, Serialize, Deserialize)]
pub struct ScreenVec {
pub x: ScreenSc,
pub y: ScreenSc,
}
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 {
Vector2f::new(self.x.into(), self.y.into())
}

View file

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

View file

@ -7,12 +7,17 @@ use log::warn;
use serde::{Deserialize, Serialize};
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)]
pub struct TileDef {
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,
}
@ -32,7 +37,7 @@ impl Default for TileDb {
const EMPTY: TileDef = TileDef {
solid: false,
emits_light: false,
light: None,
// Rendering empty tile is actually special cased, and no rendering is done.
// But just in case, put the offset to UNKNOWN
atlas_offset: UNKNOWN_ATLAS_OFF,
@ -72,7 +77,10 @@ const UNKNOWN_ATLAS_OFF: AtlasOffset = AtlasOffset { x: 320, y: 0 };
static UNKNOWN_TILE: TileDef = TileDef {
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,
};

View file

@ -1,7 +1,34 @@
use crate::{
graphics::{ScreenSc, ScreenVec},
math::TILE_SIZE,
};
use super::TileDb;
pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) {
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() {
tile_db.db.push(super::TileDef::default());
}

BIN
tiles.dat

Binary file not shown.