SpriteKit(10) - 物理引擎

边界效应

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        addStaticShapeNode()
       
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let node = SKSpriteNode()
            node.position = touch.location(in: self)
            node.size = CGSize(width: 40, height: 40)
            node.color = UIColor.randomColor
            node.physicsBody = SKPhysicsBody(rectangleOf: node.frame.size)
            self.addChild(node)
        }
    }
    
    //创建一个不规则的静态物体
    func addStaticShapeNode() {
        let shapeNode = SKShapeNode()
        shapeNode.position = CGPoint.zero
        let path = CGMutablePath()
        let point_1 = CGPoint(x: self.frame.midX - 59, y: 0)
        let point_2 = CGPoint(x: point_1.x + 59, y: point_1.y + 59)
        let point_3 = CGPoint(x: point_1.x + 100, y: point_1.y )
        let point_4 = CGPoint(x: point_1.x + 59, y: point_1.y - 59)
        let point_5 = point_1
        path.move(to: point_1)
        path.addLine(to: point_2)
        path.addLine(to: point_3)
        path.addLine(to: point_4)
        path.addLine(to: point_5)
        shapeNode.path = path
        shapeNode.strokeColor = UIColor.white       //填充颜色
        shapeNode.fillColor = UIColor.red           //线颜色
        shapeNode.lineWidth = 1                     //线宽
        shapeNode.glowWidth = 4                     //光晕
        shapeNode.lineJoin = .round                 //线连接方式
        shapeNode.physicsBody = SKPhysicsBody(polygonFrom: path)//设置物理引擎
        shapeNode.physicsBody?.isDynamic = false  //设置为静态物体
        self.addChild(shapeNode)
    }
    
}

extension UIColor {
    //返回随机颜色
    class var randomColor:UIColor{
        get{
            let red = CGFloat(arc4random()%256)/255.0
            let green = CGFloat(arc4random()%256)/255.0
            let blue = CGFloat(arc4random()%256)/255.0
            return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
        }
    }
}
物理引擎

理解

  • 物体有三种 : 动态的(往下落的小方块),静态的(中间不规则图形),边(底部地板)
  • 每个节点都有对应的物理引擎. SKPhysicsBody.也就是每一个节点都需要对它进行设定.(从代码中简单体会就好了.),各种各样的设置可以直接看SKPhysicsBody有什么可以设置的属性.比较容易理解.

物体间连接

//物体连接 :
//SKPHysicsJointFix           固定连接  在某个参考点混合两个主体在一起.固定联合用于创建以后可以打散的复杂形状
//SKPHysicsJointSliding       滑动连接  允许两个主体的锚点眼选定的滑动轴
//SKPHysicsJointSpring        弹簧连接  就像弹簧那样,它的长度是两个主体之间的初始距离
//SKPHysicsJointLimit         限制连接  限定了两个主体之间的最大距离,就像他们用绳子连接那样
//SKPHysicsJointPin           针连接    允许两个主体独立的绕锚点旋转,就像钉在一起那样.
抽象图
import SpriteKit
class GameMix: SKScene {
 
    override func didMove(to view: SKView) {
        self.size = UIScreen.main.bounds.size
        self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        setupContext()
    }
    
    //设置场景内容
    func setupContext() {
        //创建一个地板
        let ground = SKSpriteNode()
        ground.size = CGSize(width: self.frame.width, height: 10)
        ground.color = UIColor.red
        ground.position = CGPoint(x: self.frame.midX, y: 30)
        ground.physicsBody = SKPhysicsBody(rectangleOf: ground.size)
        ground.physicsBody!.isDynamic = false
        self.addChild(ground)
        print(ground.frame)
        
        //创建中心圆节点
        let centerNode = SKShapeNode()
        centerNode.path = UIBezierPath(ovalIn: CGRect(x: -10, y: -10, width: 20, height: 20)).cgPath
        centerNode.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
        centerNode.physicsBody = SKPhysicsBody(circleOfRadius: 10)
        centerNode.fillColor = UIColor.red
        centerNode.name = "center"
        self.addChild(centerNode)
        
        let angle = CGFloat.pi/10.0
        var first : SKNode?
        var previous : SKNode?
        
        for i in 0...20 {
            //计算外围圆球的x,y
            let a = Double(angle) * Double(i)
            let x = 100 * cos(a) + Double(centerNode.position.x)
            let y = 100 * sin(a) + Double(centerNode.position.y)
            
            let n = SKShapeNode()
            n.path = UIBezierPath(ovalIn: CGRect(x: -10, y: -10, width: 20, height: 20)).cgPath
            n.position = CGPoint(x: x, y: y)
            n.physicsBody = SKPhysicsBody(circleOfRadius: 10)
            n.physicsBody?.friction = 1.0
            n.physicsBody?.restitution = 1.0
            self.addChild(n)
            
            //弹簧 : 与中心圆连接
            let joint = SKPhysicsJointSpring.joint(withBodyA: centerNode.physicsBody!,
                                                   bodyB: n.physicsBody!,
                                                   anchorA: centerNode.position,
                                                   anchorB: n.position)
            joint.damping = 0.2
            joint.frequency = 10.0
            self.physicsWorld.add(joint)
            
            //限定外围两个球之间的距离
            if previous != nil {
                let limit = SKPhysicsJointLimit.joint(withBodyA: previous!.physicsBody!,
                                                      bodyB: n.physicsBody!,
                                                      anchorA: previous!.position,
                                                      anchorB: n.position)
                limit.maxLength = 30
                self.physicsWorld.add(limit)
            }else {
                first = n
            }
            previous = n
        }
        //给最后外围两个球之间限定距离
        let limit = SKPhysicsJointLimit.joint(withBodyA: previous!.physicsBody!,
                                              bodyB: first!.physicsBody!,
                                              anchorA: previous!.position,
                                              anchorB: first!.position)
        limit.maxLength = 30
        self.physicsWorld.add(limit)
    }
    
    
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let node = self.childNode(withName: "center")
        node?.physicsBody?.applyImpulse(CGVector(dx: 100, dy: 200))
        node?.physicsBody?.restitution = 1.0
        node?.physicsBody?.friction = 1.0

    }
}
连接
物体间连接.gif

参考博文 :
[SpriteKit] 通过检测掩码进行物理识别

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

推荐阅读更多精彩内容