代码
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#include "CommonAPI.h"
#include "LessonX.h"
#include<bits/stdc++.h>
int g_iPlayState=0;
int g_iHookRotToLeft=0;
float g_fHookRotation=0.f,g_fVhook=120.f;
int g_iGoldCount=0;
int iInitedHookPos = 0,g_iGetGoldState=0;
float g_fHookStartPosX,g_fHookStartPosY,g_iGoldBornMinX,g_iGoldBornMaxX,g_iGoldBornMinY,g_iGoldBornMaxY;
void DrawHookLine();
float g_fEmptyHookSpeed=50.0f;
char g_szCurGetGold[128];
///
//
// 主函数入口
//
//
void Init()
{
g_iGoldCount=20;
g_iHookRotToLeft=0;
g_fHookRotation=dGetSpriteRotation("goldhook");
if( 0 == iInitedHookPos )
{
iInitedHookPos = 1;
// 钩子初始位置值初始化
g_fHookStartPosX = dGetSpritePositionX( "goldHook" );
g_fHookStartPosY = dGetSpritePositionY( "goldHook" );
// 金子可以出现的边界范围初始化
g_iGoldBornMinX = dGetScreenLeft() + 5;
g_iGoldBornMaxX = dGetScreenRight() - 5;
g_iGoldBornMinY = dGetScreenTop() + 20;
g_iGoldBornMaxY = dGetScreenBottom() - 5;
}
for(int i=0; i<g_iGoldCount; i++)
{
char szName[128];
sprintf(szName,"goldBlock%d",i);
dCloneSprite("goldTemplate",szName);
float iSize;
if(i>=0&&i<=9)
{
iSize=4.0f;
}
else if(i>=10&&i<=15)
{
iSize=6.0f;
}
else
{
iSize=8.0f;
}
dSetSpriteWidth(szName,iSize);
dSetSpriteHeight(szName,iSize);
float fPosX=dRandomRange(g_iGoldBornMinX,g_iGoldBornMaxX);
float fPosY=dRandomRange(g_iGoldBornMinY,g_iGoldBornMaxY);
dSetSpritePosition(szName,fPosX,fPosY);
}
dAnimateSpritePlayAnimation( "goldMan", "GolderManAnimation2", 0 );
}
void Run(float time)
{
if(g_iHookRotToLeft==1 && g_iGetGoldState==0)
{
g_fHookRotation+=time*g_fVhook;
if(g_fHookRotation>=180)
{
g_iHookRotToLeft=0;
g_fHookRotation=180;
}
}
else if(g_iHookRotToLeft==0 && g_iGetGoldState==0)
{
g_fHookRotation-=time*g_fVhook;
if(g_fHookRotation<=0)
{
g_iHookRotToLeft=1;
g_fHookRotation=0;
}
}
dSetSpriteRotation("goldhook",g_fHookRotation);
// 如果当前为钩子往回归位,则判断是否已经运动到终点。到了终点,则又开始摇// 摆、等待
if( 2 == g_iGetGoldState || 3 == g_iGetGoldState )
{
// 判断是否移动到终点(判断的依据是XY方向的移动速度为0,即金子是否 // 已经停止移动)
float fSpeedX = dGetSpriteLinearVelocityX( "goldhook" );
float fSpeedY = dGetSpriteLinearVelocityY( "goldhook" );
// 当前速度不为0,还在运动中
// 浮点数是否为0,不能直接判断 == != 0
if( fSpeedX > 0.00001f || fSpeedX < -0.00001f || fSpeedY > 0.00001f || fSpeedY < -0.00001f )
return;
// 速度为0,钩子回到初始点,开始下一轮的抓取
// 当前抓取到金子,将抓取到的金子释放并删除之。然后将金子数量减一
if( 3 == g_iGetGoldState )
{
g_iGoldCount--;
dSpriteDismount( g_szCurGetGold );
dDeleteSprite( g_szCurGetGold );
}
// 恢复等待状态与播放等待动作
g_iGetGoldState = 0;
dAnimateSpritePlayAnimation( "goldMan", "GolderManAnimation2", 0 );
}
}
int PASCAL WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 初始化游戏引擎
if( !dInitGameEngine( hInstance, lpCmdLine ) )
return 0;
// To do : 在此使用API更改窗口标题
dSetWindowTitle("Lesson");
// 引擎主循环,处理屏幕图像刷新等工作
while( dEngineMainLoop() )
{
// 获取两次调用之间的时间差,传递给游戏逻辑处理
float fTimeDelta = dGetTimeDelta();
DrawHookLine();
dSetTextValue("text",g_iGoldCount);
switch( g_iPlayState )
{
// 初始化游戏,清空上一局相关数据
case 1:
{
Init();
g_iPlayState = 2; // 初始化之后,将游戏状态设置为进行中
}
break;
// 游戏进行中,处理各种游戏逻辑
case 2:
{
// 金子数量大于0的时候,继续游戏
if( g_iGoldCount > 0 )
{
Run( fTimeDelta );
}
else
{
// 游戏结束。调用游戏结数函数并把游戏状态修改为结束状态
g_iPlayState = 0;
dSetSpriteVisible("GameBegin",1);
//GameEnd();
}
}
break;
// 游戏结束/等待按空格键开始
case 0:
default:
break;
};
// 执行游戏主循环
GameMainLoop( fTimeDelta );
};
// 关闭游戏引擎
dShutdownGameEngine();
return 0;
}
//==========================================================================
//
// 引擎捕捉鼠标移动消息后,将调用到本函数
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseMove( const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
OnMouseMove(fMouseX, fMouseY );
}
//==========================================================================
//
// 引擎捕捉鼠标点击消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
OnMouseClick(iMouseType, fMouseX, fMouseY);
}
//==========================================================================
//
// 引擎捕捉鼠标弹起消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
OnMouseUp(iMouseType, fMouseX, fMouseY);
}
//==========================================================================
//
// 引擎捕捉键盘按下消息后,将调用到本函数
// 参数 iKey:被按下的键,值见 enum KeyCodes 宏定义
// 参数 iAltPress, iShiftPress,iCtrlPress:键盘上的功能键Alt,Ctrl,Shift当前是否也处于按下状态(0未按下,1按下)
//
void dOnKeyDown( const int iKey, const int iAltPress, const int iShiftPress, const int iCtrlPress )
{
// 可以在此添加游戏需要的响应函数
if(KEY_SPACE==iKey && g_iPlayState==0)
{
g_iPlayState=1;
dSetSpriteVisible("GameBegin",0);
}
else if( KEY_DOWN == iKey && 2 == g_iPlayState && 0 == g_iGetGoldState )
{
// 设置抓取状态为:钩子往外伸
g_iGetGoldState = 1;
// 以当前朝向给钩子一个向前的速度
dSetSpriteLinearVelocityPolar("goldHook",g_fEmptyHookSpeed, g_fHookRotation );
// 播放挖金者的动作(一个胳膊往下压的动作)
dAnimateSpritePlayAnimation( "goldMan", "GolderManAnimation1", 0 );
}
OnKeyDown(iKey, iAltPress, iShiftPress, iCtrlPress);
}
//==========================================================================
//
// 引擎捕捉键盘弹起消息后,将调用到本函数
// 参数 iKey:弹起的键,值见 enum KeyCodes 宏定义
//
void dOnKeyUp( const int iKey )
{
// 可以在此添加游戏需要的响应函数
OnKeyUp(iKey);
}
//===========================================================================
//
// 引擎捕捉到精灵与精灵碰撞之后,调用此函数
// 精灵之间要产生碰撞,必须在编辑器或者代码里设置精灵发送及接受碰撞
// 参数 szSrcName:发起碰撞的精灵名字
// 参数 szTarName:被碰撞的精灵名字
//
void dOnSpriteColSprite( const char *szSrcName, const char *szTarName )
{
// 可以在此添加游戏需要的响应函数
// 首先判断钩子是否伸出,已经游戏是否真在进行,否则推出函数:
if( 2 != g_iPlayState || 1 != g_iGetGoldState ){
printf("return\n");
return ;
}
//判断是否是钩子与金子进行碰撞(即这两个名字字符串里必须一个是金子名,一 //个是钩子名)
if( stricmp("goldHook",szSrcName)!=0&&stricmp("goldHook",szTarName)!=0)
return;;
// 找到哪个是金子的名字
const char *szGoldName = NULL;
if( strstr( szSrcName, "goldBlock" ) )
szGoldName = szSrcName;
else if( strstr( szTarName, "goldBlock" ) )
szGoldName = szTarName;
else
return;
// 将金子挂接到钩子的2号挂接点上
dSpriteMountToSpriteLinkPoint( szGoldName, "goldHook", 2 );
// 设置抓取状态为:钩子往回收,抓取到东西。记录金子名字
g_iGetGoldState = 3;
memset(g_szCurGetGold,'\0',sizeof g_szCurGetGold);
strcpy( g_szCurGetGold, szGoldName );
// 根据金子大小,计算钩子的往回收的速度,越大的越慢。
// 算法:之前设置的金子大小为4,6,8,用10减去该大小再除以10,得到3个小// 数:0.6,0.4,0.2.该小数乘以空钩子的速度即得到挂接不同金子后的实际速度
float fWidth = dGetSpriteWidth( szGoldName );
float fSpeed = ((10.f - fWidth) / 10.f) * g_fEmptyHookSpeed;
// 钩子往初始位置移动
dSpriteMoveTo( "goldHook", g_fHookStartPosX, g_fHookStartPosY, fSpeed, 1);
// 播放挖金者的动作(胳膊来回动的动作)
dAnimateSpritePlayAnimation( "goldMan", "GolderManAnimation3", 0 );
OnSpriteColSprite(szSrcName, szTarName);
}
//===========================================================================
//
// 引擎捕捉到精灵与世界边界碰撞之后,调用此函数.
// 精灵之间要产生碰撞,必须在编辑器或者代码里设置精灵的世界边界限制
// 参数 szName:碰撞到边界的精灵名字
// 参数 iColSide:碰撞到的边界 0 左边,1 右边,2 上边,3 下边
//
void dOnSpriteColWorldLimit( const char *szName, const int iColSide )
{
// 可以在此添加游戏需要的响应函数
if(strcmp("goldhook",szName)==0){
g_iGetGoldState=2;
dSpriteMoveTo(szName,g_fHookStartPosX,g_fHookStartPosY,g_fEmptyHookSpeed,true);
dAnimateSpritePlayAnimation( "goldMan", "GolderManAnimation3", 0 );
}
OnSpriteColWorldLimit(szName, iColSide);
}
void DrawHookLine()
{
// 首先,从矿工精灵上获取一个缆绳链接点作为绳子的起始点(该链接点在编 // 辑器里编辑好)
float fStartX = dGetSpriteLinkPointPosX( "goldMan", 1 );
float fStartY = dGetSpriteLinkPointPosY( "goldMan", 1 );
// 绳子终点在钩子精灵上获取(该链接点在编辑器里编辑好)
float fEndX = dGetSpriteLinkPointPosX( "goldHook", 1 );
float fEndY = dGetSpriteLinkPointPosY( "goldHook", 1 );
// 在这两点之间划线.线的颜色红绿蓝值都为50,即灰色
dDrawLine( fStartX, fStartY, fEndX, fEndY, 2.f, 0, 50, 50, 50, 255 );
}
注
文章以提高篇内的教程为基础,仅实现了提高篇教程中所要求的内容,修改完善了其中的bug和内容,并无任何创新。