1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-20 22:25:24 +00: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.Drawing;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces.Drawing;
using OpenDiablo2.Common.Models;
@ -28,7 +29,7 @@ namespace OpenDiablo2.Common.Interfaces
void Draw(ISprite sprite, int xSegments, int ySegments, int offset);
IMouseCursor LoadCursor(ISprite sprite, int frame, Point hotspot);
void Draw(ILabel label);
MapCellInfo CacheMapCell(MPQDT1Tile mapCell);
MapCellInfo CacheMapCell(MPQDT1Tile mapCell, eRenderCellType cellType);
void DrawMapCell(MapCellInfo mapCellInfo, int xPixel, int yPixel);
ICharacterRenderer CreateCharacterRenderer();
}

View File

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

View File

@ -200,14 +200,14 @@ namespace OpenDiablo2.Core.GameState_
{
case eRenderCellType.Floor:
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);
case eRenderCellType.WallUpper:
case eRenderCellType.WallLower:
case eRenderCellType.Roof:
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);
default:
@ -252,7 +252,7 @@ namespace OpenDiablo2.Core.GameState_
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))
{
@ -260,13 +260,12 @@ namespace OpenDiablo2.Core.GameState_
}
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;
var sub_index = props.Prop2;
var main_index = (props.Prop3 >> 4) + ((props.Prop4 & 0x03) << 4);
var orientation = 0;
// Floors can't have rotations, should we blow up here?
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 };
return null;
}
if (props.Prop1 == 0)
{
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 };
return null;
}
}
if (cellType == eRenderCellType.WallUpper || cellType == eRenderCellType.WallLower)
else if (cellType == eRenderCellType.WallUpper || cellType == eRenderCellType.WallLower)
{
orientation = wallOrientations.Orientation1;
if (props.Prop1 == 0)
{
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true };
@ -374,6 +370,39 @@ namespace OpenDiablo2.Core.GameState_
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
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);
if (mapCellInfo == null)
{
mapCellInfo = renderWindow.CacheMapCell(tile);
mapCellInfo = renderWindow.CacheMapCell(tile, cellType);
mapDataLookup.Add(mapCellInfo);
switch (cellType)
{
case eRenderCellType.WallUpper:
case eRenderCellType.WallLower:
mapCellInfo.OffY -= 80;
break;
}
}
map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = mapCellInfo;

View File

@ -28,8 +28,6 @@ namespace OpenDiablo2.Core.Map_Engine
return;
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 skewY = 300;
public void Render()
{
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))
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))
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))
{
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);
}
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))
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()
{
var wildBorder = 5; // (4-15)
//var wildBorder = 5; // (4-15)
// TODO: Is there no data file that explicitly defines this??
var townMap = gameState.LoadMap(eLevelId.Act1_Town1, new Point(0, 0));
/*
Rectangle bloodMooreRect;
// 32-37 is grassy field?
@ -61,6 +63,7 @@ namespace OpenDiablo2.Core.Map_Engine
mapTile.PrimaryMap = townMap;
}
}
*/
}

View File

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

View File

@ -18,6 +18,7 @@ using System;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Exceptions;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Interfaces.Drawing;
@ -342,28 +343,33 @@ namespace OpenDiablo2.SDL2_
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 minY = mapCell.Blocks.Min(x => x.PositionY);
var maxX = mapCell.Blocks.Max(x => x.PositionX + 32);
var maxY = mapCell.Blocks.Max(x => x.PositionY + 32);
var diffX = maxX - minX;
var diffY = maxY - minY;
var frameWidth = maxX - minX;
var frameHeight = maxY - minY;
var offX = -minX;
var offY = -minY;
var dx = minX;
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);
if (SDL.SDL_LockTexture(texId, IntPtr.Zero, out IntPtr pixels, out int pitch) != 0)
throw new OpenDiablo2Exception("Could not lock texture for map rendering");
try
{
UInt32* data = (UInt32*)pixels;
@ -373,15 +379,15 @@ namespace OpenDiablo2.SDL2_
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 yy = 0;
foreach (var colorIndex in block.PixelData)
{
try
{
if (colorIndex == 0)
continue;
var color = colors[colorIndex];
if (color > 0)
@ -396,7 +402,6 @@ namespace OpenDiablo2.SDL2_
{
index += pitchChange - 32;
xx = 0;
yy++;
}
}
}
@ -410,10 +415,8 @@ namespace OpenDiablo2.SDL2_
return new MapCellInfo
{
Tile = mapCell,
FrameHeight = frameSize.Height,
FrameWidth = frameSize.Width,
OffX = offX,
OffY = offY,
FrameHeight = frameHeight,
FrameWidth = frameWidth,
Rect = srcRect.ToRectangle(),
Texture = new SDL2Texture { Pointer = texId }
};