funcode综合教程 桌球

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#include "CommonAPI.h"
#include "LessonX.h"
#include
#include
int g_iPlayState= 0,g_iBallNumber=0;
double g_fRotateTime= 0.f;
double g_fHoleRollTime = 0.f,g_fOldRotation=0.f,fDeltaTime=0.001f;
char g_szBallName[64];
//float	g_fRotateTime;// 球杆拍下时,做个角度旋转,持续一小段时间,模拟拍下的动作
// 8个球洞当前的数字值,0 - 7来回滚动。对应的球数字打入对应的球洞才胜利
int		g_iHoleNumber[8];
char	g_szHoleName[8][64];			// 8个球洞的精灵名字
///////////////////////////////////////////////////////////////////////////////////////////
//
// 主函数入口
//
//////////////////////////////////////////////////////////////////////////////////////////
int PASCAL WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR     lpCmdLine,
                   int       nCmdShow)
{
    // 初始化游戏引擎
    if( !dInitGameEngine( hInstance, lpCmdLine ) )
        return 0;

    // To do : 在此使用API更改窗口标题
    dSetWindowTitle("Lesson");
    // 使用循环,给数组赋值:
// 将数组的8个值分别赋值0-7即可,无需随机。名字使用dMakeSpriteName分	// 别产生,为BallHole0 - BallHole7
// 球洞精灵预先摆放在场景中,因此不需要创建
    int	iLoop = 0;
    dSetSpriteVisible("win",0);
    for( iLoop = 0; iLoop < 8; iLoop++ )
    {
        g_iHoleNumber[iLoop]	=	iLoop;
        strcpy( g_szHoleName[iLoop], dMakeSpriteName( "BallHole", iLoop ) );
    }
    int	iNewBallNumber = dRandomRange( 0, 7 );

    if( iNewBallNumber != g_iBallNumber )
    {
        dSetSpritePositionY( g_szBallName, 50.f );
        // 新球,移动到屏幕中
        g_iBallNumber	=	iNewBallNumber;
        strcpy( g_szBallName, dMakeSpriteName("Ball", g_iBallNumber) );
        dSetSpritePositionX( g_szBallName, -30.f );
    }
// 在Y向上随机摆放球的出生位置,只随机Y方向坐标,不动X方向
    int	iPosY	=	dRandomRange( -25, 25 );
    dSetSpritePositionY(g_szBallName, (float)iPosY );
// 获取球拍的初始朝向,只做一次
    static int iInited = 0;
    if( !iInited )
    {
        iInited	=	1;
        g_fOldRotation	=	dGetSpriteRotation( "BallCue" );
        dShowCursor( 0 );
    }

    // 引擎主循环,处理屏幕图像刷新等工作
    while( dEngineMainLoop() )
    {
        // 获取两次调用之间的时间差,传递给游戏逻辑处理
        float	fTimeDelta	=	dGetTimeDelta();
        for(int iLoop = 0; iLoop < 8; iLoop++ )
        {
            g_iHoleNumber[iLoop]	=	iLoop;
            strcpy( g_szHoleName[iLoop], dMakeSpriteName( "BallHole", iLoop ) );
        }
        if( 0 == g_iPlayState )
        {
// 下面的代码,用于画出球前进方向的一段虚线
// 之前的案例里,有段画抛物线弹道轨迹的代码,比较复杂。这里画虚线比较		  // 简单,可以自己动手实现
// 获取球杆和球的位置
            float	fBallPosX	=	dGetSpritePositionX( g_szBallName );
            float	fBallPosY	=	dGetSpritePositionY( g_szBallName );
            float	fCuePosX	=	dGetSpritePositionX( "BallCue" );
            float	fCuePosY	=	dGetSpritePositionY( "BallCue" );
            //有A,B两点坐标,求两点间的向量 ==> B减去A得到一条由A指向B的向量。
            //下面的计算,得到一条球杆坐标指向球坐标的向量
            float	fVectorX	=	fBallPosX - fCuePosX;
            float	fVectorY	=	fBallPosY - fCuePosY;
            if( fVectorX > 0.001f || fVectorX < -0.001f || fVectorY > 0.001f || fVectorY < 			-0.001f )
            {
// 计算该向量的大小,以及将该向量单位化(sqrt函数是开平方函数,回想下	// 数学里如何求单位向量)
                float  fVectorSize = sqrt( fVectorX * fVectorX + fVectorY * fVectorY );
                float  fDirX	=  fVectorX / fVectorSize;
                float  fDirY	  =  fVectorY / fVectorSize;
                int		iLoop		= 0;
                float	fLastPosX	= fBallPosX, fLastPosY = fBallPosY;
                float	fNewPosX	= 0.f, fNewPosY = 0.f;
                float	fPosStep	= fVectorSize / 10.f;
                for( iLoop = 0; iLoop < 12; iLoop++ )
                {
                    // 新坐标等于前一坐标加上向量方向上的一个距离值
                    fNewPosX	=	fLastPosX + fDirX * fPosStep;
                    fNewPosY	=	fLastPosY + fDirY * fPosStep;
                    // 偶数段就画
                    if( iLoop % 2 == 0 )
                        dDrawLine( fLastPosX, fLastPosY, fNewPosX, fNewPosY, 2.f, 0, 0, 255, 0, 255 );
                    // 坐标往前移动(NewPos赋值给LastPos)
                    fLastPosX	=	fNewPosX;
                    fLastPosY	=	fNewPosY;
                }
            }
        }
        else
        {
            // 判断球是否位于球洞内。
            float	fVelX		=	dGetSpriteLinearVelocityX( g_szBallName );
            float	fVelY		=	dGetSpriteLinearVelocityY( g_szBallName );
            // 计算速度向量的大小.sqrt是开平方函数
            float	fSpeedValue	=	sqrt( fVelX * fVelX + fVelY * fVelY );
            if( fSpeedValue < 30.f )
            {
                float	fPosX	=	dGetSpritePositionX( g_szBallName );
                float	fPosY	=	dGetSpritePositionY( g_szBallName );
                if( dIsPointInSprite(g_szHoleName[g_iBallNumber], fPosX, fPosY ) )
                {
                    // 重新开始下一局
                    g_iPlayState = 1;
                    dSetSpriteVisible("win",1);
                    //return 0;
                }
                // 如果速度为0,则可以重新开始打球操作
                if( fSpeedValue < 0.50f )
                {
                    g_iPlayState = 0;
                }
            }

        }
        int	iLoop	= 0;
        int	iLastData	 =	0;
        float  fTempPosY	= 0.f;
        float  fLastPosY	=	0.f;
        char	 szLastName[64];
//iLoop是循环因子,iListData记录最后一个球洞的在m_iHoleNumber中的数值。
        // 隔一定时间滚动一次
        g_fHoleRollTime += fDeltaTime;
        if( g_fHoleRollTime > 1.f )
        {
            g_fHoleRollTime -= 1.f;
             // 取出最后一个值
        iLastData	=	g_iHoleNumber[7];
        fLastPosY	=	dGetSpritePositionY( g_szHoleName[7] );
        strcpy( szLastName, g_szHoleName[7] );
// 从后往前遍历数组。注意只需要做6次循环(iLoop由7递减至1)
        for( iLoop = 7; iLoop > 0; iLoop-- )
        {
            g_iHoleNumber[iLoop]	=	g_iHoleNumber[iLoop - 1];
            // 先保存需要更改坐标的精灵的Y坐标作为下一个精灵的坐标,然后再给它	// 赋值
            fTempPosY	=	dGetSpritePositionY( g_szHoleName[iLoop - 1] );
            dSetSpritePositionY( g_szHoleName[iLoop - 1], fLastPosY );
            fLastPosY 	=	fTempPosY;
            strcpy( g_szHoleName[iLoop], g_szHoleName[iLoop - 1] );
        }
// 将取出来的最后一个值赋值给第一个
        g_iHoleNumber[0]	=	iLastData;
        strcpy( g_szHoleName[0], szLastName );
        dSetSpritePositionY( g_szHoleName[0], fLastPosY );
        }

        // 执行游戏主循环
        GameMainLoop( fTimeDelta );
    };

    // 关闭游戏引擎
    dShutdownGameEngine();
    return 0;
}

