Funcode实现打飞虫1

简介: Funcode实现打飞虫1


前言:
        1、相较于文档给出的,优化了单身二十年手速所造成的问题(包括中心点问题)

        2、优化了连续点击拍子的效果不佳的问题

 

效果图:

精灵总览

背景图层数设置为0

空格开始

倒计时

拍子

 分数

 时间

 蚊子

 名字

 代码:
Main.cpp
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------

include "CommonClass.h"

include "LessonX.h"

///////////////////////////////////////////////////////////////////////////////////////////
//
// 主函数入口
//
//////////////////////////////////////////////////////////////////////////////////////////
int PASCAL WinMain(HINSTANCE hInstance,

               HINSTANCE hPrevInstance,
               LPSTR     lpCmdLine,
               int       nCmdShow)

{

// 初始化游戏引擎
if( !CSystem::InitGameEngine( hInstance, lpCmdLine ) )
    return 0;

// To do : 在此使用API更改窗口标题
CSystem::SetWindowTitle("LessonX");

// 引擎主循环,处理屏幕图像刷新等工作
while( CSystem::EngineMainLoop() )
{
    // 获取两次调用之间的时间差,传递给游戏逻辑处理
    float    fTimeDelta    =    CSystem::GetTimeDelta();

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

// 关闭游戏引擎
CSystem::ShutdownGameEngine();
return 0;

}

//==========================================================================
//
// 引擎捕捉鼠标移动消息后,将调用到本函数
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void CSystem::OnMouseMove( const float fMouseX, const float fMouseY )
{

// 可以在此添加游戏需要的响应函数
g_GameMain.OnMouseMove(fMouseX, fMouseY);

}
//==========================================================================
//
// 引擎捕捉鼠标点击消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void CSystem::OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{

// 可以在此添加游戏需要的响应函数
g_GameMain.OnMouseClick(iMouseType, fMouseX, fMouseY);

}
//==========================================================================
//
// 引擎捕捉鼠标弹起消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void CSystem::OnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY )
{

// 可以在此添加游戏需要的响应函数
g_GameMain.OnMouseUp(iMouseType, fMouseX, fMouseY);

}
//==========================================================================
//
// 引擎捕捉键盘按下消息后,将调用到本函数
// 参数 iKey:被按下的键,值见 enum KeyCodes 宏定义
// 参数 iAltPress, iShiftPress,iCtrlPress:键盘上的功能键Alt,Ctrl,Shift当前是否也处于按下状态(0未按下,1按下)
//
void CSystem::OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress )
{

// 可以在此添加游戏需要的响应函数
g_GameMain.OnKeyDown(iKey, bAltPress, bShiftPress, bCtrlPress);

}
//==========================================================================
//
// 引擎捕捉键盘弹起消息后,将调用到本函数
// 参数 iKey:弹起的键,值见 enum KeyCodes 宏定义
//
void CSystem::OnKeyUp( const int iKey )
{

// 可以在此添加游戏需要的响应函数
g_GameMain.OnKeyUp(iKey);

}

//===========================================================================
//
// 引擎捕捉到精灵与精灵碰撞之后,调用此函数
// 精灵之间要产生碰撞,必须在编辑器或者代码里设置精灵发送及接受碰撞
// 参数 szSrcName:发起碰撞的精灵名字
// 参数 szTarName:被碰撞的精灵名字
//
void CSystem::OnSpriteColSprite( const char szSrcName, const char szTarName )
{

// 可以在此添加游戏需要的响应函数
g_GameMain.OnSpriteColSprite(szSrcName, szTarName);

}

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

// 可以在此添加游戏需要的响应函数
g_GameMain.OnSpriteColWorldLimit(szName, iColSide);

}

LessonX.h

ifndef LESSON_X_H

define LESSON_X_H

//

include <Windows.h>

include

using namespace std;
/////////////////////////////////////////////////////////////////////////////////
//
// 游戏总管类。负责处理游戏主循环、游戏初始化、结束等工作
class CGameMain
{
private:

int                m_iGameState;                // 游戏状态,0:结束或者等待开始;1:初始化;2表示未开始(此时拍子不随鼠标移动),3 表示倒计时阶段, 4表示开始拍子可以随鼠标移动并拍打

public:

CGameMain();            //构造函数
~CGameMain();           //析构函数
float    m_fRotateTime;        // 拍子拍下后距离复位还差多少时间
float    m_fOldRotation;        // 拍子的初始角度
CSprite     *paizi;

// int m_iGameState;

int                countdownTime ;    //倒计时时间
float            countPassedTime;    //倒计时经过的时间
CTextSprite        *countdown;        //倒计时的文字精灵
CSprite            *kaishi;            //“空格开始”精灵
vector< CSprite *>  m_mosquitos;
vector< CSprite *>  m_names;
int        m_iMosquitoCount;
int                    m_iGameScore;        //当前得分
CTextSprite            *score;            //score精灵
float            m_fGameTime;        //游戏时间
CTextSprite        *gameTime;        //游戏时间精灵

int index = 1;
// Get方法
int                GetGameState()                                            { return m_iGameState; }

// Set方法
void            SetGameState( const int iState )                { m_iGameState    =    iState; }

// 游戏主循环等
void            GameMainLoop( float    fDeltaTime );
void            GameInit();
void            GameRun( float fDeltaTime );
void            GameEnd();
void             OnMouseMove( const float fMouseX, const float fMouseY );
void             OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY );
void             OnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY );
void             OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress );
void             OnKeyUp( const int iKey );
void             OnSpriteColSprite( const char *szSrcName, const char *szTarName );
void             OnSpriteColWorldLimit( const char *szName, const int iColSide );

};

