HGE教程翻译(6)

Tutorial 06 – 创建菜单

 

这个教程显示如何创建通用的GUI控制和菜单。

创建通用控制

首先我们定义控制类,从hgeGUIObject继承:

 

class hgeGUIMenuItem : public hgeGUIObject
     
{
     
public:
     
  hgeGUIMenuItem(int id, hgeFont *fnt, HEFFECT snd,
     
          float x, float y, float delay, char *title);
     

   
     
   
  virtual void  Render();
     
  virtual void  Update(float dt);
     

   
     
   
  virtual void  Enter();
     
  virtual void  Leave();
     
  virtual bool  IsDone();
     
  virtual void  Focus(bool bFocused);
     
  virtual void  MouseOver(bool bOver);
     

   
     
   
  virtual bool  MouseLButton(bool bDown);
     
  virtual bool  KeyClick(int key, int chr);
     

   
     
   
private:
     
  hgeFont       *fnt;
     
  HEFFECT       snd;
     
  float         delay;
     
  char          *title;
     

   
     
   
  hgeColor      scolor, dcolor, scolor2, dcolor2, color;
     
  hgeColor      sshadow, dshadow, shadow;
     
  float         soffset, doffset, offset;
     
  float         timer, timer2;
     
};
     

 

构造函数初始化数据成员id, bStatic, bVisible, bEnabled rect

 

hgeGUIMenuItem::hgeGUIMenuItem(int _id, hgeFont *_fnt,
     
                HEFFECT _snd, float _x, float _y,
     
                float _delay, char *_title)
     
{
     
  id=_id;
     
  fnt=_fnt;
     
  snd=_snd;
     
  delay=_delay;
     
  title=_title;
     

   
     
   
  color.SetHWColor(0xFFFFE060);
     
  shadow.SetHWColor(0x30000000);
     
  offset=0.0f; timer=-1.0f; timer2=-1.0f;
     

   
     
   
  bStatic=false; bVisible=true; bEnabled=true;
     

   
     
   
  float w=fnt->GetStringWidth(title);
     
  rect.Set(_x-w/2, _y, _x+w/2, _y+fnt->GetHeight());
     
}
     

 

Render函数是重点,每个控制都要定义它。

 

void hgeGUIMenuItem::Render()
     
{
     
  fnt->SetColor(shadow.GetHWColor());
     
  fnt->Render(rect.x1+offset+3, rect.y1+3, HGETEXT_LEFT, title);
     
  fnt->SetColor(color.GetHWColor());
     
  fnt->Render(rect.x1-offset, rect.y1-offset, HGETEXT_LEFT, title);
     
}
     

 

所有其他方法都是可选的,你可以不定义。


Update在每次GUI更新并需要渲染时调用。在这例子中我们有两个定时器根据时间调节颜色和位置,

 

void hgeGUIMenuItem::Update(float dt)
     
{
     
  if(timer2 != -1.0f)
     
  {
     
    timer2+=dt;
     
    if(timer2 >= delay+0.1f)
     
    {
     
      color=scolor2+dcolor2;
     
      shadow=sshadow+dshadow;
     
      offset=0.0f;
     
      timer2=-1.0f;
     
    }
     
    else
     
    {
     
      if(timer2 < delay) { color=scolor2; shadow=sshadow; }
     
      else {
     
        color=scolor2+dcolor2*(timer2-delay)*10;
     
        shadow=sshadow+dshadow*(timer2-delay)*10;
     
      }
     
    }
     
  }
     
  else if(timer != -1.0f)
     
  {
     
    timer+=dt;
     
    if(timer >= 0.2f)
     
    {
     
      color=scolor+dcolor;
     
      offset=soffset+doffset;
     
      timer=-1.0f;
     
    }
     
    else
     
    {
     
      color=scolor+dcolor*timer*5;
     
      offset=soffset+doffset*timer*5;
     
    }
     
  }
     
}
     

 

EnterGUI将要出现在屏幕上时调用。一个控制动画应该在这里进入:

 

void hgeGUIMenuItem::Enter()
     
{
     
  hgeColor tcolor2;
     

   
     
   
  scolor2.SetHWColor(0x00FFE060);
     
  tcolor2.SetHWColor(0xFFFFE060);
     
  dcolor2=tcolor2-scolor2;
     

   
     
   
  sshadow.SetHWColor(0x00000000);
     
  tcolor2.SetHWColor(0x30000000);
     
  dshadow=tcolor2-sshadow;
     

   
     
   
  timer2=0.0f;
     
}
     

 

LeaveGUI要从屏幕消失时调用。

 

void hgeGUIMenuItem::Leave()
     
{
     
  hgeColor tcolor2;
     

   
     
   
  scolor2.SetHWColor(0xFFFFE060);
     
  tcolor2.SetHWColor(0x00FFE060);
     
  dcolor2=tcolor2-scolor2;
     

   
     
   
  sshadow.SetHWColor(0x30000000);
     
  tcolor2.SetHWColor(0x00000000);
     
  dshadow=tcolor2-sshadow;
     

   
     
   
  timer2=0.0f;
     
}
     

 

