如何做资源文件,而资源文件不编译至可执行程序中去?(200分)

  • 主题发起人 主题发起人 redsky.l
  • 开始时间 开始时间
R

redsky.l

Unregistered / Unconfirmed
GUEST, unregistred user!
关于.res资源文件已经说了很多了,可恶的是可执行程序编译时,会把它编译进去,
试想:如果我做的.res文件是10M,那我的可执行程序不就是一只恐龙了呀!

除了.dll,还有什么更好的方式保护资源文件呢?很多游戏的可执行程序都不到1M,
不过它有一个.dat的文件或其他类似文件上百兆,它们是怎么做得的呢???
 
应该是把不同的文件拼起来,然后需要的时候用stream这样的类
把数据读出来再使用。
 
//除了.dll,还有什么更好的方式保护资源文件呢?
我个人认为,资源文件可以用很多很多的方法存放,如文本文件、二进制文件、数据
库文件等,主要的是看你的存取方法。例如我的软件要用到很多图片,可能这些图片
加起来有10M,我可以先把这些图以二进制形式存在*.dat(或其他扩展名)文件里,
或以Bolb的形式存在数据库里,在编程是动态的载入这些图。这就OK了。
 
Slong说的好!能否更清楚的说说或示例一下???
 
你试试HKStream这个控件。不过我试了,如果超过8M处理起来就有些困
难,因为它是用内存流来实现的。
支持压缩和加密。读写非常方便。
 
barton:哪里有呢?我想试试,做成几十个6M的文件应该不错吧!!
 
自己定义一个类 包含一个 FileStream 自己写入读出和维护资源
应该有定位索引表 用于文件内容的快速查找 当然了 空间是要多一些了
 
如果文件过大的话,强行使用TStream会造成系统反复写交换文件,造成
系统速度狂降,建议使用内存映射文件.
 
加分加分!!再加100分!!

请详述!原码!!
 
这是我一个游戏程序中调入数据文件的例程,实际上都是一些记录型的数据。
type
TEnemyAdvent = record
f: Integer; { Frame No }
c: TEnemyType; { Class Type }
x: Integer; { X }
y: Integer; { Y }
end;
var
EnemyAdventTable: array of TEnemyAdvent;

procedure InitializeDataFromFile;
var
i, DCount: integer;
Enemy: TEnemyAdvent;
eFile: file of TEnemyAdvent;
begin
try
AssignFile(eFile, DatFileName);//DatFileName--被调入的数据文件
ReSet(eFile);
{Object Count}
Read(eFile, Enemy);
DCount := Enemy.f;//总记录数

SetLength(EnemyAdventTable, DCount); //设置数据上标

{Data Objects}
for i := 0 to DCount - 1 do
begin
with Enemy do
begin
Read(eFile, Enemy);
EnemyAdventTable.f := f;
EnemyAdventTable.c := c;
EnemyAdventTable.x := x;
EnemyAdventTable.y := y;
end;
end;
{Data of Movement}
with Enemy do
begin
{Display Width/Height}
Read(eFile, Enemy);
FaceBit := iif(FaceBit = 0, f, iif(f <> FaceBit, FaceBit, f));
FaceWidth := iif(FaceWidth = 0, x, iif(x <> FaceWidth, FaceWidth, x));
FaceHeight := iif(FaceHeight = 0, y, iif(y <> FaceHeight, FaceHeight, y));
{PlayerSprite}
Read(eFile, Enemy);
iLPlayer := f;
iAPlayer := x;
iMPlayer := y;
iLife := iLPlayer;
{UFO}
Read(eFile, Enemy);
iLUFO := f;
iAUFO := x;
iMUFO := y;
{Attacker}
Read(eFile, Enemy);
iLAttacker := f;
iAAttacker := x;
iMAttacker := y;
{Boss}
Read(eFile, Enemy);
iLBoss := f;
iABoss := x;
iMBoss := y;
{Main Scene}
Read(eFile, Enemy);
PalleteDelay := f;
BounceSpeed := x;
BGScroll := y;
end;
finally
CloseFile(eFile);
end;
end;

这个过程实质上是把数据文件中的内容加载到一个记录型数据数组EnemyAdventTable中,
在此后任何调用的地方便无须对数据文件进行频繁的读写。

 
To:favinc

谢谢你的原码。只是我不能编译通过很多变量、函数都不可识别,不知你是用哪个版本
的Delphi。(如:TEnemyType不能识别;iif函数从未见过)

请再次指点!!
 
如果觉得资源太大,可以压缩后保存。需要时动态解压调入。
 
To redsky.1:
TEnemyType 是一个记录结构;
IIF 是一个自定义函数,相当于FOXPRO中的IIF函数;
SetLength 函数需要D4以上版本支持.

该程序段仅是演示一个读取过程,如果你需要更清楚的说明,我可以把完整的源代码发给你.
 
favinc:谢谢我用的D3,SetLength在中能用什么函数代替?

如果不麻烦请发:redsky.l@163.net 再次表示感谢!
 
动态连接库是最好的解决办法,没有比这个更能让你的主程序减肥的了!而且编辑方便,自己
在程序中切割文件固然可以达到同样效果,但是不利于后来对资源的改动!而且正如网友所说,
对于较大图象文件在用内存流操作时非常不便,且不说会有内存换页的问题,如果同时有好几
个程序用到该资源,那么在内存中就有该资源的多份拷贝,十分浪费内存。而用DLL就不会有
这个问题,增加几个引用计数就可以了,而且内存的回收和释放都由系统自动完成,不用担心
过多内存碎片的产生。我赞成用DLL。
 
我还是不想用DLL
 
有办法可以不将窗体文件编译到 Exe 中,
也就是发布时可以包括一个很大的 DFM 文件(改掉后缀名不知可不可以?)
我曾用这个方法来处理一张报表
但具体使用函数我忘记了,实在抱歉!(好象是 CreateComponentFromRes ???)
 
既然不想编译进可执行文件,就不要用资源文件了.
可以自己定义数据格式,用独立的数据文件
 
后退
顶部