使用Cocos2d-x-3.0游戏引擎。编写一个塔防游戏 part07

Previous: http://www.cocoachina.com/bbs/read.php?tid=203510

  1. Rotation
    旋转

In the Tower.h:
在Tower.h里面:

#pragma once
#include "cocos2d.h"
#include "Creep.h"

class Tower: public Sprite 
{
public:
……
    Creep* getClosestTarget();
……
};

```


In tower.cpp:
在tower.cpp里面:

Creep* Tower::getClosestTarget()
{
    Creep *closestCreep = NULL;
    double maxDistant = 99999; // It should be bigger than the range.

    DataModel *m = DataModel::getModel();

    for each(Sprite *target in m->targets) 
// for(Vector::iterator i = m->targets.begin(); i < m->targets.end(); ++i) // Use these code if your VC doesn’t support C++11.
    {
// Sprite *target = *i;  // Use these code if your VC doesn’t support C++11.

        Creep *creep = (Creep *)target;
        double curDistance = ccpDistance(this->getPosition(), creep->getPosition());

        if (curDistance < maxDistant) {
            closestCreep = creep;
            maxDistant = curDistance;
        }
    }
    if (maxDistant < this->range)
        return closestCreep;
    return NULL;
}

```



把这些代码加进‘void MachineGunTower::towerLogic(float dt)’:

void MachineGunTower::towerLogic(float dt)  {

    this->target = this->getClosestTarget();

    if(this->target != NULL)
    {
        Point shootVector = this->target->getPosition() - this->getPosition();
        float shootAngle = ccpToAngle(shootVector);
        float cocosAngle = CC_RADIANS_TO_DEGREES(-1 * shootAngle);

        float rotateSpeed = 0.5 / M_PI;
        float rotateDuration = fabs(shootAngle * rotateSpeed);

        this->runAction(Sequence::create(RotateTo::create(rotateDuration, cocosAngle), NULL));
    }
}
```


8.    Ammo

是的。没错。现在是时间装填子弹了。这里或许会是最为有趣和激动的事情了。在完成这个教程后,我希望你知道如何去制作不同类型的防御塔,就像我们当时创建不同的敌人那样。并且对体力、射速、机动性和伤害值设定不同的属性。

首先,我们要做的事创建子弹——我们的类‘Projectile’。创建另一对文档——Projectile.h和Projectile.cpp。

In the DataModel.h:
在DataModel里面:

#include "Projectile.h" 
```


和

Vector projectiles;
```


你知道应该要把他们放置在哪里。

In the Projectile.h:

#pragma once
#include "cocos2d.h"

USING_NS_CC;

class Projectile: public Sprite 
{
public:
    static Projectile* projectile();
};
```


In the Projectile.cpp:

#include "Projectile.h"

Projectile* Projectile::projectile()
{
    Projectile* projectile = (Projectile*)Sprite::create("Projectile.png");
    if (projectile != NULL)
    {
        return projectile;
    } else {
    return NULL;
    }
}
```



现在我们添加一些新方法进“void TutorialScene::update(float dt)”。(这个方法名我们已经添加进了TutorialScene.cpp里面。)

void TutorialScene::update(float dt)  {
    DataModel *m = DataModel::getModel();
    Vector projectilesToDelete;

    for each(Projectile *projectile in m->projectiles)
    // for (int i = 0; i < m->projectiles.size(); i++) // Use these code if your VC doesn’t support C++11.
    {
        // Projectile* projectile = (Projectile*)(m->projectiles.at(i)); // Use these code if your VC doesn’t support C++11.
        Rect projectileRect = Rect(projectile->getPositionX() - (projectile->getContentSize().width / 2),
            projectile->getPositionY() - (projectile->getContentSize().height / 2),
            projectile->getContentSize().width,
            projectile->getContentSize().height);

        Vector targetsToDelete;

        for each(Creep *target in m->targets) 
        // for (int i = 0; i < m->targets.size(); i++) // Use these code if your VC doesn’t support C++11.
        {
            // Creep* target = (Creep*)(m->targets.at(i)); // Use these code if your VC doesn’t support C++11.

            Rect targetRect = Rect(target->getPositionX() - (target->sprite->getContentSize().width / 2),
                target->getPositionY() - (target->sprite->getContentSize().height / 2),
                target->sprite->getContentSize().width,
                target->sprite->getContentSize().height);

            if (projectileRect.intersectsRect(targetRect)) 
            {
                projectilesToDelete.pushBack(projectile);

                Creep *creep = target;
                creep->curHp -= 1;

                if (creep->curHp <= 0) 
                {
                    targetsToDelete.pushBack(creep);
                }
                break;
            }
        }

        //for each(Creep *target in targetsToDelete)
        for (int i = 0; i < targetsToDelete.size(); i++)
        {
            Creep* target = (Creep*)(targetsToDelete.at(i));

            m->targets.eraseObject(target);
            this->removeChild(target, true);
        }        
    }

    for each(Projectile *projectile in projectilesToDelete)
    // for (int i =0; i < projectilesToDelete.size(); i++) // Use these code if your VC doesn’t support C++11.
    {
        // Projectile* projectile = (Projectile*)(projectilesToDelete.at(i)); // Use these code if your VC doesn’t support C++11.

        m->projectiles.eraseObject(projectile);
        this->removeChild(projectile,true);
    }
}
```




