popcap sexyframework - Demo1 基本框架

来源:互联网 发布:js页面时间格式化 编辑:程序博客网 时间:2024/05/17 22:11
// gameapp.h#ifndef __GAMEAPP_H__#define __GAMEAPP_H__//我们的游戏类必须从 SexyAppBase 类派生. 后者声明在这个头文件.#include "SexyAppFramework/SexyAppBase.h"// 声明我们定义在 Board.h 中的窗体部件类. class Board;//////////////////////////////////////////////////////////////////////////// 游戏类.// 直接从 SexyAppBase 派生. 并实现基类中的几个函数(做初始化,加载资源等工作).// 它的作用是创建窗体部件 Board (游戏的界面. 逻辑. 处理用户输入等等工作都由窗体部件来做)// 并且要加载程序中用到的资源.///////////////////////////////////////////////////////////////////////////class GameApp : public SexyAppBase{  Board*  mBoard;   //我们的窗体部件 public:  GameApp();  virtual ~GameApp();  //////////////////////////////////////////////////////////////////////////    // 初始化.  // 如果我们的程序要有一个前导. 放在这里.  // 框架会在这个函数返回后自动调用 后边的 LoadingThreadProc()  //////////////////////////////////////////////////////////////////////////  virtual void Init();  //////////////////////////////////////////////////////////////////////////  // 加载程序用到的资源  // 这个函数在一个单独的线程中进行.   // 如果加载时间稍长. 我们需要一个类似 " Loading ... "  的前导.  // 可以在这个函数中更新加载进度条.  // 这个函数执行完毕时. 框架自动调用后边的 LoadingThreadCompleted()  //////////////////////////////////////////////////////////////////////////    virtual void LoadingThreadProc();  //////////////////////////////////////////////////////////////////////////  // 资源全部加载完毕以后 应该执行的动作.  //////////////////////////////////////////////////////////////////////////    virtual void LoadingThreadCompleted();}; #endif // __GAMEAPP_H__//board.h#ifndef __BOARD_H__#define __BOARD_H__#include "SexyAppFramework/Widget.h"class Graphics;class GameApp;//////////////////////////////////////////////////////////////////////////// Board 类// 从 Widget 派生. 游戏的所有的功能. 游戏绘图,更新,处理输入. 都在这个类完成.// 因为Widget(窗口部件)被加入到 GameApp 的 WidgetManager 时. 会自动启动游戏的消息循环.// 自动调用Widget的 Update() 和 Draw(). 并在需要的时候处理用户输入. 每秒100帧.// 这样游戏的逻辑应该不能执行的太慢. //////////////////////////////////////////////////////////////////////////class Board : public Widget{  GameApp* mApp;  //持有主程序类的指针. 在本类中要调用GameApp的一些函数. public:  Board(GameApp* theApp){ mApp = theApp;}  virtual ~Board(){}  //////////////////////////////////////////////////////////////////////////  // 绘制  // 这个函数被 GameApp 的 WidgetManager 自动调用.  // 参数 g 用来在屏幕上绘制图像和文字  //////////////////////////////////////////////////////////////////////////  virtual void Draw(Graphics* g);  //////////////////////////////////////////////////////////////////////////  // 更新  // 这个函数被 GameApp 的 WidgetManager 自动调用. (每秒100次).  // 它处理游戏的逻辑.   //////////////////////////////////////////////////////////////////////////  virtual void Update();};#endif // __BOARD_H__//gameapp.cpp#include "GameApp.h"#include "Board.h"#include "SexyAppFramework/WidgetManager.h"#include "SexyAppFramework/Common.h"//SexyAppFramework 把所有的东西都声明在名字空间 Sexy 中. using namespace Sexy;//////////////////////////////////////////////////////////////////////////GameApp::GameApp(){ // 游戏的名字. 在内部使用. mProdName = "Demo 1"; // 版本 mProductVersion = "1.0"; // 游戏运行时. 在窗口的标题栏显示的内容 mTitle = StringToSexyStringFast("SexyAppFramework: " + mProdName + " - " + mProductVersion); // 注册表读写的路径 mRegKey = "PopCap\SexyAppFramework\Demo1"; // 设置宽高. 这些成员都是在GameApp的基类中定义的. mWidth = 640; mHeight = 480; // 窗体部件. 在后边的函数中创建窗体.  mBoard = NULL;}//////////////////////////////////////////////////////////////////////////GameApp::~GameApp(){ // 对所有的窗体部件来说. 在 delete 之前. 必须将之从 mWidgetManager 中 RemoveWidget(). // 否则运行的时候会有一个 assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard;}//////////////////////////////////////////////////////////////////////////void GameApp::Init(){ // 在这里总是必须先调用基类的 Init(). SexyAppBase::Init(); //在这个例子中. 我们的Init()无事可作. 但以后的例子中会使用它.  // 这个函数执行完后. 框架自动调用 LoadingThreadProc() 来加载资源.}//////////////////////////////////////////////////////////////////////////void GameApp::LoadingThreadProc(){ // 这个函数用一个单独的线程来加载资源. 并更新加载进度(如果有的话). // 在这个例子中. 它没有什么资源要加载. 但以后的例子中会使用它. // 它执行完毕后. 框架会自动调用 LoadingThreadCompleted().}//////////////////////////////////////////////////////////////////////////void GameApp::LoadingThreadCompleted(){ //调用基类的LoadingThreadCompleted() SexyAppBase::LoadingThreadCompleted(); // 当所有的资源加载都没有失败时. mloadingfailed被设置为false. 否则设置为 true. // 所以在这里要检查该变量. 若资源加载失败则返回.  if (mLoadingFailed)  return; // 创建我们定义的 Board 窗体部件. mBoard = new Board(this); // 设置窗体部件的大小和位置. 这个步骤不可以省略. 因为缺省时它们是0,0. 我们看不到. // 这里mBoard是我们的主窗口控件. 所以设置它的大小为 GameApp 的大小(mWidth, mHeight).  // 其中(mWidth, mHeight)我们已经在构造函数中指定了值. mBoard->Resize(0, 0, mWidth, mHeight); // 然后将刚才创建的窗体部件加入 mWidgetManager. // 这也是一个重要的步骤. 它意味着我们的 mBoard 对象从此可以自动的被调用 Update(). Draw(). 以及处理输入事件. mWidgetManager->AddWidget(mBoard);}//board.cpp#include "Board.h"#include "SexyAppFramework/Graphics.h"#include "SexyAppFramework/Color.h"     // 使用 Color 类.#include "SexyAppFramework/Point.h"  // 使用 Point 类.using namespace Sexy; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void Board::Update(){ // 调用基类的 Update(). 将会++mUpdateCnt. (它表示Update()被调用了多少次) // 因为这个函数每秒被调用100次. 所以我们也可以用 mUpdateCnt 的值做为游戏的计时器使用. Widget::Update(); // 下边这个函数告诉 widget manager 该部件已经变脏. 这样就会重画它. // 如果不需要重画(比如游戏变为不活动的)也可以不调用它. 节约一点cpu时间. MarkDirty();}// 绘制函数. 它自动被 WidgetManager 调用. 而且是自动双缓冲的. void Board::Draw(Graphics* g){ //填充矩形. //缺省时. 颜色是黑色.  g->FillRect(0, 0, mWidth, mHeight);  //设置当前颜色 g->SetColor(Color(255, 128, 64)); //Color可以有3个或4个参数.   //画线  //参数为X1, Y1, X2, Y2 g->DrawLine(0, 0, 200, 150); //绘制矩形(但不填充矩形内部) g->DrawRect(200, 150, (mWidth - 200) - 200, (mHeight - 150) - 150); //绘制多边形 // 先定义一个 Point数组. 保存多边形的每个顶点的坐标.  // 然后用 PolyFill() 来绘制多边形. Point trianglePoints[3]; trianglePoints[0] = Point(30, 30); trianglePoints[1] = Point(30, 60); trianglePoints[2] = Point(60, 45); g->SetColor(Color(255, 255, 0)); // yellow g->PolyFill(trianglePoints, 3);}// main.cpp #include "GameApp.h" using namespace Sexy;// 主函数// int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){  // 设置 gHInstance . 这个动作不能省略. gHInstance = hInstance; // 创建并初始化游戏主类. GameApp* anApp = new GameApp(); anApp->Init(); // 开始执行.  anApp->Start(); delete anApp; return 0;}