Very basic inventory

This commit is contained in:
crumblingstatue 2023-04-15 22:47:53 +02:00
parent cee7652e09
commit 464d8dc8be
10 changed files with 241 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -5,10 +5,10 @@ use gamedebug_core::{imm, imm_dbg};
use sfml::{ use sfml::{
audio::SoundSource, audio::SoundSource,
graphics::{ graphics::{
BlendMode, Color, Rect, RenderStates, RenderTarget, RenderTexture, RenderWindow, Sprite, BlendMode, Color, Rect, RectangleShape, RenderStates, RenderTarget, RenderTexture,
Transformable, View, RenderWindow, Shape, Sprite, Transformable, View,
}, },
system::Vector2u, system::{Vector2, Vector2u},
window::{Event, Key}, window::{Event, Key},
}; };
@ -17,6 +17,7 @@ use crate::{
game::{for_each_tile_on_screen, Biome, GameState}, game::{for_each_tile_on_screen, Biome, GameState},
graphics::{self, ScreenSc, ScreenVec}, graphics::{self, ScreenSc, ScreenVec},
input::Input, input::Input,
inventory::TileLayer,
math::{center_offset, TILE_SIZE}, math::{center_offset, TILE_SIZE},
res::Res, res::Res,
CliArgs, CliArgs,
@ -231,15 +232,22 @@ impl App {
self.game.world.player.col_en.en.pos.y = wpos.y as i32; self.game.world.player.col_en.en.pos.y = wpos.y as i32;
} }
if self.input.lmb_down { if self.input.lmb_down {
let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen); let active_slot = &self.game.inventory.slots[self.game.selected_inv_slot];
t.mid = 0; if active_slot.qty != 0 {
t.fg = 0; let def = &self.game.itemdb.db[active_slot.id as usize];
} else if self.input.rmb_down { let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen);
let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen); match &def.use_action {
if self.game.tile_to_place != 7 { crate::inventory::UseAction::PlaceTile { layer, id } => match layer {
t.mid = self.game.tile_to_place; TileLayer::Bg => t.bg = *id,
} else { TileLayer::Mid => t.mid = *id,
t.bg = self.game.tile_to_place; TileLayer::Fg => t.fg = *id,
},
crate::inventory::UseAction::RemoveTile { layer } => match layer {
TileLayer::Bg => t.bg = 0,
TileLayer::Mid => t.mid = 0,
TileLayer::Fg => t.fg = 0,
},
}
} }
} }
if self.game.camera_offset.y > 643_000 { if self.game.camera_offset.y > 643_000 {
@ -262,7 +270,7 @@ impl App {
} }
} }
} }
self.game.update(); self.game.update(&self.input);
} }
fn do_freecam(&mut self) { fn do_freecam(&mut self) {
@ -305,6 +313,18 @@ impl App {
self.light_map.display(); self.light_map.display();
spr.set_texture(self.light_map.texture(), false); spr.set_texture(self.light_map.texture(), false);
self.rw.draw_with_renderstates(&spr, &rst); self.rw.draw_with_renderstates(&spr, &rst);
drop(spr);
// Draw ui on top of in-game scene
self.rt.clear(Color::TRANSPARENT);
let ui_dims = Vector2 {
x: (self.rw.size().x / self.scale as u32) as f32,
y: (self.rw.size().y / self.scale as u32) as f32,
};
self.game.draw_ui(&mut self.rt, &self.res, ui_dims);
self.rt.display();
let mut spr = Sprite::with_texture(self.rt.texture());
spr.set_scale((self.scale as f32, self.scale as f32));
self.rw.draw(&spr);
self.sf_egui self.sf_egui
.do_frame(|ctx| { .do_frame(|ctx| {
debug::do_debug_ui( debug::do_debug_ui(
@ -317,6 +337,14 @@ impl App {
}) })
.unwrap(); .unwrap();
self.sf_egui.draw(&mut self.rw, None); self.sf_egui.draw(&mut self.rw, None);
if self.debug.show_atlas {
let atlas = &self.res.atlas.tex;
let size = atlas.size();
let mut rs = RectangleShape::from_rect(Rect::new(0., 0., size.x as f32, size.y as f32));
rs.set_fill_color(Color::MAGENTA);
self.rw.draw(&rs);
self.rw.draw(&Sprite::with_texture(atlas));
}
self.rw.display(); self.rw.display();
} }
} }

View file

@ -1,4 +1,4 @@
use egui_inspect::inspect; use egui_inspect::{derive::Inspect, inspect};
use sfml::{audio::SoundSource, window::Key}; use sfml::{audio::SoundSource, window::Key};
use crate::{ use crate::{
@ -11,11 +11,12 @@ use crate::{
tiles::tiledb_edit_ui::tiledb_edit_ui, tiles::tiledb_edit_ui::tiledb_edit_ui,
}; };
#[derive(Default, Debug)] #[derive(Default, Debug, Inspect)]
pub struct DebugState { pub struct DebugState {
panel: bool, panel: bool,
pub freecam: bool, pub freecam: bool,
tiledb_edit: bool, tiledb_edit: bool,
pub show_atlas: bool,
} }
impl DebugState { impl DebugState {
@ -30,7 +31,7 @@ impl DebugState {
} }
fn debug_panel_ui( fn debug_panel_ui(
debug: &mut DebugState, mut debug: &mut DebugState,
mut game: &mut GameState, mut game: &mut GameState,
ctx: &egui::Context, ctx: &egui::Context,
res: &mut Res, res: &mut Res,
@ -85,7 +86,7 @@ fn debug_panel_ui(
ui, ui,
scale, scale,
game, game,
debug.tiledb_edit debug
} }
}); });
if ui.button("Reload graphics").clicked() { if ui.button("Reload graphics").clicked() {

View file

@ -3,16 +3,21 @@ use std::path::PathBuf;
use derivative::Derivative; use derivative::Derivative;
use egui_inspect::derive::Inspect; use egui_inspect::derive::Inspect;
use sfml::{ use sfml::{
graphics::{Color, RectangleShape, RenderTarget, RenderTexture, Shape, Sprite, Transformable}, graphics::{
system::Vector2u, Color, Rect, RectangleShape, RenderTarget, RenderTexture, Shape, Sprite, Transformable,
},
system::{Vector2f, Vector2u},
window::Key,
}; };
use crate::{ use crate::{
graphics::{ScreenSc, ScreenVec}, graphics::{ScreenSc, ScreenVec},
input::Input,
inventory::{Inventory, ItemDb},
math::{smoothwave, wp_to_tp, WorldPos}, math::{smoothwave, wp_to_tp, WorldPos},
res::Res, res::Res,
tiles::TileDb, tiles::TileDb,
world::{Tile, TileId, TilePos, World}, world::{Tile, TilePos, World},
worldgen::Worldgen, worldgen::Worldgen,
}; };
@ -22,7 +27,6 @@ pub struct GameState {
pub camera_offset: WorldPos, pub camera_offset: WorldPos,
pub world: World, pub world: World,
pub gravity: f32, pub gravity: f32,
pub tile_to_place: TileId,
pub current_biome: Biome, pub current_biome: Biome,
pub prev_biome: Biome, pub prev_biome: Biome,
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
@ -31,6 +35,9 @@ pub struct GameState {
pub ambient_light: u8, pub ambient_light: u8,
pub light_sources: Vec<LightSource>, pub light_sources: Vec<LightSource>,
pub tile_db: TileDb, pub tile_db: TileDb,
pub inventory: Inventory,
pub itemdb: ItemDb,
pub selected_inv_slot: usize,
} }
#[derive(Debug, Inspect)] #[derive(Debug, Inspect)]
@ -45,7 +52,22 @@ pub enum Biome {
} }
impl GameState { impl GameState {
pub fn update(&mut self) { pub fn update(&mut self, input: &Input) {
if input.pressed(Key::Num1) {
self.selected_inv_slot = 0;
}
if input.pressed(Key::Num2) {
self.selected_inv_slot = 1;
}
if input.pressed(Key::Num3) {
self.selected_inv_slot = 2;
}
if input.pressed(Key::Num4) {
self.selected_inv_slot = 3;
}
if input.pressed(Key::Num5) {
self.selected_inv_slot = 4;
}
self.world.ticks += 1; self.world.ticks += 1;
} }
pub(crate) fn draw_world(&mut self, rt: &mut RenderTexture, res: &mut Res) { pub(crate) fn draw_world(&mut self, rt: &mut RenderTexture, res: &mut Res) {
@ -75,7 +97,7 @@ impl GameState {
} }
}); });
} }
pub fn draw_entities(&mut self, rw: &mut RenderTexture) { pub fn draw_entities(&mut self, rt: &mut RenderTexture) {
let (x, y, w, h) = self.world.player.col_en.en.xywh(); let (x, y, w, h) = self.world.player.col_en.en.xywh();
let mut rect_sh = RectangleShape::new(); let mut rect_sh = RectangleShape::new();
rect_sh.set_position(( rect_sh.set_position((
@ -83,14 +105,39 @@ impl GameState {
(y - self.camera_offset.y as i32) as f32, (y - self.camera_offset.y as i32) as f32,
)); ));
rect_sh.set_size((w as f32, h as f32)); rect_sh.set_size((w as f32, h as f32));
rw.draw(&rect_sh); rt.draw(&rect_sh);
rect_sh.set_size((2., 2.)); rect_sh.set_size((2., 2.));
rect_sh.set_fill_color(Color::RED); rect_sh.set_fill_color(Color::RED);
rect_sh.set_position(( rect_sh.set_position((
(self.world.player.col_en.en.pos.x - self.camera_offset.x as i32) as f32, (self.world.player.col_en.en.pos.x - self.camera_offset.x as i32) as f32,
(self.world.player.col_en.en.pos.y - self.camera_offset.y as i32) as f32, (self.world.player.col_en.en.pos.y - self.camera_offset.y as i32) as f32,
)); ));
rw.draw(&rect_sh); rt.draw(&rect_sh);
}
pub fn draw_ui(&mut self, rt: &mut RenderTexture, res: &Res, ui_dims: Vector2f) {
let mut s = Sprite::with_texture(&res.atlas.tex);
let mut rs = RectangleShape::from_rect(Rect::new(0., 0., 32., 32.));
rs.set_outline_color(Color::YELLOW);
rs.set_outline_thickness(1.0);
rs.set_fill_color(Color::TRANSPARENT);
for (i, slot) in self.inventory.slots.iter().enumerate() {
s.set_texture_rect(res.atlas.rects["ui/invframe"].to_sf());
let pos = ((i * 38) as f32 + 8.0, (ui_dims.y - 38.));
s.set_position(pos);
rt.draw(&s);
let item_def = &self.itemdb.db[slot.id as usize];
if let Some(rect) = res.atlas.rects.get(&item_def.graphic_name) {
s.set_texture_rect(rect.to_sf());
rt.draw(&s);
} else {
log::error!("Missing rect for item {}", item_def.name);
}
if i == self.selected_inv_slot {
rs.set_position(pos);
rt.draw(&rs);
}
}
} }
pub(crate) fn light_pass(&mut self, lightmap: &mut RenderTexture, res: &Res) { pub(crate) fn light_pass(&mut self, lightmap: &mut RenderTexture, res: &Res) {
@ -126,13 +173,15 @@ impl GameState {
camera_offset: spawn_point, camera_offset: spawn_point,
world: World::new(spawn_point, &world_name, path), world: World::new(spawn_point, &world_name, path),
gravity: 0.55, gravity: 0.55,
tile_to_place: 1,
current_biome: Biome::Surface, current_biome: Biome::Surface,
prev_biome: Biome::Surface, prev_biome: Biome::Surface,
worldgen: Worldgen::from_seed(0), worldgen: Worldgen::from_seed(0),
ambient_light: 0, ambient_light: 0,
light_sources: Vec::new(), light_sources: Vec::new(),
tile_db, tile_db,
inventory: Inventory::new_debug(),
itemdb: ItemDb::default(),
selected_inv_slot: 0,
} }
} }
} }

