当前位置:   article > 正文

创建HGE最简单程序的步骤:_hge创建button

hge创建button
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 个小时才发现这个。--当然这还是我的猜测,但是这样认为可以正确地贴图。

  利用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文件保存了粒子的动作、生命周期等信息。创建sprite时具体指定使用哪部分,然后Update会更新粒子系统状态,Render时就用对应的PNG图片渲染出来。)

  当hgeParticleSystem::GetAge == -2且hgeParticleSystem::GetParticlesAlive

  == 0 时,表示这个粒子系统所有粒子都消失了,可以被删除了。

  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_r()并不是我的FPS系统里的 SpeedFactor.

  引擎里的Delta通常在0.006左右,而我的SpeedFactor一般为0.200。--数量级的差别。但是二者的作用似乎都是一样的。 ----去平衡速度与动画快慢。

  2006-8-18

  关于引擎中的鼠标输入:

  鼠标坐标,只需要调用Input_GetMousePos函数即可,所得到的坐标是相对于窗口左上角的局部坐标。

  而按键状态可以直接通过Input_ GetKeyState_r( HGEK_LBUTTON );之类的代码得到。

  Input_GetMouseWheel是用来得到鼠标滚轮状态的。

  窗口程序下,当鼠标指针移动到窗口外时,GetMousePos函数得到的坐标始终是移开前那个坐标。

  HGE用精灵贴图,即使给的坐标为负数,也能被贴出来----支持裁减。(偶尔会出现闪烁的黑线)

  音乐播放,可以直接使用Effect_Load函数调用,这种方法适用ogg, mp3, wav 等。该引擎不能播放MID。但是可以把MID转换为XM文件播放。

  关于鼠标按键检测:在每一帧里,我都会调用Input_ GetKeyState_r(HGEK_LBUTTON )函数来检测按键状态,实验表明,当我只按一下鼠标左键时,记录的数据也表明这个状态被多次检测到。在使用时,最好设置个时间标志变量----在一段时间内,无论按键多少次,也只算做一次。

  Timer_ GetTime_r()返回的是秒,小数点后精确到毫秒级---还要高些。

  Effect_PlayEx返回的是HCHANNEL类型的变量,根据这个变量可以继续控制其播放属性,而控制播放中的声音属性的一组函数是以 Channel开头的。

  Effect_Play每次返回的Channel值是不一样的,即使是播放同一个HEFFECT。

  关于数据打包并读取,最简单的方法是:用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.

  关于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控件。

  关于hgeParticleManager,可以把很多粒子系统加进去让它自动管理,使用SpawnPS来加入粒子,第一个参数可以直接从 hgeParticleSystem->info得到。然后再每一帧里Update,然后Render。hgeParticleManager会管理这一切。

  hgeAnimation也可以指定在资源脚本文件里,不过使用这个类要注意的是:需要调用Play来开启动画。

  Hge154这样的代码可以把开始LOGO去掉:

  m_hgeEngine->System_SetState((hgeIntState)14, 0xFACE0FF);

  Gfx_SetTransform函数是相对于整个屏幕而言的,它可以让整个屏幕的内容旋转与缩放,但是不能操作局部范围!

  使用target:可以在同一帧里先把需要绘制的纹理绘制到target上,然后用函数Target_GetTexture得到target的纹理,再把该纹理配合sprite即可绘制出来---当offscreen使用!

  注意:Gfx_BeginScene不能嵌套使用。

  在创建hgeSprite对象时,给其指定纹理坐标时,例如:

  Sp = new hgeSprite( tex, 0, 0, 32, 32 );

  在绘制 sp 时,不会绘制 (0, 0, 32, 32 ) 0, 32, 32, 32以及 32, 0, 32, 32这两条线。

  HGE引擎的学习以及使用到今天就结束了。以后开始学着用ClanLib,多学习几个开源的引擎,到时候才能取众家之长,写出自己的引擎。

  hgeSprite::GetBoundingBox返回的是hgeSprite拥有的纹理的矩形范围。该矩形永远都是正立的,它不会因为精灵旋转而旋转。

  关于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函数,该函数忽略最后一个点。

  关于Texture_Lock函数,即使lock的是纹理上的一部分,在获取纹理上的一点颜色信息时:

  lock_ptr[ y * width + x ]

  其中width是该纹理整个的宽度,而不是lock的宽度!

  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wenzhoufeng22/archive/2008/04/25/2326437.aspx

  关于RPG类型游戏制作的一些构想 收藏

  你准备好一些素材后,你便可以开始进行最基本的设计了。呵呵,我并不反对很多人边准备素材边制作游戏,其实这也不错,至少可以给你一个继续做下去的动力。当然,假如你做RPG游戏仅仅只是为了好玩的话。

  RPG游戏制作中,比较麻烦的两个问题,一个是场景的安排及人物的操作;另一个便是剧情与游戏两种模式间的切换。对于后者,我们放到其它的文章里再讨论(因为这个问题比较复杂),我们这篇贴子里面要讨论的,主要是关于第一个问题,也就是场景的安排及人物的操作方面的问题。

  先来看地图场景的布局。

  在很古老的时候(其实也就是上个世纪未了),人们想出了一个办法,那就是采用类似于拼图的方式进行设计。将地图和场景前景都制作成一个个大小完全相同的小画片,然后分别将每个画片都编上号(例如,1号代表土地,2号代表小坑,3号代表水,4号代表……),然后便用一个比较大的二维数组(什么叫数组,不是吧!连这个都不知道还想做RPG游戏呀)来记录地图的信息,其实就是记录一些编号,在游戏初始化的时候就跟据这些编号将那些小画片一块块的拼起来形成最终的地图场景。这是一个伟大的想法,至少,在《沙丘魔堡》没有出现之前都还是非常伟大的。什么,你不知道什么是《沙丘》?!呵呵,也难怪,那已经是很古老的游戏了。不提它也罢。

  那么,为什么说《沙丘》的出现意义重大呢?(其实我也不知道是不是从它开始的,只是在我的记忆里面,它算是最早的吧)。因为《沙丘》里采用的是对象的方式进行地图的拼接,没有玩过《沙丘》的人想的话应该也知道《星际》吧。在进行地图编辑的时候,大家会发现,地图初化化的时候是整版的单一颜色。然后再加入一些树,建筑等等,最后才形成大家看到的地图的。没错,这就是采用对象列表的方式来表现的地图。而且这也是现在依然流行在2D游戏界的地图制作方式。

  这种地图的制作原理其实很简单。地面是一个二维数组,和前面一样,同样记录一些图片的编号(例如:陆地,水面,空间等),而地面上的物件却是另一个对象列表,它里面记录的是每一个对象所在的 X 轴 和Y 轴的起点坐标,也就是说,每放置一个对象,其实只是在列表中加入了一句话:X起点,Y起点,对象编号。仅此而已。那么,这些东西怎么会变成最终的地图的呢?!在游戏初始化的时候,先将地面那个二维数组存入内存,并找出相应的图片形成地表。接下来就从库里面将相应的对象都复制出来放置于相应的坐标所对应的位置,当然了,这对象也就包括了主角和一些NPC人物。这也就是时下比较流行的地图制作方式了。

  不过,如果是用程序设计语言来完成上面的这些是很简单的事情,只要用好内存,对于CPU的运算是相当小的,因为图形的运算可以通过程序设计让显卡控制芯片来帮忙完成。所以大家也不会发现这样做所带来的系统变慢的情况。

  可是,在Flash 里面,这种方式去是无法进行的。按一般形为标准,如果在同一屏幕内显示出来的对象总数大于 600 个的话,那么整个动画的显示速度将会变得奇慢无比(不信大家可以试试,不要静止的,要运动的那种),所以,在Flash上进行地图制作的话,最变通的做法便是将地图场景单独的制作成一张JPG或PNG格式的图片,然后将前景对象采用从库里复制的方式进行。这样一来,要展示一张地图的话,就不需要用到多达 600 个的元件同屏显示了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/103425
推荐阅读
相关标签
  

闽ICP备14008679号