《Cocos2D权威指南》——2.3 玩家交互

简介: 本节书摘来自华章计算机《Cocos2D权威指南》一书中的第2章,第2.3节,作者:王寒,屈光辉,周雪彬著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.3 玩家交互

2.3.1 添加加速计移动
在Cocos2D世界里添加加速计支持非常简单,只需在当前运行的CCLayer的init方法返回之前,添加代码清单2-14所示代码。
代码清单2-14 添加加速计支持

//7.enable accelerometer
self.isAccelerometerEnabled = YES;

为了让玩家能够使用加速计非常平滑地控制飞机的飞行,这里提供一种通用的方法。因为游戏是垂直射击游戏,所以我们只关心设备垂直放置时Home按键左右摆动方向的加速计值即可。
步骤1 打开HelloWorldLayer.h文件,添加一个CGPoint _playerVelocity实例变量。
步骤2 打开HelloWorldLayer.m文件,在私有分类里添加-(void) updatePlayerPosition: (ccTime)dt方法,如图2-8所示。
步骤3 在init方法返回之后,紧跟代码清单2-14所示代码后添加方法调用,如代码清单2-15所示。
代码清单2-15 紧跟代码清单2-14所示代码后添加方法调用

//8.game main loop
  [self scheduleUpdate];

此方法是本游戏的主循环。任何游戏都包含一个游戏主循环,此主循环类用来更新游戏世界的状态、碰撞处理逻辑和玩家状态等,这里主要更新玩家的位置信息。
步骤4 定义一个update方法,调用更新玩家位置信息的方法,如代码清单2-16所示。
代码清单2-16 定义update方法

-(void) update:(ccTime)dt{
    [selfupdatePlayerPosition:dt];
}

在讨论updatePlayerPositoin方法之前,我们先看看如何操作加速计,同时保存加速计的数据。在update方法之后,添加代码清单2-17所示代码。
代码清单2-17 操作加速计

#pragma mark - accelerometer callback
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration{
float deceleration = 0.4f;
float sensitivity = 6.0f;
floatmaxVelocity = 100;
playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity;
if (playerVelocity.x>maxVelocity) {
   playerVelocity.x = maxVelocity;
}else if(playerVelocity.x< -maxVelocity){
   playerVelocity.x = -maxVelocity;
    }

}

这里主要做两件事:
通过“滤波”方式,从加速计x轴方向取得数据,计算得到一个“合理”的速度值;
限制飞机飞行的最大速度。
注意 如果想获取其他方向的值,相应地计算acceleration的其他两个分量的值就可以了。
最后,看看实际更新玩家飞机位置信息的方法实现,如代码清单2-18所示。
代码清单2-18 更新玩家飞机位置信息的方法实现

-(void) updatePlayerPosition:(ccTime)dt{
    CCSprite *playerSprite = (CCSprite*)[self getChildByTag:kTagPalyer];
    CGPoint pos = playerSprite.position;
   pos.x += playerVelocity.x;

   CGSizescreenSize = [CCDirector sharedDirector].winSize;
   floatimageWidthHavled = playerSprite.texture.contentSize.width * 0.5f;
   floatleftBoderLimit = imageWidthHavled;
   floatrightBoderLimit = screenSize.width - imageWidthHavled;

   if (pos.x<leftBoderLimit) {
      pos.x = leftBoderLimit;
      playerVelocity = CGPointZero;
   }else if(pos.x>rightBoderLimit){
      pos.x = rightBoderLimit;
      playerVelocity = CGPointZero;
   }

   playerSprite.position = pos;
}

这段代码根据之前计算出来的加速计的速度值,加上玩家飞机的x轴方向的速度,同时限制玩家飞机只能在屏幕范围之内飞行。
好了,现在编译并运行,我们就可以通过加速计来控制飞机的移动了!
2.3.2 添加子弹并射击
目前来说,一切看起来还不错。但是,假如不能开枪打死这些敌机,那么游戏会非常乏味。话不多说,给玩家飞机添加子弹射击功能吧!为了玩家操作的方便性,我们希望实现在游戏开始时只要轻轻单击屏幕就可以自动发射子弹了,这样玩家只需要专心控制飞机的飞行就可以了,当然,子弹是无限的。
步骤1 在HelloWorldLayer.h中添加两个成员变量,如代码清单2-19所示。
代码清单2-19 在HelloWorldLayer.h中添加两个成员变量

