Previous: http://www.cocos2d-x.org/forums/6/topics/53962
7.Rotation
In the Tower.h:
#pragma once
#include "cocos2d.h"
#include "Creep.h"
class Tower: public Sprite
{
public:
……
Creep* getClosestTarget();
……
};
In 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<Creep*>::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;
}
Add those codes into ‘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
Yeah~ you got it. It is high time to reload the ammo. This probably is the most interesting and exciting thing. After we finished this tutorial, I hope you know how to make a different types of the defend tower exactly like how we create our different type of enemies. And set various values for HP, fire rate, mobility and damage.
So first thing first, what we are going to do is create the bullets — the class ‘Projectile’. Create another pair of files — Projectile.h and Projectile.cpp.
In the DataModel.h:
#include "Projectile.h"
and
Vector<Projectile*> projectiles;
You know exactly where you should put them.
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;
}
}
Now we add some new method into the “void TutorialScene::update(float dt)”. (We already it in the “TutorialScene.cpp”.)
void TutorialScene::update(float dt) {
DataModel *m = DataModel::getModel();
Vector<Projectile*> 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<Creep*> 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);
}
}
Here, we traverse all the projectiles. For each of projectiles, we traverse all the targets. And determine whether the bullet — ”projectile” is intersect with the targets. If that is true, the enemy HP will minus 1, the bullet which hit the target will pull into the array. Once the enemy HP equivalent to “0”, we put this enemy into the different array and for the deleting.
Finally, going back to the “Tower”, let us see the mechanism of the firing.
Don’t forget add those code in the Tower.h:
#include "Projectile.h"
void finishFiring();
void creepMoveFinished(Node* sender);
In the “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);
}
Once our tower facing the enemy, it will start shooting. This function is focusing on creating the bullets — “projectile”. As you can see, after turning to the right direction the projectile will “runAction” and “MoveTo” the certain point. And we also set the maximum value of the range. Once the bullets get out of the range, they all will be removed.
Now, enjoy yourself:
00.png (692.5 KB)