popcap sexyframework - Demo2 图像 声音 字体 窗体部件 按钮 事件 监听器

//board.h

#ifndef __BOARD_H__
#define __BOARD_H__

#include "SexyAppFramework/Widget.h" 
 
class Graphics; 
class GameApp;
 
class Board : public Widget
{ 
  GameApp* mApp;
  int   mPulseAmt;  // 一个在每次Update()时波动的值. 用于在Draw()时构造变化的颜色.
  bool  mIncPulse;  // 用来控制前边的 mPulseAmt 变大还是变小.
  

 public:
  Board(GameApp* theApp){
    mApp = theApp;
    mPulseAmt = 255;
    mIncPulse = false;
   }

  virtual ~Board(){}

  virtual void Draw(Graphics* g); 
  virtual void Update();

};

 

#endif // __BOARD_H__

//gameapp.h

#ifndef __GAMEAPP_H__
#define __GAMEAPP_H__
 

#include "SexyAppFramework/SexyAppBase.h"
  
class Board;
 
//图像和字体的类
class ImageFont;
class Image;

class GameApp : public SexyAppBase
{ 
 Board*  mBoard;  
public: 
 // 资源
 ImageFont* mTextFont;
 ImageFont* mNumberFont;

 Image*  mOpaqueBeamImg;
 Image*  mMoonImg;
 Image*  mTurbotImg;
public:
 GameApp();
 virtual ~GameApp();
  
 virtual void Init();
  
 virtual void LoadingThreadProc();
 
 virtual void LoadingThreadCompleted();

};
 

#endif // __GAMEAPP_H__

//board.cpp

#include "Board.h"
#include "GameApp.h"
#include "SexyAppFramework/Graphics.h"

// See the Draw method for more information on using the Color class.
#include "SexyAppFramework/Color.h"

// Why are we including ImageFont.h and not Font.h? Font.h is just a generic
// base class. ImageFont creates fonts from an image that contains all the
// text characters as well as a text file that indicates character widths
// and kerning information, as well as some more advanced features not used
// in this tutorial such as font layers, etc.
#include "SexyAppFramework/ImageFont.h"

// The Image.h file just declares basic functions. All images are either of 
// the DDImage or MemoryImage type. For this demo, we will use DDImage
// types, as they are the type returned by the image loading code.
// A DDImage is actually derived from MemoryImage, so where an Image or
// MemoryImage is required, a DDImage will suffice as well. A DDImage
// contains optimized code for use with DirectX 7+.
#include "SexyAppFramework/DDImage.h"

// The Rectangle template, used to specify X, Y, Width, Height
#include "SexyAppFramework/Rect.h"

// The SexyAppFramework resides in the "Sexy" namespace. As a convenience,
// you'll see in all the .cpp files "using namespace Sexy" to avoid
// having to prefix everything with Sexy::
using namespace Sexy;

 

void Board::Update()
{
 Widget::Update();

 // 这个函数每秒被调用100次. 每次更新 mPulseAmt 变量. 使其在0-255间变化.
 // 在后边 Draw() 时根据该变量的值绘画. 
 if (mIncPulse)
 {
  if (++mPulseAmt >= 255)
  {
   mIncPulse = false;
   mPulseAmt = 255;
  }
 }
 else
 {
  if (--mPulseAmt <= 0)
  {
   mIncPulse = true;
   mPulseAmt = 0;
  }
 }
 
 // mUpdateCnt 是Update()被调用的次数. 下边让它每2秒播放声音一次.
 if (mUpdateCnt % 200 == 0)
  mApp->PlaySample(1); //播放声音. 参数为GameApp::LoadingThreadProc()加载资源时指定的ID.
        //播放时还可以指定左右声道. 以及音量等. 这里就不演示了.

 // 使窗体组件变脏. 
 // 它经常在 Update() 中调用. 来要求屏幕重新绘制. (通常在更改了逻辑之后). 但也可以在其他函数中调用它. 
 MarkDirty();
}