/////////////////////////////////////////////////////////////////////////////////
//
extern CGameMain g_GameMain;

endif // LESSON_X_H

LessonX.Cpp

include <Stdio.h>

include "CommonClass.h"

include "LessonX.h"

include

using namespace std;

////////////////////////////////////////////////////////////////////////////////
//
//
CGameMain g_GameMain;

//==============================================================================
//
// 大体的程序流程为:GameMainLoop函数为主循环函数,在引擎每帧刷新屏幕图像之后,都会被调用一次。

//==============================================================================
//
// 构造函数
CGameMain::CGameMain()
{

m_iGameState =    1;
paizi = new CSprite("paizi");
countdown = new CTextSprite("countdown");
kaishi = new CSprite("kaishi");
score = new CTextSprite("score");//实例化得分
gameTime = new CTextSprite("gameTime");

}
//==============================================================================
//
// 析构函数
CGameMain::~CGameMain()
{
}

//==============================================================================
//
// 游戏主循环,此函数将被不停的调用,引擎每刷新一次屏幕,此函数即被调用一次
// 用以处理游戏的开始、进行中、结束等各种状态.
// 函数参数fDeltaTime : 上次调用本函数到此次调用本函数的时间间隔,单位:秒
void CGameMain::GameMainLoop( float fDeltaTime )
{

switch( GetGameState() )
{
    // 初始化游戏,清空上一局相关数据
case 1:
    {
        GameInit();
        SetGameState(2); // 初始化之后,将游戏状态设置为进行中
    }
    break;

    // 游戏进行中,处理各种游戏逻辑
case 2:
    {
        // TODO 修改此处游戏循环条件,完成正确游戏逻辑
        if( true )
        {
            GameRun( fDeltaTime );
        }
        else // 游戏结束。调用游戏结算函数,并把游戏状态修改为结束状态
        {
            SetGameState(0);
            GameEnd();
        }
    }
    break;

    case 3:
case 4:
{// TODO 修改此处游戏循环条件,完成正确游戏逻辑
    if( true ){
        GameRun( fDeltaTime );
    }
    else // 游戏结束。调用游戏结算函数,并把游戏状态修改为结束状态
    {
        SetGameState(0);
        GameEnd();
    }
}

    // 游戏结束/等待按空格键开始
case 0:
default:
    break;
};

}
//=============================================================================
//
// 每局开始前进行初始化,清空上一局相关数据
void CGameMain::GameInit()
{

CSystem::ShowCursor(false);    //隐藏鼠标
m_fRotateTime = 0.f;//旋转时间
m_fOldRotation = paizi->GetSpriteRotation();        //获取拍子的初始角度
countdownTime = 5;        //倒计时时间为5s
countPassedTime = 0.f;
countdown->SetSpriteVisible(false);        //设置倒计时不可见
m_iMosquitoCount = 15;//蚊子的数量
m_iGameScore = 0;//将得分设置为0

}
//=============================================================================
//
// 每局游戏进行中
void CGameMain::GameRun( float fDeltaTime )
{

/*if(m_fRotateTime > 0)    {
    m_fRotateTime -= fDeltaTime;    //每经过fDeltaTime,拍子旋转的时间也少了fDeltaTime
    if(m_fRotateTime <= 0){    //经过了0.2s以后
        paizi->SetSpriteRotation(m_fOldRotation);    //恢复拍子的初始旋转角
    }
}*/
if(m_iGameState==3){    //m_iGameState 为3时才执行
    countPassedTime += fDeltaTime;    //统计经过的时间,并存储到countPassedTime
        //思考:countPassedTime 是浮点数,那么为什么countdown -countPassedTime可以显示整数的时间?
    countdown->SetTextValue(countdownTime -countPassedTime);
    if(countPassedTime >= countdownTime){    //经过的时间超过countdownTime
        countdown->SetSpriteVisible(false);    //隐藏countdown
        countPassedTime = 0;        //重置经过的时间,为下一轮游戏做准备
        m_iGameState = 4;        //切换g_iGameState 3->4
        //蚊子的生成是在此处
        //获取最大边界
        int minX        =    CSystem::GetScreenLeft() + 5;
        int maxX        =    CSystem::GetScreenRight() - 5;
        int minY        =    CSystem::GetScreenBottom() - 5;
        int maxY        =    CSystem::GetScreenTop() + 5;
        int    iPosX = 0, iPosY = 0;        //随机产生的横纵坐标位置
        int iLoop;    //循环控制变量
        for( iLoop = 0; iLoop < m_iMosquitoCount; iLoop++ )
        {
            //利用iLoop产生不同的蚊子名
            char *szName = CSystem::MakeSpriteName("wenzi",iLoop);
            CSprite *wenzi = new CSprite(szName);
            wenzi->CloneSprite("wenziTemplate");    //复制wenziTemplate
            iPosX    =    CSystem::RandomRange(minX, maxX);        //随机产生X坐标
            iPosY    =    CSystem::RandomRange(minY, maxY);        //随机产生Y坐标
            wenzi->SetSpritePosition(iPosX,iPosY);  //设置产生蚊子的位置
            if(iLoop%3==0)
            {
                wenzi->SetSpriteWidth(3.7f);
                wenzi->SetSpriteHeight(3.7f);
            }else if(iLoop%3==1)
            {
                wenzi->SetSpriteWidth(5.7f);
                wenzi->SetSpriteHeight(5.7f);

            }else{
                wenzi->SetSpriteWidth(7.7f);
                wenzi->SetSpriteHeight(7.7f);
            }
            m_mosquitos.push_back(wenzi);        //压入vector中集中管理
        }
    }
    } else if(m_iGameState==4){
        m_fGameTime -= fDeltaTime;
        if(m_fGameTime > 0){
            gameTime->SetTextValue(m_fGameTime);    //若游戏时间未结束,则显示剩余的游戏时间
        }else{
            m_iGameState = 2;        //若游戏时间结束,完成g_iGameState 2->0的转换
            kaishi->SetSpriteVisible(true);    //显示“空格开始”
            m_fGameTime = 0;
            paizi->SetSpritePositionX(-0.852f);
            paizi->SetSpritePositionY(-1.000f);
            gameTime->SetTextValue(m_fGameTime);
    }
    }

}
//=============================================================================
//
// 本局游戏结束
void CGameMain::GameEnd()
{
}
//==========================================================================
//
// 鼠标移动
// 参数 fMouseX, fMouseY:为鼠标当前坐标
void CGameMain::OnMouseMove( const float fMouseX, const float fMouseY )
{

if(m_iGameState==4)
{
    paizi->SetSpritePosition(fMouseX, fMouseY);    //使拍子的位置和鼠标一致

}


}
//==========================================================================
//
// 鼠标点击
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
void CGameMain::OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{

if(iMouseType == MOUSE_LEFT && m_iGameState == 4) //鼠标左键按下

{
    paizi->SetSpriteRotation(m_fOldRotation - 10);        //设置拍子的旋转角,为初始值-10
    m_fRotateTime    =    0.2f;    //拍打的时间间隔 0.2s,即0.2s后恢复拍子初始角度
    //遍历判定蚊子是否被击中
    float fX,fY;int flag = -1;
    for(int i=0;i<m_mosquitos.size();i++){        //遍历vector中的蚊子
        fX = m_mosquitos[i]->GetSpritePositionX();    //获取蚊子所的纵坐标
        fY = m_mosquitos[i]->GetSpritePositionY();    //获取蚊子所在

        if(paizi->IsPointInSprite(fX,fY))            //判断蚊子是否在拍子的范围内
        {
            int h = m_mosquitos[i]->GetSpriteHeight();
            int w = m_mosquitos[i]->GetSpriteWidth();
            char *myName = CSystem::MakeSpriteName("names",i);
            CSprite *myNames = new CSprite(myName);
            myNames->CloneSprite("myName");
            myNames->SetSpritePosition(fX,fY);
            myNames->SetSpriteWidth(w+2);
            myNames->SetSpriteHeight(h);
            m_names.push_back(myNames);
            m_mosquitos[i]->DeleteSprite();    //删除该蚊子
            vector<CSprite*>::iterator it = m_mosquitos.erase(m_mosquitos.begin()+i,m_mosquitos.begin()+i+1);
            m_iGameScore++;                            //每打一只蚊子加一分
            score->SetTextValue(m_iGameScore);
            break;
        }


    }
}

}
//==========================================================================
//
// 鼠标弹起
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
void CGameMain::OnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY )
{

paizi->SetSpriteRotation(m_fOldRotation);

}
//==========================================================================
//
// 键盘按下
// 参数 iKey:被按下的键,值见 enum KeyCodes 宏定义
// 参数 iAltPress, iShiftPress,iCtrlPress:键盘上的功能键Alt,Ctrl,Shift当前是否也处于按下状态(0未按下,1按下)
void CGameMain::OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress ){

if( KEY_SPACE == iKey && 2 ==  m_iGameState )    //按下空格且游戏状态为2时
{
    m_iGameState =    3;    //设置游戏状态进入倒计时,即3
    countdown->SetSpriteVisible(true);    //显示倒计时文本框
    kaishi->SetSpriteVisible(false);        //隐藏“空格开始”
    m_iGameScore = 0.f;        //初始化新一轮游戏分数
    m_fGameTime = 10.f;        //初始化新一轮游戏时间
    score->SetTextValue(m_iGameScore);
    gameTime->SetTextValue(m_fGameTime);
    for(int i=0;i<m_mosquitos.size();i++){    //删除上一轮游戏中剩余的蚊子
        m_mosquitos[i]->DeleteSprite();
    }
    for(int i=0;i<m_names.size();i++)
    {

        m_names[i]->DeleteSprite();
    }
    m_mosquitos.clear();    //清空vector
    m_names.clear();
}

}
//==========================================================================
//
// 键盘弹起
// 参数 iKey:弹起的键,值见 enum KeyCodes 宏定义
void CGameMain::OnKeyUp( const int iKey )
{

}
//===========================================================================
//
// 精灵与精灵碰撞
// 参数 szSrcName:发起碰撞的精灵名字
// 参数 szTarName:被碰撞的精灵名字
void CGameMain::OnSpriteColSprite( const char szSrcName, const char szTarName )
{

}
//===========================================================================
//
// 精灵与世界边界碰撞
// 参数 szName:碰撞到边界的精灵名字
// 参数 iColSide:碰撞到的边界 0 左边,1 右边,2 上边,3 下边
void CGameMain::OnSpriteColWorldLimit( const char *szName, const int iColSide )
{

}

