• 物理推力

为了避免monkey“落下”,需要用物理推力让它重新跳起来。

这时要在spawnEnemy()后添加一个新的method:

func jumpPlayer() {  
  // 1 
  let impulse =  CGVector(dx: 0,dy: 75)  
  // 2 
  player.physicsBody?.applyImpulse(impulse)  
}

再回顾一下上述步骤:

首先创建一个固定数值推动力的CGVector,规定monkey跳起的距离。我也是尝试了多次才总结出具体数值的。
用applyImpulse()制造推力,再转化为线速度和角速度推力。理论上,monkey在穿行太空的时候还会旋转,所以刚刚才要将physics body设定为不旋转。
代码在被调用之前,monkey是不能跳起来的;要使monkey跳起来,就要重写点击屏幕时调用的那个method。在jumpPlayer()底下复制这些代码:

override func touchesBegan(touches: Set<NSObject>,withEvent event: UIEvent) { jumpPlayer() }

点击屏幕时,自动调用这些method。

现在就差一步了——在 didMovetoView(_:)后添加如下代码:

// 1 
let collisionFrame = CGRectInset(frame,0,-self.size.height * 0.2)  
// 2 
physicsBody = SKPhysicsBody(edgeLoopFromrect: collisionFrame)

代码会在屏幕边缘产生一个特殊的physics body,避免monkey飞出或者坠落在太空中。现在回顾一下上述代码:

首先创造一个可通过CGRectInset()扩大或缩小至多20%的矩形,即monkey的活动范围。monkey的轮廓可以稍微消失在屏幕外,但不能完全消失不见。
然后设定场景本身的physics body。刚刚创建的physics body是圆的,此处将它变为一个循环边,即“矩形的边缘”,不过听上去更简洁些。
编写完成后运行,就能看到如下场景:

一只蹦蹦跳跳的小monkey出现啦!

  • 碰撞检测

到目前为止,如果monkey遇到敌人,可以跳过去;但是跟敌人相撞的话,什么效果都没有,所以需要在游戏中添加碰撞检测(collision detection),有如下几步:

  1. 为所有sprite创建physics body:现在monkey已经有了一个physics body,但是敌人还没有,所以先完成这一步。
  2. 为每个physics body设定category(类别)和contact(接触点):这一步为sprite分类,比如为monkey和敌人设定不同的类别;同样可以在特定的physics body和其他类别的physics body之间设定“contact(接触点)”。
  3. 设置Contact Delegate:设定两个physics body何时接触。要搞清不同的physics body属于哪个类别,是敌人还是monkey。大功告成!
    还记得怎么给monkey添加physics body吗?现在轮到为敌人的sprite添加physics body了,来制造碰撞效果。

首先将如下所示添加至GameScene.swift最顶端:

enum BodyType: UInt32 {  
  case player = 1  
  case enemy = 2  
  case ground = 4  
}

这里要做的就是为每个sprite创建类别。ground number不是针对sprite,而是针对应用边框设定的,所以当monkey碰到屏幕边缘时会弹起,而不是落到屏幕之外!

接下来,执行SKPhysicsContactDelegate协定,标记GameScene(游戏场景):

class GameScene: SKScene,SKPhysicsContactDelegate { 

协议的作用是保证代码执行特定的method。此处执行针对两个physics body相撞的method。然后调整contactDelegate的值,将如下代码添加到didMovetoView(_:)末尾:

physicsWorld.contactDelegate = self 

完成后,两个physics body碰撞时,物理世界就会自动调用代码中的method。

在spawnEnemy()末尾添加如下代码:

// 1  
enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.width/4)  
// 2  
enemy.physicsBody?.dynamic = false  
// 3  
enemy.physicsBody?.affectedByGravity = false  
// 4  
enemy.physicsBody?.allowsRotation = false  
// 5  
enemy.physicsBody?.categoryBitMask = BodyType.enemy.rawValue  
// 6  
enemy.physicsBody?.contactTestBitMask = BodyType.player.rawValue  
// 7  
enemy.physicsBody?.collisionBitMask = 0