130
src/inventory.rs Normal file
View file

@ -0,0 +1,130 @@
use egui_inspect::derive::Inspect;
use crate::{math::IntRect, world::TileId};
/// We won't have more than 65535 different items
pub type ItemId = u16;
/// We won't have more than 65535 item quantity in a single slot
pub type ItemQty = u16;
/// Inventory slot
#[derive(Debug, Inspect)]
pub struct Slot {
pub id: ItemId,
pub qty: ItemQty,
}
#[derive(Debug, Inspect)]
pub struct Inventory {
pub slots: Vec<Slot>,
}
impl Inventory {
/// A new inventory filled with some debug items
pub(crate) fn new_debug() -> Inventory {
Self {
slots: vec![
Slot {
id: items::WOOD_PICK,
qty: 1,
},
Slot {
id: items::DIRT_BLOCK,
qty: 100,
},
Slot {
id: items::TORCH,
qty: 100,
},
Slot {
id: items::PLATFORM,
qty: 100,
},
],
}
}
}
#[derive(Debug, Inspect)]
pub struct ItemDef {
pub name: String,
pub graphic_name: String,
pub tex_rect: IntRect,
#[opaque]
pub use_action: UseAction,
pub consumable: bool,
}
#[derive(Debug, Inspect, PartialEq)]
pub enum TileLayer {
Bg,
Mid,
Fg,
}
#[derive(Debug)]
pub enum UseAction {
PlaceTile { layer: TileLayer, id: TileId },
RemoveTile { layer: TileLayer },
}
#[derive(Debug, Inspect)]
pub struct ItemDb {
pub db: Vec<ItemDef>,
}
impl Default for ItemDb {
fn default() -> Self {
Self {
db: vec![
ItemDef {
name: String::from("Dirt Block"),
graphic_name: String::from("tiles/dirt"),
tex_rect: IntRect::default(),
use_action: UseAction::PlaceTile {
layer: TileLayer::Mid,
id: 3,
},
consumable: true,
},
ItemDef {
name: String::from("Torch"),
graphic_name: String::from("tiles/torch"),
tex_rect: IntRect::default(),
use_action: UseAction::PlaceTile {
layer: TileLayer::Mid,
id: 4,
},
consumable: true,
},
ItemDef {
name: String::from("Platform"),
graphic_name: String::from("tiles/platform"),
tex_rect: IntRect::default(),
use_action: UseAction::PlaceTile {
layer: TileLayer::Mid,
id: 5,
},
consumable: true,
},
ItemDef {
name: String::from("Wood Pick"),
graphic_name: String::from("items/woodpick"),
tex_rect: IntRect::default(),
use_action: UseAction::RemoveTile {
layer: TileLayer::Mid,
},
consumable: true,
},
],
}
}
}
pub mod items {
use super::ItemId;
pub const DIRT_BLOCK: ItemId = 0;
pub const TORCH: ItemId = 1;
pub const PLATFORM: ItemId = 2;
pub const WOOD_PICK: ItemId = 3;
}

