//board.h
#ifndef __BOARD_H__
#define __BOARD_H__
#include "SexyAppFramework/Widget.h"
#include "SexyAppFramework/ButtonListener.h"
#include "SexyAppFramework/EditListener.h"
#include "SexyAppFramework/CheckboxListener.h"
#include "SexyAppFramework/ListListener.h"
class Graphics;
class GameApp;
class ButtonWidget;
class WidgetManager;
class Image;
//定义视差层结构体
struct ParallaxLayer
{
float mX;
float mY;
Image* mImage;
};
class Board : public Widget, public ButtonListener
{
GameApp* mApp;
ButtonWidget* mButton;
// 使用3层图片 (即一些背景靠前一些背景靠后. 移动的时候前边的背景移动较快)
struct ParallaxLayer mLayer[3];
public:
enum { OPTIONS_BUTTON_ID };
Board(GameApp* theApp);
virtual ~Board();
//
// 当有键盘键按下时调用.
virtual void KeyDown(KeyCode theKey);
//
// 它和KeyDown()不同. 它只能处理 ascii 输入
//virtual void KeyChar(char theChar);
virtual void Draw(Graphics* g);
virtual void Update();
virtual void ButtonDepress(int theId);
virtual void AddedToManager(WidgetManager* theWidgetManager);
virtual void RemovedFromManager(WidgetManager* theWidgetManager);
};
#endif // __BOARD_H__
//gameapp.h
#ifndef __GAMEAPP_H__
#define __GAMEAPP_H__
#include "SexyAppFramework/SexyAppBase.h"
class Board;
class TitleScreen;
class Dialog;
class GameApp : public SexyAppBase
{
Board* mBoard;
TitleScreen* mTitleScreen;
public:
GameApp();
virtual ~GameApp();
virtual void Init();
virtual void LoadingThreadProc();
virtual void LoadingThreadCompleted();
void TitleScreenIsFinished();
//
//我们经常需要调用基类的 SexyAppBase::DoDialog() 来创建对话框.
//而后者会调用虚函数 NewDialog(). 我们在此重写 NewDialog() 使其调用我们重写版的.
//这样我们可以在其中指定对话框的通用的皮肤等.
//该参数的意义参照 Dialog()构造函数的后几个参数.
virtual Dialog* NewDialog(int theDialogId, bool isModal, const std::string& theDialogHeader,
const std::string& theDialogLines, const std::string& theDialogFooter, int theButtonMode);
//
// 基类的函数. 用来设置是否3D 以及 是否全屏.
// 本例中我们在对话框中用一个单选框来设置/记录是否全屏.
// 但有这样一种可能: 该对话框显示的时候用户按 ALT+ENTER 来使程序全屏模式运行.
// 而这时对话框中的单选按钮的状态还没有被改变. 这就是要改写该函数的原因.
virtual void SwitchScreenMode(bool wantWindowed, bool is3d);
virtual void ButtonPress(int theId);
//
// 自定义的函数. 用来使 Board 部件获得焦点.
void SetFocusToBoard();
};
#endif // __GAMEAPP_H__
//demoDialog.h
//
// DemoDialog.h
// 这里示范如何自定义一个对话框.
// (如果是简单的 Yes/No/OK 消息框.
// 则只要重写app类的 NewDialog()并在需要的时候调用app的DoDialog()就可以了.
// 不必这么麻烦. )
//
#ifndef __DEMO_DIALOG_H__
#define __DEMO_DIALOG_H__
#include "SexyAppFramework/Dialog.h"
#include "SexyAppFramework/SliderListener.h"
#include "SexyAppFramework/CheckboxListener.h"
class Graphics;
// 滑动条部件. (这里用来控制音量).
class Slider;
// 使用DialogButton类而不是 ButtonWidget. 因为DialogButton可以自动使皮肤图片覆盖到按钮大小.
class DialogButton;
class Checkbox;
// 对话框从 Dialog 类派生.
class DemoDialog : public Dialog, public SliderListener, public CheckboxListener
{
//对话框中包含的部件们
Slider* mMusicVolumeSlider;
Slider* mSfxVolumeSlider;
DialogButton* mRandomBtn; // 生成随机数按钮
DialogButton* mClipBtn;
public:
// 部件ID使用的常数
enum{MUSIC_SLIDER_ID, SFX_SLIDER_ID, RANDOM_BTN_ID, CLIP_BTN_ID, FS_CHECKBOX_ID, HARDWARE_CHECKBOX_ID, MESSAGE_BOX_ID, DIALOG_ID};
Checkbox* m3DCheckbox; // 3D效果
Checkbox* mFSCheckbox; // 全屏效果
public:
// 构造
// 参数为 对话框的标题字符串. 对话框中的文字(文字可以换行).
DemoDialog(std::string theHeader, std::string theBody);
virtual ~DemoDialog();
// 重写基类的函数
virtual void Draw(Graphics* g);
virtual void Update();
virtual void ButtonDepress(int theId);
virtual void AddedToManager(WidgetManager* theWidgetManager);
virtual void RemovedFromManager(WidgetManager* theWidgetManager);
// 改变对话框大小时. 会调用该函数. 我们需要在此布局自定义对话框包含的部件们.
virtual void Resize(int theX, int theY, int theWidth, int theHeight);
//
// 滑动条部件有操作时. 会调用它来处理.
// 参数为 滑动条的ID, 当前值(从0到最大值).
virtual void SliderVal(int theId, double theVal);
//
// 单选框事件处理函数
void CheckboxChecked(int theId, bool checked);
};
#endif
// board.cpp
#include "Board.h"
#include "GameApp.h"
// Contains all the resources from the resources.xml file in our
// properties directory. See that file for more information.
#include "Res.h"
#include "SexyAppFramework/Graphics.h"
#include "SexyAppFramework/Color.h"
#include "SexyAppFramework/Rect.h"
#include "SexyAppFramework/ButtonWidget.h"
#include "SexyAppFramework/WidgetManager.h"
#include "SexyAppFramework/ImageFont.h"
#include "SexyAppFramework/Image.h"
// 本例子我们使用自定义的对话框类
#include "DemoDialog.h"
// 下边演示如何检测内存泄漏. 在每个要检测的文件中加上下边2句.
// 要注意的是这两句必须放在包含其他的头文件之后. 否则会产生编译/连接错误.
// 如果使用内存泄漏检测. 在程序结束时检测的结果会写入"mem_leaks.txt"文件.
#define SEXY_MEMTRACE
#include "SexyAppFramework/memmgr.h"
using namespace Sexy;
//
Board::Board(GameApp* theApp)
{
mApp = theApp;
mButton = NULL;
// 初始化3个视差层.
for (int i = 0; i < 3; i++)
{
mLayer[i].mX = 0;
// 设置 mLayer[i] 的图片. 例如第一层的图片ID是 IMAGE_BG1, 第二层是IMAGE_BG2...
std::string imageStringID = StrFormat("IMAGE_BG%d", i);
// 把上边构造的字符串ID映射到对应的整数ID. 函数 GetIdByStringId() 我们定义在res.cpp中
int id = GetIdByStringId(imageStringID.c_str());
// 通过该ID取得对应的图片对象的指针. 函数GetImageById() 我们也定义在res.cpp中.
mLayer[i].mImage = GetImageById(id);
mLayer[i].mY = (float)(mApp->mHeight - mLayer[i].mImage->GetHeight());
}
// 故意泄漏一块内存. 做为测试用.
int* aLeakedInteger = new int;
}
Board::~Board()
{
delete mButton;
}
void Board::Update()
{
Widget::Update();
MarkDirty();
}
void Board::KeyDown(KeyCode theKey)
{
// 当按下左右箭头时. 水平移动这3个层. 但每个层移动的速度不同.
if (theKey == KEYCODE_RIGHT)
{
for (int i = 0; i < 3; i++)
{
mLayer[i].mX -= 1.0f * (i + 1);
if (mLayer[i].mX <= -mLayer[i].mImage->GetWidth())
mLayer[i].mX = 0;
}
}
else if (theKey == KEYCODE_LEFT)
{
for (int i = 0; i < 3; i++)
{
mLayer[i].mX += 1.0f * (i + 1);
if (mLayer[i].mX >= mLayer[i].mImage->GetWidth())
mLayer[i].mX = 0;
}
}
}
void Board::Draw(Graphics* g)
{
g->SetColor(Color(0, 0, 0));
g->FillRect(0, 0, mWidth, mHeight);
for (int i = 0; i < 3; i++)
{
int imgWidth = mLayer[i].mImage->GetWidth();
// 设置新的绘制原点. 则绘制函数使用的(x,y)都是对这个点的偏移值.
g->TranslateF(mLayer[i].mX, mLayer[i].mY);
// 根据是否有3D加速. 使用不同的绘制函数.
if (mApp->Is3DAccelerated())
{
g->DrawImageF(mLayer[i].mImage, (float)-imgWidth, 0.0f);
g->DrawImageF(mLayer[i].mImage, 0.0f, 0.0f);
g->DrawImageF(mLayer[i].mImage, (float)imgWidth, 0.0f);
}
else
{
g->DrawImage(mLayer[i].mImage, -imgWidth, 0);
g->DrawImage(mLayer[i].mImage, 0, 0);
g->DrawImage(mLayer[i].mImage, imgWidth, 0);
}
// 将绘制原点移动回来..
g->TranslateF(-mLayer[i].mX, -mLayer[i].mY);
}
}
void Board::AddedToManager(WidgetManager* theWidgetManager)
{
Widget::AddedToManager(theWidgetManager);
mButton = new ButtonWidget(Board::OPTIONS_BUTTON_ID, this);
mButton->SetFont(FONT_DEFAULT);
mButton->mLabel = _S("Click Me!");
// 这次我们为按钮带点皮肤.
mButton->mOverImage = IMAGE_BUTTON_OVER; // 鼠标经过图片
mButton->mDownImage = IMAGE_BUTTON_DOWN; // 按钮按下图片
mButton->mButtonImage = IMAGE_BUTTON_NORMAL; // 正常按钮图片
mButton->mDoFinger = true; //允许鼠标移上时鼠标变为手形.
mButton->Resize(56, 5, IMAGE_BUTTON_NORMAL->GetWidth(), IMAGE_BUTTON_NORMAL->GetHeight());
theWidgetManager->AddWidget(mButton);
}
//
void Board::RemovedFromManager(WidgetManager* theWidgetManager)
{
Widget::RemovedFromManager(theWidgetManager);
theWidgetManager->RemoveWidget(mButton);
}
//
void Board::ButtonDepress(int theId)
{
if (theId == Board::OPTIONS_BUTTON_ID)
{
// 创建自定义的对话框.
DemoDialog* dlg = new DemoDialog("Header", "Hello! I am a dialog box.");
dlg->Resize(50, 50, 300, 400);
// 对于对话框. 我们不把它加入 WidgetManager. 而是调用如下函数:
mApp->AddDialog(DemoDialog::DIALOG_ID, dlg);
}
}
//gameapp.cpp
#include "GameApp.h"
#include "TitleScreen.h"
#include "Board.h"
#include "DemoDialog.h"
#include "SexyAppFramework/WidgetManager.h"
#include "SexyAppFramework/Checkbox.h"
// We will be accessing the resource manager in this demo, so include it's header
#include "SexyAppFramework/ResourceManager.h"
// Required for playing music
#include "SexyAppFramework/BassMusicInterface.h"
// Contains all the resources from the resources.xml file in our
// properties directory. See that file for more information.
#include "Res.h"
#include "SexyAppFramework/Dialog.h"
using namespace Sexy;
//
//
GameApp::GameApp()
{
mProdName = "Demo 5";
mProductVersion = "1.0";
mTitle = StringToSexyStringFast("SexyAppFramework: " + mProdName + " - " + mProductVersion);
mRegKey = "PopCap\SexyAppFramework\Demo5";
mWidth = 640;
mHeight = 480;
mAutoEnable3D = true;
mBoard = NULL;
mTitleScreen = NULL;
}
//
GameApp::~GameApp()
{
if (mBoard != NULL)
mWidgetManager->RemoveWidget(mBoard);
delete mBoard;
if (mTitleScreen != NULL)
mWidgetManager->RemoveWidget(mTitleScreen);
delete mTitleScreen;
mResourceManager->DeleteResources("Init");
mResourceManager->DeleteResources("TitleScreen");
mResourceManager->DeleteResources("Game");
}
//
void GameApp::Init()
{
SexyAppBase::Init();
//加载资源.
LoadResourceManifest();
if (!mResourceManager->LoadResources("Init"))
{
mLoadingFailed = true;
// 显示资源加载失败信息
ShowResourceError(true);
return;
}
if (!ExtractInitResources(mResourceManager))
{
mLoadingFailed = true;
ShowResourceError(true);
return;
}
if (!mResourceManager->LoadResources("TitleScreen"))
{
mLoadingFailed = true;
ShowResourceError(true);
return;
}
if (!ExtractTitleScreenResources(mResourceManager))
{
mLoadingFailed = true;
ShowResourceError(true);
return;
}
// 开始前导屏幕
mTitleScreen = new TitleScreen(this);
mTitleScreen->Resize(0, 0, mWidth, mHeight);
mTitleScreen->Init();
mWidgetManager->AddWidget(mTitleScreen);
mMusicInterface->LoadMusic(0, "music/music.mo3");
mMusicInterface->LoadMusic(1, "music/music.mo3");
mMusicInterface->FadeIn(0, 0, 0.002, false);
mNumLoadingThreadTasks = mResourceManager->GetNumResources("Game");
}
//
void GameApp::LoadingThreadProc()
{
// 加载资源
mResourceManager->StartLoadResources("Game");
while (mResourceManager->LoadNextResource())
{
mCompletedLoadingThreadTasks++;
if (mShutdown)
return;
mTitleScreen->MarkDirty();
}
if (mResourceManager->HadError() || !ExtractGameResources(mResourceManager))
{
ShowResourceError(false);
mLoadingFailed = true;
return;
}
}
//
void GameApp::LoadingThreadCompleted()
{
SexyAppBase::LoadingThreadCompleted();
if (mLoadingFailed)
return;
mTitleScreen->LoadingComplete();
mTitleScreen->MarkDirty();
}
//
void GameApp::TitleScreenIsFinished()
{
// 结束前导屏幕. 开始 board部件.
mTitleScreen = NULL;
mBoard = new Board(this);
// 释放前导屏幕使用的资源
mResourceManager->DeleteResources("TitleScreen");
mBoard->Resize(0, 0, mWidth, mHeight);
mWidgetManager->AddWidget(mBoard);
// 使输入焦点放在 mBoard 上.
mWidgetManager->SetFocus(mBoard);
// 淡出声音0.淡入声音1.
mMusicInterface->FadeOut(0, true, 0.004);
mMusicInterface->FadeIn(1, 9, 0.002, false);
}
//
// 改写基类的NewDialog()函数
// 这个函数会被基类的 DoDialog() 调用. 在这里我们可以设置对话框通用一些特征. 例如皮肤. 字体. 大小等.
Dialog* GameApp::NewDialog(int theDialogId, bool isModal, const std::string& theDialogHeader,
const std::string& theDialogLines, const std::string& theDialogFooter, int theButtonMode)
{
// 下边的 Dialog() 构造函数指定了对话框皮肤和按钮皮肤. 这样我们以后使用 YES/NO 对话框时就自动拥有这些皮肤了.
Dialog* d = new Dialog(IMAGE_DIALOG_BOX, IMAGE_DIALOG_BUTTON, theDialogId, isModal,
StringToSexyStringFast(theDialogHeader), StringToSexyStringFast(theDialogLines), StringToSexyStringFast(theDialogFooter), theButtonMode);
d->SetButtonFont(FONT_DEFAULT);
d->SetLinesFont(FONT_DEFAULT);
d->SetHeaderFont(FONT_DEFAULT);
d->SetColor(Dialog::COLOR_HEADER, Color::Black);
d->SetColor(Dialog::COLOR_LINES, Color::Black);
d->mSpaceAfterHeader = 30;
d->Resize(100, 100, 300, 250);
return d;
}
//
// 在设置3D模式 全屏模式 时. 我们想干点其他事...
void GameApp::SwitchScreenMode(bool wantWindowed, bool is3d)
{
SexyAppBase::SwitchScreenMode(wantWindowed, is3d);
// 根据对话框ID得到对话框的指针. 这需要调用 SexyAppBase::GetDialog().
DemoDialog* d = (DemoDialog*) GetDialog(DemoDialog::DIALOG_ID);
// 即使用户通过Alt+Enter的办法切换全屏/窗口模式. 也应该使单选框 mFSCheckbox 的状态和它保持一致.
if ((d != NULL) && (d->mFSCheckbox != NULL))
d->mFSCheckbox->SetChecked(!wantWindowed);
}
//
void GameApp::ButtonPress(int theId)
{
// 点对话框底部的按钮时. 关掉该对话框.
if (theId == DemoDialog::MESSAGE_BOX_ID + 2000)
KillDialog(theId - 2000); //关闭对话框.
}
//
void GameApp::SetFocusToBoard()
{
if (mBoard != NULL)
mWidgetManager->SetFocus(mBoard);
}
//demoDialog.cpp
#include "DemoDialog.h"
#include "Res.h"
#include "GameApp.h"
#include "SexyAppFramework/SexyAppBase.h"
#include "SexyAppFramework/WidgetManager.h"
#include "SexyAppFramework/Font.h"
#include "SexyAppFramework/DialogButton.h"
#include "SexyAppFramework/Checkbox.h"
#include "SexyAppFramework/Slider.h"
using namespace Sexy;
//
// 对话框的基类 Dialog 的构造函数参数:
// 对话框的外观图片 (本例中的图片在 images/dialog.gif)
// 对话框中按钮的图片(本例中的图片在 images/dialog_btn.gif)
// 对话框ID
// 是否模式对话框
// 对话框顶部文字
// 对话框中间文字(可以用 \n 分行)
// 如果允许最下部按钮( 即下一个参数是 Dialog::BUTTONS_FOOTER ). 这个参数是按钮上的文字.
// 最后一个参数是对话框带的默认按钮的风格: 可以是
// // BUTTONS_YES_NO //YES按钮的ID为: ID_YES //NO按钮的ID为: ID_NO
// // BUTTONS_OK_CANCEL //OK按钮的ID为: ID_OK //CANCEL按钮的ID为: ID_CANCEL
// // BUTTONS_NONE(没有默认按钮)
// // BUTTONS_FOOTER(对话框底部有一个按钮). //该按钮的ID为 ID_FOOTER
//
DemoDialog::DemoDialog(std::string theHeader, std::string theBody) :
Dialog(IMAGE_DIALOG_BOX, IMAGE_DIALOG_BUTTON, DemoDialog::DIALOG_ID, true, StringToSexyStringFast(theHeader), StringToSexyStringFast(theBody), _S("CLOSE"), Dialog::BUTTONS_FOOTER)
{
// 为对话框设置一个区域. 其中所有的文本/按钮等等都会被调整到该区域内.
mContentInsets = Insets(23, 20, 23, 20); // Insets()的参数表示区域到四边的距离
// 设置对话框中间的文字(参数theBody) 显示时距离标题栏的距离
mSpaceAfterHeader = 30;
// 设置对话框的 标题字体. 中间文字的字体. 按钮的字体.
SetHeaderFont(FONT_DEFAULT);
SetLinesFont(FONT_DEFAULT);
SetButtonFont(FONT_DEFAULT);
// 设置对话框使用的一些颜色.
SetColor(COLOR_HEADER, Color::Black);
SetColor(COLOR_LINES, Color::Black);
// 创建滑动条部件. Slider的构造函数参数分别是:
// 滑动路径图片. 滑块图片. 本部件ID, 监听者
mMusicVolumeSlider = new Slider(IMAGE_SLIDER_TRACK, IMAGE_SLIDER_THUMB, DemoDialog::MUSIC_SLIDER_ID, this);
// 设置滑块的当前位置值(范围在0.0 - 1.0 之间). 这里我们设置为当前的音量.
// 获取当前音量用 SexyAppBase::GetMusicVolume() 函数.
mMusicVolumeSlider->SetValue(gSexyAppBase->GetMusicVolume()); //对话框部件没有保存App的指针. 但可以使用声明在SexyAppBase.h文件的 gSexyAppBase
// 另一个滑动条部件
mSfxVolumeSlider = new Slider(IMAGE_SLIDER_TRACK, IMAGE_SLIDER_THUMB, DemoDialog::SFX_SLIDER_ID, this);
mSfxVolumeSlider->SetValue(gSexyAppBase->GetSfxVolume());
// 创建按钮. 使用 DialogButton 类 而不是它的父类 ButtonWidget.
// 构造函数参数为: 按钮图片. 按钮ID. 监听器
mRandomBtn = new DialogButton(IMAGE_DIALOG_BUTTON, DemoDialog::RANDOM_BTN_ID, this);
mRandomBtn->mLabel = _S("Random #");
mRandomBtn->SetFont(FONT_DEFAULT);
mClipBtn = new DialogButton(IMAGE_DIALOG_BUTTON, DemoDialog::CLIP_BTN_ID, this);
mClipBtn->mLabel = _S("Clipping");
mClipBtn->SetFont(FONT_DEFAULT);
m3DCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, DemoDialog::HARDWARE_CHECKBOX_ID, this);
mFSCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, DemoDialog::FS_CHECKBOX_ID, this);
}
//
//
DemoDialog::~DemoDialog()
{
delete mMusicVolumeSlider;
delete mSfxVolumeSlider;
delete mRandomBtn;
delete mClipBtn;
delete m3DCheckbox;
delete mFSCheckbox;
}
//
void DemoDialog::Draw(Graphics* g)
{
Dialog::Draw(g);
// 绘制几个文字.
g->SetFont(FONT_DEFAULT);
g->SetColor(Color::Black);
g->DrawString(_S("Music volume:"), mMusicVolumeSlider->mX - mX,
mMusicVolumeSlider->mY - mY - mMusicVolumeSlider->mHeight);
g->DrawString(_S("Sound volume:"), mSfxVolumeSlider->mX - mX,
mSfxVolumeSlider->mY - mY - mSfxVolumeSlider->mHeight);
g->DrawString(_S("3D Mode:"), m3DCheckbox->mX - mX, m3DCheckbox->mY - mY - m3DCheckbox->mHeight + 20);
g->DrawString(_S("Full Screen:"), mFSCheckbox->mX - mX, mFSCheckbox->mY - mY - mFSCheckbox->mHeight + 20);
// 在对话框的矩形区域之外绘制一点东西.
// 但只有当基类的 mClip 成员被设置时这些东西才能真正绘制到屏幕上.
g->SetColor(Color(255, 0, 0, 128));
g->FillRect(mWidth, mHeight, 100, 100);
g->FillRect(-100, -100, 100, 100);
g->SetColor(Color::Black);
g->DrawString(_S("Top left"), -90, -20);
g->DrawString(_S("Bottom right"), mWidth + 10, mHeight + 20);
}
//
void DemoDialog::Update()
{
Dialog::Update();
}
//
void DemoDialog::AddedToManager(WidgetManager* theWidgetManager)
{
Dialog::AddedToManager(theWidgetManager);
theWidgetManager->AddWidget(mMusicVolumeSlider);
theWidgetManager->AddWidget(mSfxVolumeSlider);
theWidgetManager->AddWidget(mRandomBtn);
theWidgetManager->AddWidget(mClipBtn);
int checkWidth = IMAGE_CHECKBOX->GetWidth() / 2;
m3DCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight());
m3DCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight());
mFSCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight());
mFSCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight());
m3DCheckbox->mChecked = gSexyAppBase->Is3DAccelerated();
mFSCheckbox->mChecked = !gSexyAppBase->mIsWindowed;
theWidgetManager->AddWidget(m3DCheckbox);
theWidgetManager->AddWidget(mFSCheckbox);
}
//
//
void DemoDialog::RemovedFromManager(WidgetManager* theWidgetManager)
{
Dialog::RemovedFromManager(theWidgetManager);
theWidgetManager->RemoveWidget(mMusicVolumeSlider);
theWidgetManager->RemoveWidget(mSfxVolumeSlider);
theWidgetManager->RemoveWidget(mRandomBtn);
theWidgetManager->RemoveWidget(mClipBtn);
theWidgetManager->RemoveWidget(m3DCheckbox);
theWidgetManager->RemoveWidget(mFSCheckbox);
}
//
//设置对话框大小时改变它的部件的布局.
void DemoDialog::Resize(int theX, int theY, int theWidth, int theHeight)
{
Dialog::Resize(theX, theY, theWidth, theHeight); //先调用基类的Resize()
// 调整每个部件的位置/大小. 使其适应对话框的 mContentInsets 区域.
mMusicVolumeSlider->Resize(theX + mContentInsets.mLeft,
theY + 140,
mWidth - mContentInsets.mLeft - mContentInsets.mRight,
IMAGE_SLIDER_THUMB->GetHeight());
// 用另一种方法布局部件.
// 这里设置第二个滑动条部件. 它和 mMusicVolumeSlider 的x坐标.宽度.高度一样. 只是Y坐标低一些.
// 所以这里根据 mMusicVolumeSlider 的位置来布局它.
mSfxVolumeSlider->Layout(LAY_SameLeft | LAY_Below | LAY_SameWidth | LAY_SameHeight,
mMusicVolumeSlider, 0, 40, 0, 0);
// 同样. 根据 mSfxVolumeSlider 的位置布局 mRandomBtn.
mRandomBtn->Layout(LAY_SameLeft | LAY_SameTop, mSfxVolumeSlider, 0, 40, 0, 0);
mRandomBtn->Resize(mRandomBtn->mX, mRandomBtn->mY,
mSfxVolumeSlider->mWidth / 2, IMAGE_DIALOG_BUTTON->mHeight);
// 再根据 mRandomBtn 的位置和 对话框mContentInsets的区域边界来调整 mClipBtn 部件的位置.
mClipBtn->Layout(LAY_Right | LAY_SameTop | LAY_SameWidth | LAY_SameHeight,
mRandomBtn, 0, 0, 0, 0);
//布局两个单选框
m3DCheckbox->Layout(LAY_SameLeft | LAY_Below, mRandomBtn, 0, 40, 0, 0);
m3DCheckbox->Resize(m3DCheckbox->mX, m3DCheckbox->mY,
IMAGE_CHECKBOX->mWidth / 2, IMAGE_CHECKBOX->mHeight);
mFSCheckbox->Layout(LAY_SameTop | LAY_SameWidth | LAY_SameHeight, m3DCheckbox);
mFSCheckbox->Layout(LAY_SameLeft, mClipBtn);
}
//
//处理滑动条事件
void DemoDialog::SliderVal(int theId, double theVal)
{
if (theId == DemoDialog::MUSIC_SLIDER_ID)
{
gSexyAppBase->SetMusicVolume(theVal);
}
else if (theId == DemoDialog::SFX_SLIDER_ID)
{
gSexyAppBase->SetSfxVolume(theVal);
// 当用户鼠标释放滑块时播放提示音.
if (!mSfxVolumeSlider->mDragging)
gSexyAppBase->PlaySample(SOUND_TIMER);
}
}
//
void DemoDialog::ButtonDepress(int theId)
{
Dialog::ButtonDepress(theId);
if (theId == mRandomBtn->mId) //按钮的ID记录在 ButtonWidget::mID .
{
// 点击 Random 按钮时. 生成一个随机整数.
int r = Rand();
// 并设置 该整数串做为对话框的 中间文字.
// 可以看出. 修改对话框的中的文字很容易. 只要修改 mDialogLines 成员即可.
mDialogLines = StrFormat(_S("Random number: %d"), r);
}
else if (theId == mClipBtn->mId)
{
// 点击这个按钮时我们设置基类的 mClip 成员(该成员声明在WidgetContainer类中).
// 当 mClip 关闭时我们可以在该部件的矩形区域之外绘制.
mClip = !mClip;
if (mClip)
mClipBtn->mLabel = _S("Clipping");
else
mClipBtn->mLabel = _S("No clipping");
}
else if (theId == ID_YES)
{
// 点击这个按钮将要关闭对话框. 在这里我们使用户的设置生效.
// 调用 app 的 SwitchScreenMode() 可以设置全屏/窗口模式. 以及是否3D.
gSexyAppBase->SwitchScreenMode(!mFSCheckbox->mChecked, m3DCheckbox->mChecked);
// 关掉对话框.
gSexyAppBase->KillDialog(this);
((GameApp*)gSexyAppBase)->SetFocusToBoard(); //设置焦点
}
}
//
// 处理单选框事件
void DemoDialog::CheckboxChecked(int theId, bool checked)
{
if (theId == m3DCheckbox->mId)
{
if (checked)
{
if (!gSexyAppBase->Is3DAccelerationSupported())
{
//如果3D不被支持. 则不设置该单选框. 并弹出一个对话框通知用户.
m3DCheckbox->SetChecked(false);
//调用 SexyAppBase::DoDialog() 来创建对话框.
//这个函数将调用 NewDialog() 来创建对话框. 而NewDialog()调用的是我们重写版的. 我们在其中指定了对话框的通用的皮肤等.
//参数的意义参照 Dialog()构造函数的后几个参数.
gSexyAppBase->DoDialog(DemoDialog::MESSAGE_BOX_ID, true, _S("Not Supported"),
_S("Hardware acceleration can not be enabled on this computer. \nYour\
video card does not meet the minimum requirements for this game."),
_S("OK"), Dialog::BUTTONS_FOOTER);
}
else if(!gSexyAppBase->Is3DAccelerationRecommended())
{
gSexyAppBase->DoDialog(DemoDialog::MESSAGE_BOX_ID, true, _S("Warning"),
_S("Your video card may not fully support this feature.\n\
If you experience slower performance, please disable Hardware Acceleration."),
_S("OK"), Dialog::BUTTONS_FOOTER);
}
}
}
else if (theId == mFSCheckbox->mId)
{
if (gSexyAppBase->mForceFullscreen && !checked)
{
gSexyAppBase->DoDialog(DemoDialog::MESSAGE_BOX_ID, true, _S("No Windowed Mode"),
_S("Windowed mode is only available if your desktop is running in\n\
either 16 bit or 32 bit color mode, which it is not."), _S("OK"), Dialog::BUTTONS_FOOTER);
mFSCheckbox->SetChecked(true);
}
}
}
//main.cpp
//
// 本例子学习:
//
// * Drawing differently if 3D or 2D
// * Using Translate instead of using XYs
// * 键盘输入. 设置输入焦点.
// * 学习新的部件: 对话框. 滑动条.
// * Advanced widget topics: mClip, using Layout_ flags, using images
// * 设置3D模式. 全屏模式. 设置音量.
// * Parallax scrolling
// * 随机数
// * 检测内存泄漏
// * Profiling
//
#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 - Demo5 键盘输入 对话框 滑动条 设置音量
最新推荐文章于 2019-09-12 18:44:56 发布