1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-20 14:15:23 +00:00

Rendering refactor

This commit is contained in:
Tim Sarbin 2018-11-25 14:15:13 -05:00
parent cb8916c085
commit ea5c8bd787
7 changed files with 151 additions and 111 deletions

View File

@ -10,6 +10,9 @@ namespace OpenDiablo2.Common.Enums
{
None,
Act1_Town = 1,
Act2_Town = 40,
Act2_Harem = 50,
Act3_Town = 75,
Act4_Fortress = 103,
Act5_Baal_Entrance = 120
}

View File

@ -12,6 +12,7 @@ namespace OpenDiablo2.Common.Interfaces
{
MPQDS1 MapData { get; }
int Act { get; }
int Seed { get; }
string MapName { get; }
Palette CurrentPalette { get; }

View File

@ -29,6 +29,6 @@ namespace OpenDiablo2.Common.Interfaces
void Draw(ISprite sprite, int frame);
void Draw(ISprite sprite, int xSegments, int ySegments, int offset);
void Draw(ILabel label);
void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette);
void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette, MPQDS1WallOrientationTileProps orientation);
}
}

View File

@ -58,6 +58,17 @@ namespace OpenDiablo2.Common.Models
public Int32 Height { get; internal set; }
}
public struct DS1LookupTable
{
public int Orientation;
public int MainIndex;
public int SubIndex;
public int Frame;
public MPQDT1Tile TileRef;
}
public sealed class MPQDS1
{
static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@ -76,6 +87,7 @@ namespace OpenDiablo2.Common.Models
public Int32 NumberOfGroups { get; internal set; }
public MPQDT1[] DT1s = new MPQDT1[33];
public List<DS1LookupTable> LookupTable { get; internal set; }
public List<string> FileNames { get; internal set; } = new List<string>();
public MPQDS1WallLayer[] WallLayers { get; internal set; }
@ -230,7 +242,13 @@ namespace OpenDiablo2.Common.Models
}
else
{
br.ReadBytes(4);
WallLayers[layoutStream[n] - 5].Orientations[x + (y * Width)] = new MPQDS1WallOrientationTileProps
{
Orientation1 = br.ReadByte(),
Orientation2 = br.ReadByte(),
Orientation3 = br.ReadByte(),
Orientation4 = br.ReadByte(),
};
}
break;
@ -264,60 +282,6 @@ namespace OpenDiablo2.Common.Models
}
}
}
/*
NumberOfObjects = 0;
if (Version >= 2)
{
NumberOfObjects = br.ReadInt32();
Objects = new MPQDS1Object[NumberOfObjects];
for (int i = 0; i < NumberOfObjects; i++)
{
Objects[i] = new MPQDS1Object
{
Type = br.ReadInt32(),
Id = br.ReadInt32(),
X = br.ReadInt32(),
Y = br.ReadInt32()
};
if (Version > 5)
Objects[i].DS1Flags = br.ReadInt32();
}
}
if (Version >= 12 && TagType == 1 || TagType == 2)
{
if (Version >= 18)
br.ReadBytes(4);
NumberOfGroups = br.ReadInt32();
}
else NumberOfGroups = 0;
Groups = new MPQDS1Group[NumberOfGroups];
for (var x = 0; x < NumberOfGroups; x++)
{
Groups[x] = new MPQDS1Group
{
TileX = br.ReadInt32(),
TileY = br.ReadInt32(),
Width = br.ReadInt32(),
Height = br.ReadInt32(),
};
if (Version >= 13)
br.ReadBytes(4);
}
if (Version >= 14)
{
NumberOfNPCs = br.ReadInt32();
}*/
@ -335,6 +299,24 @@ namespace OpenDiablo2.Common.Models
DT1s[i] = resourceManager.GetMPQDT1("data\\global\\tiles\\" + levelType.File[i].Replace("/", "\\"));
}
LookupTable = new List<DS1LookupTable>();
foreach(var dt1 in DT1s.Where(x => x != null))
{
foreach(var tile in dt1.Tiles)
{
LookupTable.Add(new DS1LookupTable
{
MainIndex = tile.MainIndex,
Orientation = tile.Orientation,
SubIndex = tile.SubIndex,
Frame = tile.RarityOrFrameIndex,
TileRef = tile
});
}
}
}
}
}

View File