这里,我们遍历所有的投射物。对每一个投射物我们遍历所有的敌人。并且决定子弹是否和目标重叠。如果结果为真,敌人的体力将会减1,撞击到敌人的子弹将会被放入数组。一旦敌人的体力降为0,我们就将敌人添加进另一个用来删除的数组里。

最后,回到类“Tower”里面,让我们看看开火的机制。

别忘了添加这些代码到Tower.h里面:

#include "Projectile.h"  

void finishFiring(); 
void creepMoveFinished(Node* sender);
Projectile* nextProjectile;

```



在“void MachineGunTower::towerLogic(float dt)”里面:

this->runAction(Sequence::create(RotateTo::create(rotateDuration, cocosAngle), CallFunc::create(this, callfunc_selector(MachineGunTower::finishFiring)), NULL)); // Delete the old one.删掉原本旧的那行代码
```


Then:

void MachineGunTower::finishFiring()
{
    DataModel *m = DataModel::getModel();

    if (this->target != NULL && this->target->curHp > 0 && this->target->curHp < 100)
    {
        this->nextProjectile = Projectile::projectile();
        this->nextProjectile->setPosition(this->getPosition());

        this->getParent()->addChild(this->nextProjectile, 1);
        m->projectiles.pushBack(this->nextProjectile);

        float delta = 1.0f;
        Point shootVector = -(this->target->getPosition() - this->getPosition());
        Point normalizedShootVector = ccpNormalize(shootVector);
        Point overshotVector = normalizedShootVector * 320;
        Point offscreenPoint = (this->getPosition() - overshotVector);

        this->nextProjectile->runAction(Sequence::create(MoveTo::create(delta, offscreenPoint), CallFuncN::create(this, callfuncN_selector(MachineGunTower::creepMoveFinished)), NULL));

        this->nextProjectile->setTag(2);

        this->nextProjectile = NULL;

    }
}

void MachineGunTower::creepMoveFinished(Node* sender)
 {
    DataModel * m = DataModel::getModel();
    Sprite *sprite = (Sprite *)sender;
    this->getParent()->removeChild(sprite,true);

    m->projectiles.eraseObject((Projectile*)sprite);
}
```



一旦你的他面对着敌人,它就会开始射击。这个功能是用来专门制造子弹——“projectile”的。正如你所看到的。在转向正确的方向后,投射物会“runAction”和“MoveTo”到指定的位置。并且我们也设置了射程的最大值。一旦子弹超出了射程,它们就都会被消除。


现在,好好享受吧。

  


完~
 

完整代码在6L

DataModel为何没有实现呢

LZ,能把完整代码的放一份不

求一份完整代码,1653431520@qq.com。 谢谢了

是不是,还有下一节啊?等候中。。。。。。。。。。。。。。。

this->nextProjectile 在哪定义?

全部Class文件夹里的代码

在:Tower.h

class MachineGunTower : public Tower
{
public:

Projectile* nextProjectile;

};

完整代码在6L

已完结。。。完整代码在6L

OK,万分感谢!

感谢分享,谢谢

什么叫6L,不知道什么意思,,:6:

好吧,自问自答 I KNOW

That’s a good question!!! :2:

万分感谢!

:2: :2: :2: :2: :2: :2:

非常好的教程!!

hello 有木有跑酷类的教程??希望出一个。

没有资源么,,:2::2::2:

楼主。。。这个文件下载完了是PHP格式的。。不是RAR啊。。求楼主再传一次啊 。。或者能否发一份到本人邮箱啊。。。chashaochan@qq.com 不胜感激啊啊啊啊~~~:904: