源码下载地址:
http://cid-620792b9d0909341.skydrive.live.com/self.aspx/.Public/src/飞机在关卡中上下左右移动.rar
//////////////////////////////////////////////////////////////////
// main.cpp
// 飞机在关卡中上下左右移动
#include <SexyAppBase.h>
#include <WidgetManager.h>
#include <ResourceManager.h>
#include <Widget.h>
#include <Image.h>
#include <SWTri.h>
#include "res/res.h"
#define ASSERT(value) if (!(value)) { _asm{int 3};}
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
const int Img_Width = 800;
const int Img_Hight = 2400;
const int LevelWidth = 700;
const int LevelHeight = 3000;
const int G_WINDOW_WIDTH = 550;
const int G_WINDOW_HEIGHT = 650;
Rect mColRect; //used for collision check
int mBackImagePos = 0; // 绘制地图时,取这个做为y 坐标
// 在窗体上画战争迷雾用这个坐标(mBackPos.mX, mBackFogPos)
// fog1 比fog2 下降的速度快两倍
// fog1 和fog2 使用的是同一张图片
int mBackFogPos = 0; // fog 1
int mBackFogPos2 = 0; // fog 2
// 窗体在关卡中的位置
// 实际上,在窗体上画地图是用这个坐标(mBackPos.mX, mBackImagePos)
Point mBackPos;
typedef TPoint<float> fPoint;
// player
fPoint mMapPos; // 飞机在关卡中的位置
fPoint mScrPos; // 飞机在窗口中的位置
const float mCVX = 2; // 飞机X 速度
const float mCVY = 2; // 飞机Y 速度
int mUpdateCnt;
enum
{
SCROLL_SPEED = 1,
UPDATE_FPS = 20, //20 fps
};
class CApp;
class CWidget : public Widget
{
public:
CWidget( CApp *app );
~CWidget();
void Draw( Graphics *g );
void Update();
public:
CApp *mApp;
};
class CWidget;
class CApp : public SexyAppBase
{
public:
CApp();
~CApp();
virtual void Init();
virtual void LoadingThreadProc();
virtual void LoadingThreadCompleted();
public:
Image* mMapImg;
CWidget* mWidget;
};
CApp::CApp()
{
mWidth = G_WINDOW_WIDTH;
mHeight = G_WINDOW_HEIGHT;
mTitle = "APP";
mNoSoundNeeded = true;
mAutoEnable3D = true;
mMapImg = NULL;
}
CApp::~CApp()
{
mWidgetManager->RemoveWidget(mWidget);
delete mWidget;
}
void CApp::Init()
{
SexyAppBase::Init();
}
void CApp::LoadingThreadProc()
{
//you must call this to enable all the transform function
SWTri_AddAllDrawTriFuncs();
//first, it should load resouces
LoadResourceManifest();
mResourceManager->StartLoadResources("Game");
while (mResourceManager->LoadNextResource())
{
mCompletedLoadingThreadTasks++;
//mLoadingWidget->MarkDirty();
}
if (mResourceManager->HadError() || !ExtractGameResources(mResourceManager))
{
ASSERT(false);
ShowResourceError(false);
mLoadingFailed = true;
return;
}
mMapImg = (Image*)GetImage("./data/images/map"); // /Debug/image/map.jpg // Debug 目录是生成的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);
}
CWidget::CWidget( CApp *app )
{
mApp = app;
// 窗体位于关卡的中间
mBackPos.mX = ( LevelWidth - G_WINDOW_WIDTH ) / 2; // 75
mBackPos.mY = LevelHeight - G_WINDOW_HEIGHT; // 2350
mBackFogPos = 0;
mUpdateCnt = 0;
// 初始化飞机数据
mColRect.mWidth = 64;
mColRect.mHeight = 58;
// 飞机在关卡的位置
mMapPos.mX = ( LevelWidth - mColRect.mWidth ) / 2; // 关卡中间
mMapPos.mY = LevelHeight - mColRect.mHeight; // 关卡底部
}
CWidget::~CWidget()
{
}
void CWidget::Draw( Graphics *g )
{
// 清屏,否则会有重影
g->SetColor( Color( 0, 0, 0 ) );
g->FillRect( 0, 0, mWidth, mHeight );
if (mBackImagePos + G_WINDOW_HEIGHT <= Img_Hight) // 从图片的y = mBackImagePos 的位置足够画一屏
{
// DrawImageF(img, 窗体坐标x, 窗体坐标y, Rect(图片坐标x, 图片坐标y, 宽, 高) )
g->DrawImageF( mApp->mMapImg, 0, 0, Rect( mBackPos.mX, mBackImagePos,
550, 650 ) );
}
else // 不够一屏,分两次画;先从y = mBackImagePos 画到 2400,然后不足的部分从 y = 0 处开始画
{
g->DrawImageF( mApp->mMapImg, 0, 0, Rect( mBackPos.mX, mBackImagePos,
550, Img_Hight - mBackImagePos) );
g->DrawImageF( mApp->mMapImg, 0, Img_Hight - mBackImagePos, Rect( mBackPos.mX, 0,
550, G_WINDOW_HEIGHT - (Img_Hight - mBackImagePos) ) );
}
// fog
if (mBackFogPos + G_WINDOW_HEIGHT <= BACK_FOG->GetHeight())
{
// X 值用mBackPos.mX 而不是0,因为要保证这张图与地图的相对位置固定不变
g->DrawImageF( BACK_FOG, 0, 0, Rect( mBackPos.mX, mBackFogPos,
G_WINDOW_WIDTH, G_WINDOW_HEIGHT ) );
}
else
{
g->DrawImageF( BACK_FOG, 0, 0, Rect( mBackPos.mX, mBackFogPos,
G_WINDOW_WIDTH, BACK_FOG->GetHeight() - mBackFogPos) );
g->DrawImageF( BACK_FOG, 0, BACK_FOG->GetHeight() - mBackFogPos, Rect( mBackPos.mX, 0,
550, G_WINDOW_HEIGHT - (BACK_FOG->GetHeight() - mBackFogPos) ) );
}
// fog 2
if (mBackFogPos2 + G_WINDOW_HEIGHT <= BACK_FOG->GetHeight())
{
// X 值用mBackPos.mX 而不是0,因为要保证这张图与地图的相对位置固定不变
g->DrawImageF( BACK_FOG, 0, 0, Rect( mBackPos.mX, mBackFogPos2,
G_WINDOW_WIDTH, G_WINDOW_HEIGHT ) );
}
else
{
g->DrawImageF( BACK_FOG, 0, 0, Rect( mBackPos.mX, mBackFogPos2,
G_WINDOW_WIDTH, BACK_FOG->GetHeight() - mBackFogPos2) );
g->DrawImageF( BACK_FOG, 0, BACK_FOG->GetHeight() - mBackFogPos2, Rect( mBackPos.mX, 0,
550, G_WINDOW_HEIGHT - (BACK_FOG->GetHeight() - mBackFogPos2) ) );
}
// Player
// 飞机要画在窗体的中间,X 坐标是窗体宽度的半 - 飞机宽度的一半
g->DrawImage( PLAYER_IMAGE, mScrPos.mX/*(G_WINDOW_WIDTH - mColRect.mWidth) / 2*/, mScrPos.mY, Rect(0,0,64,58) );
//g->DrawImage( mResMgr.mImage, mProperty.mScrPos.mX, mProperty.mScrPos.mY, Rect(0,0,64,58) );
}
void SetBackPosX( int xadd )
{
mBackPos.mX += xadd;
if( mBackPos.mX < 0 )
mBackPos.mX = 0;
if( mBackPos.mX > LevelWidth - G_WINDOW_WIDTH )
mBackPos.mX = LevelWidth - G_WINDOW_WIDTH;
}
void OnLeftKey()
{
// 更新飞机在关卡中的X 位置
mMapPos.mX -= mCVX;
if( mMapPos.mX < 0 )
mMapPos.mX = 0;
// 更新
SetBackPosX( -1 );
}
void OnRightKey()
{
// 更新飞机在关卡中的X 位置
mMapPos.mX += mCVX;
if( mMapPos.mX > LevelWidth - mColRect.mWidth)
mMapPos.mX = LevelWidth - mColRect.mWidth;
SetBackPosX( 1 );
}
void OnUpKey()
{
// 飞机在关卡中的Y 位置是不能小于窗口在关卡中的Y 位置的
// 这里,让飞机最小到窗口的 1 / 5 处
if( mMapPos.mY > mBackPos.mY + G_WINDOW_HEIGHT / 5 )
mMapPos.mY -= 2;
}
void OnDownKey()
{
// 飞机在关卡中的Y 位置是不能大于窗口在关卡中的Y 位置 + 一个窗口的高 - 飞机高度
if( mMapPos.mY < mBackPos.mY + G_WINDOW_HEIGHT - mColRect.mHeight )
mMapPos.mY += 2;
}
void LevelPosToScrPos( int mapX, int mapY )
{
// 窗体在关卡中的坐标 - 飞机在关卡中的坐标 = 飞机在窗口中的坐标
mScrPos.mX = mMapPos.mX - mapX;
mScrPos.mY = mMapPos.mY - mapY;
}
void CWidget::Update()
{
Widget::Update();
// 按键处理每秒一百次
if( mApp->mWidgetManager->mKeyDown[ KEYCODE_LEFT ] )
{
OnLeftKey();
}
if( mApp->mWidgetManager->mKeyDown[ KEYCODE_RIGHT ] )
{
OnRightKey();
}
if( mApp->mWidgetManager->mKeyDown[ KEYCODE_UP ] )
{
OnUpKey();
}
if( mApp->mWidgetManager->mKeyDown[ KEYCODE_DOWN ] )
{
OnDownKey();
}
// 计算飞机在窗口中的位置
LevelPosToScrPos(mBackPos.mX,mBackPos.mY );
// 地图位置更新每秒 5次
mUpdateCnt ++;
if( mUpdateCnt >= 100 / UPDATE_FPS)
{
mUpdateCnt = 0;
mBackImagePos -= SCROLL_SPEED;
if (mBackImagePos < 0)
{
mBackImagePos = Img_Hight - 1; // 注意不是2400,如果把地图卷成一个圆圈,y = 0 和 y = 2400 是同一个位置
}
// fog
mBackFogPos -= SCROLL_SPEED * 2;
if( mBackFogPos < 0 )
{
mBackFogPos = BACK_FOG->GetHeight() - 1;
}
// fog1
mBackFogPos2 -= SCROLL_SPEED * 3;
if( mBackFogPos2 < 0 )
{
mBackFogPos2 = BACK_FOG->GetHeight() - 1;
}
}
MarkDirty();
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
gHInstance = hInstance;
CApp *app = new CApp();
app->Init();
app->Start();
delete app;
return 0;
}
//////////////////////////////////////////////////////////////////