@ -23,6 +23,8 @@ namespace OpenDiablo2.Core.GameState_
public string MapName { get; private set; }
public Palette CurrentPalette => paletteProvider.PaletteTable[$"ACT{Act}"];
public int Seed { get; internal set; }
public GameState(
ISceneManager sceneManager,
IResourceManager resourceManager,
@ -36,10 +38,15 @@ namespace OpenDiablo2.Core.GameState_
this.paletteProvider = paletteProvider;
this.getMapEngine = getMapEngine;
this.engineDataManager = engineDataManager;
}
public void Initialize(string characterName, eHero hero)
{
var random = new Random();
Seed = random.Next();
sceneManager.ChangeScene("Game");
ChangeMap(eLevelId.Act1_Town);
}
@ -59,10 +66,10 @@ namespace OpenDiablo2.Core.GameState_
if (level.File5 != "0") mapNames.Add(level.File5);
if (level.File6 != "0") mapNames.Add(level.File6);
var random = new Random();
var random = new Random(Seed);
var mapName = "data\\global\\tiles\\" + mapNames[random.Next(mapNames.Count())].Replace("/", "\\");
MapName = level.Name;
Act = Convert.ToInt32(mapNames.First().Substring(3, 1));
Act = levelType.Act;
MapData = resourceManager.GetMPQDS1(mapName, level, levelDetails, levelType);
getMapEngine().NotifyMapChanged();
}

View File

@ -57,36 +57,27 @@ namespace OpenDiablo2.Core.Map_Engine
{
PurgeAllMapData();
LoadNewMapData();
CameraLocation = new PointF(gameState.MapData.Width / 2, gameState.MapData.Height / 2);
//CameraLocation = new PointF(gameState.MapData.Width / 2, gameState.MapData.Height / 2);
}
private void LoadNewMapData()
{
/*
var cellsToLoad = gameState.MapData.Width * gameState.MapData.Height;
tempMapCell = new ISprite[cellsToLoad];
for (var cell = 0; cell < cellsToLoad; cell++)
{
renderWindow.Clear();
loadingSprite.Frame = (int)(loadingSprite.TotalFrames * ((float)cell / (float)cellsToLoad));
renderWindow.Draw(loadingSprite);
renderWindow.Sync();
tempMapCell[cell] = renderWindow.GenerateMapCell(
gameState.MapData,
cell % gameState.MapData.Width,
cell / gameState.MapData.Width,
Common.Enums.eRenderCellType.Floor,
gameState.CurrentPalette
);
}
*/
//CameraLocation = new Point(((gameState.MapData.Width * cellSizeX) / 2) - 400, ((gameState.MapData.Height * cellSizeY) / 2) - 300);
}
public void Render()
{
// Lower Walls, Floors, and Shadows
// Shadows of objects
// Objects with OrderFlag = 1
// Upper Walls and objects with ORderFlag = 0 or 2
// Roofs
for (int y = 0; y < gameState.MapData.Width; y++)
for (int x = 0; x < gameState.MapData.Height; x++)
{
@ -94,27 +85,63 @@ namespace OpenDiablo2.Core.Map_Engine
var visualX = ((x - y) * (cellSizeX / 2)) - cOffX;
var visualY = ((x + y) * (cellSizeY / 2)) - cOffY;
if (visualX < -160 || visualX > 800 || visualY < -80 || visualY > 600)
if (visualX < -160 || visualX > 800 || visualY < -120 || visualY > 650)
continue;
var floorLayer = gameState.MapData.FloorLayers[0];
var idx = x + (y * gameState.MapData.Width);
if (idx >= floorLayer.Props.Length)
break;
var floor = floorLayer.Props[idx];
// Render the floor
foreach (var floorLayer in gameState.MapData.FloorLayers)
{
var idx = x + (y * gameState.MapData.Width);
if (idx >= floorLayer.Props.Length)
break;
var floor = floorLayer.Props[idx];
if (floor.Prop1 == 0)
return;
if (floor.Prop1 == 0)
continue;
var sub_index = floor.Prop2;
var main_index = (floor.Prop3 >> 4) + ((floor.Prop4 & 0x03) << 4);
var sub_index = floor.Prop2;
var main_index = (floor.Prop3 >> 4) + ((floor.Prop4 & 0x03) << 4);
if (x < 0 || y < 0 || x >= gameState.MapData.Width || y >= gameState.MapData.Height)
continue;
renderWindow.DrawMapCell(x, y, ((x - y) * 80) - cOffX, ((x + y) * 40) - cOffY, gameState.MapData, main_index, sub_index, gameState.CurrentPalette, null);
}
renderWindow.DrawMapCell(x, y, ((x - y) * 80) - cOffX, ((x + y) * 40) - cOffY, gameState.MapData, main_index, sub_index, gameState.CurrentPalette);
}
/*
// Render the walls
foreach (var wallLayer in gameState.MapData.WallLayers)
{
for (int y = 0; y < gameState.MapData.Width; y++)
for (int x = 0; x < gameState.MapData.Height; x++)
{
var visualX = ((x - y) * (cellSizeX / 2)) - cOffX;
var visualY = ((x + y) * (cellSizeY / 2)) - cOffY;
if (visualX < -160 || visualX > 800 || visualY < -120 || visualY > 650)
continue;
var idx = x + (y * gameState.MapData.Width);
if (idx >= wallLayer.Props.Length)
continue;
var wall = wallLayer.Props[idx];
if (wall.Prop1 == 0)
continue;
var sub_index = wall.Prop2;
var main_index = (wall.Prop3 >> 4) + ((wall.Prop4 & 0x03) << 4);
var orientation = wallLayer.Orientations[x + (y * gameState.MapData.Width)];
renderWindow.DrawMapCell(x, y, ((x - y) * 80) - cOffX, ((x + y) * 40) - cOffY + 80, gameState.MapData, main_index, sub_index, gameState.CurrentPalette, orientation);
}
}
*/
}
public void Update(long ms)