BOOL _isTouchToShoot;
CCSprite *_bulletSprite;

步骤2 在HelloWorldLayer()的@end之前添加一个新方法,如代码清单2-20所示。
代码清单2-20 在HelloWorldLayer()的@end之前添加新方法
-(void) bulletFinishedMoving:(id)sender;
步骤3 为了能接收玩家的触摸消息,我们在init方法返回之前添加代码清单2-21所示代码。
代码清单2-21 在init方法返回之前添加代码

//9.enable touch
self.isTouchEnabled = YES;
_isTouchToShoot = NO;

//10.init bullets
_bulletSprite = [CCSprite spriteWithFile:@"bullet1.png"];
_bulletSprite.visible = NO;
[self addChild:_bulletSprite z:4];

其他self.isTouchEnabled设置为YES之后,就可以在CCLayer里处理触摸消息了。
步骤4 框架自动调用ccTouchesEnded方法,实现代码如代码清单2-22所示。
代码清单2-22 ccTouchesEnded方法的实现

-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    CCLOG(@"touch!");
    _isTouchToShoot = YES;
}

在init方法最后初始化子弹精灵。
注意 这里我们没有采用敌机那种方式用数组保存一系列精灵图片,因为这里要设计子弹消失了才可以发射下一颗子弹,这样可以给游戏添加一些难度和趣味性。
步骤5 在update方法底部添加发射子弹的方法。
[self updatePlayerShooting:dt]方法的作用就是让玩家飞机不断地发射子弹,具体实现如代码清单2-23所示。
代码清单2-23 在update方法底部添加[self updatePlayerShooting:dt]方法

-(void) updatePlayerShooting:(ccTime)dt{
if (_bulletSprite.visible || !_isTouchToShoot) {
return;
    }

    CCSprite *playerSprite = (CCSprite*)[self getChildByTag:kTagPalyer];
    CGPoint pos = playerSprite.position;

    CGPoint bulletPos = CGPointMake(pos.x, 
pos.y + playerSprite.contentSize.height/ 2 + _bulletSprite.contentSize.height);
    _bulletSprite.position = bulletPos;
    _bulletSprite.visible = YES;

CGSizewinSize = [CCDirector sharedDirector].winSize;
idmoveBy = [CCMoveBy actionWithDuration:1.0 position:ccp(0,winSize.height - bulletPos.y)];
id callback = [CCCallFuncN actionWithTarget:self selector:@selector(bulletFinishedMoving:)];
id ac = [CCSequence actions:moveBy,callback, nil];
    [_bulletSpriterunAction:ac];
}
-(void) bulletFinishedMoving:(id)sender{
    _bulletSprite.visible = NO;
}

这段代码很简单,主要判断子弹当前是否可见。如果可见或者玩家还没有触摸屏幕,则直接返回。接下来就是计算子弹的起始坐标,然后让子弹运行一个action往上飞行就OK了。等子弹到达屏幕顶端时,我们再把子弹的可见性重新设置为NO,这样下一颗子弹又可以从玩家飞机上空发射出来了。
编译并运行,然后轻轻触摸屏幕,是不是有真实的射击游戏的感觉了呢?

相关文章
|
JavaScript Android开发 C++
【Cocos2d-x】开发基础-第一个Cocos2d-x游戏
【Cocos2d-x】开发基础-第一个Cocos2d-x游戏
232 0
|
图形学
《Unity 游戏案例开发大全》一6.3 游戏的架构
在6.2小节介绍了游戏开发前的策划和准备工作。本节将简单介绍游戏的架构。读者通过这一节可以进一步了解游戏的开发思路,对整个开发过程也会更加熟悉。
3563 1
|
图形学
带你读《Unity游戏开发(原书第3版)》之二:游戏对象
本书主要介绍Unity2018的使用和游戏开发流程中涉及的各种知识。每一章的结构特别清晰,先综述该章要介绍的内容,然后一步步深入讲解,中间穿插着很多动手做的实践操作,可以让读者加深对某个概念、方法的理解,每章的最后还有一个小测验和一个稍微大一点的实践练习,用于巩固该章的学习内容。