From 75a39118a971817bde075b086554009f220b5b7f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 30 Sep 2015 20:03:51 -0400 Subject: [PATCH] Add numbers to slots on inventory --- TrueCraft.API/Logic/IBlockProvider.cs | 2 +- TrueCraft.Client/Modules/DebugInfoModule.cs | 12 --- TrueCraft.Client/Modules/HUDModule.cs | 80 ++++++++++++++++++- .../Rendering/Blocks/GrassRenderer.cs | 2 +- TrueCraft.Client/Rendering/IconRenderer.cs | 74 +++++++++++++++++ TrueCraft.Client/Rendering/TextureMapper.cs | 2 +- TrueCraft.Client/TrueCraft.Client.csproj | 1 + TrueCraft.Client/TrueCraftGame.cs | 10 ++- 8 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 TrueCraft.Client/Rendering/IconRenderer.cs diff --git a/TrueCraft.API/Logic/IBlockProvider.cs b/TrueCraft.API/Logic/IBlockProvider.cs index b3d2cdb..85e24a4 100644 --- a/TrueCraft.API/Logic/IBlockProvider.cs +++ b/TrueCraft.API/Logic/IBlockProvider.cs @@ -6,7 +6,7 @@ using fNbt; namespace TrueCraft.API.Logic { - public interface IBlockProvider + public interface IBlockProvider : IItemProvider { byte ID { get; } double BlastResistance { get; } diff --git a/TrueCraft.Client/Modules/DebugInfoModule.cs b/TrueCraft.Client/Modules/DebugInfoModule.cs index 20f0af8..98e0316 100644 --- a/TrueCraft.Client/Modules/DebugInfoModule.cs +++ b/TrueCraft.Client/Modules/DebugInfoModule.cs @@ -99,18 +99,6 @@ namespace TrueCraft.Client.Modules Font.DrawText(SpriteBatch, xOrigin, yOrigin + (yOffset * 3), string.Format(ChatColor.Gray + "{0} pending chunks", Game.ChunkModule.ChunkRenderer.PendingChunks)); - var sb = new StringBuilder(ChatColor.DarkGray + "inv: "); - for (int i = 0; i < Game.Client.Inventory.Hotbar.Length; i++) - { - var provider = Game.ItemRepository.GetItemProvider(Game.Client.Inventory.Hotbar[i].ID); - if (provider != null) - sb.Append(provider.DisplayName + " "); - else - sb.Append("[empty]"); - } - - Font.DrawText(SpriteBatch, xOrigin, yOrigin + (yOffset * 4), sb.ToString()); - SpriteBatch.End(); } diff --git a/TrueCraft.Client/Modules/HUDModule.cs b/TrueCraft.Client/Modules/HUDModule.cs index 021f8a6..149680a 100644 --- a/TrueCraft.Client/Modules/HUDModule.cs +++ b/TrueCraft.Client/Modules/HUDModule.cs @@ -1,5 +1,8 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using TrueCraft.Client.Rendering; +using TrueCraft.Core.Logic.Items; +using TrueCraft.API.Logic; namespace TrueCraft.Client.Modules { @@ -9,13 +12,17 @@ namespace TrueCraft.Client.Modules private SpriteBatch SpriteBatch { get; set; } private Texture2D GUI { get; set; } private Texture2D Icons { get; set; } + private Texture2D Items { get; set; } + private FontRenderer Font { get; set; } - public HUDModule(TrueCraftGame game) + public HUDModule(TrueCraftGame game, FontRenderer font) { Game = game; + Font = font; SpriteBatch = new SpriteBatch(game.GraphicsDevice); GUI = game.TextureMapper.GetTexture("gui/gui.png"); Icons = game.TextureMapper.GetTexture("gui/icons.png"); + Items = game.TextureMapper.GetTexture("gui/items.png"); } public void Update(GameTime gameTime) @@ -35,8 +42,16 @@ namespace TrueCraft.Client.Modules 0, Vector2.Zero, Game.ScaleFactor * 2, SpriteEffects.None, 1); DrawHotbar(gameTime); + DrawHotbarItemSprites(gameTime); SpriteBatch.End(); + + DrawHotbarBlockSprites(gameTime); + + // Once more, with feeling + SpriteBatch.Begin(samplerState: SamplerState.PointClamp, blendState: BlendState.NonPremultiplied); + DrawHotbarSlotCounts(gameTime); + SpriteBatch.End(); } #region "Hotbar" @@ -74,6 +89,69 @@ namespace TrueCraft.Client.Modules HotbarSelectionRect, Color.White, 0, Vector2.Zero, Game.ScaleFactor * 2, SpriteEffects.None, 1); } + private void DrawHotbarItemSprites(GameTime gameTime) + { + var scale = new Point((int)(16 * Game.ScaleFactor * 2)); + var origin = new Point((int)(Game.GraphicsDevice.Viewport.Width / 2 - Scale(HotbarBackgroundRect.Width / 2)), + (int)(Game.GraphicsDevice.Viewport.Height - Scale(HotbarBackgroundRect.Height + 5))); + origin.X += (int)Scale(3); + origin.Y += (int)Scale(3); + for (int i = 0; i < Game.Client.Inventory.Hotbar.Length; i++) + { + var item = Game.Client.Inventory.Hotbar[i]; + if (item.Empty) + continue; + var provider = Game.ItemRepository.GetItemProvider(item.ID); + if (provider.GetIconTexture((byte)item.Metadata) == null) + continue; + var position = origin + new Point((int)Scale(i * 20), 0); + var rect = new Rectangle(position, scale); + IconRenderer.RenderItemIcon(SpriteBatch, Items, provider, + (byte)item.Metadata, rect, Color.White); // TODO: Fuck, metadata was supposed to be a short + } + } + + private void DrawHotbarBlockSprites(GameTime gameTime) + { + var scale = new Point((int)(16 * Game.ScaleFactor * 2)); + var origin = new Point((int)(Game.GraphicsDevice.Viewport.Width / 2 - Scale(HotbarBackgroundRect.Width / 2)), + (int)(Game.GraphicsDevice.Viewport.Height - Scale(HotbarBackgroundRect.Height + 5))); + origin.X += (int)Scale(3); + origin.Y += (int)Scale(3); + for (int i = 0; i < Game.Client.Inventory.Hotbar.Length; i++) + { + var item = Game.Client.Inventory.Hotbar[i]; + if (item.Empty) + continue; + var provider = Game.ItemRepository.GetItemProvider(item.ID) as IBlockProvider; + if (provider == null || provider.GetIconTexture((byte)item.Metadata) != null) + continue; + var position = origin + new Point((int)Scale(i * 20), 0); + var rect = new Rectangle(position, scale); + IconRenderer.RenderBlockIcon(Game, Items, provider, + (byte)item.Metadata, rect, Color.White); // TODO: Fuck, metadata was supposed to be a short + } + } + + private void DrawHotbarSlotCounts(GameTime gameTime) + { + var origin = new Point((int)(Game.GraphicsDevice.Viewport.Width / 2 - Scale(HotbarBackgroundRect.Width / 2)), + (int)(Game.GraphicsDevice.Viewport.Height - Scale(HotbarBackgroundRect.Height + 5))); + origin.X += (int)Scale(3); + origin.Y += (int)Scale(3); + for (int i = 0; i < Game.Client.Inventory.Hotbar.Length; i++) + { + var item = Game.Client.Inventory.Hotbar[i]; + if (item.Empty || item.Count == 1) + continue; + int offset = 12; + if (item.Count >= 10) + offset -= 6; + var position = origin + new Point((int)Scale(i * 20 + offset), (int)Scale(5)); + Font.DrawText(SpriteBatch, position.X, position.Y, item.Count.ToString(), Game.ScaleFactor); + } + } + #endregion /// diff --git a/TrueCraft.Client/Rendering/Blocks/GrassRenderer.cs b/TrueCraft.Client/Rendering/Blocks/GrassRenderer.cs index 1661510..8a723db 100644 --- a/TrueCraft.Client/Rendering/Blocks/GrassRenderer.cs +++ b/TrueCraft.Client/Rendering/Blocks/GrassRenderer.cs @@ -96,7 +96,7 @@ namespace TrueCraft.Client.Rendering.Blocks VisibleFaces faces, Tuple textureMap, int indiciesOffset, out int[] indicies) { var texture = Texture; - if (descriptor.Coordinates.Y < World.Height) + if (descriptor.Coordinates.Y < World.Height && descriptor.Chunk != null) { if (descriptor.Chunk.GetBlockID(descriptor.Coordinates + Coordinates3D.Up) == SnowfallBlock.BlockID) { diff --git a/TrueCraft.Client/Rendering/IconRenderer.cs b/TrueCraft.Client/Rendering/IconRenderer.cs new file mode 100644 index 0000000..41799f0 --- /dev/null +++ b/TrueCraft.Client/Rendering/IconRenderer.cs @@ -0,0 +1,74 @@ +using System; +using TrueCraft.API.Logic; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace TrueCraft.Client.Rendering +{ + public static class IconRenderer + { + private static Mesh[] BlockMeshes = new Mesh[0x100]; + private static BasicEffect RenderEffect; + + public static void CreateBlocks(TrueCraftGame game, IBlockRepository repository) + { + for (int i = 0; i < 0x100; i++) + { + var provider = repository.GetBlockProvider((byte)i); + if (provider == null || provider.GetIconTexture(0) != null) + continue; + int[] indicies; + var verticies = BlockRenderer.RenderBlock(provider, + new BlockDescriptor { ID = provider.ID }, VisibleFaces.All, new Vector3(-0.5f), + 0, out indicies); + var mesh = new Mesh(game, verticies, indicies); + BlockMeshes[provider.ID] = mesh; + } + + PrepareEffects(game); + } + + public static void PrepareEffects(TrueCraftGame game) + { + RenderEffect = new BasicEffect(game.GraphicsDevice); + RenderEffect.Texture = game.TextureMapper.GetTexture("terrain.png"); + RenderEffect.TextureEnabled = true; + RenderEffect.VertexColorEnabled = true; + RenderEffect.EnableDefaultLighting(); + // TODO: Figure out how to make the lighting give the cubes some sense of depth + RenderEffect.DirectionalLight0.Direction = new Vector3(-0.75f, -0.75f, -0.75f); + RenderEffect.Projection = Matrix.CreateOrthographicOffCenter( + 0, game.GraphicsDevice.Viewport.Width, + 0, game.GraphicsDevice.Viewport.Height, + 0.1f, 1000.0f); + RenderEffect.View = Matrix.CreateLookAt(Vector3.UnitZ, Vector3.Zero, Vector3.Up); + } + + public static void RenderItemIcon(SpriteBatch spriteBatch, Texture2D texture, IItemProvider provider, + byte metadata, Rectangle destination, Color color) + { + var icon = provider.GetIconTexture(metadata); + var scale = texture.Width / 16; + var source = new Rectangle(icon.Item1 * scale, icon.Item2 * scale, scale, scale); + spriteBatch.Draw(texture, destination, source, color); + } + + public static void RenderBlockIcon(TrueCraftGame game, Texture2D texture, IBlockProvider provider, + byte metadata, Rectangle destination, Color color) + { + var mesh = BlockMeshes[provider.ID]; + if (mesh != null) + { + RenderEffect.World = Matrix.Identity + * Matrix.CreateScale(0.6f) + * Matrix.CreateRotationY(-MathHelper.PiOver4) + * Matrix.CreateRotationX(MathHelper.ToRadians(30)) + * Matrix.CreateScale(new Vector3(destination.Width, destination.Height, 1)) + * Matrix.CreateTranslation(new Vector3( + destination.X, -(destination.Y - game.GraphicsDevice.Viewport.Height / 2) + game.GraphicsDevice.Viewport.Height / 2, 0)) + * Matrix.CreateTranslation(new Vector3(destination.Width / 2, -destination.Height / 2, 0)); + mesh.Draw(RenderEffect); + } + } + } +} \ No newline at end of file diff --git a/TrueCraft.Client/Rendering/TextureMapper.cs b/TrueCraft.Client/Rendering/TextureMapper.cs index a6557d1..f096ff7 100644 --- a/TrueCraft.Client/Rendering/TextureMapper.cs +++ b/TrueCraft.Client/Rendering/TextureMapper.cs @@ -29,8 +29,8 @@ namespace TrueCraft.Client.Rendering { Defaults.Clear(); - Defaults.Add("items.png", new PngReader().Read(File.OpenRead("Content/items.png"), graphicsDevice)); Defaults.Add("terrain.png", new PngReader().Read(File.OpenRead("Content/terrain.png"), graphicsDevice)); + Defaults.Add("gui/items.png", new PngReader().Read(File.OpenRead("Content/items.png"), graphicsDevice)); Defaults.Add("gui/gui.png", new PngReader().Read(File.OpenRead("Content/gui.png"), graphicsDevice)); Defaults.Add("gui/icons.png", new PngReader().Read(File.OpenRead("Content/icons.png"), graphicsDevice)); } diff --git a/TrueCraft.Client/TrueCraft.Client.csproj b/TrueCraft.Client/TrueCraft.Client.csproj index 0f35ffb..b7fb8ed 100644 --- a/TrueCraft.Client/TrueCraft.Client.csproj +++ b/TrueCraft.Client/TrueCraft.Client.csproj @@ -136,6 +136,7 @@ + diff --git a/TrueCraft.Client/TrueCraftGame.cs b/TrueCraft.Client/TrueCraftGame.cs index 10117a3..944c81b 100644 --- a/TrueCraft.Client/TrueCraftGame.cs +++ b/TrueCraft.Client/TrueCraftGame.cs @@ -100,6 +100,9 @@ namespace TrueCraft.Client ScaleFactor = 1.0f; else ScaleFactor = 1.5f; + IconRenderer.PrepareEffects(this); + UpdateCamera(); + CreateRenderTarget(); } protected override void Initialize() @@ -114,7 +117,7 @@ namespace TrueCraft.Client Modules.Add(ChunkModule); Modules.Add(new HighlightModule(this)); Modules.Add(new PlayerControlModule(this)); - Modules.Add(new HUDModule(this)); + Modules.Add(new HUDModule(this, Pixel)); Modules.Add(DebugInfoModule); Client.PropertyChanged += HandleClientPropertyChanged; @@ -126,6 +129,8 @@ namespace TrueCraft.Client ItemRepository = itemRepository; BlockProvider.ItemRepository = ItemRepository; + IconRenderer.CreateBlocks(this, BlockRepository); + var centerX = GraphicsDevice.Viewport.Width / 2; var centerY = GraphicsDevice.Viewport.Height / 2; Mouse.SetPosition(centerX, centerY); @@ -140,11 +145,8 @@ namespace TrueCraft.Client KeyboardComponent.KeyDown += OnKeyboardKeyDown; KeyboardComponent.KeyUp += OnKeyboardKeyUp; - Window.ClientSizeChanged += (sender, e) => CreateRenderTarget(); CreateRenderTarget(); SpriteBatch = new SpriteBatch(GraphicsDevice); - - Window_ClientSizeChanged(null, null); ThreadID = Thread.CurrentThread.ManagedThreadId; }