SpriteKit是否支持精灵/纹理/形状的密集镶嵌,以便它可以自由变形? [英] Does SpriteKit support dense tessellation of a sprite / texture / shape so it can be warped freely?

查看:285
本文介绍了SpriteKit是否支持精灵/纹理/形状的密集镶嵌,以便它可以自由变形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,如果您有蹦床的图像,并且有一个跳跃的角色。然后你想要设想蹦床在中心弯曲的方式。

For example if you have an image of a trampoline, and a character jumping on it. Then you want to animate how the trampoline bends down in the center.

要做到这一点,我必须采用位图并将其应用于密集镶嵌的OpenGL ES网格。然后将纹理应用于它。然后变形网格。

To do this I would have to take a bitmap and apply it to a densely tessellated OpenGL ES mesh. Then apply texture to it. Then deform the mesh.

SpriteKit是否支持此功能,还是只能按原样显示纹理?

Does SpriteKit support this or can it only display textures as-is?

推荐答案

使用iOS 10,添加了 SKWarpGeometry ,允许您变形精灵。使用包含八个控制点的源和目标网格定义扭曲,这些点定义扭曲变换; Sprite Kit将处理曲面细分和其他低级细节。

With iOS 10, SKWarpGeometry has been added that allows you to deform sprites. Warps are defined using a source and destination grid containing eight control points, these points define the warp transform; Sprite Kit will take care of tessellation and other low level details.

您可以直接设置精灵的包裹几何体,或使用SKActions设置变形动画。

You can set the wrap geometry for a sprite directly, or animate warping with SKActions.

SKAction.animate(withWarps: [SKWarpGeometry], times: [NSNumber]) ->     SKAction?
SKAction.animate(withWarps: [SKWarpGeometry], times: [NSNumber], restore: Bool) -> SKAction?
SKAction.warp(to: SKWarpGeometry, duration: TimeInterval) -> SKAction?






2016年11月更新

在Xcode 8+上,可以在游乐场中使用以下代码片段:拖动控制点,看看生成的SKSpriteNode会相应地变形。

On Xcode 8+, the following code snippet can be used in a playground: Drag the control points and see the resulting SKSpriteNode get deformed accordingly.

// SpriteKit warp geometry example
// Copy the following in an Xcode 8+ playground
// and make sure your Assistant View is open
// 


import UIKit
import PlaygroundSupport
import SpriteKit


let view = SKView(frame: CGRect(x: 0, y: 0, width: 480, height: 320))

let scene = SKScene(size: view.frame.size)


view.showsFPS = true
view.presentScene(scene)

PlaygroundSupport.PlaygroundPage.current.liveView = view


func drawCanvas1(frame: CGRect = CGRect(x: 0, y: 0, width: 200, height: 200)) -> UIImage {

    UIGraphicsBeginImageContext(frame.size)

    //// Star Drawing
    let starPath = UIBezierPath()
    starPath.move(to: CGPoint(x: frame.minX + 100.5, y: frame.minY + 24))
    starPath.addLine(to: CGPoint(x: frame.minX + 130.48, y: frame.minY + 67.74))
    starPath.addLine(to: CGPoint(x: frame.minX + 181.34, y: frame.minY + 82.73))
    starPath.addLine(to: CGPoint(x: frame.minX + 149, y: frame.minY + 124.76))
    starPath.addLine(to: CGPoint(x: frame.minX + 150.46, y: frame.minY + 177.77))
    starPath.addLine(to: CGPoint(x: frame.minX + 100.5, y: frame.minY + 160))
    starPath.addLine(to: CGPoint(x: frame.minX + 50.54, y: frame.minY + 177.77))
    starPath.addLine(to: CGPoint(x: frame.minX + 52, y: frame.minY + 124.76))
    starPath.addLine(to: CGPoint(x: frame.minX + 19.66, y: frame.minY + 82.73))
    starPath.addLine(to: CGPoint(x: frame.minX + 70.52, y: frame.minY + 67.74))
    starPath.close()
    UIColor.red.setFill()
    starPath.fill()
    UIColor.green.setStroke()
    starPath.lineWidth = 10
    starPath.lineCapStyle = .round
    starPath.lineJoinStyle = .round
    starPath.stroke()

    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}

class ControlNode : SKShapeNode {

    override init() {
        super.init()
        self.path = CGPath(ellipseIn: CGRect.init(x: 0, y: 0, width: 10, height: 10), transform: nil)
        self.fillColor = UIColor.red
        self.isUserInteractionEnabled = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    typealias UpdateHandler = (ControlNode) -> ()
    var positionUpdated: UpdateHandler? = nil

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.fillColor = UIColor.yellow
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first, let parent = self.parent {
            let pos = touch.location(in: parent).applying(CGAffineTransform(translationX: -5, y: -5))
            self.position = pos
            positionUpdated?(self)
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.fillColor = UIColor.red
    }

    var warpPosition: vector_float2 {
        if let parent = self.parent {
            let size = parent.frame.size
            let pos = self.position.applying(CGAffineTransform(translationX: -size.width/2 + 5, y: -size.height/2 + 5))
            return vector_float2(
                x: Float(1 + pos.x / size.width),
                y: Float(1 + pos.y / size.height)
            )
        }
        return vector_float2(x: 0, y: 0)
    }
}

extension SKSpriteNode {
    func addControlNode(x: CGFloat, y: CGFloat) -> ControlNode {
        let node = ControlNode()
        node.position = CGPoint(
            x: x * frame.width - frame.width / 2 - 5,
            y: y * frame.height - frame.height / 2 - 5
        )
        self.addChild(node)
        return node
    }
}




let texture = SKTexture(image: drawCanvas1())
let image = SKSpriteNode(texture: texture)
image.position = CGPoint(x: 200, y: 160)
scene.addChild(image)

let controlPoints: [(x:CGFloat, y:CGFloat)] = [
    (0, 0),
    (0.5, 0),
    (1.0, 0),
    (0, 0.5),
    (0.5, 0.5),
    (1.0, 0.5),
    (0, 1.0),
    (0.5, 1.0),
    (1.0, 1.0),
]

let sourcePositions = controlPoints.map {
    vector_float2.init(Float($0.x), Float($0.y))
}

var controlNodes: [ControlNode] = []

controlPoints.forEach { controlNodes.append(image.addControlNode(x: $0.x, y: $0.y)) }


for node in controlNodes {
    node.positionUpdated = {
        [weak image]
        _ in
        let destinationPoints = controlNodes.map {
            $0.warpPosition
        }
        image?.warpGeometry = SKWarpGeometryGrid(columns: 2, rows: 2, sourcePositions: sourcePositions, destinationPositions: destinationPoints)
    }
}

PS:我提到了 SKWarpGeometry 文档。

PS: I referred to the SKWarpGeometry documentation.

这篇关于SpriteKit是否支持精灵/纹理/形状的密集镶嵌,以便它可以自由变形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