www.pudn.com > Map±à¼­Æ÷DELPHIÔ´´úÂë.rar > 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.