此处稍稍解释一下:

  1. 为敌人创建physics body。physics body不一定要跟sprite的形状完全吻合,近似就好。这里用的是圆形,半径设为sprite的1/4,免得碰撞效果太猛。
  2. 把dynamic关掉,实现物理控制sprite。
  3. 防止引力对sprite的影响。这一步不言自明,主要让敌人的sprite避免物理引力的干扰。
  4. 这一步是为了避免sprite在physics body碰撞时旋转。
  5. 将类别位掩码设为之前设置过的敌人类别。
  6. 敌人和monkey接触时,Sprite Kit发出提醒。
  7. 为monkey设置 collisionBitMask后,当接触到敌人时,两者会互相弹开;如果不想要这种效果,将值设为0。

将如下所示添加到didMovetoView(_:)的后面:

physicsBody?.categoryBitMask = BodyType.ground.rawValue  

player.physicsBody?.categoryBitMask = BodyType.player.rawValue  
player.physicsBody?.contactTestBitMask = BodyType.enemy.rawValue  
player.physicsBody?.collisionBitMask = BodyType.ground.rawValue

这里为monkey和ground设置类别和碰撞位掩码,让两者彼此碰撞;在monkey和敌人之间设置“contact(接触点)”。

现在到了最重要的一步,完善碰撞检测,执行之前提到的method来处理“contacts”:

func didBeginContact(contact: SKPhysicsContact) {  
  let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask  
  switch(contactMask) {  
  case BodyType.player.rawValue | BodyType.enemy.rawValue:  
    let secondNode = contact.bodyB.node  
    secondNode?.removeFromParent()  
    let firstNode = contact.bodyA.node  
    firstNode?.removeFromParent()  
  default:  
    return  
  }  
}

因为之前已将场景设置为物理世界的contactDelegate,两个physics body碰撞时会自动调用这个method。

它将两个位掩码结合成一个单个的接触点掩码,检验是否是monkey和敌人相撞,如果是,就将两者从屏幕上移除。

编写完成后运行,效果如下:

转自:http://www.csdn.net/article/2015-05-26/2824772-sprite-kit-for-kids-with-swift/3

Swift开发Sprite Kit游戏实践三:物理推力与碰撞检测的更多相关文章

  1. Swift开发Sprite Kit游戏实践三:物理推力与碰撞检测

    物理推力为了避免monkey“落下”,需要用物理推力让它重新跳起来。现在轮到为敌人的sprite添加physicsbody了,来制造碰撞效果。首先将如下所示添加至GameScene.swift最顶端:这里要做的就是为每个sprite创建类别。此处执行针对两个physicsbody相撞的method。physicsbody不一定要跟sprite的形状完全吻合,近似就好。这里用的是圆形,半径设为sprite的1/4,免得碰撞效果太猛。把dynamic关掉,实现物理控制sprite。防止引力对sprite的影响

  2. 用Swift做个游戏Lecture06 —— 碰撞的检测

    collisionBitMask告知能与哪些物体碰撞。确实,如果通过自己实时检测实在过于劳累,何不让SpriteKit来帮你代劳,每当物体之间发生碰撞了,立马通知你来处理事件。正处于游戏的状态。Player因为不小心碰到障碍物失败下落时刻。标识符,记录Player是否碰撞了仙人掌。好吧,请看lecture02中的时间间隔图,匆忙的你找找原因,试试解决吧。

  3. angularjs – 为什么在使用离子滚动时需要$parent来启用ng-click功能?

    我使用以下版本:>Ionic,v1.0.0-beta.14>AngularJSv1.3.6路线配置:控制器配置:查看配置:正如您在视图中看到的,我需要在以下字段中使用$parent来使其工作:>ng-model=“$parent.search_contact”>ng-repeat=“联系$parent.filteredContacts=(contactsToBeInvited|filter:sea

  4. angularjs – Angular TypeError:无法在字符串”上创建属性

    单击“添加”后尝试清除输入框,就像这个人在thistutorial中所做的那样.我使用这个简短的代码重新创建了错误,而没有使用API.您还可以查看Plunker.HTMLJS似乎我可以添加1项,但在第二个我得到此错误:您没有以正确的方式清理联系人对象.在Add()函数中,更改:至:ForkedPlunker

  5. angular2的组件传值Input和Output

    #parent-to-child

  6. ios – 雪碧套装套装和最大为跳

    但是有些情况下,当与空气…

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部