cocos2dx3的官方demo游戏c++实现(Kill Bugs)

10 篇文章 0 订阅

       最近一直在研究cocos2dx引擎,由于之前没有接触过,所以算是从小白入门,在官网找了下demo,但是是lua实现,没学过。所以只能自己一步步的搞,现在基本有个原型了,其他就是细节的方面。

1.效果图

开始界面

游戏界面

死亡画面

可以看到bug的死亡方向有点奇怪,这主要是因为官方给的资源里面bug的死亡图与存活图的头部朝向不一致,所以不太好根据死亡的位置去设置旋转。

2.代码

2.1蚂蚁bug

AntSptite.h

#ifndef _ANT_SPRITE_H
#define _ANT_SPTITE_H
#include"cocos2d.h"
#include<string>
using namespace std;
USING_NS_CC;

class Ant :public cocos2d::Sprite
{
public:
    static Ant* createAnt(string filename,Rect rect);
    virtual bool init()override;
    //添加点击事件
    bool onTouchBegan(Touch* touch,Event* event);
    void onTouchEnded(Touch* touch,Event* event);
    //设置点击事件
    bool setListener();
    CREATE_FUNC(Ant);
};
#endif

AntSprite.cpp

#include"AntSprite.h"
#include"string"
USING_NS_CC;
using namespace std;

