You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpriteKit中如何基于触摸实现精灵相对原始位置的跟随移动

嘿,我完全懂你想要的效果——让精灵跟着手指的滑动轨迹同步移动,而不是用SKAction.moveTo那种预先设定路径的方式对吧?这种实时跟随的交互其实比动作类更直接,核心就是监听触摸事件,实时计算位移并更新精灵位置。我给你拆解一下具体的实现步骤,用SpriteKit的常规Swift写法:

核心思路

我们需要记录两个关键状态:触摸开始时的手指位置,以及此时精灵的初始位置。之后在手指滑动过程中,计算手指的移动偏移量,再把这个偏移量叠加到精灵的初始位置上,就能实现精灵跟着手指的滑动轨迹同步移动的效果——就像你说的,精灵从屏幕中心出发,跟着向上滑动的手指一起移动。

具体实现(Swift + SpriteKit)

假设你已经在场景里创建了名为playerSprite的精灵节点,接下来在你的SKScene子类里添加以下代码:

1. 定义变量记录初始状态

先声明两个私有变量,用来存储触摸开始时的手指位置和精灵位置:

private var initialTouchPosition: CGPoint?
private var initialSpritePosition: CGPoint?

2. 监听触摸开始事件

当用户按下屏幕时,记录当前的触摸点(转换为SpriteKit场景坐标系)和精灵的初始位置:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    // 将UI坐标系的触摸点转换为SpriteKit场景坐标系
    initialTouchPosition = touch.location(in: self)
    // 记录精灵当前的初始位置
    initialSpritePosition = playerSprite.position
}

3. 实时更新精灵位置

在手指滑动过程中,计算手指的位移偏移量,然后同步更新精灵的位置:

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first,
          let initialTouchPos = initialTouchPosition,
          let initialSpritePos = initialSpritePosition else { return }
    
    let currentTouchPos = touch.location(in: self)
    // 计算手指从初始位置到当前位置的偏移量
    let offset = CGPoint(x: currentTouchPos.x - initialTouchPos.x,
                         y: currentTouchPos.y - initialTouchPos.y)
    // 更新精灵位置:初始位置 + 手指偏移量
    playerSprite.position = CGPoint(x: initialSpritePos.x + offset.x,
                                    y: initialSpritePos.y + offset.y)
}

4. 触摸结束后重置状态

当用户松开手指或者触摸被取消时,清空记录的初始状态,避免影响下一次触摸操作:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    initialTouchPosition = nil
    initialSpritePosition = nil
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    touchesEnded(touches, with: event)
}
额外优化建议
  • 平滑移动效果:如果你想要更丝滑的跟随感,可以给精灵的位置更新加上一点缓动,比如用短时长的SKAction:

    let targetPosition = CGPoint(x: initialSpritePos.x + offset.x, y: initialSpritePos.y + offset.y)
    playerSprite.run(SKAction.move(to: targetPosition, duration: 0.05))
    

    注意这种方式会有轻微的延迟,适合追求流畅感而非绝对同步的场景。

  • 边界限制:如果不想让精灵移出屏幕,可以在更新位置时加上边界检测:

    let spriteHalfWidth = playerSprite.size.width / 2
    let spriteHalfHeight = playerSprite.size.height / 2
    let minX = spriteHalfWidth
    let maxX = size.width - spriteHalfWidth
    let minY = spriteHalfHeight
    let maxY = size.height - spriteHalfHeight
    
    let targetX = max(minX, min(maxX, initialSpritePos.x + offset.x))
    let targetY = max(minY, min(maxY, initialSpritePos.y + offset.y))
    playerSprite.position = CGPoint(x: targetX, y: targetY)
    
  • 直接跟随手指位置:如果你想要精灵直接跟着手指的当前位置走(而非相对初始位置偏移),那更简单,直接在touchesMoved里把精灵位置设为currentTouchPos即可。

内容的提问来源于stack exchange,提问作者Cryohazards

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:48:55