SpriteKit 是否支持精灵/纹理/形状的密集镶嵌,以便可以自由扭曲?

2024-01-25

例如,如果您有一张蹦床的图像,以及一个在上面跳跃的角色。然后您想要制作蹦床如何在中心弯曲的动画。

为此,我必须获取位图并将其应用到密集细分的 OpenGL ES 网格。然后对其应用纹理。然后使网格变形。

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


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

您可以直接设置精灵的包裹几何形状,或使用 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+ 上,可以在 Playground 中使用以下代码片段:拖动控制点并查看生成的 SKSpriteNode 相应变形。

// 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:我提到了SK扭曲几何 https://developer.apple.com/reference/spritekit/skwarpgeometrygrid文档。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpriteKit 是否支持精灵/纹理/形状的密集镶嵌,以便可以自由扭曲? 的相关文章

  • 为什么我们在 @synchronized 块中传递 self ?

    我猜 synchronized 块不依赖于对象 而是依赖于线程 对吗 既然如此 我们为什么要传递 self 呢 synchronized是语言提供的用于创建同步作用域的构造 因为使用简单的全局共享互斥锁效率非常低 因此序列化每个单独的互斥锁
  • 适用于 iOS 的 Google Cast SDK 2.3.0 不支持 64 位

    似乎是适用于 iOS 的 Google Cast SDK 2 3 0 版本 https developers google com cast downloads GoogleCastFramework 2 3 0 Release zip停止
  • 从 Plist 中存储和检索 [重复]

    这个问题在这里已经有答案了 可能的重复 iOS 在 plist 文件中存储两个 NSMutableArray https stackoverflow com questions 6070568 ios store two nsmutable
  • 自动调整大小完成后如何获取帧大小

    我想知道 如何以及何时 viewDidLoad viewWillAppear viewDidAppear 可以获得自动调整大小以适合其父视图的 UIViews 框架大小 从你的问题中不清楚你为什么想要它 但我想这是为了布局你的子视图 幸运的
  • iPhone 上的最大蓝牙连接数是多少?

    如果您对此有任何见解 那么了解连接之间是否存在很大的延迟也会很高兴 蓝牙协议规定连接是点对点的 因此称为 配对 但不同的站可以同时使用不同的配置文件 每个配置文件一次仅支持一个连接 您可以同时与汽车建立立体声耳机连接并与笔记本电脑建立数据连
  • iOS 4.2.1 丢失文件?

    这是我第一次使用最新的 xcode 3 2 5 和新的 iOS 4 2 1 当我在设备上运行应用程序时 我收到以下运行时错误 无法读取 Developer Platforms iPhoneOS platform DeviceSupport
  • 使用 UIActionSheet 更改视图时工具栏项目消失

    当从 a 启动视图时UIActionSheet按钮 通过导航栏后退按钮返回视图后 工具栏虽然仍然可见 但上面没有任何以前的按钮 自从更新到 iOS 6 以来 这个错误就出现了 并且是在模拟器和仅运行 iOS 6 的设备上测试时发生的 如果我
  • iOS App布局错误,调用状态栏

    在主动通话和应用程序布局期间面临状态栏问题 我正在使用自动布局 当我运行应用程序 然后开始通话时 一切正常 UI 会随着状态栏的更改而正确缩放 但是 如果我首先开始通话 然后运行应用程序 应用程序屏幕会移动到底部 20pt 就像它们对新状态
  • 尝试从独立的 Apple Watch 应用发出网络请求

    当应用程序是独立应用程序时 Apple Watch 是否无法进行网络通话 即使手表已连接到 iPhone 我正在使用新的独立应用程序目标 它没有附带可以发出 WatchConnectivity 请求的配对 iOS 应用程序 我十有八九收到
  • 在 iOS 中录制音频并永久保存

    我制作了 2 个 iPhone 应用程序 可以录制音频并将其保存到文件中并再次播放 其中之一使用 AVAudiorecorder 和 AVAudioplayer 第二个是苹果的在这里说话 http developer apple com l
  • iOS 中的等宽字体是什么?

    我想要在我的 iOS 应用程序中为 UILabel 使用等宽字体 不幸的是 我找不到一个 甚至 美国打字机 实际上也不是等宽的 XCode 中可用的等宽字体是什么 iOS 等宽字体 Courier Courier Bold Courier
  • iPad 2 的 HTML5 源元素错误是否已修复?

    根据这个页面 http camendesign com code video for everybody webm http camendesign com code video for everybody webm 第一个 iPad 有一
  • 在 Swift 中检查一个数组是否包含另一个数组的所有元素

    我想为数组编写一个扩展来检查一个数组是否包含另一个数组的所有元素 在我的用例中它是字符串对象 但我一直得到 Cannot convert value of type T Generator Element to expected argum
  • 如果 NSExtensionActivationRule 设置为仅音频,则共享扩展不会出现在有功能的应用程序中

    我正在尝试创建一个共享扩展 用户可以从任何有能力的应用程序上传她的录音 该文档甚至有一个简单的示例 请参阅声明共享或操作扩展支持的数据类型 https developer apple com library content document
  • iPhone SDK - 在后台线程中运行重复进程

    我有一个iPhone我想在其中每隔一段时间在后台执行一个方法的应用程序1第二 所以在我的主线程中 我有以下代码UIViewController viewDidLoad NSTimer timerWithTimeInterval 1 0 ta
  • 如何在ios中以编程方式添加水平间距和垂直间距?

    我在 ios 8 中创建了一个应用程序 因为我有 4 个可垂直使用的标签 它应该在某些条件下更改位置 所以我已禁用自动布局并以编程方式设置约束 现在的问题是 我可以设置水平和垂直位置 宽度和高度的约束 但我找不到任何方法来添加标签之间的水平
  • 具有多种自定义单元格类型的 RxSwift 表视图

    我想知道是否有任何代码示例RxSwift当我可以在一个表视图中使用多个自定义单元格时 例如 我有两个部分 第一部分有 10 个单元格 类型为CellWithImage标识符和第二部分有 10 个带有类型的单元格CellWithVideo标识
  • 为什么 GDB 调试器不断冻结 Xcode 4?

    这真是一个奇怪的错误 我正在开发一个使用相机源的 iPhone 项目 并通过 OpenGL 着色器运行它以对其应用效果 然而 每次我在代码中简单地创建一个新的 GLfloat 时 调试器都会在启动时冻结 我无法复制和粘贴文本 因为整个 XC
  • 应用未能及时恢复

    我在一个非常具体的场景中遇到 未能及时恢复 崩溃 我认为与看门狗相关 仅在从后台恢复时 并且仅在进入后台后在很短的时间内执行此操作 a最多几秒钟 这似乎是相关的崩溃日志 Incident Identifier E30F2238 5B15 4
  • 下标:使用字符串枚举访问我的字典值

    我想做类似的事情 使用字符串枚举访问我的字典值 我试图重载字典的下标但没有成功 访问字典 let district address JsonKeys district 其中 JsonKeys 是 enum JsonKeys String c

