代码

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#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和内容,并无任何创新。