View File

@ -32,18 +32,21 @@ namespace OpenDiablo2.SDL2_
private readonly IMPQProvider mpqProvider;
private readonly IPaletteProvider paletteProvider;
private readonly IResourceManager resourceManager;
private readonly IGameState gameState;
private IntPtr cellTexture;
public SDL2RenderWindow(
IMPQProvider mpqProvider,
IPaletteProvider paletteProvider,
IResourceManager resourceManager
IResourceManager resourceManager,
IGameState gameState
)
{
this.mpqProvider = mpqProvider;
this.paletteProvider = paletteProvider;
this.resourceManager = resourceManager;
this.gameState = gameState;
SDL.SDL_Init(SDL.SDL_INIT_EVERYTHING);
if (SDL.SDL_SetHint(SDL.SDL_HINT_RENDER_SCALE_QUALITY, "0") == SDL.SDL_bool.SDL_FALSE)
@ -61,7 +64,7 @@ namespace OpenDiablo2.SDL2_
SDL.SDL_SetRenderDrawBlendMode(renderer, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
SDL.SDL_ShowCursor(0);
cellTexture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, 256, 256);
cellTexture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, 256, 1024);
SDL.SDL_SetTextureBlendMode(cellTexture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
@ -277,23 +280,34 @@ namespace OpenDiablo2.SDL2_
SDL.SDL_RenderCopy(renderer, lbl.texture, IntPtr.Zero, ref destRect);
}
public unsafe void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette)
public unsafe void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette, MPQDS1WallOrientationTileProps orientation)
{
var tiles = mapData.LookupTable.Where(x =>
x.MainIndex == main_index &&
x.SubIndex == sub_index &&
(orientation == null || x.Orientation == orientation.Orientation1)).Select(x => x.TileRef);
if (!tiles.Any())
return; // TODO: Why does this happen....
MPQDT1Tile tile = null;
for (int i = 0; i < mapData.DT1s.Count(); i++)
if (tiles.Count() > 0)
{
if (mapData.DT1s[i] == null)
continue;
tile = mapData.DT1s[i].Tiles.FirstOrDefault(z => z.MainIndex == main_index && z.SubIndex == sub_index);
if (tile != null)
break;
}
if (tile == null)
throw new ApplicationException("Could not locate tile!");
var totalRarity = tiles.Sum(q => q.RarityOrFrameIndex);
var random = new Random(gameState.Seed + xCell + (mapData.Width * yCell));
var x = random.Next(totalRarity);
var z = 0;
foreach(var t in tiles)
{
z += t.RarityOrFrameIndex;
if (x <= z)
{
tile = t;
break;
}
}
} else tile = tiles.First();
var frameSize = new Size(tile.Width, Math.Abs(tile.Height));
var srcRect = new SDL.SDL_Rect { x = 0, y = 0, w = frameSize.Width, h = frameSize.Height };
@ -315,16 +329,20 @@ namespace OpenDiablo2.SDL2_
{
var index = block.PositionX + ((block.PositionY) * pitchChange);
var xx = 0;
var yy = 0;
foreach (var colorIndex in block.PixelData)
{
try
{
if (colorIndex == 0)
continue;
var color = palette.Colors[colorIndex];
if ((color & 0xFFFFFF) > 0)
data[index] = color;
} finally
}
finally
{
index++;
xx++;
@ -333,6 +351,7 @@ namespace OpenDiablo2.SDL2_
index -= 32;
index += pitchChange;
xx = 0;
yy++;
}
}
}
@ -343,8 +362,9 @@ namespace OpenDiablo2.SDL2_
SDL.SDL_UnlockTexture(cellTexture);
}
var dstRect = new SDL.SDL_Rect { x = xPixel, y = yPixel, w = frameSize.Width, h = frameSize.Height };
SDL.SDL_SetRenderDrawBlendMode(renderer, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
SDL.SDL_SetTextureBlendMode(cellTexture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
var dstRect = new SDL.SDL_Rect { x = xPixel, y = yPixel - tile.RoofHeight, w = frameSize.Width, h = frameSize.Height };
SDL.SDL_RenderCopy(renderer, cellTexture, ref srcRect, ref dstRect);
}