免责声明:本系列教程是根据该系列教程实践过程所作的自己使用kobold2D框架经历。仅供学习与交流使用,请勿进行商业传播,转载时不要移除本声明。如果产生任何纠纷均与博客所有者无关。欢迎转载。
作者:Rush.xzj
本篇文章的目标:1.炮台发射子弹
2.炮台可以旋转
3.子弹可以消灭怪物
子弹:
在这里,我们的炮台需要有一些行动了--因此让我们增加一些射击吧!这里有许许多多实现射击的方式,但是在这个游戏里面,我们想让用户触摸一下屏幕,然后子弹就会从player开始,沿着你触摸的位置发射出来。
发射子弹
我们使用CCMoveTo action来实现这个功能。但是,为了使用这个功能,我们必须首先来做一些数学题。这是因为,CCMoveTo需要我们为子弹指定目的地。但是我们又不能使用触摸点,因为触摸点仅仅代表飞盘飞的方向。我们实际上想让子弹超过触摸点,然后飞出屏幕之外去。
下面这张图解释了这个问题:
因此,就像你看到的,在触摸点和player之间有一个小的三角形,由origin点,offx和offy组成。我们只需要画一个更大的三角形,同时使用一样的比率就行了。然后我们就可以根据比例算出飞盘飞出屏幕的位置。
为了能让屏幕能响应触摸事件,在init函数中添加如下代码:
//可以接受触摸消息 self.isTouchEnabled = YES;
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; //添加子弹到屏幕,子弹对应的图片文件名称:Projectile2.png" CCSprite *projectile = [CCSprite spriteWithFile:@"Projectile2.png"]; projectile.position = player.position; [self addChild:projectile]; //屏幕大小 CGSize winSize = [[CCDirector sharedDirector] winSize]; float maxWinSizeLength = winSize.height > winSize.width ? winSize.height : winSize.width; //发射坐标 CGPoint startPoint = player.position; //点击坐标,点触的屏幕坐标到当前屏幕的坐标转换,必须要是同一个坐标系 //对于home键在右侧(也就是当前游戏的横版模式),坐标原点在左下角,向上是Y正值,向左是X正值 //对于home健在下面(正常iphone的位置),坐标原点在左上角,想下是Y正值,想左是X正值,touch的坐标是此坐标系 //也许这里有更好的解决方案直接就可以得到touch在屏幕的坐标 CGPoint touchPoint2 = [touch locationInView:[touch view]]; CGPoint touchPoint; touchPoint.x = touchPoint2.y; touchPoint.y = touchPoint2.x; //计算射击的向量 CGPoint shootVector = ccpSub(touchPoint, startPoint); //向量的单位化 CGPoint normalizedShootVector = ccpNormalize(shootVector); //延长线,足够长 CGPoint overshootVector = ccpMult(normalizedShootVector, maxWinSizeLength); //计算终点的坐标 CGPoint endPoint = ccpAdd(startPoint, overshootVector); //设置子弹多长时间移动完 ccTime delta = 1.0; CCMoveTo *moveTo = [CCMoveTo actionWithDuration:delta position:endPoint]; CCCallFuncN *callFuncN = [CCCallFuncN actionWithTarget:self selector:@selector(spriteMoveFinished:)]; CCSequence *sequence = [CCSequence actions:moveTo, callFuncN, nil]; [projectile runAction:sequence]; }
首先在HelloWorldLayer.h中
添加
CCSprite *player;
@property (nonatomic, strong) CCSprite *player;
@synthesize player;
CSprite *player = [CCSprite spriteWithFile:@"player2.png"];
player = [CCSprite spriteWithFile:@"player2.png"];
炮台旋转
现在子弹已经可以发射了,但是炮台还不可以旋转,这个给人的感觉很不好,现在我们就来添加炮台旋转
炮台旋转和发射子弹的逻辑顺序:
1.先旋转炮台,2.添加子弹3,子弹移动
所以先把子弹
CCSprite *projectile = [CCSprite spriteWithFile:@"Projectile2.png"];
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { //防止点击过快 if(projectile != nil) return; UITouch *touch = [touches anyObject]; //添加子弹到屏幕,子弹对应的图片文件名称:Projectile2.png" projectile = [CCSprite spriteWithFile:@"Projectile2.png"]; projectile.position = player.position; //[self addChild:projectile]; //屏幕大小 CGSize winSize = [[CCDirector sharedDirector] winSize]; float maxWinSizeLength = winSize.height > winSize.width ? winSize.height : winSize.width; //发射坐标 CGPoint startPoint = player.position; //点击坐标,点触的屏幕坐标到当前屏幕的坐标转换,必须要是同一个坐标系 //对于home键在右侧(也就是当前游戏的横版模式),坐标原点在左下角,向上是Y正值,向左是X正值 //对于home健在下面(正常iphone的位置),坐标原点在左上角,想下是Y正值,想左是X正值,touch的坐标是此坐标系 //也许这里有更好的解决方案直接就可以得到touch在屏幕的坐标 CGPoint touchPoint2 = [touch locationInView:[touch view]]; CGPoint touchPoint; touchPoint.x = touchPoint2.y; touchPoint.y = touchPoint2.x; //计算射击的向量 CGPoint shootVector = ccpSub(touchPoint, startPoint); //向量的单位化 CGPoint normalizedShootVector = ccpNormalize(shootVector); //延长线,足够长 CGPoint overshootVector = ccpMult(normalizedShootVector, maxWinSizeLength); //计算终点的坐标 CGPoint endPoint = ccpAdd(startPoint, overshootVector); //计算旋转角度 CGFloat shootAngle = ccpToAngle(shootVector); //弧度值转换为角度值,cocos2D是用角度值进行计算的 //关于角度的计算和为什么* -1 请参照: //http://www.cnblogs.com/andyque/articles/1997820.html CGFloat cocosAngle = CC_RADIANS_TO_DEGREES(-1 * shootAngle); CGFloat curAngle = player.rotation; CGFloat rotationDiff = cocosAngle - curAngle; if(rotationDiff > 180) rotationDiff -= 360; if(rotationDiff < -180) rotationDiff += 360; CGFloat rotationSpeed = 0.5 / 180; CGFloat rotationduration = fabs(rotationDiff * rotationSpeed); //设置炮台的旋转动作 CCRotateTo *rotateTo = [CCRotateTo actionWithDuration:rotationduration angle:cocosAngle]; CCCallFunc *callFunc = [CCCallFunc actionWithTarget:self selector:@selector(finishShoot)]; CCSequence *playSequence = [CCSequence actions:rotateTo, callFunc, nil]; [player runAction:playSequence]; //设置子弹多长时间移动完 ccTime delta = 1.0; CCMoveTo *moveTo = [CCMoveTo actionWithDuration:delta position:endPoint]; CCCallFuncN *callFuncN = [CCCallFuncN actionWithTarget:self selector:@selector(spriteMoveFinished:)]; CCSequence *projectileSequence = [CCSequence actions:moveTo, callFuncN, nil]; [projectile runAction:projectileSequence]; }当炮台旋转完成后:需要一个回调函数finishShoot:
-(void)finishShoot { [self addChild:projectile]; projectile = nil; }
到此为止,本篇教程就结束了。
该篇主要是介绍了旋转炮台和发射子弹。敬请期待下一篇文章!