1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-27 21:56:19 -04:00

Map engine improvements

This commit is contained in:
Tim Sarbin 2018-12-09 18:38:54 -05:00
parent 862ea62b44
commit 602c1014cc
7 changed files with 78 additions and 64 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Drawing; using System.Drawing;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces.Drawing; using OpenDiablo2.Common.Interfaces.Drawing;
using OpenDiablo2.Common.Models; using OpenDiablo2.Common.Models;
@ -28,7 +29,7 @@ namespace OpenDiablo2.Common.Interfaces
void Draw(ISprite sprite, int xSegments, int ySegments, int offset); void Draw(ISprite sprite, int xSegments, int ySegments, int offset);
IMouseCursor LoadCursor(ISprite sprite, int frame, Point hotspot); IMouseCursor LoadCursor(ISprite sprite, int frame, Point hotspot);
void Draw(ILabel label); void Draw(ILabel label);
MapCellInfo CacheMapCell(MPQDT1Tile mapCell); MapCellInfo CacheMapCell(MPQDT1Tile mapCell, eRenderCellType cellType);
void DrawMapCell(MapCellInfo mapCellInfo, int xPixel, int yPixel); void DrawMapCell(MapCellInfo mapCellInfo, int xPixel, int yPixel);
ICharacterRenderer CreateCharacterRenderer(); ICharacterRenderer CreateCharacterRenderer();
} }

View File