//==========================================================================
//
// 引擎捕捉鼠标移动消息后,将调用到本函数
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseMove( const float fMouseX, const float fMouseY )
{
    // 可以在此添加游戏需要的响应函数
    dSetSpritePosition( "BallCue", fMouseX, fMouseY );
    OnMouseMove(fMouseX, fMouseY );
}
//==========================================================================
//
// 引擎捕捉鼠标点击消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{
    // 可以在此添加游戏需要的响应函数
    //printf("%d %d\n",iMouseType,g_iPlayState);
    if( 2 != iMouseType || 0 != g_iPlayState ){
        //return ;
    }
    g_iPlayState = 1;
    g_fRotateTime	=0.2f;
    dSetSpriteRotation( "BallCue", g_fOldRotation + 10.f );
    // 球的位置
    float	fPosX		=	dGetSpritePositionX( g_szBallName );
    float	fPosY		=	dGetSpritePositionY( g_szBallName );
    // 有A,B两点坐标,求两点间向量 ==> B减去A得到一条由A指向B的向量。
    // 下面的计算,得到一条鼠标坐标指向球坐标的向量
    float	fVectorX	=	fPosX - fMouseX;
    float	fVectorY	=	fPosY - fMouseY;
    // 将该向量放大,得到我们想要的速度
    fVectorX	*= 12.f;
    fVectorY	*= 12.f;
    // 给球设置该速度,以及设置一个速度衰减系数,使其逐渐停止
    dSetSpriteLinearVelocity( g_szBallName, fVectorX, fVectorY );
    dSetSpriteDamping( g_szBallName, 1.6f );
    // 球杆按下之后,做了个旋转。时间到了,将球杆复位
    if( g_fRotateTime > 0.f )
    {
        g_fRotateTime	-= fDeltaTime;
        if( g_fRotateTime <= 0.f )
        {
            // 球杆旋转复位
            dSetSpriteRotation( "BallCue", g_fOldRotation );
        }
    }


    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 )
{
    // 可以在此添加游戏需要的响应函数
    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(strcmp( szSrcName, g_szBallName )  ==  0  ||  strcmp( szTarName, g_szBallName ) == 0)
    {
        if( strstr( szSrcName, "VerSide" ) || strstr( szTarName, "VerSide" ) )
        {
            float	fVelX	=	dGetSpriteLinearVelocityX( g_szBallName );
            dSetSpriteLinearVelocityX( g_szBallName, fVelX * -1.f );
        }
        else if( strstr( szSrcName, "HorSide" ) || strstr( szTarName, "HorSide" ) )
        {
            float	fVelY	=	dGetSpriteLinearVelocityY( g_szBallName );
            dSetSpriteLinearVelocityY( g_szBallName, fVelY * -1.f );
        }
    }

    OnSpriteColSprite(szSrcName, szTarName);
}

//===========================================================================
//
// 引擎捕捉到精灵与世界边界碰撞之后,调用此函数.
// 精灵之间要产生碰撞,必须在编辑器或者代码里设置精灵的世界边界限制
// 参数 szName:碰撞到边界的精灵名字
// 参数 iColSide:碰撞到的边界 0 左边,1 右边,2 上边,3 下边
//
void dOnSpriteColWorldLimit( const char *szName, const int iColSide )
{
    // 可以在此添加游戏需要的响应函数
    OnSpriteColWorldLimit(szName, iColSide);
}

你可能感兴趣的:(funcode)