Ios SpriteKit是否支持精灵/纹理/形状的密集细分,以便可以自由扭曲?
例如,如果你有一张蹦床的图片,一个角色在上面跳跃。然后,您需要设置蹦床如何在中心弯曲的动画 要做到这一点,我必须采取一个位图,并将其应用到一个密集细分的OpenGL ES网格。然后对其应用纹理。然后使网格变形Ios SpriteKit是否支持精灵/纹理/形状的密集细分,以便可以自由扭曲?,ios,iphone,ipad,opengl-es,sprite-kit,Ios,Iphone,Ipad,Opengl Es,Sprite Kit,例如,如果你有一张蹦床的图片,一个角色在上面跳跃。然后,您需要设置蹦床如何在中心弯曲的动画 要做到这一点,我必须采取一个位图,并将其应用到一个密集细分的OpenGL ES网格。然后对其应用纹理。然后使网格变形 SpriteKit支持此功能还是只能按原样显示纹理?编辑:有关使用iOS 10/tvOS 10/macOS 10.12中提供的SKWarpGeometryAPI的良好选项,请参阅。在这些版本之前,Sprite Kit只能将纹理显示为广告牌-本答案的其余部分解决了2016年之前的情况,如果您
SpriteKit支持此功能还是只能按原样显示纹理?编辑:有关使用iOS 10/tvOS 10/macOS 10.12中提供的
SKWarpGeometry
API的良好选项,请参阅。在这些版本之前,Sprite Kit只能将纹理显示为广告牌-本答案的其余部分解决了2016年之前的情况,如果您针对的是较旧的设备,这可能仍然是相关的
不过,通过使用
SKEffectNode
和一个几何体失真核心图像过滤器,您可能可以获得想要的失真效果。(例如,CibumpTransformation。)在游戏逻辑代码中(在SKScene
子类或您放置它的任何地方)保留对效果节点或其filter
属性的引用,您可以使用setValue:forKey:
为动画的每一帧调整过滤器的参数。iOS 10,已添加允许变形精灵的SKWarpGeometry
。使用包含八个控制点的源栅格和目标栅格定义扭曲,这些点定义扭曲变换;精灵套件将处理镶嵌和其他低级细节
可以直接为精灵设置包裹几何体,或使用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相应地变形
//SpriteKit扭曲几何体示例
//在Xcode 8+中复制以下内容
//并确保您的助手视图处于打开状态
//
导入UIKit
导入PlaygroundSupport
进口SpriteKit
let view=SKView(帧:CGRect(x:0,y:0,宽度:480,高度:320))
let scene=SKScene(大小:view.frame.size)
view.showsFPS=true
view.presentScene(场景)
PlaygroundSupport.PlaygroundPage.current.liveView=view
func drawCanvas1(帧:CGRect=CGRect(x:0,y:0,宽度:200,高度:200))->UIImage{
UIGraphicsBeginImageContext(frame.size)
////星图
设starPath=UIBezierPath()
移动到:CGPoint(x:frame.minX+100.5,y:frame.minY+24))
starPath.addLine(到:CGPoint(x:frame.minX+130.48,y:frame.minY+67.74))
starPath.addLine(到:CGPoint(x:frame.minX+181.34,y:frame.minY+82.73))
starPath.addLine(到:CGPoint(x:frame.minX+149,y:frame.minY+124.76))
starPath.addLine(到:CGPoint(x:frame.minX+150.46,y:frame.minY+177.77))
starPath.addLine(到:CGPoint(x:frame.minX+100.5,y:frame.minY+160))
starPath.addLine(到:CGPoint(x:frame.minX+50.54,y:frame.minY+177.77))
starPath.addLine(到:CGPoint(x:frame.minX+52,y:frame.minY+124.76))
starPath.addLine(到:CGPoint(x:frame.minX+19.66,y:frame.minY+82.73))
starPath.addLine(到: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()
让image=UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsSendImageContext()
返回图像
}
类控制节点:SKShapeNode{
重写init(){
super.init()
self.path=CGPath(ellipseIn:CGRect.init(x:0,y:0,宽度:10,高度:10),变换:nil)
self.fillColor=UIColor.red
self.isUserInteractionEnabled=true
}
必需的初始化?(编码器aDecoder:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
typealias UpdateHandler=(控制节点)->()
变量位置更新:UpdateHandler?=nil
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
self.fillColor=UIColor.yellow
}
覆盖功能触摸移动(touchs:Set,带有事件:UIEvent?){
如果让touch=touch.first,则让parent=self.parent{
让pos=触摸位置(在:父项中)。应用(CGAffineTransform(translationX:-5,y:-5))
self.position=pos
职位更新?(自我)
}
}
覆盖函数touchesend(touchs:Set,带有事件:UIEvent?){
self.fillColor=UIColor.red
}
变量位置:向量_float2{
如果let parent=self.parent{
让size=parent.frame.size
设pos=self.position.application(CGAffineTransform(translationX:-size.width/2+5,y:-size.height/2+5))
返回向量2(
x:浮动(1+位置x/尺寸宽度),
y:浮动(1+位置y/尺寸高度)
)
}
返回向量_float2(x:0,y:0)
}
}
延伸斯普瑞泰诺{
func addControlNode(x:CGFloat,y:CGFloat)->ControlNode{
让节点=控制节点()
node.position=CGPoint(
x:x*frame.width-frame.width/2-5,
y:y*frame.height-frame.height/2-5
)
self.addChild(节点)
返回节点
}
}
let texture=SKTexture(图像:drawCanvas1())
let image=SKSpriteNode(纹理:纹理)
image.position=CGPoint(x:200,y:160)
scene.addChild(图像)
让控制点:[(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),
]
让sourcePositions=controlPoints.map{
向量_float2.init(Float($0.x),Float($0.y))
}
变量controlNodes:[ControlNode]=[]
controlPoints.forEach{controlNodes.append(image.addControlNode(x:$0.x,y:$0.y))}
对于中的节点
// 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)
}
}