IsDone用来检测这个控制是否完成Enter/Leave动画。完成返回true

 

bool hgeGUIMenuItem::IsDone()
     
{
     
  if(timer2==-1.0f) return true;
     
  else return false;
     
}
     

 

Focus当控制获得或失去键盘输入焦点时调用。

 

void hgeGUIMenuItem::Focus(bool bFocused)
     
{
     
  hgeColor tcolor;
     

   
     
   
  if(bFocused)
     
  {
     
    hge->Effect_Play(snd);
     
    scolor.SetHWColor(0xFFFFE060);
     
    tcolor.SetHWColor(0xFFFFFFFF);
     
    soffset=0;
     
    doffset=4;
     
  }
     
  else
     
  {
     
    scolor.SetHWColor(0xFFFFFFFF);
     
    tcolor.SetHWColor(0xFFFFE060);
     
    soffset=4;
     
    doffset=-4;
     
  }
     

   
     
   
  dcolor=tcolor-scolor;
     
  timer=0.0f;
     
}
     

 

MouseOver用来通知鼠标指针进入或离开它的区域。这里我们只设置输入焦点到控制当鼠标经过它时。

 

void hgeGUIMenuItem::MouseOver(bool bOver)
     
{
     
  if(bOver) gui->SetFocus(id);
     
}
     

 

MouseLButton当左键状态改变时调用。如果控制改变它的状态并希望通知调用者,应该返回true

 

bool hgeGUIMenuItem::MouseLButton(bool bDown)
     
{
     
  if(!bDown)
     
  {
     
    offset=4;
     
    return true;
     
  }
     
  else 
     
  {
     
    hge->Effect_Play(snd);
     
    offset=0;
     
    return false;
     
  }
     
}
     

 

KeyClick用来通知控制一个键被点击。如果控制改变它的状态并希望通知调用者,应返回true

 

bool hgeGUIMenuItem::KeyClick(int key, int chr)
     
{
     
  if(key==HGEK_ENTER || key==HGEK_SPACE)
     
  {
     
    MouseLButton(true);
     
    return MouseLButton(false);
     
  }
     

   
     
   
  return false;
     
}
     

 

现在我们有通用的控制行为定义了。

使用GUI

这里是简单部分。首先我们需要资源变量:

 

HEFFECT    snd;
     
HTEXTURE   tex;
     

   
     
   
hgeGUI     *gui;
     
hgeFont    *fnt;
     
hgeSprite  *spr;
     

 

WinMain中,在初始化过程中载入资源:

 

  snd=hge->Effect_Load("menu.wav");
     
  tex=hge->Texture_Load("cursor.png");
     

   
     
   
  fnt=new hgeFont("font1.fnt");
     
  spr=new hgeSprite(tex,0,0,32,32);
     

 

现在创建GUI并添加菜单部件。GUI控制在内部处理,你不需要关心。

 

  gui=new hgeGUI();
     

   
     
   
  gui->AddCtrl(new hgeGUIMenuItem(
     
               1,fnt,snd,400,200,0.0f,"Play"));
     
  gui->AddCtrl(new hgeGUIMenuItem(
     
               2,fnt,snd,400,240,0.1f,"Options"));
     
  gui->AddCtrl(new hgeGUIMenuItem(
     
               3,fnt,snd,400,280,0.2f,"Instructions"));
     
  gui->AddCtrl(new hgeGUIMenuItem(
     
               4,fnt,snd,400,320,0.3f,"Credits"));
     
  gui->AddCtrl(new hgeGUIMenuItem(
     
               5,fnt,snd,400,360,0.4f,"Exit"));
     

 

现在我们设置GUI模式,鼠标图象和默认键盘焦点,然后开始进入动画:

 

  gui->SetNavMode(HGEGUI_UPDOWN | HGEGUI_CYCLED);
     
  gui->SetCursor(spr);
     
  gui->SetFocus(1);
     
  gui->Enter();
     

 

现在看看我们如何更新菜单和接收通知。在FrameFunc中我们调用hgeGUI::Update来更新状态,它返回控制的鉴定值。如果所有的控制都完成离开动画,它返回-1。如果没有事情发生返回0

 

  int id;
     
  static int lastid=0;
     
  float dt=hge->Timer_GetDelta();
     

   
     
   
  id=gui->Update(dt);
     
  if(id == -1)
     
  {
     
    switch(lastid)
     
    {
     
      case 1:
     
      case 2:
     
      case 3:
     
      case 4:
     
        gui->SetFocus(1);
     
        gui->Enter();
     
        break;
     

   
     
   
      case 5: return true;
     
    }
     
  }
     
  else if(id) { lastid=id; gui->Leave(); }
     

 

RenderFunc中调用hgeGUI::Render来渲染菜单:

 

  hge->Gfx_BeginScene();
     
  gui->Render();
     
  hge->Gfx_EndScene();
     

 

菜单出现并运行。现在来到WinMain。程序结束时删除GUI并释放资源。

 

  delete gui;
     
  delete fnt;
     
  delete spr;
     
  hge->Texture_Free(tex);
     
  hge->Effect_Free(snd);
     
 

你可能感兴趣的:(timer,delete,Class,360,float,delay)