diff --git a/OpenDiablo2.Common/Models/MPQDCC.cs b/OpenDiablo2.Common/Models/MPQDCC.cs index 3944d1c7..6b71a6d4 100644 --- a/OpenDiablo2.Common/Models/MPQDCC.cs +++ b/OpenDiablo2.Common/Models/MPQDCC.cs @@ -42,6 +42,7 @@ namespace OpenDiablo2.Common.Models public bool FrameIsBottomUp { get; private set; } public Rectangle Box { get; private set; } public Cell[] Cells { get; private set; } + public byte[] PixelData { get; internal set; } public int HorizontalCellCount { get; private set; } public int VerticalCellCount { get; private set; } @@ -289,48 +290,64 @@ namespace OpenDiablo2.Common.Models cell.PixelData = new byte[cell.Width * cell.Height]; } - - var frameIndex = -1; + + var frameIndex = -1; foreach (var frame in Frames) { frameIndex++; + frame.PixelData = new byte[Box.Width * Box.Height]; var c = -1; foreach (var cell in frame.Cells) { c++; + + if (cell.PixelData == null) + cell.PixelData = new byte[cell.Width * cell.Height]; + var cellX = cell.XOffset / 4; var cellY = cell.YOffset / 4; var cellIndex = cellX + (cellY * HorizontalCellCount); var bufferCell = Cells[cellIndex]; - var pbe = PixelBuffer[pbIdx]; + if ((pbe.Frame != frameIndex) || (pbe.FrameCellIndex != c)) { // This buffer cell has an EqualCell bit set to 1, so copy the frame cell or clear it - if ((cell.Width != bufferCell.LastWidth) || (cell.Height != bufferCell.LastHeight)) { // Different sizes /// TODO: Clear the pixels of the frame cell - for (var i = 0; i < bufferCell.PixelData.Length; i++) - bufferCell.PixelData[i] = 0x00; - + cell.PixelData = new byte[cell.Width * cell.Height]; } else { // Same sizes // Copy the old frame cell into the new position - // blit(dir->bmp, dir->bmp, buff_cell->last_x0, buff_cell->last_y0, cell->x0, cell->y0, cell->w, cell->h ); - for (var i = 0; i < bufferCell.PixelData.Length; i++) - bufferCell.PixelData[i] = cell.PixelData[i]; + for (var fy = 0; fy < cell.Height; fy++) + { + for (var fx = 0; fx < cell.Width; fx++) + { + // blit(dir->bmp, dir->bmp, buff_cell->last_x0, buff_cell->last_y0, cell->x0, cell->y0, cell->w, cell->h ); + frame.PixelData[fx + cell.XOffset + ((fy + cell.YOffset) * Box.Width)] + = frame.PixelData[fx + bufferCell.LastXOffset + ((fy + bufferCell.LastYOffset) * Box.Width)]; + + } + } + + //// Copy it again into the final frame image + for (var fy = 0; fy < cell.Height; fy++) + { + for (var fx = 0; fx < cell.Width; fx++) + { + // blit(cell->bmp, frm_bmp, 0, 0, cell->x0, cell->y0, cell->w, cell->h ); + frame.PixelData[fx + cell.XOffset + ((fy + cell.YOffset) * Box.Width)] + = cell.PixelData[fx + (fy * cell.Width)]; + } + } - bufferCell.LastWidth = cell.LastWidth; - bufferCell.LastHeight = cell.LastHeight; - // Copy it again into the final frame image - // blit(cell->bmp, frm_bmp, 0, 0, cell->x0, cell->y0, cell->w, cell->h ); } } else @@ -338,12 +355,12 @@ namespace OpenDiablo2.Common.Models if (pbe.Value[0] == pbe.Value[1]) { // Clear the frame + cell.PixelData = new byte[cell.Width * cell.Height]; } else { // Fill the frame cell with the pixels var bitsToRead = (pbe.Value[1] == pbe.Value[2]) ? 1 : 2; - cell.PixelData = new byte[cell.Width * cell.Height]; for (var y = 0; y < cell.Height; y++) { @@ -356,9 +373,23 @@ namespace OpenDiablo2.Common.Models } // Copy the frame cell into the frame - //blit(cell->bmp, frm_bmp, 0, 0, cell->x0, cell->y0, cell->w, cell->h ); + for (var fy = 0; fy < cell.Height; fy++) + { + for (var fx = 0; fx < cell.Width; fx++) + { + //blit(cell->bmp, frm_bmp, 0, 0, cell->x0, cell->y0, cell->w, cell->h ); + frame.PixelData[fx + cell.XOffset + ((fy + cell.YOffset) * Box.Width)] + = cell.PixelData[fx + (fy * cell.Width)]; + } + } pbIdx++; } + + bufferCell.LastWidth = cell.Width; + bufferCell.LastHeight = cell.Height; + + bufferCell.LastXOffset = cell.XOffset; + bufferCell.LastYOffset = cell.YOffset; } } } diff --git a/OpenDiablo2.Core/Map Engine/MapEngine.cs b/OpenDiablo2.Core/Map Engine/MapEngine.cs index cddbfab4..51f8ed08 100644 --- a/OpenDiablo2.Core/Map Engine/MapEngine.cs +++ b/OpenDiablo2.Core/Map Engine/MapEngine.cs @@ -106,9 +106,9 @@ namespace OpenDiablo2.Core.Map_Engine var cx = -(cameraLocation.X - Math.Truncate(cameraLocation.X)); var cy = -(cameraLocation.Y - Math.Truncate(cameraLocation.Y)); - for (int ty = -5; ty <= 9; ty++) + for (int ty = -7; ty <= 8; ty++) { - for (int tx = -5; tx <= 9; tx++) + for (int tx = -7; tx <= 8; tx++) { var ax = tx + Math.Truncate(cameraLocation.X); var ay = ty + Math.Truncate(cameraLocation.Y); @@ -121,27 +121,27 @@ namespace OpenDiablo2.Core.Map_Engine foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Floor)) - renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 210 + py + (int)oy); + renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 300 + py + (int)oy); foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallLower)) - renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 210 + py + (int)oy + 80); + renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 300 + py + (int)oy + 80); foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallUpper)) - renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 210 + py + (int)oy); + renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 300 + py + (int)oy); // TODO: We need to render the characters infront of, or behind the wall properly... - if (ty == 1 && tx == 1) + if (ty == 0 && tx == 0) { foreach (var character in characterRenderers/*.Where(x => Math.Truncate(x.LocationDetails.PlayerX) == ax && Math.Truncate(x.LocationDetails.PlayerY) == ay)*/) { // TODO: Temporary hack - character.Render(400 + gameState.CameraOffset, 280); + character.Render(400 + gameState.CameraOffset, 300); } } foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Roof)) - renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 210 + py + (int)oy); + renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 300 + py + (int)oy); } } diff --git a/OpenDiablo2.SDL2/SDL2CharacterRenderer.cs b/OpenDiablo2.SDL2/SDL2CharacterRenderer.cs index 7758772b..e1cd41c0 100644 --- a/OpenDiablo2.SDL2/SDL2CharacterRenderer.cs +++ b/OpenDiablo2.SDL2/SDL2CharacterRenderer.cs @@ -143,7 +143,7 @@ namespace OpenDiablo2.SDL2_ private unsafe void CacheFrames(IEnumerable layerData) { - var cache = new DirectionCacheItem + var directionCache = new DirectionCacheItem { MobMode = MobMode, Direction = directionConversion[LocationDetails.MovementDirection] @@ -152,9 +152,9 @@ namespace OpenDiablo2.SDL2_ var palette = paletteProvider.PaletteTable[Palettes.Units]; var dirAnimation = animationData.Animations[0]; - cache.FramesToAnimate = dirAnimation.FramesPerDirection; - cache.AnimationSpeed = dirAnimation.AnimationSpeed; - cache.RenderFrameIndex = 0; + directionCache.FramesToAnimate = dirAnimation.FramesPerDirection; + directionCache.AnimationSpeed = dirAnimation.AnimationSpeed; + directionCache.RenderFrameIndex = 0; var minX = Int32.MaxValue; var minY = Int32.MaxValue; @@ -181,13 +181,13 @@ namespace OpenDiablo2.SDL2_ if (layersIgnored > 0) log.Warn($"{layersIgnored} animation layer(s) were not found!"); - var frameW = (maxX - minX) * 2; // Hack - var frameH = (maxY - minY) * 2; + var frameW = (maxX - minX); + var frameH = (maxY - minY); - cache.SpriteTexture = new IntPtr[cache.FramesToAnimate]; - cache.SpriteRect = new SDL.SDL_Rect[cache.FramesToAnimate]; + directionCache.SpriteTexture = new IntPtr[directionCache.FramesToAnimate]; + directionCache.SpriteRect = new SDL.SDL_Rect[directionCache.FramesToAnimate]; - for (var frameIndex = 0; frameIndex < cache.FramesToAnimate; frameIndex++) + for (var frameIndex = 0; frameIndex < directionCache.FramesToAnimate; frameIndex++) { var texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameW, frameH); @@ -202,43 +202,34 @@ namespace OpenDiablo2.SDL2_ var direction = layer.Directions[directionConversion[LocationDetails.MovementDirection]]; var frame = direction.Frames[frameIndex]; - foreach (var cell in frame.Cells) + for (var y = 0; y < direction.Box.Height; y++) { - if (cell.PixelData == null) - continue; // TODO: This isn't good - - for (int y = 0; y < cell.Height; y++) + for (var x = 0; x < direction.Box.Width; x++) { - for (int x = 0; x < cell.Width; x++) - { - // Index 0 is always transparent - var paletteIndex = cell.PixelData[x + (y * cell.Width)]; + var paletteIndex = frame.PixelData[x + (y * direction.Box.Width)]; - if (paletteIndex == 0) - continue; + if (paletteIndex == 0) + continue; - var color = palette.Colors[paletteIndex]; + var color = palette.Colors[paletteIndex]; + var actualX = x + direction.Box.X - minX; + var actualY = y + direction.Box.Y - minY; - var offsetX = x + cell.XOffset + (frame.Box.X - minX); - var offsetY = y + cell.YOffset + (frame.Box.Y - minY); - if (offsetX < 0 || offsetX > frameW || offsetY < 0 || offsetY > frameH) - throw new OpenDiablo2Exception("There is nothing we can do now."); + data[actualX + (actualY * (pitch / 4))] = color; - data[offsetX + (offsetY * (pitch / 4))] = color; - } } } + } SDL.SDL_UnlockTexture(texture); SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + + directionCache.SpriteTexture[frameIndex] = texture; + directionCache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH }; - // TODO: Temporary code! - cache.SpriteTexture[frameIndex] = texture; - cache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH }; - - directionCache.Add(cache); - currentDirectionCache = cache; + this.directionCache.Add(directionCache); + currentDirectionCache = directionCache; } }