这些日志都是很早前陆续写的,拿出来分享经验:
2006-8-15
7:30开始学习HGE引擎。
从以前的接触中知道,HGE引擎基于DX8。
创建HGE最简单程序的步骤:
1. 定义HGE类型的指针,用来保存引擎指针。
2. 调用 hgeCreate函数得到HGE引擎指针----这是个标准的C语言函数,从以前阅读这个引擎的部分代码得知,引擎内部模仿了COM,采用引用计数的方式创建引擎对象。
3. 设置引擎状态值: System_SetState。在这里必须设置帧更新函数,这是必须的,这个引擎把消息循环隐藏了,程序的表面流程变为: mainàrenderFuncàend。当然程序底层还是一般的消息循环。设置了帧渲染函数后,引擎会不断地调用这个函数。
在这里还可以设置其他状态信息,如渲染状态,窗口尺寸,还可以设置是否需要LOG文件。
4. 调用System_Initiate函数初始化引擎。
5. 开始,System_Start。这个时候底层基本上就进入了消息主循环了
6. 在渲染函数里(渲染函数没有参数,返回值为布尔类型)返回TRUE时,底层消息循环就跳出。System_Start函数也返回了。
7. 调用System_Shutdown做一些恢复工作
8. 调用Release彻底销毁引擎。
9. 程度退出。
关于基本渲染图元(Quad is the basic HGE graphic primitive)hgeQuad对象。
文档里描述Quad is the basic HGE graphic primitive。HgeQuad是个结构体,里面保存着一个纹理对象的ID值,一个渲染模式值,和一个hgeVertex结构体,这个结构体里又包含了四个float和一个DWORD值。
如下:
struct hgeVertex{ float x, y; float z; DWORD col; float tx, ty;}; struct hgeQuad{ hgeVertex v[4]; HTEXTURE tex; int blend;};
其中,x,y被描述为屏幕坐标,tx,ty被描述为纹理坐标,col被描述为颜色。回忆下DX8中的做法:创建一组顶点,每个顶点包含了位置坐标,和纹理坐标(纹理坐标一般为0--1),还有颜色等信息,于是这里的情况也就很好理解了。
一个点在屏幕上有坐标,一个矩形区域需要把一张图片映射进来,如果采用纹理方式,就需要为每一个点指定一个二维的坐标。
如果我没推算错,那么在tutorial2中显示图片的原理,就是利用了渲染顶点的方式,而不是用D3Dsprite去渲染Texture的,同样的,texture还是不能自己渲染自己。
利用hgeQuad显示图片的过程:
1. 用Texture_Load载入外部文件作为纹理。
2. 设置hgeQuad的纹理坐标,窗口坐标,以及渲染模式。
3. 每一帧都调用 Gfx_RenderQuad函数
注意:设置纹理坐标以及窗口坐标时,v[0]表示左上角坐标,v[1]表示右上角坐标,v[2]表示右下角坐标,v[3]表示左下角坐标。我用了2个小时才发现这个。--当然这还是我的猜测,但是这样认为可以正确地贴图。
2006-8-16
利用hgeSprite和HTEXTURE也可以实现贴图。
步骤为:
1.HTEXTURE tex = hge->Texute_Load( filename );
2. hgeSprite *sprite = new hgeSprite( tex, 0, 0, 64, 64 );
3.sprite->Render( x, y )
载入一幅背景透明的PNG图片,用以上代码就可以实现透明传送。
3D里面没有颜色键,只有alpha-channel。通过对 sprite的color的alpha值进行设置,可以实现淡入淡出效果,quad的四个顶点的颜色进行设置也可以---两者底层其实都一样,都是设置顶点颜色。
HGE要显示文字,似乎只能载入 fnt 文件---fnt文件里又指定了 PNG图片,PNG图片里指定了各种字体,例如里面没有汉字,程序里就显示不出汉字。有点麻烦。
显示文字步骤:
1. New一个 hgeFont对象,构造函数传其fnt文件。
2. 设置文字颜色,以及缩放程度(SetScale)
3. 调用 printf 显示,或 Render。
通过使用 hgeSprite::SetFlip可以在Render的时候是水平翻转图象还是垂直翻转图象,还是两者都翻转。
可以动态设置 sprite的尺寸,以及texture ,从而达到用一个sprite去显示多个texture的目的,但是一定要注意在显示一幅texture时,必须重新设置textureRect。
如下代码所示:
g_sprite->SetTexture( g_texture );
g_sprite->SetColor( 0x55ffffff );
g_sprite->SetTextureRect( 0, 0, 64, 64 );
g_sprite->Render( 0, 0 );
g_font->printf( 0, 64, "alpha-blend" );
g_fishSpr->SetFlip( false, false );
g_fishSpr->SetColor( ARGB( 255, 255, 255, 255 ) );
g_fishSpr->Render( 100, 0 );
g_font->printf( 100, 100, "normal transparent" );
g_fishSpr->SetFlip( true, false );
g_fishSpr->Render( 0, 200 );
g_font->printf( 0, 300, "horizontally blit" );
g_sprite->SetTexture( g_fish );
g_sprite->SetColor( 0xffffffff );
g_sprite->SetTextureRect( 0, 0, 200, 180 );
g_sprite->Render( 200, 200 );
可以直接调用 hgeSprite::RenderEx进行缩放和旋转,如下代码为缩放一半:
g_sprite->SetTexture( g_fish );
g_sprite->SetColor( 0xffffffff );
g_sprite->SetTextureRect( 0, 0, 200, 180 );
g_sprite->RenderEx( 200, 200, 0, 0.5f );
所有sprite的默认blend mode都是全局的 BLEND_DEFAUT,即:BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE
FrameFunc如果放在类里,则必须是静态成员函数,否则编译器会报“编译器错误”之类的错误。但是如果它作为静态函数了,则很多类里的成员无法访问,好的方法是:创建一个桥梁全局函数,然后在Cgame::Init时传该函数指针过去,然后在 Init里就可以通过这个指针设置FrameFunc,这个桥梁函数,会显示地调用Cgame::FrameFunc ,后者才是真正有意义的帧处理函数。游戏运行时,引擎先调用那个桥梁函数,然后桥梁函数再调用那个类成员函数。(参看hge3代码)
使用HGE引擎的 Particle Editor可以很轻易地在程序里实现粒子系统。
大体步骤:
1.先用Particle Editor编辑好粒子系统
2.把对应的 psi 文件以及particle.png图片复制到自己的程序目录下。
4. 程序里new hgeParticleSystem对象,以及对应的sprite,和texture ,然后就可以fire启动粒子系统
5. 在FrameFunc里 hgeParticleSystem::Update,然后在渲染代码块里Render就可以了。
(大致原理,我猜测是:psi文件保存了粒子系统信息,其对应着要使用particle.png这个图片。创建sprite时具体指定使用哪部分,然后Update会更新粒子系统状态,Render时就用对应的PNG图片渲染出来。)
当hgeParticleSystem::GetAge == -2且hgeParticleSystem::GetParticlesAlive
== 0 时,表示这个粒子系统所有粒子都消失了,可以被删除了。
(2006-8-29,论坛上看到的:
1) Set hotspot of particle sprite in center (if width and height = 64, then hotspot of x and y must be 32).
2) Be sure that when you create hgeParticleManager, fps in parameter same as in particle editor.)
使用z-buffer可以方便地绘制各种精灵,z-buffer越大,就越后面,反之,就被绘制得越前面。要使用z-buffer,大致步骤为:
1. System_SetState时要让 HGE_ZBUFFER 为 TRUE。否则所有的z值都会被忽略。
2. 渲染时,因为纹理是靠精灵绘制出来的,所以这个时候只需要设置精灵的Z值: hgeSprite::SetZ即可。
3. 渲染。
(但是particle虽然也可以设置其内部的精灵Z值,但是显示出来就有问题。)
实验发现:HGE引擎里的 HGE::Timer_GetDelta()并不是我的FPS系统里的 SpeedFactor.
引擎里的Delta通常在0.006左右,而我的SpeedFactor一般为0.200。--数量级的差别。但是二者的作用似乎都是一样的。----去平衡速度与动画快慢。
2006-8-18
关于引擎中的鼠标输入:
鼠标坐标,只需要调用Input_GetMousePos函数即可,所得到的坐标是相对于窗口左上角的局部坐标。
而按键状态可以直接通过Input_GetKeyState( HGEK_LBUTTON );之类的代码得到。
Input_GetMouseWheel是用来得到鼠标滚轮状态的。
窗口程序下,当鼠标指针移动到窗口外时,GetMousePos函数得到的坐标始终是移开前那个坐标。
HGE用精灵贴图,即使给的坐标为负数,也能被贴出来----支持裁减。(偶尔会出现闪烁的黑线)
音乐播放,可以直接使用Effect_Load函数调用,这种方法适用ogg, mp3, wav 等。该引擎不能播放MID。但是可以把MID转换为XM文件播放。
2006-8-23
关于鼠标按键检测:在每一帧里,我都会调用Input_GetKeyState(HGEK_LBUTTON )函数来检测按键状态,实验表明,当我只按一下鼠标左键时,记录的数据也表明这个状态被多次检测到。在使用时,最好设置个时间标志变量----在一段时间内,无论按键多少次,也只算做一次。
Timer_GetTime()返回的是秒,小数点后精确到毫秒级---还要高些。
2006-8-24
Effect_PlayEx返回的是HCHANNEL类型的变量,根据这个变量可以继续控制其播放属性,而控制播放中的声音属性的一组函数是以Channel开头的。
2006-8-25
Effect_Play每次返回的Channel值是不一样的,即使是播放同一个HEFFECT。
2006-8-27(HGE154)
关于数据打包并读取,最简单的方法是:用winrar压缩数据为zip格式,可以加密码,然后在程序里m_hge->Resource_AttachPack( "data", "kevinlynx" );关联数据文件,然后以后加载图片,声音等数据文件时,给的路径为文件在zip里的路径即可自动载入。
引擎里的很多加载资源函数都有这么个描述:
If filename specifies relative path, texture file is first searched within all resource packs attached with Resource_AttachPack, then in the application disk folder. If filename specifies absolute disk path, texture file is loaded directly from disk.
2006-8-31
关于Resource Script File可以具体参看Resource Manager.doc文件。
2006-9-3
关于HGE里的GUI系统。
要使用按钮控件,做以下几步:
1. 创建hgeGUI对象,该对象会管理所有的控件
2. 创建一个按钮纹理,其格式包含两幅横向放着的图象,一幅用于按钮未按下时的外观,一幅用于按下时的外观:The texture must hold two images, one for the button in the unpressed state, and directly to the right from it, the image for the button in pressed state.
3. 把创建的按钮加入hgeGUI对象。
4. 在每一帧里调用hgeGUI::Update,在渲染里hgeGUI::Render。
5. 可以通过hgeGUIButton::GetState来得到按钮是否被按下。
注意:HGE里的按钮,只有当鼠标按下时才会改变外观显示。当鼠标指针放在其上时,它不改变状态。对于按钮如果SetMode( true )了,按钮将变为一个类似RadioButton的控件。当hgeGUI对象被删除时,其AddCtrl加进来的对象会被自动删除。
要使用文本控件,同使用按钮控件一样,不同的是,文本控件需要个hgeFont对象,文本控件被初始化后,改变hgeFont对象,也会对文本控件产生作用。
虽然HGE引擎的GUI很简单,但是其扩展性很好。因为hgeGUI::Update基本上派发了所有控件需要的消息---键盘操作,以及鼠标操作;而hgeGUIObject基类的很多成员函数都会处理这些消息,我们只需要派生hgeGUIObject,然后重载我们需要的消息处理即可。这样我们很容易地就可以设计出各种GUI控件。
2006-9-30
关于hgeParticleManager,可以把很多粒子系统加进去让它自动管理,使用SpawnPS来加入粒子,第一个参数可以直接从hgeParticleSystem->info得到。然后再每一帧里Update,然后Render。hgeParticleManager会管理这一切。
2006-10-1
关于ini文件操作:
所有操作ini文件的函数都有这三个参数:1,section.2,name. 3,value,查看一个DEMO ini文件便可知道它们三个的含义:
[snd_shoot] //section
volume=30 //name = value
要注意的,要使用ini文件,需要设置一个引擎状态:HGE_INIFILE
2006-10-1
hgeAnimation也可以指定在资源脚本文件里,不过使用这个类要注意的是:需要调用Play来开启动画。
Hge154这样的代码可以把开始LOGO去掉:
m_hgeEngine->System_SetState((hgeIntState)14, 0xFACE0FF);
2006-10-4
Gfx_SetTransform函数是相对于整个屏幕而言的,它可以让整个屏幕的内容旋转与缩放,但是不能操作局部范围!
使用target:可以在同一帧里先把需要绘制的纹理绘制到target上,然后用函数Target_GetTexture得到target的纹理,再把该纹理配合sprite即可绘制出来---当offscreen使用!
注意:Gfx_BeginScene不能嵌套使用。
2006-10-15
在创建hgeSprite对象时,给其指定纹理坐标时,例如:
Sp = new hgeSprite( tex, 0, 0, 32, 32 );
在绘制 sp 时,不会绘制 (0, 0, 32, 32 ) 0, 32, 32, 32以及 32, 0, 32, 32这两条线。
2006-11-10
HGE引擎的学习以及使用到今天就结束了。以后开始学着用ClanLib,多学习几个开源的引擎,到时候才能取众家之长,写出自己的引擎。
2006-12-27
hgeSprite::GetBoundingBox返回的是hgeSprite拥有的纹理的矩形范围。该矩形永远都是正立的,它不会因为精灵旋转而旋转。
2007-3-15
关于Gfx_SetClipping函数,当设置裁减矩形为 ( 100, 100, 300, 200 )时,绘制图形在 (100, 100 )处绘制不出,而在(100+300, 100+200)处则能绘制出。也就是说,可以被显示的区域为:(101, 101, 100 + 300, 100 + 200 ) (包括这里列出的坐标本身)。当其宽度或高度为0时,该函数可能会设置失败,从而导致重新设置为整个渲染对象。
关于Gfx_RenderQuad函数,如果设置的矩形区域为(100, 200, 100, 200 ),绘制时,不会绘制横坐标为100这条线。也不会绘制纵坐标为200这条线,但是可以横坐标方向可以绘制到100+99处,纵坐标也是。
关于Gfx_RenderLine函数,该函数忽略最后一个点。
2007-5-13
关于Texture_Lock函数,即使lock的是纹理上的一部分,在获取纹理上的一点颜色信息时:
lock_ptr[ y * width + x ]
其中width是该纹理整个的宽度,而不是lock的宽度!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kevinlynx/archive/2007/06/20/1659734.aspx