www.pudn.com > MapEditor.zip > ImgMan.pas
unit ImgMan;
interface
uses
Windows, Classes, SysUtils, Mmsystem, cimllib, Grobal, IMLUtil,
cimlLibB, ClUtil, Bmputil, DGC, HUtil32;
const
DATADIR = '.\Data\';
MAXMONRACE = 300;
MAXMONMEMORY = 10 * (1024 * 1000); //1¸¶¸®´ç 1M 10¸¶¸®
HUMANFRAME = 224;
MAGEFFECTFRAME = 24;
type
TSurfaceImage = record
px, py: Integer;
Surface: TDGCSurface;
end;
PTSurfaceImage = ^TSurfaceImage;
TBufSurfaceImage = record
px, py: Integer;
Surface: TDGCSurface;
BufSize: integer; //»ç¿ë ¹öÆÛ Å©±â
UseTime: integer; //¸¶Áö¸· »ç¿ë ½Ã°£
end;
PTBufSurfaceImage = ^TBufSurfaceImage;
TBufImgInfo = record
ImageSize: integer;
LatestTime: integer;
Surface: TDGCSurface;
end;
PTBufImgInfo = ^TBufImgInfo;
TBufImgMonInfo = record
ImageSize: integer;
LatestTime: integer;
SurfaceList: TList; //¸ó½ºÅÍ SurfaceÀÇ ¸®½ºÆ®
end;
PTBufImgMonInfo = ^TBufImgMonInfo;
TIndexTable = record
DiskPos: LongInt;
ImageSize: LongInt;
ImgHdr: TImgLibImage;
end;
PTIndexTable = ^TIndexTable;
TIndexTableArr = array[0..65535] of TIndexTable;
TBufImgArr = array[0..MaxListSize div 4] of PTBufImgInfo;
PTBufImgArr = ^TBufImgArr;
{-------------------------------------------------------------}
TScreenImages = class //Ç×»ó ¸Þ¸ð¸®¿¡ ¿Ã·Á¾ß ÇÏ´Â À̹ÌÁöµé...
private
ImgHeader: TImgLibHeader;
public
dScreen: TDGCScreen;
BodyFile: string;
HairFile: string;
WeaponFile: string;
MagEffectFile: string;
ScreenFile: string;
ILBody: TList;
ILHair: TList;
ILWeapon: TList;
ILMagEffect: TList;
ILScreenImage: TList;
constructor Create;
destructor Destroy; override;
procedure Initialize;
//sex 0:female 1: male
function GetHumBody (dresstype, sex, frameindex: integer): TSurfaceImage;
function GetHumHair (hairtype, sex, frameindex: integer): TSurfaceImage;
function GetHumWeapon (weapontype, sex, frameindex: integer): TSurfaceImage;
function GetMagEffect (magictype, frameindex: integer): TSurfaceImage;
function GetScreenImage (index: integer): TDgcSurface;
end;
TLoginImages = class //Load, Free Á¶Á¤ÀÌ °¡´É
private
ImgHeader: TImgLibHeader;
public
dScreen: TDGCScreen;
LoginImageFile: string;
ILLogin: TList;
constructor Create;
destructor Destroy; override;
procedure Initialize;
procedure LoadImages;
procedure FreeImages;
function GetImage (index: integer): TDgcSurface;
end;
TBufferingImages = class //ÀÏÁ¤ ¸Þ¸ð¸®¸¸Å¸¸
private
public
dScreen: TDGCScreen;
FileName: string;
ImageArr: PTBufImgArr; //array of PTBufImgInfo
IndexList: TList; //À妽º
ImageCount: integer; //Image °¹¼ö
MemorySize: inteter;
constructor Create;
destructor Destroy; override;
procedure Initialize;
function GetSurface (index: integer): TDGCSurface;
end;
TMonsterImage = class
private
ImgHeader: TImgLibHeader;
procedure LoadMonImages (monfile: string; surlist: TList; var imgsize: integer);
public
dScreen: TDGCScreen;
MonMemorySize: integer;
MonArr: array[0..MAXMONRACE-1] of TBufImgMonInfo; //ÇϳªÀÇ ÆÄÀÏ¿¡ ÇÑ ¸ó½ºÅÍ
constructor Create;
destructor Destroy; override;
procedure Initialize;
function MonValid (race: integer): Boolean;
function LoadMonster (race: integer): TList;
procedure FreeMonster (race: integer);
end;
implementation
constructor TScreenImages.Create;
begin
dScreen := nil;
BodyFile := '';
HairFile := '';
WeaponFile := '';
MagEffectFile := '';
ScreenFile := '';
ILBody := TList.Create;
ILHair := TList.Create;
ILWeapon := TList.Create;
ILMagEffect := TList.Create;
ILScreenImage := TList.Create;
end;
destructor TScreenImages.Destroy;
begin
ILBody.Free;
ILHair.Free;
ILWeapon.Free;
ILMagEffect.Free;
ILScreenImage.Free;
inherited Destroy;
end;
procedure TScreenImages.Initialize;
begin
if dScreen = nil then begin
ShowMessage ('Initialize Error! TScreenImages.dScreen ¼³Á¤ ¾ÈµÆÀ½.');
exit;
end;
if (BodyFile = '') or (HairFile = '') or (WeaponFile = '') or (MagEffectFile = '') or
(ScreenFile = '') then begin
ShowMessage ('Initialize error. no filename');
exit;
end;
LoadLibrary (BodyFile, ILBody);
LoadLibrary (HairFile, ILHair);
LoadLibrary (WeaponFile, ILWeapon);
LoadLibrary (MagEffectFile, ILMagEffect);
LoadLibrary (ScreenFile, ILScreenImage);
end;
procedure TScreenImages.LoadLibrary (flname: string; ilist: TList);
var
fhandle: integer;
stream: TFileStream;
i, j: integer;
ImgHdr: TImgLibImage;
surfaceimage: PTSurfaceImage;
begin
stream := TFileStream.Create (flname, fmOpenRead or fmShareDenyNone);
if stream <> nil then begin
stream.ReadBuffer (ImgHeader, SizeOf(TImgLibHeader));
for i:=0 to ImgHeader.ImageCount - 1 do begin
stream.ReadBuffer(ImgHdr, SizeOf(TImgLibImage) - SizeOf(PByte));
GetMem (ImgHdr.Bits, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
stream.ReadBuffer(ImgHdr.Bits^, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
new (surfaceimage);
with surfaceimage^ do begin
Surface := CreateSurface (dScreen, ImgHdr);
px := GetX(ImgHdr);
py := GetY(ImgHdr);
end;
ilist.Add(surfaceimage);
Dispose (ImgHdr.Bits);
end;
stream.Free; end; end;
//sex 0:female 1: male
function TScreenImages.GetHumBody (dresstype, sex, frameindex: integer): TSurfaceImage;
var
idx: integer;
begin
Result.Surface := nil;
idx := HUMANFRAME * dresstype * 2 + sex + frameindex;
if idx < ILBody.Count then begin
Result := ILBody[idx];
end;
end;
function TScreenImages.GetHumHair (hairtype, sex, frameindex: integer): TSurfaceImage;
var
idx: integer;
begin
Result.Surface := nil;
idx := HUMANFRAME * hairtype * 2 + sex + frameindex;
if idx < ILHair.Count then begin
Result := ILHair[idx];
end;
end;
function TScreenImages.GetHumWeapon (weapontype, sex, frameindex: integer): TSurfaceImage;
var
idx: integer;
begin
Result.Surface := nil;
idx := HUMANFRAME * weapontype * 2 + sex + frameindex;
if idx < ILWeapon.Count then begin
Result := ILWeapon[idx];
end;
end;
function TScreenImages.GetMagEffect (magictype, frameindex: integer): TSurfaceImage;
var
idx: integer;
begin
Result.Surface := nil;
idx := MAGEFFECTFRAME * magictype + frameindex;
if idx < ILMagEffect.Count then begin
Result := ILMagEffect[idx];
end;
end;
function TScreenImages.GetScreenImage (index: integer): TDgcSurface;
begin
Result := nil;
if index < ILScreenImage.Count then begin
Result := ILScreenImage[index].Surface;
end;
end;
{======================================================================}
constructor TLoginImages.Create; //Load, Free Á¶Á¤ÀÌ °¡´É
begin
dScreen := nil;
LoginImageFile := '';
ILLogin := TList.Create;
end;
destructor TLoginImages.Destroy;
begin
ILLogin.Free;
inherited Destroy;
end;
procedure TLoginImages.Initialize;
begin
if LoginImageFile = '' then begin
ShowMessage ('LoginImageFile¿¡ ÆÄÀÏÀ̸§ÀÌ ¼³Á¤µÇÁö ¾Ê¾ÒÀ½.');
exit;
end;
if dScreen = nil then begin
ShowMessage ('TLoginImages.dScreenÀÇ ÃʱâȰ¡ ¾ÈµÆ½À´Ï´Ù.');
exit;
end;
end;
procedure TLoginImages.LoadImages;
var
fhandle: integer;
stream: TFileStream;
i, j: integer;
ImgHdr: TImgLibImage;
surface: TDGCSurface;
begin
stream := TFileStream.Create (LoginImageFile, fmOpenRead or fmShareDenyNone);
if stream <> nil then begin
stream.ReadBuffer (ImgHeader, SizeOf(TImgLibHeader));
for i:=0 to ImgHeader.ImageCount - 1 do begin
stream.ReadBuffer(ImgHdr, SizeOf(TImgLibImage) - SizeOf(PByte));
GetMem (ImgHdr.Bits, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
stream.ReadBuffer(ImgHdr.Bits^, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
surface := CreateSurface (dScreen, ImgHdr);
ILLogin.Add(surface);
Dispose (ImgHdr.Bits);
end;
stream.Free; end; end;
procedure TLoginImages.FreeImages;
var
i: integer;
begin
for i:=0 to ILLogin.Count-1 do begin
TDGCSurface(ILLogin[i]).Free;
end;
ILLogin.Clear;
end;
function TLoginImages.GetImage (index: integer): TDgcSurface;
end;
Result := nil;
if index < ILLogin.Count then
Result := ILLogin[i];
end;
{======================================================================}
constructor TBufferingImages.Create;
begin
dScreen := nil;
ImageFile := '';
ImageArr := nil;
IndexList := TList.Create;
ImageCount := 0;
MemorySize := 0;
end;
destructor TBufferingImages.Destroy;
begin
IndexList.Free;
inherited Destroy;
end;
procedure TBufferingImages.Initialize;
var
i, n: integer;
stream: TFileStream;
ImgHdr: TImgLibImage;
begin
if ImageFile <> '' then begin
stream := TFileStream.Create (ImageFile, fmOpenRead or fmShareDenyNone);
if stream <> nil then begin
stream.ReadBuffer (ImgHeader, SizeOf(TImgLibHeader));
GetMem (ImageArr, sizeof(TBufImgInfo) * ImgHeader.ImageCount);
ImageCount := ImgHeader.ImageCount;
//Build Index
for i:=0 to ImgHeader.ImageCount-1 do begin
stream.ReadBuffer(ImgHdr, SizeOf(TImgLibImage) - SizeOf(PByte));
n := stream.Seek (WidthBytes(ImgHdr.Width) * ImgHdr.Height, 1);
IndexList.Add (pointer(n));
end;
end else
ShowMessage ('File not found.. ' + ImageFile);
end;
if MaxMemorySize <= 0 then
ShowMessage ('Maximum memory size is not setting..');
end;
procedure TBufferingImages.LoadImages (flname: string; findex: integer; var imginfo: TBufImgInfo);
var
fhandle: integer;
stream: TFileStream;
i, j: integer;
ImgHdr: TImgLibImage;
begin
stream := TFileStream.Create (flname, fmOpenRead or fmShareDenyNone);
if stream <> nil then begin
stream.Seek (findex, 0);
stream.ReadBuffer(ImgHdr, SizeOf(TImgLibImage) - SizeOf(PByte));
GetMem (ImgHdr.Bits, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
stream.ReadBuffer(ImgHdr.Bits^, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
imginfo.Surface := CreateSurface (dScreen, ImgHdr);
imginfo.ImageSize := WidthBytes(ImgHdr.Width) * ImgHdr.Height;
imginfo.LatestTime := GetCurrentTime;
Dispose (ImgHdr.Bits);
stream.Free;
end; end;
function TBufferingImages.GetSurface (index: integer): TDGCSurface;
var
findex: integer;
bimg: PTBufImgInfo;
begin
Result := nil;
if not (index in [0..ImageCount-1]) then exit;
if ImageArr[index] = nil then begin
if index < IndexList.Count then begin
findex := Integer(IndexList[index]);
new (bimg);
LoadImages (ItemFile, findex, bimg^);
ImageArr[index] := bimg;
Result := bimg.Surface;
MemorySize := MemorySize + bimg.ImageSize;
if MemorySize > MaxMemorySize then begin
FreeOldMemorys;
end;
end;
end else begin
bimg := ImageArr[index];
bimg.LatestTime := GetCurrentTime;
Result := bimg.Surface;
end;
end;
//¸Þ¸ð¸® ÇØÁ¦ ±ÔÄ¢
//Çã¿ëÇѵµ¸¦ ³Ñ¾úÀ»¶§ È£ÃâµÈ´Ù.
//3ºÐÀÌ»óµÈ°Í ºÎÅÍ ÇØÁ¦ ½ÃŲ´Ù.
//±×·¡µµ ¸ðÀÚ¶ó¸é ¿À·¡µÈ ¼øÀ¸·Î..
procedure TBufferingImages.FreeOldMemorys;
var
i, n, ntime, curtime: integer;
begin
n := -1;
ntime := 0;
for i:=0 to ImageCount-1 do begin
curtime := GetCurrentTime;
if curtime - ImageArr[i].LatestTime > 3 * 60 * 1000 then begin
MemorySize := MemorySize - PTBufImgInfo(ImageArr[i]).ImageSize;
ImageArr[i].Surface.Free;
Dispose (PTBufImgInfo(ImageArr[i]));
ImageArr[i] := nil;
end else begin
if curtime - ImageArr[i].LatestTime > ntime then begin
ntime := curtime - ImageArr[i].LatestTime
n := i;
end;
end;
if MemorySize < MaxMemorySize * 9 div 10 then begin
n := -1;
break;
end;
end;
if n >= 0 then begin
MemorySize := MemorySize - PTBufImgInfo(ImageArr[n]).ImageSize;
ImageArr[n].Surface.Free;
Dispose (PTBufImgInfo(ImageArr[n]));
ImageArr[n] := nil;
end;
end;
{----------------------Monster Images--------------------------}
constructor TMonsterImage.Create;
begin
dScreen := nil;
FillChar (MonArr, sizeof(MonArr), #0);
MonMemorySize := 0;
end;
destructor TMonsterImage.Destroy;
begin
inherited Destroy;
end;
procedure TMonsterImage.Initialize;
begin
end;
procedure TBufferingImages.LoadMonImages (monfile: string; surlist: TList; var imgsize: integer);
var
fhandle: integer;
stream: TFileStream;
i, j: integer;
ImgHdr: TImgLibImage;
surface: TDGCSurface;
begin
stream := TFileStream.Create (monfile, fmOpenRead or fmShareDenyNone);
if stream <> nil then begin
stream.ReadBuffer (ImgHeader, SizeOf(TImgLibHeader));
imgsize := 0;
for i:=0 to ImgHeader.ImageCount - 1 do begin
stream.ReadBuffer(ImgHdr, SizeOf(TImgLibImage) - SizeOf(PByte));
GetMem (ImgHdr.Bits, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
stream.ReadBuffer(ImgHdr.Bits^, WidthBytes(ImgHdr.Width) * ImgHdr.Height);
imgsize := imgsize + WidthBytes(ImgHdr.Width) * ImgHdr.Height;
surface := CreateSurface (dScreen, ImgHdr);
surlist.Add(surface);
Dispose (ImgHdr.Bits);
end;
stream.Free; end; end;
//LoadMonster¸¦ ÅëÇØ¼ ¾òÀº SurfaceListÀÇ À¯È¿¼ºÀ» °Ë»çÇØÁà¾ß ÇÑ´Ù.
function TMonsterImage.MonValid (race: integer): Boolean;
begin
Result := FALSE;
if not (race in [0..MAXMONRACE-1]) then exit;
if MonArr[race].SurfaceList <> nil then
Result := TRUE;
end;
//ActorUnit¿¡¼ È£Ãâ, Á¾Á·¹øÈ£¸¦ ÁÖ°í SurfaceList¸¦ ¾ò¾î¿Â´Ù.
function TMonsterImage.LoadMonster (race: integer): TList;
var
i: integer;
n, old: integer;
begin
Result := nil;
if not (race in [0..MAXMONRACE-1]) then exit;
if MonArr[race].SurfaceList <> nil then exit; //ÀÌ¹Ì ·ÎµùµÇ¾úÀ½.
MonArr[race].SurfaceList := TList.Create;
LoadMonImages (DATADIR + IntToStr(race) + '.WMD', MonArr[race].SurfaceList, MonArr[race].ImageSize);
MonArr[race].LatestTime := GetCurrentTime;
MonMemorySize := MonMemorySize + MonArr[race].ImageSize;
if MonMemorySize > MAXMONMEMORY then begin //Á¦ÇÑ ¸Þ¸ð¸®¸¦ ÃʰúÇÏ¿´À¸¸é
old := GetCurrentTime;
n := -1;
for i:=0 to MAXMONRACE-1 do begin
if (MonArr[i].LatestTime < old) and (MonArr[i].SurfaceList <> nil) then begin
n := i;
old := MonArr[i].LatestTime;
end;
end;
if n >= 0 then begin
FreeMonster (n); //°¡Àå ¿À·¡µÈ °ÍÀ» Áö¿î´Ù.
end;
end;
Result := MonArr[race].SurfaceList;
end;
procedure TMonsterImage.FreeMonster (race: integer);
var
i: integer;
list: TList;
begin
if MonArr[race].SurfaceList <> nil then begin
MonMemorySize := MonMemorySize - MonArr[race].ImageSize;
list := MonArr[race].SurfaceList;
for i:=0 to list.Count-1 do
TDGCSurface(list[i]).Free;
list.Free;
MonArr[race].SurfaceList := nil;
end;
end;
end.