View file

@ -4,6 +4,7 @@ mod debug;
mod game; mod game;
mod graphics; mod graphics;
mod input; mod input;
mod inventory;
mod math; mod math;
mod player; mod player;
mod res; mod res;

View file

@ -20,7 +20,7 @@ impl AtlasBundle {
max_height: 4096, max_height: 4096,
allow_rotation: false, allow_rotation: false,
border_padding: 0, border_padding: 0,
texture_padding: 1, texture_padding: 0,
texture_extrusion: 0, texture_extrusion: 0,
trim: true, trim: true,
texture_outlines: false, texture_outlines: false,
@ -34,6 +34,11 @@ impl AtlasBundle {
}); });
let mut rects = HashMap::new(); let mut rects = HashMap::new();
let mut tex = Texture::new().unwrap(); let mut tex = Texture::new().unwrap();
log::info!(
"Texture atlas size is: {}x{}",
packer.width(),
packer.height()
);
if !tex.create(packer.width(), packer.height()) { if !tex.create(packer.width(), packer.height()) {
panic!("Failed to create texture"); panic!("Failed to create texture");
} }

View file

@ -19,7 +19,6 @@ pub struct TileDef {
pub light: Option<ScreenVec>, pub light: Option<ScreenVec>,
/// Platform behavior: Horizontally passable, vertically passable upwards /// Platform behavior: Horizontally passable, vertically passable upwards
pub platform: bool, pub platform: bool,
#[serde(default)]
pub graphic_name: String, pub graphic_name: String,
pub tex_rect: IntRect, pub tex_rect: IntRect,
} }

BIN
tiles.dat

Binary file not shown.