mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-19 02:46:35 -05:00
Added animations. Added walking/running.
This commit is contained in:
parent
0b545fb876
commit
9f078a8ace
@ -8,19 +8,26 @@ namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
public sealed class MPQDCC
|
||||
{
|
||||
public class PixelBufferEntry
|
||||
public sealed class PixelBufferEntry
|
||||
{
|
||||
public byte[] Value;
|
||||
public int Frame;
|
||||
public int FrameCellIndex;
|
||||
}
|
||||
|
||||
public struct Cell
|
||||
public sealed class Cell
|
||||
{
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int XOffset;
|
||||
public int YOffset;
|
||||
|
||||
public int LastWidth;
|
||||
public int LastHeight;
|
||||
public int LastXOffset;
|
||||
public int LastYOffset;
|
||||
|
||||
public byte[] PixelData;
|
||||
}
|
||||
|
||||
public sealed class MPQDCCDirectionFrame
|
||||
@ -59,7 +66,7 @@ namespace OpenDiablo2.Common.Models
|
||||
|
||||
}
|
||||
|
||||
public void MakeCells(MPQDCCDirection direction)
|
||||
public void CalculateCells(MPQDCCDirection direction)
|
||||
{
|
||||
var w = 4 - ((Box.Left - direction.Box.Left) % 4); // Width of the first column (in pixels)
|
||||
if ((Width - w) <= 1)
|
||||
@ -131,7 +138,6 @@ namespace OpenDiablo2.Common.Models
|
||||
}
|
||||
public sealed class MPQDCCDirection
|
||||
{
|
||||
const int DCC_MAX_PB_ENTRY = 8500; // But why is this the magic number?
|
||||
public int OutSizeCoded { get; private set; }
|
||||
public int CompressionFlags { get; private set; }
|
||||
public int Variable0Bits { get; private set; }
|
||||
@ -166,14 +172,14 @@ namespace OpenDiablo2.Common.Models
|
||||
OptionalDataBits = crazyBitTable[bm.GetBits(4)];
|
||||
CodedBytesBits = crazyBitTable[bm.GetBits(4)];
|
||||
|
||||
Frames = new MPQDCCDirectionFrame[file.NumberOfFrames];
|
||||
Frames = new MPQDCCDirectionFrame[file.FramesPerDirection];
|
||||
|
||||
var minx = long.MaxValue;
|
||||
var miny = long.MaxValue;
|
||||
var maxx = long.MinValue;
|
||||
var maxy = long.MinValue;
|
||||
// Load the frame headers
|
||||
for (var frameIdx = 0; frameIdx < file.NumberOfFrames; frameIdx++)
|
||||
for (var frameIdx = 0; frameIdx < file.FramesPerDirection; frameIdx++)
|
||||
{
|
||||
Frames[frameIdx] = new MPQDCCDirectionFrame(bm, this);
|
||||
|
||||
@ -242,13 +248,20 @@ namespace OpenDiablo2.Common.Models
|
||||
|
||||
var pixelCodeandDisplacement = new BitMuncher(bm);
|
||||
|
||||
CalculateCellOffsets();
|
||||
// Calculate the cells for the direction
|
||||
CaculateCells();
|
||||
|
||||
// Caculate the cells for each of the frames
|
||||
foreach (var frame in Frames)
|
||||
frame.MakeCells(this);
|
||||
frame.CalculateCells(this);
|
||||
|
||||
// Fill in the pixel buffer
|
||||
FillPixelBuffer(pixelCodeandDisplacement, equalCellsBitstream, pixelMaskBitstream, encodingTypeBitsream, rawPixelCodesBitstream);
|
||||
|
||||
// Generate the actual frame pixel data
|
||||
GenerateFrames(file, pixelCodeandDisplacement);
|
||||
|
||||
// Verify that everything we expected to read was actually read (sanity check)...
|
||||
if (equalCellsBitstream.BitsRead != EqualCellsBitstreamSize)
|
||||
throw new ApplicationException("Did not read the correct number of bits!");
|
||||
|
||||
@ -264,13 +277,103 @@ namespace OpenDiablo2.Common.Models
|
||||
bm.SkipBits(pixelCodeandDisplacement.BitsRead);
|
||||
}
|
||||
|
||||
private void GenerateFrames(MPQDCC file, BitMuncher pcd)
|
||||
{
|
||||
var pbIdx = 0;
|
||||
|
||||
foreach (var cell in Cells)
|
||||
{
|
||||
cell.LastWidth = -1;
|
||||
cell.LastHeight = -1;
|
||||
cell.PixelData = new byte[cell.Width * cell.Height];
|
||||
}
|
||||
|
||||
|
||||
|
||||
var frameIndex = -1;
|
||||
foreach (var frame in Frames)
|
||||
{
|
||||
frameIndex++;
|
||||
var numberOfCells = frame.HorizontalCellCount * frame.VerticalCellCount;
|
||||
|
||||
var c = -1;
|
||||
foreach (var cell in frame.Cells)
|
||||
{
|
||||
c++;
|
||||
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;
|
||||
|
||||
}
|
||||
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];
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
if (pbe.Value[0] == pbe.Value[1])
|
||||
{
|
||||
// Clear the frame
|
||||
}
|
||||
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++)
|
||||
{
|
||||
for (var x = 0; x < cell.Width; x++)
|
||||
{
|
||||
var paletteIndex = pcd.GetBits(bitsToRead);
|
||||
cell.PixelData[x + (y * cell.Width)] = pbe.Value[paletteIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the frame cell into the frame
|
||||
//blit(cell->bmp, frm_bmp, 0, 0, cell->x0, cell->y0, cell->w, cell->h );
|
||||
pbIdx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int[] pixelMaskLookup = new int[] { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
||||
private void FillPixelBuffer(BitMuncher pcd, BitMuncher ec, BitMuncher pm, BitMuncher et, BitMuncher rp)
|
||||
{
|
||||
UInt32 lastPixel = 0;
|
||||
|
||||
PixelBuffer = new PixelBufferEntry[DCC_MAX_PB_ENTRY];
|
||||
for (var i = 0; i < DCC_MAX_PB_ENTRY; i++)
|
||||
var maxCellX = Frames.Sum(x => x.HorizontalCellCount);
|
||||
var maxCellY = Frames.Sum(x => x.VerticalCellCount);
|
||||
|
||||
PixelBuffer = new PixelBufferEntry[maxCellX * maxCellY];
|
||||
for (var i = 0; i < maxCellX * maxCellY; i++)
|
||||
PixelBuffer[i] = new PixelBufferEntry { Frame = -1, FrameCellIndex = -1, Value = new byte[4] };
|
||||
|
||||
var cellBuffer = new PixelBufferEntry[HorizontalCellCount * VerticalCellCount];
|
||||
@ -386,7 +489,7 @@ namespace OpenDiablo2.Common.Models
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateCellOffsets()
|
||||
private void CaculateCells()
|
||||
{
|
||||
// Calculate the number of vertical and horizontal cells we need
|
||||
HorizontalCellCount = 1 + (Box.Width - 1) / 4;
|
||||
@ -441,7 +544,7 @@ namespace OpenDiablo2.Common.Models
|
||||
public int Signature { get; private set; }
|
||||
public int Version { get; private set; }
|
||||
public int NumberOfDirections { get; private set; }
|
||||
public int NumberOfFrames { get; private set; }
|
||||
public int FramesPerDirection { get; private set; }
|
||||
public MPQDCCDirection[] Directions { get; private set; }
|
||||
|
||||
public MPQDCC(byte[] data, Palette palette)
|
||||
@ -453,7 +556,7 @@ namespace OpenDiablo2.Common.Models
|
||||
|
||||
Version = bm.GetByte();
|
||||
NumberOfDirections = bm.GetByte();
|
||||
NumberOfFrames = bm.GetInt32();
|
||||
FramesPerDirection = bm.GetInt32();
|
||||
|
||||
if (bm.GetInt32() != 1)
|
||||
throw new ApplicationException("This value isn't 1. It has to be 1.");
|
||||
|
@ -16,7 +16,7 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
public eMovementType MovementType { get; set; } = eMovementType.Stopped; // TODO: This needs to mess with MobMode somehow
|
||||
public eWeaponClass WeaponClass { get; set; } = eWeaponClass.HandToHand; // Temporary
|
||||
public eArmorType ArmorType { get; set; } = eArmorType.Lite; // Temporary
|
||||
public eMobMode MobMode { get; set; } = eMobMode.PlayerNeutral; // Temporary
|
||||
public eMobMode MobMode { get; set; } = eMobMode.PlayerTownWalk; // Temporary
|
||||
|
||||
// Player character stats
|
||||
protected Stat Vitality;
|
||||
|
@ -42,12 +42,12 @@ namespace OpenDiablo2.Common.Models
|
||||
result.Name = Encoding.UTF8.GetString(data, offset + 8, nameLength);
|
||||
result.LocationDetails = PlayerLocationDetails.FromBytes(data, offset + 8 + nameLength);
|
||||
var uidBytes = new byte[16];
|
||||
Array.Copy(data, offset + 8 + nameLength + PlayerLocationDetails.SizeInBytes + 1, uidBytes, 0, 16);
|
||||
Array.Copy(data, offset + 8 + nameLength + PlayerLocationDetails.SizeInBytes, uidBytes, 0, 16);
|
||||
result.UID = new Guid(uidBytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
public int SizeInBytes => 5 + Encoding.UTF8.GetByteCount(Name) + PlayerLocationDetails.SizeInBytes;
|
||||
public int SizeInBytes => 8 + Encoding.UTF8.GetByteCount(Name) + PlayerLocationDetails.SizeInBytes + 16;
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@ namespace OpenDiablo2.Common.Models
|
||||
public float PlayerY { get; set; }
|
||||
public eMovementType MovementType { get; set; }
|
||||
public int MovementDirection { get; set; }
|
||||
public float MovementSpeed { get; set; }
|
||||
// TODO: They may not be on the same 'anchor map'...
|
||||
|
||||
public byte[] GetBytes()
|
||||
@ -22,32 +23,40 @@ namespace OpenDiablo2.Common.Models
|
||||
result.AddRange(BitConverter.GetBytes((float)PlayerY));
|
||||
result.AddRange(BitConverter.GetBytes((Int32)MovementDirection));
|
||||
result.AddRange(BitConverter.GetBytes((byte)MovementType));
|
||||
result.AddRange(BitConverter.GetBytes((float)MovementSpeed));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static PlayerLocationDetails FromBytes(byte[] data, int offset = 0)
|
||||
=> new PlayerLocationDetails
|
||||
{
|
||||
var result = new PlayerLocationDetails
|
||||
{
|
||||
PlayerId = BitConverter.ToInt32(data, offset + 0),
|
||||
PlayerX = BitConverter.ToSingle(data, offset + 4),
|
||||
PlayerY = BitConverter.ToSingle(data, offset + 8),
|
||||
MovementDirection = BitConverter.ToInt32(data, offset + 12),
|
||||
MovementType = (eMovementType)data[offset + 16]
|
||||
MovementType = (eMovementType)data[offset + 16],
|
||||
MovementSpeed = BitConverter.ToSingle(data, offset + 18)
|
||||
};
|
||||
|
||||
public static int SizeInBytes => 17;
|
||||
return result;
|
||||
}
|
||||
public static int SizeInBytes => 22;
|
||||
}
|
||||
|
||||
public static class PlayerLocationDetailsExtensions
|
||||
{
|
||||
public static PlayerLocationDetails ToPlayerLocationDetails(this PlayerState source)
|
||||
=> new PlayerLocationDetails
|
||||
{
|
||||
var result = new PlayerLocationDetails
|
||||
{
|
||||
PlayerId = source.Id,
|
||||
PlayerX = source.GetPosition().X,
|
||||
PlayerY = source.GetPosition().Y,
|
||||
MovementType = source.MovementType,
|
||||
MovementDirection = source.MovementDirection
|
||||
MovementDirection = source.MovementDirection,
|
||||
MovementSpeed = (float)(source.MovementType == eMovementType.Running ? source.GetRunVelocity() : source.GetWalkVeloicty()) / 4f
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -434,8 +434,8 @@ namespace OpenDiablo2.Core.GameState_
|
||||
|
||||
var rads = (float)player.LocationDetails.MovementDirection * 22 * (float)Deg2Rad;
|
||||
|
||||
var moveX = (float)Math.Cos(rads) * seconds * 2f;
|
||||
var moveY = (float)Math.Sin(rads) * seconds * 2f;
|
||||
var moveX = (float)Math.Cos(rads) * seconds * player.LocationDetails.MovementSpeed;
|
||||
var moveY = (float)Math.Sin(rads) * seconds * player.LocationDetails.MovementSpeed;
|
||||
|
||||
player.LocationDetails.PlayerX += moveX;
|
||||
player.LocationDetails.PlayerY += moveY;
|
||||
|
@ -67,7 +67,11 @@ namespace OpenDiablo2.Core.Map_Engine
|
||||
foreach(var loc in playerLocationDetails)
|
||||
{
|
||||
var cr = characterRenderers.FirstOrDefault(x => x.LocationDetails.PlayerId == loc.PlayerId);
|
||||
var newDirection = loc.MovementDirection != cr.LocationDetails.MovementDirection;
|
||||
var stanceChanged = loc.MovementType != cr.LocationDetails.MovementType;
|
||||
cr.LocationDetails = loc;
|
||||
if (newDirection || stanceChanged)
|
||||
cr.ResetAnimationData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,20 +139,27 @@ namespace OpenDiablo2.Core.Map_Engine
|
||||
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallLower))
|
||||
renderWindow.DrawMapCell(cellInfo, 320 + (int)px + (int)ox + xOffset, 210 + (int)py + (int)oy);
|
||||
|
||||
// TODO: We need to render the characters infront of, or behind the wall properly...
|
||||
foreach (var character in characterRenderers.Where(x => Math.Truncate(x.LocationDetails.PlayerX) == ax && Math.Truncate(x.LocationDetails.PlayerY) == ay))
|
||||
character.Render(320 + (int)px + (int)ox + xOffset, 210 + (int)py + (int)oy);
|
||||
|
||||
|
||||
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallUpper))
|
||||
renderWindow.DrawMapCell(cellInfo, 320 + (int)px + (int)ox + xOffset, 210 + (int)py + (int)oy);
|
||||
|
||||
// TODO: We need to render the characters infront of, or behind the wall properly...
|
||||
if (ty == 1 && tx == 1)
|
||||
{
|
||||
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, 280);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Roof))
|
||||
renderWindow.DrawMapCell(cellInfo, 320 + (int)px + (int)ox + xOffset, 210 + (int)py + (int)oy);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,8 +84,10 @@ namespace OpenDiablo2.GameServer_
|
||||
|
||||
var rads = (float)player.MovementDirection * 22 * (float)Deg2Rad;
|
||||
|
||||
var moveX = (float)Math.Cos(rads) * seconds * 2f;
|
||||
var moveY = (float)Math.Sin(rads) * seconds * 2f;
|
||||
var speed = (float)(player.MovementType == eMovementType.Running ? player.GetRunVelocity() : player.GetWalkVeloicty()) / 4f;
|
||||
|
||||
var moveX = (float)Math.Cos(rads) * seconds * speed;
|
||||
var moveY = (float)Math.Sin(rads) * seconds * speed;
|
||||
|
||||
player.X += moveX;
|
||||
player.Y += moveY;
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenDiablo2.Common;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Interfaces.Drawing;
|
||||
@ -10,6 +13,18 @@ namespace OpenDiablo2.SDL2_
|
||||
{
|
||||
public sealed class SDL2CharacterRenderer : ICharacterRenderer
|
||||
{
|
||||
sealed class DirectionCacheItem
|
||||
{
|
||||
public int Direction { get; set; }
|
||||
public eMobMode MobMode { get; set; }
|
||||
|
||||
public SDL.SDL_Rect[] SpriteRect { get; set; }
|
||||
public IntPtr[] SpriteTexture { get; set; }
|
||||
public int FramesToAnimate { get; set; }
|
||||
public int AnimationSpeed { get; set; }
|
||||
public int RenderFrameIndex { get; set; }
|
||||
}
|
||||
|
||||
static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public Guid UID { get; set; }
|
||||
@ -20,7 +35,10 @@ namespace OpenDiablo2.SDL2_
|
||||
public eMobMode MobMode { get; set; }
|
||||
|
||||
private IntPtr renderer;
|
||||
private IntPtr tempTexture;
|
||||
|
||||
private List<DirectionCacheItem> directionCache = new List<DirectionCacheItem>();
|
||||
DirectionCacheItem currentDirectionCache;
|
||||
private float seconds;
|
||||
|
||||
private readonly IResourceManager resourceManager;
|
||||
private readonly IPaletteProvider paletteProvider;
|
||||
@ -28,6 +46,8 @@ namespace OpenDiablo2.SDL2_
|
||||
private MPQCOF animationData;
|
||||
private MPQDCC[] layerData;
|
||||
|
||||
static readonly byte[] directionConversion = new byte[] { 3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14 };
|
||||
|
||||
public SDL2CharacterRenderer(IntPtr renderer, IResourceManager resourceManager, IPaletteProvider paletteProvider)
|
||||
{
|
||||
this.resourceManager = resourceManager;
|
||||
@ -37,12 +57,34 @@ namespace OpenDiablo2.SDL2_
|
||||
|
||||
public void Render(int pixelOffsetX, int pixelOffsetY)
|
||||
{
|
||||
if (currentDirectionCache == null)
|
||||
return;
|
||||
|
||||
var destRect = new SDL.SDL_Rect
|
||||
{
|
||||
x = pixelOffsetX + currentDirectionCache.SpriteRect[currentDirectionCache.RenderFrameIndex].x,
|
||||
y = pixelOffsetY + currentDirectionCache.SpriteRect[currentDirectionCache.RenderFrameIndex].y,
|
||||
w = currentDirectionCache.SpriteRect[currentDirectionCache.RenderFrameIndex].w,
|
||||
h = currentDirectionCache.SpriteRect[currentDirectionCache.RenderFrameIndex].h
|
||||
};
|
||||
|
||||
SDL.SDL_RenderCopy(renderer, currentDirectionCache.SpriteTexture[currentDirectionCache.RenderFrameIndex], IntPtr.Zero, ref destRect);
|
||||
}
|
||||
|
||||
public void Update(long ms)
|
||||
{
|
||||
if (currentDirectionCache == null)
|
||||
return;
|
||||
|
||||
seconds += ((float)ms / 1000f);
|
||||
var animationSeg = (15f / (float)currentDirectionCache.AnimationSpeed);
|
||||
while (seconds >= animationSeg)
|
||||
{
|
||||
seconds -= animationSeg;
|
||||
currentDirectionCache.RenderFrameIndex++;
|
||||
if (currentDirectionCache.RenderFrameIndex >= currentDirectionCache.FramesToAnimate)
|
||||
currentDirectionCache.RenderFrameIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@ -52,6 +94,29 @@ namespace OpenDiablo2.SDL2_
|
||||
|
||||
public void ResetAnimationData()
|
||||
{
|
||||
switch (LocationDetails.MovementType)
|
||||
{
|
||||
case eMovementType.Stopped:
|
||||
MobMode = eMobMode.PlayerTownNeutral;
|
||||
break;
|
||||
case eMovementType.Walking:
|
||||
MobMode = eMobMode.PlayerTownWalk;
|
||||
break;
|
||||
case eMovementType.Running:
|
||||
MobMode = eMobMode.PlayerRun;
|
||||
break;
|
||||
default:
|
||||
MobMode = eMobMode.PlayerNeutral;
|
||||
break;
|
||||
}
|
||||
|
||||
currentDirectionCache = directionCache.FirstOrDefault(x => x.MobMode == MobMode && x.Direction == directionConversion[LocationDetails.MovementDirection]);
|
||||
if (currentDirectionCache != null)
|
||||
{
|
||||
currentDirectionCache.RenderFrameIndex = 0;
|
||||
seconds = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
animationData = resourceManager.GetPlayerAnimation(Hero, WeaponClass, MobMode);
|
||||
if (animationData == null)
|
||||
@ -72,35 +137,92 @@ namespace OpenDiablo2.SDL2_
|
||||
|
||||
private unsafe void CacheFrames()
|
||||
{
|
||||
var dirIndex = 0; // TODO: Specify the real direction
|
||||
var frameIndex = 0;
|
||||
var cache = new DirectionCacheItem
|
||||
{
|
||||
MobMode = MobMode,
|
||||
Direction = directionConversion[LocationDetails.MovementDirection]
|
||||
};
|
||||
|
||||
var dirAnimation = animationData.Animations[dirIndex];
|
||||
var framesToAnimate = dirAnimation.FramesPerDirection;
|
||||
var palette = paletteProvider.PaletteTable[Palettes.Units];
|
||||
|
||||
var dirAnimation = animationData.Animations[0];
|
||||
cache.FramesToAnimate = dirAnimation.FramesPerDirection;
|
||||
cache.AnimationSpeed = dirAnimation.AnimationSpeed;
|
||||
cache.RenderFrameIndex = 0;
|
||||
|
||||
var minX = Int32.MaxValue;
|
||||
var minY = Int32.MaxValue;
|
||||
var maxX = Int32.MinValue;
|
||||
var maxY = Int32.MinValue;
|
||||
|
||||
foreach (var layer in layerData)
|
||||
{
|
||||
var direction = layer.Directions[dirIndex];
|
||||
var frame = direction.Frames[0];
|
||||
var texture = SDL.SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL.SDL_PIXELFORMAT_ARGB8888,
|
||||
(int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING,
|
||||
frame.Width,
|
||||
frame.Height
|
||||
);
|
||||
minX = Math.Min(minX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Left);
|
||||
minY = Math.Min(minY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Top);
|
||||
maxX = Math.Max(maxX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Right);
|
||||
maxY = Math.Max(maxY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Bottom);
|
||||
}
|
||||
|
||||
var frameW = (maxX - minX) * 2; // Hack
|
||||
var frameH = (maxY - minY) * 2;
|
||||
|
||||
cache.SpriteTexture = new IntPtr[cache.FramesToAnimate];
|
||||
cache.SpriteRect = new SDL.SDL_Rect[cache.FramesToAnimate];
|
||||
|
||||
for (var frameIndex = 0; frameIndex < cache.FramesToAnimate; frameIndex++)
|
||||
{
|
||||
var texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameW, frameH);
|
||||
IntPtr pixels;
|
||||
int pitch;
|
||||
|
||||
SDL.SDL_LockTexture(texture, IntPtr.Zero, out pixels, out pitch);
|
||||
UInt32* data = (UInt32*)pixels;
|
||||
|
||||
foreach (var layer in layerData)
|
||||
{
|
||||
var direction = layer.Directions[directionConversion[LocationDetails.MovementDirection]];
|
||||
var frame = direction.Frames[frameIndex];
|
||||
|
||||
foreach (var cell in frame.Cells)
|
||||
{
|
||||
if (cell.PixelData == null)
|
||||
continue; // TODO: This isn't good
|
||||
|
||||
for (int y = 0; y < cell.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < cell.Width; x++)
|
||||
{
|
||||
// Index 0 is always transparent
|
||||
var paletteIndex = cell.PixelData[x + (y * cell.Width)];
|
||||
|
||||
if (paletteIndex == 0)
|
||||
continue;
|
||||
|
||||
var color = palette.Colors[paletteIndex];
|
||||
var relativeX = (frame.XOffset - minX);
|
||||
var relativeY = (frame.YOffset - 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 ApplicationException("There is nothing we can do now.");
|
||||
|
||||
data[offsetX + (offsetY * (pitch / 4))] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL.SDL_UnlockTexture(texture);
|
||||
SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
|
||||
// TODO: Temporary code!
|
||||
cache.SpriteTexture[frameIndex] = texture;
|
||||
cache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH };
|
||||
|
||||
|
||||
tempTexture = texture;
|
||||
directionCache.Add(cache);
|
||||
currentDirectionCache = cache;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +153,8 @@ namespace OpenDiablo2.Scenes
|
||||
if (cursorDirection < 0)
|
||||
cursorDirection += 360;
|
||||
var actualDirection = (byte)(cursorDirection / 22);
|
||||
if (actualDirection >= 16)
|
||||
actualDirection -= 16;
|
||||
|
||||
if (mouseInfoProvider.LeftMouseDown && (lastMovementType == eMovementType.Stopped || lastDirection != actualDirection))
|
||||
{
|
||||
|
@ -110,16 +110,15 @@ namespace OpenDiablo2.ServiceBus
|
||||
|
||||
private void OnMovementRequestHandler(int clientHash, byte direction, eMovementType movementType)
|
||||
{
|
||||
// TODO: Actually move the player ....
|
||||
var player = gameServer.Players.FirstOrDefault(x => x.ClientHash == clientHash);
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
// TODO: The server needs to actually manage player movement...
|
||||
player.MovementDirection = direction;
|
||||
player.MovementType = movementType;
|
||||
player.MovementDirection = direction;
|
||||
|
||||
|
||||
Send(new MFLocatePlayers(gameServer.Players.Select(x => x.ToPlayerLocationDetails())));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user