void Board::Draw(Graphics* g)
{ 
 g->SetColor(Color(0, 0, 0));      //指定颜色为黑色. 用3个参数构造颜色时表示alpha为255.
 g->FillRect(0, 0, mWidth, mHeight);

 /////////////////////////////////////////////////////
 // 绘制文字. 
 // 在绘制之前. 我们要用 SetFont() 指定 Graphics 使用的字体. 
 // 并且要指定绘制文字使用的颜色. 缺省的是白色. 
 g->SetColor(Color(255, 0, 0));
 g->SetFont(mApp->mTextFont);
 g->DrawString(_S("Woo! Text! Ya!"), 10, 10); //这里指定的Y坐标为10. 
             //但实际绘制时. 不会从10开始. 
             //因为字体的基准Y位置有一些偏移.

 
 //为了演示. 现在我们为Graphics重新指定一种字体. 
 //在这个字体中只包含数字和几个符号. 可以查看其对应的资源文件图像. 
 //它只有 0123456789+-,;
 g->SetFont(mApp->mNumberFont);
 g->SetColor(Color(255, 255, 0));
 g->DrawString(_S("+200"), 10, 40);
 g->DrawString(_S("+200 pts"), 10, 60);       //可以看到.当字符串中包含字体中没有的字符时. 会跳过该字符.


 //SexString 是common.h中定义的一个typedef. 根据当前是否使用宽字符而表示string或wstring.
 SexyString myString = StrFormat(_S("You got %d points!"), 147);
 g->SetFont(mApp->mTextFont);
 g->DrawString(myString, 10, 80);
 g->SetColor(Color(0, 255, 0));
 // 我们也可以取得一个字符串在给定字体时的宽度(象素). 
 // 如下一行先用 mTextFont->StringWidth() 取得 myString 占的宽度. 然后在该位置绘制另一个字符串.
 g->DrawString(_S(" I am to the right of that previous string."), 10 + mApp->mTextFont->StringWidth(myString), 80);
  
 // 可以指定更多格式的绘制函数:

 // WriteString()
 // 它的最后一个参数可以为 -1, 0, 1 分别表示左/中/右对齐 
 WriteString(g, _S("Left justified at X of 200"), 200, 95, -1, -1);
 WriteString(g, _S("Centered using app width"), 0, 110, mWidth, 0);
 WriteString(g, _S("Centered using width of 200, X of 200"), 200, 125, mWidth, 1);

 //WriteWordWrapped() 
 //把要绘制的文字放入一个指定的举行区域.
 WriteWordWrapped(g, Rect(30, 140, 200, 400), _S("This is some text that is wrapped inside of the rectangle \
            at X of 30, Y of 140, width of 200, height of 400. It has \
            been wrapped using the default left justification and the \
            default line spacing."), -1, -1);

 

 ///////////////////////////////////////////////////
 //绘制图像


 // 最简单的: 只要指定图像的指针以及图像的位置.
 g->DrawImage(mApp->mTurbotImg, 230, 140);

 

 

 ///////////////////////////////////////////////////
 // 用指定的颜色绘制图像
 // 例如我们把上一个绘制的图像改成红色的. 
 // 需要注意的是: 
 //     1. 这种绘制比正常绘制图像要慢.
 //     2. 在绘制前要调用 g->SetColorizeImages(true); 
 //     3. 在改变颜色的绘制语句结束后. 要调用g->SetColorizeImages(false);
 // 指定要改变的颜色值.本例是红色.
 g->SetColor(Color(255, 0, 0));
 g->SetColorizeImages(true);
 g->DrawImage(mApp->mTurbotImg, 230, 140 + mApp->mTurbotImg->GetHeight());
 g->SetColorizeImages(false);

 //////////////////////////////////////////////////////
 // 附加绘制
 // 即在原有的图像上再绘制另一个图像.
 // 例如下边我们把这个图像画2次. 让它看起来明亮一些.
 // 需要注意的是. 附加绘制比前边的用指定颜色绘制. 还要慢些. 
 g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth(), 140);
 // 设置绘制模式为附加绘制
 g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); 
 g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth(), 140);
 // 设置绘制模式为正常绘制
 g->SetDrawMode(Graphics::DRAWMODE_NORMAL);

 

 /////////////////////////////////////////////////////////
 // 下一个是用附加绘制和指定颜色绘制结合起来的应用.
 // 它用一个不断变化的值来构造颜色. 再用该颜色附加绘制该图像. 
 // 使该图像的色彩不断变化.

 //先正常绘制一次
 g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth() * 2, 140);

 //再用指定颜色的方法 附加绘制一次.
 g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); 
 g->SetColor(Color(mPulseAmt, mPulseAmt, mPulseAmt));   //mPulseAmt在Update()中一直变化. 
 g->SetColorizeImages(true);
 g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth() * 2, 140);
 g->SetDrawMode(Graphics::DRAWMODE_NORMAL);
 g->SetColorizeImages(false);


 ////////////////////////////////////////////////
 // 使用 alpha 绘制
 // 下边的例子用指定颜色绘制时. 指定的颜色是半透明的白色. 
 // 这样绘制图像的效果是: 该图像也成为半透明的了.

 // 先绘制一副图像. 
 g->DrawImage(mApp->mMoonImg, 400, 300);
 // 再用半透明的办法绘制另一幅图像
 g->SetColor(Color(255, 255, 255, 60)); //指定一个半透明的白色.
 g->SetColorizeImages(true);
 g->DrawImage(mApp->mTurbotImg, 400, 300);  //用半透明的白色绘制图像。
 g->SetColorizeImages(false);

}

