如何使用kobold2d来做一个简单的iphone游戏教程(第四部分)

来源:互联网 发布:js鼠标滚轮控制滚动条 编辑:程序博客网 时间:2024/04/29 19:54

免责声明:本系列教程是根据该系列教程实践过程所作的自己使用kobold2D框架经历。仅供学习与交流使用,请勿进行商业传播,转载时不要移除本声明。如果产生任何纠纷均与博客所有者无关。欢迎转载。

作者:Rush.xzj

本篇文章的目标:

1.炮台发射子弹

2.炮台可以旋转

3.子弹可以消灭怪物

子弹:

在这里,我们的炮台需要有一些行动了--因此让我们增加一些射击吧!这里有许许多多实现射击的方式,但是在这个游戏里面,我们想让用户触摸一下屏幕,然后子弹就会从player开始,沿着你触摸的位置发射出来。

发射子弹  

我们使用CCMoveTo action来实现这个功能。但是,为了使用这个功能,我们必须首先来做一些数学题。这是因为,CCMoveTo需要我们为子弹指定目的地。但是我们又不能使用触摸点,因为触摸点仅仅代表飞盘飞的方向。我们实际上想让子弹超过触摸点,然后飞出屏幕之外去。

  下面这张图解释了这个问题:


因此,就像你看到的,在触摸点和player之间有一个小的三角形,由origin点,offx和offy组成。我们只需要画一个更大的三角形,同时使用一样的比率就行了。然后我们就可以根据比例算出飞盘飞出屏幕的位置。

为了能让屏幕能响应触摸事件,在init函数中添加如下代码:

        //可以接受触摸消息        self.isTouchEnabled = YES;

因为我们已经设置Layer的isTouchEnabled的属性为YES,所以我们要在H恶劣咯HelloWorldLayer.m中实现ccTouchesEnded方法,为了让用户点击一次的时候可以调用

-(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];}

因为在子弹是从炮台的位置发射的,所以我们需要获取炮台的相关信息,可以把炮台的Sprite设置成一个属性,修改如下

首先在HelloWorldLayer.h中

添加

CCSprite *player;

然后添加属性:

@property (nonatomic, strong) CCSprite *player;

在HelloWorldLayer.m中添加:

@synthesize player;

修改init方法中:

CSprite *player = [CCSprite spriteWithFile:@"player2.png"];

更改成:

player = [CCSprite spriteWithFile:@"player2.png"];

也就是一句话,把CSprite *player换成属性

炮台旋转

现在子弹已经可以发射了,但是炮台还不可以旋转,这个给人的感觉很不好,现在我们就来添加炮台旋转

炮台旋转和发射子弹的逻辑顺序:

1.先旋转炮台,2.添加子弹3,子弹移动

所以先把子弹

CCSprite *projectile = [CCSprite spriteWithFile:@"Projectile2.png"];

提取成属性projectile,以下是修改后的代码:

-(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;}

运行就可以看见,发射子弹的时候,炮台也开始旋转了


到此为止,本篇教程就结束了。

该篇主要是介绍了旋转炮台和发射子弹。敬请期待下一篇文章!

原创粉丝点击