1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-12-26 12:06:24 -05:00

Added start of cell renderer. Still trying to fix map load issue

This commit is contained in:
Tim Sarbin 2018-11-24 10:54:02 -05:00
parent 6c2847e4b3
commit ecc6eb2138
9 changed files with 161 additions and 50 deletions

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums
{
public enum eRenderCellType
{
Floor,
Wall
}
}

View File

@ -1,4 +1,5 @@
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Models;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -18,6 +19,7 @@ namespace OpenDiablo2.Common.Interfaces
void Quit();
ISprite LoadSprite(string resourcePath, string palette, Point location);
ISprite LoadSprite(string resourcePath, string palette);
ISprite GenerateMapCell(MPQDS1 mapData, int x, int y, eRenderCellType cellType, Palette palette);
IFont LoadFont(string resourcePath, string palette);
ILabel CreateLabel(IFont font);
ILabel CreateLabel(IFont font, string text);

View File

@ -15,7 +15,7 @@ namespace OpenDiablo2.Common.Models
public byte GridY { get; internal set; }
public UInt16 Format { get; internal set; }
public UInt32 Length { get; internal set; }
public Int32 FileOffset { get; internal set; }
public UInt32 FileOffset { get; internal set; }
public Int16[] PixelData { get; internal set; }
}
@ -55,57 +55,53 @@ namespace OpenDiablo2.Common.Models
for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++)
{
stream.Seek(tileHeaderOffset + (96 * tileIndex), SeekOrigin.Begin);
Tiles[tileIndex] = new MPQDT1Tile();
Tiles[tileIndex].Direction = br.ReadUInt32();
Tiles[tileIndex].RoofHeight = br.ReadUInt16();
Tiles[tileIndex].SoundIndex = br.ReadByte();
Tiles[tileIndex].Animated = br.ReadByte() == 1;
Tiles[tileIndex].Height = br.ReadInt32();
Tiles[tileIndex].Width = br.ReadInt32();
var tile = Tiles[tileIndex];
tile.Direction = br.ReadUInt32();
tile.RoofHeight = br.ReadUInt16();
tile.SoundIndex = br.ReadByte();
tile.Animated = br.ReadByte() == 1;
tile.Height = br.ReadInt32();
tile.Width = br.ReadInt32();
br.ReadBytes(4);
Tiles[tileIndex].Orientation = br.ReadUInt32();
Tiles[tileIndex].MainIndex = br.ReadUInt32();
Tiles[tileIndex].SubIndex = br.ReadUInt32();
Tiles[tileIndex].RarityOrFrameIndex = br.ReadUInt32();
tile.Orientation = br.ReadUInt32();
tile.MainIndex = br.ReadUInt32();
tile.SubIndex = br.ReadUInt32();
tile.RarityOrFrameIndex = br.ReadUInt32();
br.ReadBytes(4);
for (int i = 0; i < 25; i++)
Tiles[tileIndex].SubTileFlags[i] = br.ReadByte();
tile.SubTileFlags[i] = br.ReadByte();
br.ReadBytes(7);
Tiles[tileIndex].BlockHeadersPointer = br.ReadUInt32();
Tiles[tileIndex].BlockDataLength = br.ReadUInt32();
Tiles[tileIndex].NumberOfBlocks = br.ReadUInt32();
tile.BlockHeadersPointer = br.ReadUInt32();
tile.BlockDataLength = br.ReadUInt32();
tile.NumberOfBlocks = br.ReadUInt32();
br.ReadBytes(12);
}
for (int tileIndex = 0; tileIndex < NumberOfTiles; tileIndex++)
{
var tile = Tiles[tileIndex];
if (tile.BlockHeadersPointer == 0)
if (tile.BlockHeadersPointer == 0 || tile.Width == 0 || tile.Height == 0)
{
tile.Blocks = new MPQDT1Block[0];
continue;
}
stream.Seek(tile.BlockHeadersPointer, SeekOrigin.Begin);
tile.Blocks = new MPQDT1Block[tile.NumberOfBlocks];
for (int blockIndex = 0; blockIndex < tile.NumberOfBlocks; blockIndex++)
{
stream.Seek(tile.BlockHeadersPointer + (20 * blockIndex), SeekOrigin.Begin);
tile.Blocks[blockIndex] = new MPQDT1Block();
tile.Blocks[blockIndex].PositionX = br.ReadUInt16();
tile.Blocks[blockIndex].PositionY = br.ReadUInt16();
br.ReadBytes(2);
tile.Blocks[blockIndex].GridX = br.ReadByte();
tile.Blocks[blockIndex].GridX = br.ReadByte();
tile.Blocks[blockIndex].Format = br.ReadUInt16();
tile.Blocks[blockIndex].Length = br.ReadUInt32();
br.ReadBytes(2);
tile.Blocks[blockIndex].FileOffset = br.ReadInt32();
}
for (int blockIndex = 0; blockIndex < tile.NumberOfBlocks; blockIndex++)
{
var block = tile.Blocks[blockIndex];
block.PositionX = br.ReadUInt16();
block.PositionY = br.ReadUInt16();
br.ReadBytes(2);
block.GridX = br.ReadByte();
block.GridX = br.ReadByte();
block.Format = br.ReadUInt16();
block.Length = br.ReadUInt32();
br.ReadBytes(2);
block.FileOffset = br.ReadUInt32();
stream.Seek(tile.BlockHeadersPointer + block.FileOffset, SeekOrigin.Begin);
if (block.Format == 1)
@ -136,18 +132,18 @@ namespace OpenDiablo2.Common.Models
}
}
else
else
{
// TODO: This doesn't work.. memory pointer issues?
continue;
// RLE block
/* TODO: BROKEN
var length = block.Length;
byte b1;
byte b2;
int x = 0;
int y = 0;
block.PixelData = new Int16[32 * 16];
int width = (block.Format >> 8);
int height = (block.Format & 0xFF);
block.PixelData = new Int16[width * height];
while (length > 0)
{
b1 = br.ReadByte();
@ -157,7 +153,7 @@ namespace OpenDiablo2.Common.Models
{
x += b1;
length -= b2;
while(b2 > 0)
while (b2 > 0)
{
block.PixelData[x + (y * 32)] = br.ReadByte();
br.ReadByte();
@ -171,6 +167,7 @@ namespace OpenDiablo2.Common.Models
y++;
}
}
*/
}
}
}