//gameapp.cpp

#include "GameApp.h"
#include "Board.h"
#include "SexyAppFramework/WidgetManager.h"

// 用 ImageFont.h 而不是 Font.h. 
// 因为 Font 是 ImageFont 的基类. ImageFont从图像创建字体. 
#include "SexyAppFramework/ImageFont.h"

// DDImage 类 派生自 MemoryImage类. 而 MemoryImage 派生自 Image 类. 
#include "SexyAppFramework/DDImage.h"

// 音效类
#include "SexyAppFramework/SoundManager.h"

using namespace Sexy;
 
GameApp::GameApp()
{
 mWidth = 800;
 mHeight = 600;

 mBoard = NULL;

 mTextFont = NULL;
 mNumberFont = NULL;
 mTurbotImg = NULL;
 mMoonImg = NULL;
 mOpaqueBeamImg = NULL;
}


//////////////////////////////////////////////////////////////////////////
GameApp::~GameApp()
{
 mWidgetManager->RemoveWidget(mBoard);
 delete mBoard;       //必须先执行上句


 delete mTextFont;
 delete mNumberFont;
 delete mTurbotImg;
 delete mMoonImg;
 delete mOpaqueBeamImg;

 mSoundManager->ReleaseSounds();   //释放所有音效占用的内存
}


void GameApp::Init()
{
 SexyAppBase::Init();
}