相关文章
|
存储 编译器 测试技术
CppCheck的使用
CppCheck的使用
599 0
|
存储 NoSQL Redis
【360开源】Pika最佳实践
Pika是360 热门的c++开源项目,基于rocksdb开发的大容量类Redis存储,力求在完全兼容Redis协议、继承Redis便捷运维设计的前提下通过持久化存储方式解决Redis在大容量场景下主从同步代价高、恢复时间慢、单线程相对脆弱、内存成本高等问题。
2611 0
|
存储 算法 C++
虚拟存储管理(OPT,FIFO,LRU,LFU,NUR算法的C++实现)
虚拟存储管理(OPT,FIFO,LRU,LFU,NUR算法的C++实现)
477 1
|
算法 调度
操作系统实验二-虚拟存储器/内存管理(二)
操作系统实验二-虚拟存储器/内存管理
258 0
操作系统实验二-虚拟存储器/内存管理(二)
Funcode实现黄金矿工
Funcode实现黄金矿工
|
敏捷开发 运维 监控
【DevOps】深入了解探究DevOps
探究DevOps 的起源、原则和实践
【DevOps】深入了解探究DevOps
|
存储
逻辑地址转物理地址
若在一分页存储管理系统中,某作业的页表如表所示。已知页面大小为1024字节,试将逻辑地址1011,2148,3000,4000转换为相应的物理地址。
378 0
逻辑地址转物理地址
|
容灾 Dubbo Java
如何基于AppActive 设计一套多数据中心应用多活方案
系统在运行过程中总是会遇到各种各样的问题,比如硬件故障,包括磁盘损坏、内存短路、智能系统损坏等;比如软件故障,包括容量不足、健康检查失效等;比如人为故障,包括错误配置、错误发布、删库跑路等;再比如不可抗力,包括地震、火山雷电、断电断网等。 只要系统规模足够大或运营时间足够长,就一定会出现故常。因此,需要使用有效手段来应对和缓解故障。
如何基于AppActive 设计一套多数据中心应用多活方案
|
Kubernetes 监控 Cloud Native
工具篇:云效云原生 DevOps 解决方案(一)|学习笔记
快速学习工具篇:云效云原生 DevOps 解决方案(一)
328 0
工具篇:云效云原生 DevOps 解决方案(一)|学习笔记
|
移动开发 前端开发 JavaScript
轻松使用纯css3打造有点意思的故障艺术(附React/Vue加强组件版)
很早之前就看到国外很多酷炫的网站在实践&quot;故障艺术&quot;, 或者错位动画&quot;, 感觉非常有意思, 现在APP端的抖音启动界面有着这种设计的影子, 作为一名用于探索未知的前端工程师, 有必要好好实践一下这一设计.
361 0