@ -9,8 +9,6 @@ namespace OpenDiablo2.Common.Models
{ {
public bool Ignore { get; set; } = false; public bool Ignore { get; set; } = false;
public int AnimationId { get; set; } public int AnimationId { get; set; }
public int OffX { get; set; }
public int OffY { get; set; }
public int FrameWidth { get; set; } public int FrameWidth { get; set; }
public int FrameHeight { get; set; } public int FrameHeight { get; set; }
public MPQDT1Tile Tile { get; set; } public MPQDT1Tile Tile { get; set; }

View File

@ -200,14 +200,14 @@ namespace OpenDiablo2.Core.GameState_
{ {
case eRenderCellType.Floor: case eRenderCellType.Floor:
return map.FileData.FloorLayers return map.FileData.FloorLayers
.Select(floorLayer => GetMapCellInfo(map, cellX, cellY, floorLayer.Props[idx], eRenderCellType.Floor)) .Select(floorLayer => GetMapCellInfo(map, cellX, cellY, floorLayer.Props[idx], eRenderCellType.Floor, 0))
.Where(x => x != null); .Where(x => x != null);
case eRenderCellType.WallUpper: case eRenderCellType.WallUpper:
case eRenderCellType.WallLower: case eRenderCellType.WallLower:
case eRenderCellType.Roof: case eRenderCellType.Roof:
return map.FileData.WallLayers return map.FileData.WallLayers
.Select(wallLayer => GetMapCellInfo(map, cellX, cellY, wallLayer.Props[idx], renderCellType, wallLayer.Orientations[idx])) .Select(wallLayer => GetMapCellInfo(map, cellX, cellY, wallLayer.Props[idx], renderCellType, wallLayer.Orientations[idx].Orientation1))
.Where(x => x != null); .Where(x => x != null);
default: default:
@ -252,7 +252,7 @@ namespace OpenDiablo2.Core.GameState_
this.SelectedItem = item; this.SelectedItem = item;
} }
private MapCellInfo GetMapCellInfo(MapInfo map, int cellX, int cellY, MPQDS1TileProps props, eRenderCellType cellType, MPQDS1WallOrientationTileProps wallOrientations = null) private MapCellInfo GetMapCellInfo(MapInfo map, int cellX, int cellY, MPQDS1TileProps props, eRenderCellType cellType, byte orientation)
{ {
if (!map.CellInfo.ContainsKey(cellType)) if (!map.CellInfo.ContainsKey(cellType))
{ {
@ -260,13 +260,12 @@ namespace OpenDiablo2.Core.GameState_
} }
var cellInfo = map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)]; var cellInfo = map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)];
if (cellInfo != null) if (cellInfo != null && cellInfo?.Tile?.Animated != true)
return cellInfo.Ignore ? null : cellInfo; return cellInfo.Ignore ? null : cellInfo;
var sub_index = props.Prop2; var sub_index = props.Prop2;
var main_index = (props.Prop3 >> 4) + ((props.Prop4 & 0x03) << 4); var main_index = (props.Prop3 >> 4) + ((props.Prop4 & 0x03) << 4);
var orientation = 0;
// Floors can't have rotations, should we blow up here? // Floors can't have rotations, should we blow up here?
if (cellType == eRenderCellType.Floor && props.Prop1 == 0) if (cellType == eRenderCellType.Floor && props.Prop1 == 0)
@ -282,7 +281,7 @@ namespace OpenDiablo2.Core.GameState_
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
return null; return null;
} }
if (props.Prop1 == 0) if (props.Prop1 == 0)
{ {
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
@ -294,13 +293,10 @@ namespace OpenDiablo2.Core.GameState_
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
return null; return null;
} }
} }
if (cellType == eRenderCellType.WallUpper || cellType == eRenderCellType.WallLower) else if (cellType == eRenderCellType.WallUpper || cellType == eRenderCellType.WallLower)
{ {
orientation = wallOrientations.Orientation1;
if (props.Prop1 == 0) if (props.Prop1 == 0)
{ {
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
@ -374,6 +370,39 @@ namespace OpenDiablo2.Core.GameState_
else tile = tiles.First(); else tile = tiles.First();
} }
switch (cellType)
{
case eRenderCellType.Floor:
if (tile.Orientation != 0)
{
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
return null;
}
break;
case eRenderCellType.WallLower:
if (tile.Orientation < 1 || tile.Orientation == 10 || tile.Orientation == 11 || tile.Orientation == 13 || tile.Orientation > 14)
{
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
return null;
}
break;
case eRenderCellType.WallUpper:
if (tile.Orientation <= 15)
{
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
return null;
}
break;
case eRenderCellType.Roof:
if (tile.Orientation != 15)
{
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
return null;
}
break;
default:
break;
}
// This WILL happen to you // This WILL happen to you
if (tile.Width == 0 || tile.Height == 0) if (tile.Width == 0 || tile.Height == 0)
{ {
@ -392,17 +421,8 @@ namespace OpenDiablo2.Core.GameState_
var mapCellInfo = mapDataLookup.FirstOrDefault(x => x.Tile.Id == tile.Id && x.AnimationId == frame); var mapCellInfo = mapDataLookup.FirstOrDefault(x => x.Tile.Id == tile.Id && x.AnimationId == frame);
if (mapCellInfo == null) if (mapCellInfo == null)
{ {
mapCellInfo = renderWindow.CacheMapCell(tile); mapCellInfo = renderWindow.CacheMapCell(tile, cellType);
mapDataLookup.Add(mapCellInfo); mapDataLookup.Add(mapCellInfo);
switch (cellType)
{
case eRenderCellType.WallUpper:
case eRenderCellType.WallLower:
mapCellInfo.OffY -= 80;
break;
}
} }
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = mapCellInfo; map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = mapCellInfo;

View File

@ -28,8 +28,6 @@ namespace OpenDiablo2.Core.Map_Engine
return; return;
cameraLocation = value; cameraLocation = value;
//cOffX = (int)((cameraLocation.X - cameraLocation.Y) * (cellSizeX / 2));
//cOffY = (int)((cameraLocation.X + cameraLocation.Y) * (cellSizeY / 2));
} }
} }
@ -102,6 +100,7 @@ namespace OpenDiablo2.Core.Map_Engine
const int skewX = 400; const int skewX = 400;
const int skewY = 300; const int skewY = 300;
public void Render() public void Render()
{ {
var xOffset = gameState.CameraOffset; var xOffset = gameState.CameraOffset;
@ -126,25 +125,12 @@ namespace OpenDiablo2.Core.Map_Engine
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Floor)) foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Floor))
renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy); renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy);
}
}
for (int ty = -7; ty <= 9; ty++)
{
for (int tx = -8; tx <= 8; tx++)
{
var ax = tx + Math.Truncate(cameraLocation.X);
var ay = ty + Math.Truncate(cameraLocation.Y);
var px = (tx - ty) * (cellSizeX / 2);
var py = (tx + ty) * (cellSizeY / 2);
var ox = (cx - cy) * (cellSizeX / 2);
var oy = (cx + cy) * (cellSizeY / 2);
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallLower)) foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallLower))
renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy + 80); renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy + 80);
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallUpper))
renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy + 80);
foreach (var character in characterRenderers.Where(x => Math.Truncate(x.LocationDetails.PlayerX) == ax && Math.Truncate(x.LocationDetails.PlayerY) == ay)) foreach (var character in characterRenderers.Where(x => Math.Truncate(x.LocationDetails.PlayerX) == ax && Math.Truncate(x.LocationDetails.PlayerY) == ay))
{ {
var ptx = character.LocationDetails.PlayerX - Math.Truncate(cameraLocation.X); var ptx = character.LocationDetails.PlayerX - Math.Truncate(cameraLocation.X);
@ -156,11 +142,8 @@ namespace OpenDiablo2.Core.Map_Engine
character.Render(skewX + (int)ppx + (int)ox + xOffset, skewY + (int)ppy + (int)oy); character.Render(skewX + (int)ppx + (int)ox + xOffset, skewY + (int)ppy + (int)oy);
} }
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallUpper))
renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy);
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Roof)) foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Roof))
renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 300 + py + (int)oy); renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy);
} }
} }