void GameApp::LoadingThreadProc()
{

 

 // You need to clean up the memory allocated by these functions yourself.
 // 加载图像资源很简单. 
 // 它支持的图像格式有: Targa, JPEG, PNG, GIF.
 // 加载时可以不指定扩展名. 而让程序自动判断. 例如:
 mOpaqueBeamImg = GetImage("images/beam_opaque");  //不指定扩展名. 而让程序自动判断.

 // 像 JPEG 这样的图片没有alpha信息. 所以用一个 "同名加_" 的黑白图像来做为它的alpha信息.
 // 缺省的. 加载一个图像时程序会自动检查该图像对应的alpha信息. 
 // 但现在用PNG格式的图像. 不用那么麻烦了.

 //另外. GetImage() 得到的图像的指针必须手动删除. 见本例子中的本类的析够函数.

 // 如果上一步中. 资源加载失败. GetImage()会返回 NULL.
 // 一定要检查这个返回值. 然后设置 mLoadingFailed 为true. 并返回错误信息退出. 
 if (mOpaqueBeamImg == NULL)
 {

  // PopUp() 相当于一个 MessageBox()
  Popup("There was an error loading the file: images/beam_opaque");
  mLoadingFailed = true;

  return;
 }

 mMoonImg = GetImage("images/moon");
 if (mMoonImg == NULL)
 {
  Popup("There was an error loading the file: images/moon");
  mLoadingFailed = true;
  return;
 }

 mTurbotImg = GetImage("images/turbot_worry");
 if (mTurbotImg == NULL)
 {
  Popup("There was an error loading the file: images/turbot_worry");
  mLoadingFailed = true;
  return;
 }

 //加载图像后应该调用它的 Palletize() 函数. 用来获得更好的性能.
 ((DDImage*)mOpaqueBeamImg)->Palletize();
 ((DDImage*)mMoonImg)->Palletize();
 ((DDImage*)mTurbotImg)->Palletize();


 ////////////////////////////////////////////////////
 // 加载字体
 // 每种字体资源由图像文件和文本文件组成. (两个文件名几乎相同. 除了图像文件名以_开始).
 // 加载时只要指出字体的文本文件名. 然后对应的图像文件也会被加载. 例如:
 mTextFont = new ImageFont(this, "fonts/Kiloton9.txt");

 //检查 mTextFont->mFontData->mInitialized 来确认字体是否加载成功.
 if (!mTextFont->mFontData->mInitialized) 
 {
  delete mTextFont;
  Popup("There was an error loading fonts/Kiloton9.txt");
  mLoadingFailed = true;
  return;
 }

 mNumberFont = new ImageFont(this, "fonts/supernova20.txt");
 if (!mNumberFont->mFontData->mInitialized) 
 {
  delete mNumberFont;
  Popup("There was an error loading fonts/supernova20.txt");
  mLoadingFailed = true;
  return;
 }

 //////////////////////////////////////
 // 加载声音
 // 如下例. 调用mSoundManager->LoadSound() 即可.
 // 参数为 该声音资源的ID(以后播放时就用该ID).  文件名. 
 // 文件名可以不指定格式. 而让程序自动识别. 支持的格式有 WAV, OGG, AU, MP3
 // 最后. 应该检查该函数的返回值. 确定声音文件是否加载成功.
 if (!mSoundManager->LoadSound(1, "sounds/timer"))
 {
  Popup("There was an error loading sounds/timer");
  mLoadingFailed = true;  
  return;
 }

 if (!mSoundManager->LoadSound(2, "sounds/mutator"))
 {
  Popup("There was an error loading sounds/mutator");
  mLoadingFailed = true;
  return;
 }
}

 

void GameApp::LoadingThreadCompleted()
{
 SexyAppBase::LoadingThreadCompleted();

 // 检查在 LoadingThreadProc() 的时候是否设置mLoadingFailed
 if (mLoadingFailed)
  return;

 // 创建主窗口部件.
 mBoard = new Board(this);
 mBoard->Resize(0, 0, mWidth, mHeight);

 mWidgetManager->AddWidget(mBoard);

 // 播放声音 ID为2
 PlaySample(2);
}

//main.cpp

//////////////////////////////////////////////////////////////////////////
// 本例子学习
//
// 加载/显示字体.
// 加载/显示图像
// 加载/播放声音
// 按钮 / 监听器 / 事件 
// * Colorizing images
// * Additive drawing
// * Palletizing images to use less RAM (when possible) 
// * Widget introduction: buttons, listeners, events, adding/removing
//////////////////////////////////////////////////////////////////////////

#include "GameApp.h"
 
using namespace Sexy;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{  
 gHInstance = hInstance; 
 GameApp* anApp = new GameApp();
 anApp->Init(); 
 anApp->Start();
 
 delete anApp; 
 return 0;
}

你可能感兴趣的:(popcap sexyframework - Demo2 图像 声音 字体 窗体部件 按钮 事件 监听器)