// 地图卷动
#include <Widget.h>
#include <Graphics.h>
#include <SexyAppBase.h>
#include <Common.h>
#include <DDImage.h>
#include <Image.h>
#include <WidgetManager.h>
#include <Common.h>
using namespace Sexy;
#pragma comment( lib, "winmm.lib" )
#pragma comment( lib, "wsock32.lib" )
#ifdef _DEBUG
#pragma comment( lib, "SexyAppFramework_D.lib" )
#else
#pragma comment( lib, "SexyAppFramework.lib" )
#endif
#define ASSERT(value) if (!(value)) { /
_asm{int 3};}
const int G_WINDOW_WIDTH = 550;
const int G_WINDOW_HEIGHT = 650;
class CApp;
class CLevelMgr;
class CWidget : public Widget
{
public:
CWidget( CApp *app );
~CWidget();
void Draw( Graphics *g );
void Update();
public:
CApp *mApp;
CLevelMgr *mLevelMgr;
};
class CWidget;
class CLevelMgr
{
public:
enum
{
SCROLL_SPEED = 1,
UPDATE_FPS = 20, //20 fps
};
public:
CLevelMgr( CWidget *gameWidget );
~CLevelMgr();
void Draw( Graphics *g );
bool Update();
public:
CWidget *mWidget;
int mUpdateCnt;
private:
int mBackImagePos;
};
class CApp : public SexyAppBase
{
public:
CApp();
~CApp();
virtual void Init();
virtual void LoadingThreadProc();
virtual void LoadingThreadCompleted();
public:
DDImage* mMapImg;
CWidget* mWidget;
};
CWidget::CWidget( CApp *app )
{
mApp = app;
mLevelMgr = new CLevelMgr( this );
Resize( 0, 0, mWidth, mHeight );
}
CWidget::~CWidget()
{
delete mLevelMgr;
}
void CWidget::Draw( Graphics *g )
{
g->SetColor( Color( 0, 0, 0 ) );
g->FillRect( 0, 0, mWidth, mHeight );
mLevelMgr->Draw( g );
}
void CWidget::Update()
{
Widget::Update();
mLevelMgr->Update();
MarkDirty();
}
// size of map.jpg
const int Img_Width = 800;
const int Img_Hight = 2400;
CLevelMgr::CLevelMgr( CWidget *widget )
{
mWidget = widget;
mUpdateCnt = 0;
mBackImagePos= 0;
}
CLevelMgr::~CLevelMgr()
{
}
void CLevelMgr::Draw( Graphics *g )
{
if( gSexyAppBase->Is3DAccelerated() )
{
// 图片从pos 位置足够截一屏的长度,就直接画
if( mBackImagePos + G_WINDOW_HEIGHT < Img_Hight )
{
//blt directly
g->DrawImageF( mWidget->mApp->mMapImg, 0, 0, Rect( 0, mBackImagePos,
G_WINDOW_WIDTH, G_WINDOW_HEIGHT ) );
}
else // 否则,先从pos 处截到尾,再从开头截一部分直到满屏
{
//should do more details
g->DrawImageF( mWidget->mApp->mMapImg, 0, 0, Rect( 0, mBackImagePos,
G_WINDOW_WIDTH, Img_Hight - mBackImagePos ) );
g->DrawImageF( mWidget->mApp->mMapImg, 0, Img_Hight - mBackImagePos + 0/*mYOffset*/,
Rect( 0, 0, G_WINDOW_WIDTH,
G_WINDOW_HEIGHT - ( Img_Hight - mBackImagePos )) );
}
}
}
bool CLevelMgr::Update()
{
mUpdateCnt ++;
if( mUpdateCnt < 100 / UPDATE_FPS ) // UPDATE_FPS = 20 // 20 fps // Widget 的update() 每秒调用100 次
return false; // 如果每调用一次就更新一次,则FPS(刷新速度)为100 次/秒
// 调用2 次,更新1 次,FPS = (100/2)次 /秒 = 50 次/秒
// 调用n 次,更新1 次,FPS = (100/n)次 /秒,既FPS = 100 / n
// 现在我们想要 FPS = 20, 则 n = 100 / FPS,应该每隔 100 / FPS 次,进行一次刷新操作
mUpdateCnt = 0; // 进行一次刷新,计数器清零
mBackImagePos -= SCROLL_SPEED; // SCROLL_SPEED = 1 // 卷动速度,FPS = 20,所以每秒卷动20 个单位(这里是像素)
if( mBackImagePos < 0 ) // 关卡管理器的构造函数将mBackImagePos 初始化为 0
{
mBackImagePos = Img_Hight - 1; // 图片高Img_Hight = 2400; // 所以,程序开始时,mBackImagePos = 2399,从地图的y = 2399 处开始截一个窗口高度的像素显示。
// 实际是从 2399 - 2400 画一像素,接下来从0 - 648 再取649 象素 // 窗口高为650
}
return false;
}
CApp::CApp()
{
// 初始窗口化宽高mWidth,mHeight(只是SexyAppBase 的成员变量,当全局变量用。真正的窗口宽高通过CWidget::Resize() 设置)
mWidth = G_WINDOW_WIDTH; // 550
mHeight = G_WINDOW_HEIGHT; // 650
mTitle = "APP"; // 标题
mNoSoundNeeded = true; // 不再需要Bass.dll
mAutoEnable3D = true;
// 内存图像指针设为NULL
mMapImg = NULL; // DDImage* CApp::mMapImg; // 内存图像
}
CApp::~CApp()
{
mWidgetManager->RemoveWidget(mWidget);
delete mWidget;
}
void CApp::Init()
{
SexyAppBase::Init();
}
// 图片声音等资源在这里加载,由此启动的loading 线程还可以更新"进度指示器"
void CApp::LoadingThreadProc()
{
mMapImg = (DDImage*)GetImage("./image/map"); // 图片从exe 所在目录搜索
ASSERT(mMapImg != NULL);
}
void CApp::LoadingThreadCompleted()
{
SexyAppBase::LoadingThreadCompleted();
if (mLoadingFailed)
return;
mWidget = new CWidget(this);
mWidget->Resize(0, 0, mWidth, mHeight);
mWidgetManager->AddWidget(mWidget);
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
gHInstance = hInstance;
CApp *app = new CApp();
app->Init();
app->Start();
// SexyAppBase::Start() 将调用以下函数:
// CApp::LoadingThreadProc() // 图片声音等资源在这里加载,由此启动的loading 线程还可以更新"进度指示器"
// CApp::LoadingThreadCompleted() // “主widget 类”(负责所有绘制和更新输入处理),在这里初始化;还有处理已加载的资源,如图片颜色。
// CWidget::Update() // 此函数由引擎每秒调用100 次
// CWidget::Draw() // 和Update 的调用先后(应该是Upadate 在前),第秒多少次是一个迷
delete app;
return 0;
}