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::{
audio::SoundSource,
graphics::{
BlendMode, Color, Rect, RenderStates, RenderTarget, RenderTexture, RenderWindow, Sprite,
Transformable, View,
BlendMode, Color, Rect, RectangleShape, RenderStates, RenderTarget, RenderTexture,
RenderWindow, Shape, Sprite, Transformable, View,
},
system::Vector2u,
system::{Vector2, Vector2u},
window::{Event, Key},
};
@ -17,6 +17,7 @@ use crate::{
game::{for_each_tile_on_screen, Biome, GameState},
graphics::{self, ScreenSc, ScreenVec},
input::Input,
inventory::TileLayer,
math::{center_offset, TILE_SIZE},
res::Res,
CliArgs,
@ -231,15 +232,22 @@ impl App {
self.game.world.player.col_en.en.pos.y = wpos.y as i32;
}
if self.input.lmb_down {
let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen);
t.mid = 0;
t.fg = 0;
} else if self.input.rmb_down {
let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen);
if self.game.tile_to_place != 7 {
t.mid = self.game.tile_to_place;
} else {
t.bg = self.game.tile_to_place;
let active_slot = &self.game.inventory.slots[self.game.selected_inv_slot];
if active_slot.qty != 0 {
let def = &self.game.itemdb.db[active_slot.id as usize];
let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen);
match &def.use_action {
crate::inventory::UseAction::PlaceTile { layer, id } => match layer {
TileLayer::Bg => t.bg = *id,
TileLayer::Mid => t.mid = *id,
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 {
@ -262,7 +270,7 @@ impl App {
}
}
}
self.game.update();
self.game.update(&self.input);
}
fn do_freecam(&mut self) {
@ -305,6 +313,18 @@ impl App {
self.light_map.display();
spr.set_texture(self.light_map.texture(), false);
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
.do_frame(|ctx| {
debug::do_debug_ui(
@ -317,6 +337,14 @@ impl App {
})
.unwrap();
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();
}
}

View file

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

View file

@ -3,16 +3,21 @@ use std::path::PathBuf;
use derivative::Derivative;
use egui_inspect::derive::Inspect;
use sfml::{
graphics::{Color, RectangleShape, RenderTarget, RenderTexture, Shape, Sprite, Transformable},
system::Vector2u,
graphics::{
Color, Rect, RectangleShape, RenderTarget, RenderTexture, Shape, Sprite, Transformable,
},
system::{Vector2f, Vector2u},
window::Key,
};
use crate::{
graphics::{ScreenSc, ScreenVec},
input::Input,
inventory::{Inventory, ItemDb},
math::{smoothwave, wp_to_tp, WorldPos},
res::Res,
tiles::TileDb,
world::{Tile, TileId, TilePos, World},
world::{Tile, TilePos, World},
worldgen::Worldgen,
};
@ -22,7 +27,6 @@ pub struct GameState {
pub camera_offset: WorldPos,
pub world: World,
pub gravity: f32,
pub tile_to_place: TileId,
pub current_biome: Biome,
pub prev_biome: Biome,
#[derivative(Debug = "ignore")]
@ -31,6 +35,9 @@ pub struct GameState {
pub ambient_light: u8,
pub light_sources: Vec<LightSource>,
pub tile_db: TileDb,
pub inventory: Inventory,
pub itemdb: ItemDb,
pub selected_inv_slot: usize,
}
#[derive(Debug, Inspect)]
@ -45,7 +52,22 @@ pub enum Biome {
}
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;
}
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 mut rect_sh = RectangleShape::new();
rect_sh.set_position((
@ -83,14 +105,39 @@ impl GameState {
(y - self.camera_offset.y as i32) 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_fill_color(Color::RED);
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.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) {
@ -126,13 +173,15 @@ impl GameState {
camera_offset: spawn_point,
world: World::new(spawn_point, &world_name, path),
gravity: 0.55,
tile_to_place: 1,
current_biome: Biome::Surface,
prev_biome: Biome::Surface,
worldgen: Worldgen::from_seed(0),
ambient_light: 0,
light_sources: Vec::new(),
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 graphics;
mod input;
mod inventory;
mod math;
mod player;
mod res;

View file

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

View file

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

BIN
tiles.dat

Binary file not shown.