Original article link: http://www.iphonegametutorials.com/2011/04/21/cocos2d-game-tutorial-how-to-build-a-tower-defense-game-for-the-iphone-part-4-starting-the-tower-attack/
Tutorial:
In this part of the tutorial, we will implement the complete anti-tower game we discussed at the beginning. This is the fourth and last part of this series of tutorials. Before proceeding, we recommend that you check the first three tutorials.
Today, we will learn something new-"Let the turret open fire !". This is the most important part of anti-tower gamesProgramThe most interesting part. I certainly cannot cover all the fun things in the anti-tower games in this tutorial, But I promise we will not create any kind of towers in the future. I think, after learning this series of tutorials, you can also create very interesting anti-tower games by yourself. I will try to makeCodeThe robust is better!
The complete source code of this tutorial is provided here.
First, what we need to do is to create the actual projectile-projectile class, which is a little simple at present and contains nothing, but it does not mean that it will have no content in the future.
Projectile. h
# Import " Cocos2d. h "
@ Interface projectile: ccsprite {
}
+(ID) projectile;
@ End
Projectile. m
# Import " Projectile. h "
@ Implementation Projectile
+(ID) projectile {
Projectile*Projectile=Nil;
If(Projectile=[[Super alloc] initwithfile:@"Projectile.png"] Autorelease]) {
}
ReturnProjectile;
}
-(Void) Dealloc
{
[Super dealloc];
}
@ End
Now we add a new method to the update function, which is in towerscene. It handles the collision detection of the current bullet and creep. The basic logic is simple:
1. traverse all Projectiles
2. For each projectiles, traverse all targets
3. Check whether the projectile boundary is cross with the target boundary.
4. If there is a crossover, reduce the creep life value and add projectile to the projectilestodelete array to be deleted.
5. If the life value of creep is = 0, add it to the targettodelete array.
The specific code is as follows: (in fact, this code is the same as how to use cocos2d to create a simple iPhone game)
- ( Void ) Update :( cctime) dt {
Datamodel * M = [Datamodel GetModel];
Nsmutablearray * Projectilestodelete = [[Nsmutablearray alloc] init];
for (projectile * projectile in M. _ projectiles) {
cgrect projectilerect = cgrectmake (projectile. position. x - (projectile. contentsize. width / 2 ),
projectile. position. Y - (projectile. contentsize. height / 2 ),
projectile. contentsize. width,
projectile. contentsize. height);
nsmutablearray * targetstodelete = [[nsmutablearray alloc] init];
for (ccsprite * Target in M. _ targets) {
cgrect targetrect = cgrectmake (target. position. x - (target. contentsize. width / 2 ),
target. position. Y - (target. contentsize. height / 2 ),
target. contentsize. width,
target. contentsize. height);
If(Cgrectintersectsrect (projectilerect, targetrect )){
[Projectilestodelete addobject: Projectile];
Creep*Creep=(Creep*) Target;
Creep. HP--;
If(Creep. HP<=0){
[Targetstodelete addobject: Target];
}
Break;
}
}
For(Ccsprite*TargetInTargetstodelete ){
[M. _ targets removeobject: Target];
[Self removechild: Target cleanup: Yes];
}
[Targetstodelete release];
}
For(Ccsprite*ProjectileInProjectilestodelete ){
[M. _ projectiles removeobject: Projectile];
[Self removechild: Projectile cleanup: Yes];
}
[Projectilestodelete release];
}
Finally, let's go back to the tower code to see how we handle the fire-opening mechanism. In the towerlogic code, we add another action after rotateto action, called cccallfunc. It triggers a finishfiring method.
[Self runaction: [ccsequence actions:
[Ccrotateto actionwithduration: rotateduration angle: cocosangle],
[Cccallfunc actionwithtarget: Self selector: @ selector (finishfiring)],
Nil];
Finishfiring only fires when we know Tower is in the right direction. It mainly creates a new bullet, adds it to the projectile array of datamodel, and gives it a position and a destination point.
- ( Void ) Finishfiring {
Datamodel*M=[Datamodel GetModel];
Self. nextprojectile=[Projectile];
Self. nextprojectile. Position=Self. position;
[Self. Parent addchild: Self. nextprojectile Z:1];
[M. _ projectiles addobject: Self. nextprojectile];
Cctime Delta=1.0;
Cgpoint shootvector=Ccpsub(self.tar get. Position, self. position );
Cgpoint normalizedshootvector=Ccpnormalize (shootvector );
Cgpoint overshotvector=Ccpmult (normalizedshootvector,320);
Cgpoint offscreenpoint=Ccpadd (self. Position, overshotvector );
[Self. nextprojectile runaction: [ccsequence actions:
[Ccmoveto actionwithduration: Delta position: offscreenpoint],
[Cccallfuncn actionwithtarget: Self selector: @ selector (creepmovefinished :)],
Nil];
Self. nextprojectile. Tag=2;
Self. nextprojectile=Nil;
}
You can see the code above. We run another ccmoveto action on the projectile to move it in a specific direction. This will make it look like tower is launching bullets, but the default distance is 320. once a bullet arrives at its destination, the "creepmovefinished" method is called, which removes the projectile from the datamodel projectile array and removes it from the stage.
- ( Void ) Creepmovefinished :( ID) sender {
Datamodel*M=[Datamodel GetModel];
Ccsprite*Sprite=(Ccsprite*) Sender;
[Self. Parent removechild: SPRITE cleanup: Yes];
[M. _ projectiles removeobject: SPRITE];
}
Well, that's all. Compile and run it. Now you can rotate the turret and they can attack and be killed by creep. Cool, right? In fact, our work has not been completed yet. In fact, we still need to add some tower power, a sales system, and a wave number control system (which can control the speed of the current wave, total number of wave numbers ). There are a lot of things to do, but we are on the road...
Continue to improve!
Copyright statement: This article consistsHttp://www.cnblogs.com/andyqueTranslation. You are welcome to share it with me. Please respect the work of the author. Keep this note and the author's blog link when reprinting. Thank you!