Ant* Ant::createAnt(string filename,Rect rect)
{
    Ant* sprite = new Ant();
    if (sprite && sprite->initWithFile(filename,rect))
    {
        sprite->autorelease(); 
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}
bool Ant::init()
{
    if (!Sprite::init())
    {
        return false;
    }
    return true;
}
bool Ant::onTouchBegan(Touch* touch,Event* event)
{
    auto target = static_cast<Sprite*>(event->getCurrentTarget());
    int tag = target->getTag();
    auto pos = target->convertTouchToNodeSpace(touch);
    auto size = target->getContentSize();
    auto rect = Rect(0, 0, size.width, size.height);
    if (rect.containsPoint(pos))
    {
        auto sprite = this->createAnt("BugAnt.png", Rect(480, 0, 240, 240));
        sprite->setTag(3);
        sprite->setPosition(this->getPosition());
        this->getParent()->addChild(sprite);
        this->getParent()->removeChild(this);
        return true;
    }
    return false;
}
void Ant::onTouchEnded(Touch* touch,Event* event)
{
    log("touchended");
}
bool Ant::setListener()
{
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(Ant::onTouchBegan, this);
    listener->onTouchEnded = CC_CALLBACK_2(Ant::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    return true;
}

2.2蜘蛛bug

SpiderSprite.h

#ifndef _SPIDER_SPRITE_H
#define _SPIDER_SPRITE_H
#include"cocos2d.h"
#include<string>
using namespace std;
USING_NS_CC;
class Spider:public cocos2d::Sprite
{
public:
    CREATE_FUNC(Spider);
    static Spider* createSpider(string filename, cocos2d::Rect rect);
    virtual bool init();
    //添加点击事件
    bool onTouchBegan(Touch* touch, Event* event);
    void onTouchEnded(Touch* touch, Event* event);
    //设置点击事件
    bool setListener();
};
#endif // !_SPIDER_SPRITE_H

 

SpiderSprite.cpp

#include"SpiderSprite.h"

Spider* Spider::createSpider(string filename, Rect rect)
{
    Spider* sprite = new Spider();
    if (sprite && sprite->initWithFile(filename, rect))
    {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}
bool Spider::init()
{
    if (!Sprite::init())
    {
        return false;
    }
    return true;
}
bool Spider::onTouchBegan(Touch* touch, Event* event)
{
    auto target = static_cast<Sprite*>(event->getCurrentTarget());
    int tag = target->getTag();
    auto pos = target->convertTouchToNodeSpace(touch);
    auto size = target->getContentSize();
    auto rect = Rect(0, 0, size.width, size.height);
    if (rect.containsPoint(pos))
    {
        auto sprite = this->createSpider("BugSpider.png", Rect(320, 0, 160, 160));
        sprite->setTag(4);
        sprite->setPosition(this->getPosition());
        this->getParent()->addChild(sprite);
        this->getParent()->removeChild(this);
        return true;
    }
    return false;
}
void Spider::onTouchEnded(Touch* touch, Event* event)
{
    log("touchended");
}
bool Spider::setListener()
{
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(Spider::onTouchBegan, this);
    listener->onTouchEnded = CC_CALLBACK_2(Spider::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    return true;
}

3.开始场景

MainScene.h

#ifndef __MAIN_SCENE_H__
#define __MAIN_SCENE_H__
#include"cocos2d.h"
#include"extensions/cocos-ext.h"
USING_NS_CC_EXT;
//开始类声明
class GameStart :public cocos2d::Scene
{
public:
    int flag = 0;
    static cocos2d::Scene* createScene();
    bool init()override;
    //点击开始按钮事件
    void startClicked(cocos2d::Ref* sender,Control::EventType event);
    void loadSouce();
    CREATE_FUNC(GameStart);
};
#endif

MainScene.cpp

#include "MainScene.h"
#include "PlayScene.h"
USING_NS_CC;

Scene* GameStart::createScene()
{
    return GameStart::create();
}

bool GameStart::init()
{
    if (!Scene::init())
    {
        return false;
    }
    auto director = Director::getInstance();
    auto size = director->getVisibleSize();
    //添加背景
    auto bgsprite = Sprite::create("MainSceneBg.png");
    if (bgsprite == nullptr)
    {
        log("No such file path");
    }
    else
    {
        bgsprite->setPosition(Vec2(size.width/2,size.height/2));
        this->addChild(bgsprite, -1);
    }
    auto statrtSprite = Scale9Sprite::create("PlayButton.png");
    auto startButton = ControlButton::create(statrtSprite);
    if (startButton == nullptr)
    {
        log("No such file path");
    }
    startButton->setPosition(Vec2(415,30));
    startButton->setAnchorPoint(Vec2::ZERO);
    startButton->addTargetWithActionForControlEvents(this, cccontrol_selector(GameStart::startClicked), Control::EventType::TOUCH_DOWN);
    this->addChild(startButton);
    loadSouce();
    return true;
}
void GameStart::startClicked(Ref* sender,Control::EventType event)
{
    auto playScene = Play::createScene();
    Director::getInstance()->replaceScene(TransitionFlipX::create(1.0f,playScene));
}

void GameStart::loadSouce()
{
    SimpleAudioEngine::getInstance()->setEffectsVolume(1.0f);
    SimpleAudioEngine::getInstance()->preloadEffect("music/BugDead.wav");
    SimpleAudioEngine::getInstance()->preloadEffect("music/BugEnterHole.wav");
    flag++;
}

4.游戏界面

PlayScene.h

#ifndef _PLAY_SCENE_H
#define _PLAY_SCENE_H
#include"cocos2d.h"
#include"SimpleAudioEngine.h"
#include<math.h>
using namespace CocosDenshion;
USING_NS_CC;

class Play : public cocos2d::Scene
{
public:
    static cocos2d::Scene* createScene();
    CREATE_FUNC(Play);
    bool init()override;
    //设置生成怪物类型
    bool flag = true;
    //血量
    int health = 10;
    //怪物随机生成
    void monstergenerated(float dt);
    //怪物的点击监听器
    cocos2d::EventListenerTouchOneByOne listener;
    //怪物点击事件
    bool onTouchBegan(Touch* touch, Event* event);
    void onTouchEnded(Touch* touch, Event* event);
    //移除进入洞中且未被点击的精灵
    void isEnterHole(float dt);
    //移除死亡图像
    void removeDeadSprite(float dt);
    //计算旋转角度
    float calculateAngel(float x, float y);
};
#endif 

 

PlayScene.cpp

#include"PlayScene.h"
#include<string>
#include"AntSprite.h"
#include"SpiderSprite.h"
#include<time.h>
#include<vector>
using namespace std;

Scene*    Play::createScene()
{
    return Play::create();
}
bool Play::init()
{

    if (!Scene::init())
    {
        return false;
    }
    //获取导演及屏幕尺寸
    auto director = Director::getInstance();
    auto size = director->getVisibleSize();
    auto bgSptite = Sprite::create("PlaySceneBg.png");
    bgSptite->setPosition(Vec2(size.width/2,size.height/2));
    bgSptite->setTag(0);
    addChild(bgSptite, -1);
    //绘制血量显示
    auto starSprite = Sprite::create("Star.png");    
    if (starSprite == nullptr)
    {
        log("No sunch file path");
    }
    else
    {
        starSprite->setTag(0);
        starSprite->setAnchorPoint(Vec2(0,0));
        starSprite->setPosition(Vec2(0,size.height-starSprite->getContentSize().height));
        this->addChild(starSprite);
    }
    //绘制血量数值
    auto healthSprite = Label::createWithTTF(to_string(health), "fonts/Marker Felt.ttf",24);
    if (healthSprite == nullptr)
    {
        log("No such file path");
    }
    else
    {
        healthSprite->setTag(0);
        healthSprite->setAnchorPoint(Vec2(0,0));
        healthSprite->setPosition(starSprite->getContentSize().width,starSprite->getPosition().y+10);
        this->addChild(healthSprite);
    }
    listener.onTouchBegan = CC_CALLBACK_2(Play::onTouchBegan, this);
    listener.onTouchEnded = CC_CALLBACK_2(Play::onTouchEnded, this);
    schedule(schedule_selector(Play::monstergenerated),3);
    schedule(schedule_selector(Play::isEnterHole));
    schedule(schedule_selector(Play::removeDeadSprite), 1);
    return true;
}
//怪物生成
void Play::monstergenerated(float dt)
{
    //设置随机性
    int randnum = time(nullptr);
    srand(randnum);
    //flag==true,生成Ant
    if (flag)
    {
        Ant* sprite = Ant::createAnt("BugAnt.png", Rect(0, 0, 240, 240));
        int x = rand() % 1377 - 120;
        //根据随机位置进行X坐标的修正
        if (x < 120)
        {
            x = -120;
        }
        if (x > 1016)
        {
            x = 1256;
        }
        //修正X坐标后设置Y坐标并进行旋转
        //精灵位于背景的左侧
        if (x == -120)
        {
            int y = rand() % 401 + 120;
            sprite->setPosition(Vec2(x, y));
            float angle = calculateAngel(x, y);
            if (y > 250)
            {
                sprite->setRotation(angle);
            }
            if (y < 250)
            {
                sprite->setRotation(-angle);
            }
        }
        //精灵位于背景的右侧
        else if (x==1256)
        {
            int y = rand() % 401 + 120;
            sprite->setPosition(Vec2(x, y));
            float angle = calculateAngel(x, y);
            if (y > 250)
            {
                sprite->setRotation(180-angle);
            }
            else if (y < 250)
            {
                sprite->setRotation(-(180-angle));
            }
            else
            {
                sprite->setRotation(180);
            }
        }
        //精灵位于背景的中央
        else
        {
            //随机决定精灵位于上侧还是下侧
            int direction = rand() % 2;
            //位于上侧
            if (direction == 0)
            {
                sprite->setPosition(Vec2(x, 760));
                float angel = calculateAngel(x, 760);
                if (x < 535)
                {
                    sprite->setRotation(angel);
                }
                else if (x>535)
                {
                    sprite->setRotation(180-angel);
                }
                else
                {
                    sprite->setRotation(90);
                }
            }
            //位于下侧
            else
            {
                sprite->setPosition(Vec2(x,-120));
                if (x < 535)
                {
                    sprite->setRotation(-calculateAngel(x,-120));
                }
                else if (x>535)
                {
                    sprite->setRotation(-(180-calculateAngel(x,-120)));
                }
                else
                {
                    sprite->setRotation(-90);
                }
            }
        }
        sprite->setListener();
        sprite->setTag(1);
        this->addChild(sprite);
    }
    //flag==false,生成Spider
    else
    {
        Spider* sprite = Spider::createSpider("BugSpider.png", Rect(0, 0, 160, 160));
        int x = rand() % 1297 - 80;
        if (x < 80)
        {
            x = -80;
        }
        if (x > 1056)
        {
            x = 1216;
        }
        //左侧
        if (x == -80)
        {
            int y = rand() % 481 + 80;//y的范围为[80,560]
            sprite->setPosition(Vec2(x, y));
            float angle = calculateAngel(x, y);
            if (y > 250)
            {
                sprite->setRotation(angle);
            }
            if (y < 250)
            {
                sprite->setRotation(-angle);
            }
        }
        //右侧
        else if (x == 1216)
        {
            int y = rand() % 481+80;
            sprite->setPosition(Vec2(x, y));
            float angle = calculateAngel(x, y);
            if (y > 250)
            {
                sprite->setRotation(180 - angle);
            }
            else if (y < 250)
            {
                sprite->setRotation(-(180 - angle));
            }
            else
            {
                sprite->setRotation(180);
            }
        }
        //上下侧
        else
        {
            int direction = rand() % 2;
            //上侧
            if (direction == 0)
            {
                sprite->setPosition(Vec2(x, 720));
                float angel = calculateAngel(x, 720);
                if (x < 535)
                {
                    sprite->setRotation(angel);
                }
                else if (x > 535)
                {
                    sprite->setRotation(180 - angel);
                }
                else
                {
                    sprite->setRotation(90);
                }
            }
            //下侧
            else
            {
                sprite->setPosition(Vec2(x, -80));
                if (x < 535)
                {
                    sprite->setRotation(-calculateAngel(x, -80));
                }
                else if (x > 535)
                {
                    sprite->setRotation(-(180 - calculateAngel(x, -80)));
                }
                else
                {
                    sprite->setRotation(-90);
                }
            }
        }
        sprite->setListener();
        sprite->setTag(2);
        this->addChild(sprite);
    }
    flag = !flag;
}
//触摸事件开始
bool Play::onTouchBegan(Touch* touch,Event* event)
{
    auto target = static_cast<Sprite*>(event->getCurrentTarget());
    auto pos = target->convertTouchToNodeSpace(touch);
    //获取大小
    Size size = target->getContentSize(); 
    Rect rect = Rect(0, 0, size.width / 2, size.height / 2);
    int tag=0;
    if (rect.containsPoint(pos))
    {

        Vec2 point;
        if (target)
        {
            point = target->getPosition();
            tag = target->getTag();
        }
        Sprite* sprite = nullptr;
        if (tag == 1)
        {
            sprite = Ant::createAnt("BugAnt.png", Rect(480, 0, 240, 240));
        }
        else
        {
            sprite = Spider::createSpider("BugSpider.png", Rect(320, 0, 160, 160));
        }
        if (sprite)
        {

            sprite->setScale(0.5);
            sprite->setPosition(point);
            this->removeChild(target);
            this->addChild(sprite);
        }
        log("true");
        return true;
    }
    log("false");
    return false;
}
//触摸事件结束
void Play::onTouchEnded(Touch* touch, Event* event)
{
    log("end");
}
//判断是否进入虫洞
void Play::isEnterHole(float dt)
{
    auto spriteVector = this->getChildren();
    auto length = spriteVector.size();
    for (int i = 4; i < length; i++)
    {
        auto sprite = spriteVector.at(i);
        int tag = sprite->getTag();
        float x = sprite->getPositionX();
        float y = sprite->getPositionY();
        if (tag != 0)
        {
            if (tag <= 2)
            {
                float distance = sqrt(pow((x - 535), 2) + pow((y - 250), 2));
                if (distance < 10)
                {
                    this->removeChild(sprite);
                }
                else
                {
                    if (x != 535)
                    {
                        float k = (y - 250) / (x - 535);
                        float b = y - k * x;
                        if (x > 535)
                        {
                            sprite->setPosition(x - 1, k * (x - 1) + b);
                        }
                        else
                        {
                            sprite->setPosition(x + 1, k * (x + 1) + b);
                        }
                    }
                    else
                    {
                        if (y > 250)
                        {
                            sprite->setPosition(x, y - 0.2);
                        }
                        else
                        {
                            sprite->setPosition(x, y + 0.2);
                        }
                    }
                }
            }
        }
    }
}
//移除怪物的死亡画面
void Play::removeDeadSprite(float dt)
{
    auto spriteVector = this->getChildren();
    int length = spriteVector.size();
    if (length > 0)
    {
        for (int i = 0; i < length; i++)
        {
            auto sprite = spriteVector.at(i);
            int tag = sprite->getTag();
            if (tag > 2)
            {
                this->removeChild(sprite);
            }
        }
    }
    
}
//计算旋转角度
float Play::calculateAngel(float x, float y)
{
    //洞中心的坐标为(535,250)
    if (x == 535)
    {
        return 0;
    }
    float k = fabs((y - 250.0) / (x - 535));
    float angel = atan(k);
    return angel*57.3;
}

3.上面的代码还有很多瑕疵,还需要完善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值