随机推荐

  • 更改 SQLite3 中的值

    我将首先展示代码 create table products name text primary key price INTEGER insert into table products name price values coke 8 i
  • pom.xml(Maven 多模块项目)中的 在本地工作,但不在公司服务器上工作

    我在用着
  • 由于与 UserInterfaceState.xcuserstate 冲突而无法合并

    我创建了一个分支并做了很多更改 我提交了更改 然后存档了更改 然后我切换到master分支并尝试进行合并 它说我有未提交的更改 所以我在 master 分支上做了一次提交 看看它在说什么 它说有一个名为 UserInterfaceState
  • 扩展 Scala Enumeration.Val 时如何获得正确的值类型

    虽然 S O 上有很多关于 Scala 枚举困难的问题 但我还没有找到解决我的问题的问题 具体来说 我正在尝试将 Planet 示例从Oracle Java 枚举文档 http docs oracle com javase tutorial
  • Primefaces 菜单栏菜单项宽度

    我在使用菜单项时遇到问题 想要附上照片 但不允许所以如果没有它 问题就很愚蠢 我似乎无法更改下拉菜单的宽度 我已经在我的头脑中包含了一个样式 并在其中包含了一个宽度属性 每个菜单项 但它们没有区别 当菜单项突出显示时 选择栏的宽度是正确的
  • 尝试从 MySQL DB 添加视图时出现“命令执行期间遇到致命错误”

    我正在尝试将 MySQL 数据库中的一些表和视图添加到 VS2005 中的项目中 经过大量研究后 我最终使用了 ADO NET 连接器 它工作得很好 除了尝试使用数据源配置向导添加视图时 我收到 命令执行期间遇到致命错误 错误消息 并且当我
  • tableView.tableHeaderView 已设置但未绘制

    每当我设置 tableHeaderView 时 我都不会在模拟器中看到它 如果我将其添加为子视图 它最终会绘制在节标题下方 知道我在这里缺少什么吗 我有一个 XIB 文件 不过 我没有在 IB 中看到任何影响 headerView 的属性
  • 从 JSF 中的托管 bean 获取资源文件的路径

    我遇到这种情况 我试图在从托管 bean 中放置新的头像图像之前删除用户的旧头像图像 String fileName resources img useravatars getSessionBean getSearchAccount get
  • Dagger v2:将 2 个不同的范围注入到一个对象中

    我将 moduleA 设置为应用程序范围的单例提供程序 将 ModuleB 设置为用户相关的对象提供程序 我的用户显示片段将使用系统范围总线向其他人发送消息并使用用户相关对象进行显示 问题是无法将不同的作用域类注入一个对象 使用 compo
  • 动态设置DIV的高度

    在 Web 应用程序中 我有一个页面 其中包含一个 DIV 该 DIV 具有自动宽度 具体取决于浏览器窗口的宽度 我需要对象的自动高度 DIV 从距顶部屏幕约 300 像素的位置开始 其高度应使其延伸到浏览器屏幕的底部 我有容器 DIV 的
  • invoke virtual 总是动态绑定吗?

    今天我的一位朋友告诉我 如果一条指令是invoke virtual 那么它总是动态绑定 而invokespecial总是静态绑定 这是真的吗 如果是 那么为什么当带有final关键字的方法也调用virtual时呢 请澄清我的这个疑问 从本质
  • 基于 APR 的 Apache Tomcat Native 库的不兼容版本 [1.1.34]

    在我的 openSUSE Leap 42 3 服务器上 在嵌入式 Tomcat 服务器上启动 Spring Boot 2 0 0 M6 应用程序期间 我在日志中看到以下错误 ERROR 30471 main o a catalina cor
  • 检查字符是否为数字?

    我需要检查是否justPrices i substr commapos 2 1 该字符串类似于 blabla 120 在本例中 它将检查 0 是否是一个数字 如何才能做到这一点 您可以使用比较运算符来查看它是否在数字字符范围内 var c
  • 基于 Spring Javaconfig 的按名称自动装配不起作用

    我正在尝试使用基于 Javaconfig 的 Spring 配置 我有两个相同类型的 bean 并尝试通过限定符自动装配它们 但它似乎不起作用 这是我的配置类 Configuration EnableAutoConfiguration Co
  • 从日期选择器获取可用性

    我试图通过单击日期选择器日历中的下一个按钮来获取 homeaway 每天的价格 但没有运气 我当前的代码是这样的 def handle self args options def homeaway self display Display
  • 判断线段的方向是顺时针还是逆时针

    我有一个代表曲线段的二维点 x1 y1 x2 y2 Xn Yn 列表 是否有任何公式可以确定绘制该段的方向是顺时针还是顺时针逆时针 任何帮助表示赞赏 或者 您可以使用一些线性代数 如果按顺序有 a b 和 c 三个点 则执行以下操作 1 c
  • 方法语法“public function direct(){}”在 PHP 中如何工作?

    我现在正在学习 Zend Framework 并遇到了以下语法 class Zend Controller Action Helper Redirector extends Zend Controller Action Helper Abs
  • 为什么不在 java servlet 中创建 pdf 文档? [复制]

    这个问题在这里已经有答案了 我使用 iText Pdfbox 创建 PDF 文档 当我使用独立的 Java 类创建 PDF 时 一切正常 public static void main String args 该文档已正确创建 但我需要从
  • 不使用 SendMessage 和 PostMessage 发送密钥

    是否可以将密钥发送到程序而无需SendMessage and PostMessage API 伪造输入的官方方法不涉及直接发送或发布 Windows 消息 相反 你应该打电话SendInput http msdn microsoft com
  • SpriteKit 是否支持精灵/纹理/形状的密集镶嵌,以便可以自由扭曲?

    例如 如果您有一张蹦床的图像 以及一个在上面跳跃的角色 然后您想要制作蹦床如何在中心弯曲的动画 为此 我必须获取位图并将其应用到密集细分的 OpenGL ES 网格 然后对其应用纹理 然后使网格变形 SpriteKit 是否支持此功能 或者