View File

@ -16,9 +16,11 @@ namespace OpenDiablo2.Core.Map_Engine
public void Generate() public void Generate()
{ {
var wildBorder = 5; // (4-15) //var wildBorder = 5; // (4-15)
// TODO: Is there no data file that explicitly defines this?? // TODO: Is there no data file that explicitly defines this??
var townMap = gameState.LoadMap(eLevelId.Act1_Town1, new Point(0, 0)); var townMap = gameState.LoadMap(eLevelId.Act1_Town1, new Point(0, 0));
/*
Rectangle bloodMooreRect; Rectangle bloodMooreRect;
// 32-37 is grassy field? // 32-37 is grassy field?
@ -61,6 +63,7 @@ namespace OpenDiablo2.Core.Map_Engine
mapTile.PrimaryMap = townMap; mapTile.PrimaryMap = townMap;
} }
} }
*/
} }

View File

@ -25,6 +25,8 @@ namespace OpenDiablo2.Core
{ {
public sealed class ResourceManager : IResourceManager public sealed class ResourceManager : IResourceManager
{ {
static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly ICache cache; private readonly ICache cache;
private readonly IMPQProvider mpqProvider; private readonly IMPQProvider mpqProvider;
private readonly IEngineDataManager engineDataManager; private readonly IEngineDataManager engineDataManager;
@ -73,10 +75,14 @@ namespace OpenDiablo2.Core
// TODO: We need to cache this... // TODO: We need to cache this...
byte[] binaryData; byte[] binaryData;
using (var stream = mpqProvider.GetStream(cofLayer.GetDCCPath(armorType))) var streamPath = cofLayer.GetDCCPath(armorType);
using (var stream = mpqProvider.GetStream(streamPath))
{ {
if (stream == null) if (stream == null)
{
log.Error($"Could not load Player DCC: {streamPath}");
return null; return null;
}
binaryData = new byte[stream.Length]; binaryData = new byte[stream.Length];
stream.Read(binaryData, 0, (int)stream.Length); stream.Read(binaryData, 0, (int)stream.Length);

View File

@ -18,6 +18,7 @@ using System;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Exceptions; using OpenDiablo2.Common.Exceptions;
using OpenDiablo2.Common.Interfaces; using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Interfaces.Drawing; using OpenDiablo2.Common.Interfaces.Drawing;
@ -342,28 +343,33 @@ namespace OpenDiablo2.SDL2_
SDL.SDL_RenderCopy(renderer, lbl.texture, IntPtr.Zero, ref destRect); SDL.SDL_RenderCopy(renderer, lbl.texture, IntPtr.Zero, ref destRect);
} }
public unsafe MapCellInfo CacheMapCell(MPQDT1Tile mapCell) public unsafe MapCellInfo CacheMapCell(MPQDT1Tile mapCell, eRenderCellType cellType)
{ {
var minX = mapCell.Blocks.Min(x => x.PositionX); var minX = mapCell.Blocks.Min(x => x.PositionX);
var minY = mapCell.Blocks.Min(x => x.PositionY); var minY = mapCell.Blocks.Min(x => x.PositionY);
var maxX = mapCell.Blocks.Max(x => x.PositionX + 32); var maxX = mapCell.Blocks.Max(x => x.PositionX + 32);
var maxY = mapCell.Blocks.Max(x => x.PositionY + 32); var maxY = mapCell.Blocks.Max(x => x.PositionY + 32);
var diffX = maxX - minX; var frameWidth = maxX - minX;
var diffY = maxY - minY; var frameHeight = maxY - minY;
var offX = -minX; var dx = minX;
var offY = -minY; var dy = minY;
var frameSize = new Size(Math.Abs(diffX), Math.Abs(diffY)); dx -= 80;
var srcRect = new SDL.SDL_Rect { x = minX, y = minY, w = frameSize.Width, h = frameSize.Height };
var srcRect = new SDL.SDL_Rect { x = dx, y = dy, w = frameWidth, h = frameHeight };
var texId = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameWidth, frameHeight);
if (texId == IntPtr.Zero)
throw new OpenDiablo2Exception("Could not create texture");
var texId = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameSize.Width, frameSize.Height);
SDL.SDL_SetTextureBlendMode(texId, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); SDL.SDL_SetTextureBlendMode(texId, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
if (SDL.SDL_LockTexture(texId, IntPtr.Zero, out IntPtr pixels, out int pitch) != 0) if (SDL.SDL_LockTexture(texId, IntPtr.Zero, out IntPtr pixels, out int pitch) != 0)
throw new OpenDiablo2Exception("Could not lock texture for map rendering"); throw new OpenDiablo2Exception("Could not lock texture for map rendering");
try try
{ {
UInt32* data = (UInt32*)pixels; UInt32* data = (UInt32*)pixels;
@ -373,15 +379,15 @@ namespace OpenDiablo2.SDL2_
foreach (var block in mapCell.Blocks) foreach (var block in mapCell.Blocks)
{ {
var index = block.PositionX + offX + ((block.PositionY + offY) * pitchChange); var index = (block.PositionX - minX) + ((block.PositionY - minY) * pitchChange);
var xx = 0; var xx = 0;
var yy = 0;
foreach (var colorIndex in block.PixelData) foreach (var colorIndex in block.PixelData)
{ {
try try
{ {
if (colorIndex == 0) if (colorIndex == 0)
continue; continue;
var color = colors[colorIndex]; var color = colors[colorIndex];
if (color > 0) if (color > 0)
@ -396,7 +402,6 @@ namespace OpenDiablo2.SDL2_
{ {
index += pitchChange - 32; index += pitchChange - 32;
xx = 0; xx = 0;
yy++;
} }
} }
} }
@ -410,10 +415,8 @@ namespace OpenDiablo2.SDL2_
return new MapCellInfo return new MapCellInfo
{ {
Tile = mapCell, Tile = mapCell,
FrameHeight = frameSize.Height, FrameHeight = frameHeight,
FrameWidth = frameSize.Width, FrameWidth = frameWidth,
OffX = offX,
OffY = offY,
Rect = srcRect.ToRectangle(), Rect = srcRect.ToRectangle(),
Texture = new SDL2Texture { Pointer = texId } Texture = new SDL2Texture { Pointer = texId }
}; };