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 )
{

}

相关文章
|
传感器 编解码 区块链
Google Earth Engine(GEE)——Landsat8/modis/sentinel2 NDVI时序影像差异对比分析图表
Google Earth Engine(GEE)——Landsat8/modis/sentinel2 NDVI时序影像差异对比分析图表
458 0
|
12月前
|
存储 关系型数据库 MySQL
10个案例告诉你mysql不使用子查询的原因
大家好,我是V哥。上周与朋友讨论数据库子查询问题,深受启发。为此,我整理了10个案例,详细说明如何通过优化子查询提升MySQL性能。主要问题包括性能瓶颈、索引失效、查询优化器复杂度及数据传输开销等。解决方案涵盖使用EXISTS、JOIN、IN操作符、窗口函数、临时表及索引优化等。希望通过这些案例,帮助大家在实际开发中选择更高效的查询方式,提升系统性能。关注V哥,一起探讨技术,欢迎点赞支持!
570 5
|
IDE 开发工具 iOS开发
【10月更文挑战第3天】「Mac上学Python 3」入门篇3 - 安装Python与开发环境配置
本篇将详细介绍如何在Mac系统上安装Python,并配置Python开发环境。内容涵盖Python的安装、pip包管理工具的配置与国内镜像源替换、安装与配置PyCharm开发工具,以及通过PyCharm编写并运行第一个Python程序。通过本篇的学习,用户将完成Python开发环境的搭建,为后续的Python编程工作打下基础。
974 2
【10月更文挑战第3天】「Mac上学Python 3」入门篇3 - 安装Python与开发环境配置
|
存储 固态存储 测试技术
电脑性能的影响因素
电脑性能的影响因素【10月更文挑战第31天】
899 2
|
JavaScript API 开发工具
(H5-Web3D-ThreeJS)在网页三维CAD中绘制窗户模型
本文介绍了如何使用mxcad3d在网页中创建一个简单的三维窗户模型。通过官方教程搭建环境,编写绘制窗户模型的代码,并在点击按钮后展示模型效果。最终模型包括窗框和玻璃部分,具备丰富的三维建模功能和便捷的API支持。
|
存储 监控 安全
网站安全防护措施
【10月更文挑战第13天】网站安全防护措施
747 4
|
安全 网络协议 网络安全
Python Socket编程大揭秘:从菜鸟到黑客的进阶之路,你准备好了吗?
【10月更文挑战第4天】在编程领域,Python Socket编程犹如一把开启网络世界的钥匙,带领开发者从简单数据传输迈向复杂应用构建。本文将引导你从零开始,逐步掌握Socket编程的核心技巧,包括基本概念、TCP服务器与客户端的搭建、并发处理及异常管理、SSL/TLS加密通信,直至深入了解网络协议与安全漏洞。通过实战演练与理论学习,助你成为驾驭网络世界的高手。
165 1
|
消息中间件 监控 Java
在RocketMQ中,Proxy的gRPC参数调优是一项重要的性能优化工作
在RocketMQ中,Proxy的gRPC参数调优是一项重要的性能优化工作【1月更文挑战第10天】【1月更文挑战第46篇】
407 2
|
存储 关系型数据库 MySQL
【MySQL】存储引擎简介、存储引擎特点、存储引擎区别
【MySQL】存储引擎简介、存储引擎特点、存储引擎区别
348 2
|
弹性计算 人工智能 数据挖掘
阿里云高校计划“云工开物”解读,适合学生及高校教师参考
阿里云推出“云工开物”高校计划,向学生和教师提供优惠,旨在支持高等教育和培养科技人才。学生通过学信网认证可获300元优惠券和3折云服务器优惠;教师享5折全线产品折扣。此外,还有“极速上云”活动和各类挑战赛,促进实践和创新。
阿里云高校计划“云工开物”解读,适合学生及高校教师参考