iOS游戏框架Sprite Kit技术详解
上QQ阅读APP看书,第一时间看更新

3.7 移动精灵

作为被玩家控制的精灵或者是作为敌人的精灵大部分是可以进行移动的。本节将主要讲解如何实现一个精灵的移动。

【示例3-18】以下将场景中的精灵进行移动。具体的操作步骤如下:

(1)创建一个Game类型的项目,命名为3-12。

(2)添加图像1.png、2.jpg到创建项目的Supporting Files文件夹中。

(3)将设备的方向设置为水平方向。

(4)打开GameScene.swift文件,将此文件中多余的代码删除,然后编写新的代码,这里将代码分为了3大块:场景布局、移动精灵以及边界设置。

1.场景布局

(1)在GameScene.swift文件的GameScene类中实例化一个精灵对象。代码如下:

let sprite: SKSpriteNode = SKSpriteNode(imageNamed: "1.png")

(2)在didMoveToView()方法中实现场景的布局,即背景图像和足球图像的添加。代码如下:

override func didMoveToView(view: SKView) {
    //创建并设置作为背景的精灵对象
    let background = SKSpriteNode(imageNamed: "2.jpg")
    background.position = CGPointMake(CGRectGetMidX(self.frame), 
    CGRectGetMidY(self.frame))                                                  //设置位置
    background.setScale(1.05)                                                   //设置缩放
    self.addChild(background)                                                   //添加
    //设置作为移动主角出现的精灵对象
    sprite.position=CGPoint(x: 400, y: 400)
    sprite.setScale(0.3)
    self.addChild(sprite)
}

此时运行程序,会看到如图3.37所示的效果。

图3.37 运行效果

2.移动精灵

(1)添加变量到GameScene.swift文件中,代码如下:

var lastUpdateTime: NSTimeInterval = 0                             //上一次更新的时间
var dt: NSTimeInterval = 0                                                      //时间间距
let spriteMovePointsPerSec: CGFloat = 480.0             //精灵在每秒钟移动的点
var velocity = CGPointZero                                                      //速度

注意:CGPointZero表示是点(0,0)

(2)添加moveSprite()方法,在此方法中编写代码,实现精灵的移动。代码如下:

func moveSprite(sprite: SKSpriteNode, velocity: CGPoint) {
    let amountToMove = CGPoint(x: velocity.x * CGFloat(dt), y: 0) //偏移量
    sprite.position = CGPoint(x: sprite.position.x + amountToMove.x,y: 
    sprite.position.y) //设置精灵的位置
}

(3)添加movespriteToward()方法,在此方法中编写代码,实现精灵向前移动的功能。代码如下:

func movespriteToward(location: CGPoint) {
    let offset = CGPoint(x: location.x - sprite.position.x,y: 0) //偏移量
    let length = sqrt(Double(offset.x * offset.x))                             //长度
    let direction = CGPoint(x: offset.x / CGFloat(length),y: 0)  //方向
    velocity = CGPoint(x: direction.x * spriteMovePointsPerSec,y: 0)//速度
}

(4)添加sceneTouched()方法,在此方法中编写代码,实现moveSprite()方法的调用。代码如下:

func sceneTouched(touchLocation:CGPoint) {
        movespriteToward(touchLocation)
}

(5)在touchesBegan()中编写代码,实现触摸屏幕的功能。代码如下:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    let mytouch=touches as NSSet
    let touch = mytouch.anyObject() as! UITouch
    let touchLocation = touch.locationInNode(self)                  //获取触摸位置
    sceneTouched(touchLocation)                                     //调用
}

(6)在update()方法中编写代码,实现数据的更新,进而实现精灵的移动,代码如下:

override func update(currentTime: CFTimeInterval) {
   //判断lastUpdateTime是否大于0
    if lastUpdateTime > 0 {
        dt = currentTime - lastUpdateTime
    } else {
        dt = 0
    }
    lastUpdateTime = currentTime
    moveSprite(sprite, velocity: velocity)
}

此时运行程序,会看到如图3.38所示的效果。

图3.38 运行效果

3.设置边界

在图3.38中可以看到,当单击运行按钮后,场景中足球就开始移动了,但是此足球会一直移动,以至于超出场景的边界,如图3.39所示。

图3.39 效果

以下将解决这一不足。实现一个来回滚动的足球,并且不会超出场景的边界。

(1)添加boundsChecksprite()方法,在此方法中编写代码,实现边界的检测,代码如下:

func boundsChecksprite() {
    //判断足球即精灵是否小于0
    if sprite.position.x <= 0 {
        sprite.position.x = 0
        velocity.x = -velocity.x
}
//判断足球即精灵是否大于场景
    if sprite.position.x >= self.size.width{
        sprite.position.x = self.size.width
        velocity.x = -velocity.x
    }
}

(2)在update()方法中添加以下代码:

lastUpdateTime = currentTime
moveSprite(sprite, velocity: velocity)
boundsChecksprite()

此时运行程序,会看到如图3.40所示的效果。

图3.40 运行效果