View File

@ -73,6 +73,7 @@
<Compile Include="Enums\eButtonType.cs" />
<Compile Include="Enums\eHero.cs" />
<Compile Include="Enums\eMPQFormatVersion.cs" />
<Compile Include="Enums\eRenderCellType.cs" />
<Compile Include="Interfaces\IEngineDataManager.cs" />
<Compile Include="Interfaces\IFont.cs" />
<Compile Include="Interfaces\IGameEngine.cs" />

View File

@ -14,18 +14,33 @@ namespace OpenDiablo2.Core.GameState_
{
private readonly ISceneManager sceneManager;
private readonly IResourceManager resourceManager;
MPQDS1 mapData;
private readonly IPaletteProvider paletteProvider;
public GameState(ISceneManager sceneManager, IResourceManager resourceManager)
public MPQDS1 MapData { get; set; }
public bool MapDirty { get; set; }
public int Act { get; private set; }
public string MapName { get; set; }
public Palette CurrentPalette => paletteProvider.PaletteTable[$"ACT{Act}"];
public GameState(ISceneManager sceneManager, IResourceManager resourceManager, IPaletteProvider paletteProvider)
{
this.sceneManager = sceneManager;
this.resourceManager = resourceManager;
this.paletteProvider = paletteProvider;
}
public void Initialize(string characterName, eHero hero)
{
sceneManager.ChangeScene("Game");
mapData = resourceManager.GetMPQDS1(ResourcePaths.MapAct1TownE1, -1, 1);
ChangeMap(ResourcePaths.MapAct1TownE1, 1);
}
public void ChangeMap(string mapName, int act)
{
MapName = mapName;
Act = act;
MapDirty = true;
MapData = resourceManager.GetMPQDS1(mapName, -1, act);
}
}
}

View File

@ -10,6 +10,7 @@ using System.Drawing;
using OpenDiablo2.Common.Models;
using Autofac;
using System.Runtime.InteropServices;
using OpenDiablo2.Common.Enums;
namespace OpenDiablo2.SDL2_
{
@ -266,5 +267,8 @@ namespace OpenDiablo2.SDL2_
SDL.SDL_RenderCopy(renderer, lbl.texture, IntPtr.Zero, ref destRect);
}
public ISprite GenerateMapCell(MPQDS1 mapData, int x, int y, eRenderCellType cellType, Palette palette)
=> new SDL2Sprite(this.renderer, palette, mapData, x, y, cellType);
}
}

View File

