2018-01-15 CHAPTER3 - SKAction

昨天一天把SKAction常见的用法都实操过了一遍,基本都实现了sample code中要实现的需求。先总结如下:

  1. 最基本的SKAction.move(to:)和 SKAction.move(by:)用法

学过英语的都从字面上能理解到move to和move by的区别,
move to代表具体移动到哪个位置CGPoint,
而move by的话是指sprite移动的矢量offset(大概可以这样理解)。
这个太简单了,就不举例了。

  1. Sequence action

其实sequence action就是将一个SKAction数组里面的action依次执行。首先依次定义好单独的SKAction,然后通过以下方法将之前定义好单独的SKAction append进来

let actionSequence:[SKAction] = []

actionSequence.append(action)

然后通过以下方法依次执行各个action:

run.SKAction(SKAction.sequence(actionAction))
  1. Wait-for-duration action
    在执行sequence的SKAction时,有时需要在两个动作之间有一些间歇时间,我们可以通过以下方法实现:
let action1 = SKAction()
        
let action2 = SKAction()
        
let actionWait = SKAction.wait(forDuration: 2.0)
   
zombie.run(SKAction.sequence([action1,actionWait,action2]))

然后action1和action2在执行时,中间就会停顿2秒

  1. Run-block action

如果想在sequence里面加一些打log的动作,可通过以下方法实现:

let logMessage = SKAction.run() {
  print("Reached bottom!")
}
  1. Reversing actions
    所谓的reverse,就是把可逆的action进行反向操作,比如move(by:),如下图所示


    image.png

    用法如下:

let reverseMid = actionMidMove.reversed()
  1. Repeat & RepeatForever actions
    前者是指定重复动作的次数,用法如下:
let repeatAction = SKAction.repeat(SKAction, count: Int)

后者是永远重复,用法如下:

let repeatAction = SKAction.repeatForever(SKAction)
  1. 在教程中间,插了一个取最小值与最大值之间随机数的算法,如下:
extension CGFloat {
  static func random() -> CGFloat {
//arc4random()是返回UInt32以内的一个随机数,UInt32.max是UInt32内的最大值,前者除以后者得到了一个0-1之间的随机数。
    return CGFloat(Float(arc4random()) / Float(UInt32.max))
  }
  static func random(min: CGFloat, max: CGFloat) -> CGFloat {
//首先断言最小值应该小于最大值,然后下面这个公式应该就不用赘述了
    assert(min < max)
    return CGFloat.random() * (max - min) + min
  }
}
  1. 在该section中,sample创建了很多元素,比如僵尸啊,敌人啊,猫猫狗狗之类的,他们都是用了一个spawnXXX()的方法将sprite素材加载出来、初始化位置(可能是固定的,也可能位置是随机的)、然后匹配一些初始化的动作。如果场景初始化的时候需要他们出现,则直接将spawnXXX()的方法在didMove()中进行调用即可,比如如下所示的方法:
func spawnEnemy() {
  let enemy = SKSpriteNode(imageNamed: "enemy")
  enemy.position = CGPoint(
    x: size.width + enemy.size.width/2,
    y: CGFloat.random(
      min: playableRect.minY + enemy.size.height/2,
      max: playableRect.maxY - enemy.size.height/2))
  addChild(enemy)
  let actionMove =
    SKAction.moveTo(x: -enemy.size.width/2, duration: 2.0)
  enemy.run(actionMove)
}

9.在创建敌人的时候使用了弱引用weak reference,原文的解释如下:

Note: You are using a weak reference to self here. Otherwise the closure passed to run(_ block:) will create a strong reference cycle and result in a memory leak.

暂时对内存泄漏的了解不是太多,先暂时知其然吧,后面再来看weak/strong reference的专题文章。

run(SKAction.repeatForever(
  SKAction.sequence([SKAction.run() { [weak self] in
                      self?.spawnEnemy()
                    },
                    SKAction.wait(forDuration: 2.0)])))

10.Remove-from-parent action
这个方法就是不用sprite的时候无情干掉,免得占用内存,浪费资源,用法如下:

 let actionRemove = SKAction.removeFromParent()
enemy.run(SKAction.sequence([actionMove, actionRemove]))

这个方法removeFromParent()顾名思义就是从他的父节点中移除他,不仅适用于SKAction也适用于node节点的移除

  1. Animation action
    这个就是序列帧素材的动画action,用法如下:
// 1
var textures:[SKTexture] = []
// 2
for i in 1...4 {
  textures.append(SKTexture(imageNamed: "zombie\(i)"))
}
// 3
textures.append(textures[2])
textures.append(textures[1])
// 4
zombieAnimation = SKAction.animate(with: textures,
  timePerFrame: 0.1)
//创建好动画后,就直接在sprite节点run这个动画即可
zombie.run(SKAction.repeatForever(zombieAnimation))
  1. Stop animation
    用过一个key介质来控制动画的开始和停止
func startZombieAnimation() {
  if zombie.action(forKey: "animation") == nil {
    zombie.run(
      SKAction.repeatForever(zombieAnimation),
      withKey: "animation")
} }
func stopZombieAnimation() {
  zombie.removeAction(forKey: "animation")
}
  1. Scale actions
    初始化scale
    cat.setScale(0)
    然后就是scale(to:) scale(by:)

  2. Rotate actions
    rotate(byAngle: )
    rotate(toAngle: )
    注:swift中π的用法为Double.pi

  3. Group actions
    之前学到的actions都是串行的,如果我们想让多个动作并行,应该怎么做呢?比如sample项目中的小猫,我们要他在rotate的同时,也要scale,那么group action的用法就派上用场了,方法如下:

//fullScale为scale的action, fullWiggle为rotate的action
let group = SKAction.group([fullScale, fullWiggle])

15.Collision detection
因为SK中有强大的物理引擎碰撞检测,所以我就打算跳过这个不学,所以此处略(不过还是把sample code贴进来做note),看了一下下面的sample code,大概的意思就是通过frame.intersects看不同sprite之间的交集,如果交集上了,就算是碰撞了

func zombieHit(cat: SKSpriteNode) {
  cat.removeFromParent()
}
func zombieHit(enemy: SKSpriteNode) {
  enemy.removeFromParent()
}
func checkCollisions() {
  var hitCats: [SKSpriteNode] = []
  enumerateChildNodes(withName: "cat") { node, _ in
    let cat = node as! SKSpriteNode
    if cat.frame.intersects(self.zombie.frame) {
      hitCats.append(cat)
    }
  }
  for cat in hitCats {
    zombieHit(cat: cat)
  }
  var hitEnemies: [SKSpriteNode] = []
  enumerateChildNodes(withName: "enemy") { node, _ in
    let enemy = node as! SKSpriteNode
    if node.frame.insetBy(dx: 20, dy: 20).intersects(
      self.zombie.frame) {
      hitEnemies.append(enemy)
    }
  }
  for enemy in hitEnemies {
    zombieHit(enemy: enemy)
  }

16.Sound actions
播放声音,用法如下:

  run(SKAction.playSoundFileNamed("hitCat.wav",
  waitForCompletion: false))

好了,SKAction的笔记大概就记到这了,本Section后还有三个challenges,现在就去完成它们。

PS:中英文夹杂做笔记切换好累啊,从下一篇起,尝试使用英文来记了,顺便也可以练习丢了很久的英文写作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容