@ -2,6 +2,7 @@
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models;
using SDL2;
@ -15,10 +16,12 @@ namespace OpenDiablo2.SDL2_
internal readonly ImageSet source;
private readonly IntPtr renderer;
internal IntPtr texture = IntPtr.Zero;
private Point globalFrameOffset = new Point(0, 0);
public Point Location { get; set; } = new Point();
public Size FrameSize { get; set; } = new Size();
private bool darken;
public bool Darken
{
@ -80,11 +83,63 @@ namespace OpenDiablo2.SDL2_
FrameSize = new Size(Pow2((int)source.Frames.Max(x => x.Width)), Pow2((int)source.Frames.Max(x => x.Height)));
}
public unsafe SDL2Sprite(IntPtr renderer, Palette palette, MPQDS1 mapData, int x, int y, eRenderCellType cellType)
{
this.renderer = renderer;
// TODO: Cell types
// Floor cell types
// Todo: multiple floor layers
var floorLayer = mapData.FloorLayers.First();
var floor = floorLayer.Props[x + (y * mapData.Width)];
if (floor.Prop1 == 0)
return;
var sub_index = floor.Prop2;
var main_index = (floor.Prop3 / 16) + ((floor.Prop4 & 0x0F) * 16);
var tile = mapData.DT1s[main_index].Tiles[sub_index];
FrameSize = new Size(tile.Width, Math.Abs(tile.Height));
TotalFrames = 1;
frame = 0;
IntPtr pixels;
int pitch;
texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, FrameSize.Width, FrameSize.Height);
if (texture == IntPtr.Zero)
throw new ApplicationException($"Unaple to initialize texture: {SDL.SDL_GetError()}");
SDL.SDL_LockTexture(texture, IntPtr.Zero, out pixels, out pitch);
try
{
UInt32* data = (UInt32*)pixels;
for (var i = 0; i < FrameSize.Width * FrameSize.Height; i++)
data[i] = 0;
for (var subtileX = 0; subtileX < 5; subtileX++)
{
for (var subtileY = 0; subtileY < 5; subtileY++)
{
var subtileFlags = tile.SubTileFlags[subtileX + (subtileY * 5)];
}
}
}
finally
{
SDL.SDL_UnlockTexture(texture);
}
}
internal Point GetRenderPoint()
=> new Point(
Location.X + source.Frames[Frame].OffsetX,
(Location.Y - FrameSize.Height) + source.Frames[Frame].OffsetY
);
{
return source == null
? globalFrameOffset
: new Point(Location.X + source.Frames[Frame].OffsetX, (Location.Y - FrameSize.Height) + source.Frames[Frame].OffsetY);
}
public Size LocalFrameSize => new Size((int)source.Frames[Frame].Width, (int)source.Frames[Frame].Height);
@ -152,5 +207,6 @@ namespace OpenDiablo2.SDL2_
{
SDL.SDL_DestroyTexture(texture);
}
}
}

View File

@ -6,7 +6,9 @@ using System.Text;
using System.Threading.Tasks;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Attributes;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Core.GameState_;
namespace OpenDiablo2.Scenes
{
@ -15,13 +17,17 @@ namespace OpenDiablo2.Scenes
{
private readonly IRenderWindow renderWindow;
private readonly IResourceManager resourceManager;
private GameState gameState;
private ISprite testSprite;
private ISprite panelSprite, healthManaSprite, gameGlobeOverlapSprite;
public Game(IRenderWindow renderWindow, IResourceManager resourceManager)
public Game(IRenderWindow renderWindow, IResourceManager resourceManager, GameState gameState)
{
this.renderWindow = renderWindow;
this.resourceManager = resourceManager;
this.gameState = gameState;
panelSprite = renderWindow.LoadSprite(ResourcePaths.GamePanels, Palettes.Act1);
healthManaSprite = renderWindow.LoadSprite(ResourcePaths.HealthMana, Palettes.Act1);
@ -30,6 +36,10 @@ namespace OpenDiablo2.Scenes
public void Render()
{
if (gameState.MapDirty)
RedrawMap();
renderWindow.Draw(testSprite);
DrawPanel();
@ -64,5 +74,15 @@ namespace OpenDiablo2.Scenes
{
}
private void RedrawMap()
{
gameState.MapDirty = false;
var x = 0;
var y = 0;
testSprite = renderWindow.GenerateMapCell(gameState.MapData, 0, 0, eRenderCellType.Floor, gameState.CurrentPalette);
testSprite.Location = new Point(((x * 80) - (y * 80)) + 100, ((x * 40) + (y * 40)) + 100);
}
}
}

View File

@ -50,6 +50,8 @@ namespace OpenDiablo2.Scenes
this.mouseInfoProvider = mouseInfoProvider;
this.sceneManager = sceneManager;
resourceManager.GetMPQDS1(ResourcePaths.MapAct1TownE1, -1, 1);
backgroundSprite = renderWindow.LoadSprite(ResourcePaths.GameSelectScreen, Palettes.Sky);
diabloLogoLeft = renderWindow.LoadSprite(ResourcePaths.Diablo2LogoFireLeft, Palettes.Units, new Point(400, 120));
diabloLogoLeft.Blend = true;