ios - SpriteKit : sprite looks blurry (with ghosting) at high velocity but fine at low velocity

标签 ios iphone sprite-kit skspritenode skscene

在 SpriteKit 中使用高速(线性或角度)时, Sprite 看起来很模糊,好像有“幽灵”尾随 Sprite 。 Sprite 在低速时看起来很好。

下面是一个屏幕截图和 GIF,说明了高线速度的模糊/重影问题,但该问题也出现在 angularVelocity 属性上。

Ball 代码(使用下面的 SKScene 重现模糊):

    let radius = CGFloat(8)

    let body = SKPhysicsBody(circleOfRadius: radius)
    body.isDynamic = true
    body.affectedByGravity = false
    body.allowsRotation = true
    body.friction = 0
    body.restitution = 0.0
    body.linearDamping = 0.0
    body.angularDamping = 0
    body.categoryBitMask = categoryBitMask

    let ball = SKShapeNode(circleOfRadius: radius)
    ball.physicsBody = body
    ball.physicsBody?.velocity.dx = 0
    ball.physicsBody?.velocity.dy = -1200

看起来不错:

ball.physicsBody?.velocity.dy = -200

看起来模糊:

ball.physicsBody?.velocity.dy = -1200

截图:

enter image description here

动图:

enter image description here

SKScene(放入项目和当前场景以查看模糊度):

import Foundation
import SpriteKit


class TestScene : SKScene, SKPhysicsContactDelegate {
    let BallBitMask                   : UInt32 = 0x1 << 1
    let BottomWallBitMask             : UInt32 = 0x1 << 3
    let TopWallBitMask                : UInt32 = 0x1 << 4
    let RightWallBitMask              : UInt32 = 0x1 << 5
    let LeftWallBitMask               : UInt32 = 0x1 << 6

    let SceneBackgroundColor = UIColor(red: 58/255.0, green: 50/255.0, blue: 96/255.0, alpha: 1.0)

    let HorizontalWallHeight = CGFloat(10)
    let VerticallWallWidth = CGFloat(5)

    override init() {
        super.init()
    }


    override init(size: CGSize) {
        super.init(size: size)
        doInit()
    }


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


    fileprivate func doInit() {
        // Set background
        backgroundColor = SceneBackgroundColor

        // Set scale mode
        scaleMode = .resizeFill

        // Set anchor point to screen center
        anchorPoint = CGPoint(x: 0.5, y: 0.5)

        // Add walls
        layoutWalls()

        // Create ball
        let radius = CGFloat(8)
        let body = SKPhysicsBody(circleOfRadius: radius)
        body.isDynamic = true
        body.affectedByGravity = false
        body.allowsRotation = true
        body.friction = 0
        body.restitution = 0.0
        body.linearDamping = 0.0
        body.angularDamping = 0
        body.categoryBitMask = BallBitMask
        body.collisionBitMask =  TopWallBitMask | RightWallBitMask | BottomWallBitMask | LeftWallBitMask

        let ball = SKShapeNode(circleOfRadius: radius)
        ball.fillColor = UIColor.orange
        ball.physicsBody = body
        ball.physicsBody?.velocity.dx = 0
        ball.physicsBody?.velocity.dy = -1200

        // Add ball to scene
        addChild(ball)
    }


    fileprivate func layoutWalls() {
        // Set wall offset
        let wallOffset = CGFloat(3)

        // Layout bottom wall
        let bottomWallSize = CGSize(width: UIScreen.main.bounds.width, height: HorizontalWallHeight)
        let bottomWall = SKSpriteNode(color: UIColor.red, size: bottomWallSize)
        bottomWall.position.y = -UIScreen.main.bounds.height/2 - bottomWallSize.height/2 - wallOffset
        bottomWall.physicsBody = createWallPhysics(categoryBitMask: BottomWallBitMask, wallSize: bottomWallSize)
        addChild(bottomWall)

        // Layout top wall
        let topWallSize = CGSize(width: UIScreen.main.bounds.width, height: HorizontalWallHeight)
        let topWall = SKSpriteNode(color: UIColor.red, size: topWallSize)
        topWall.position.y = UIScreen.main.bounds.height/2 + topWallSize.height/2 + wallOffset
        topWall.physicsBody = createWallPhysics(categoryBitMask: TopWallBitMask, wallSize: topWallSize)
        addChild(topWall)

        // Layout right wall
        let rightWallSize = CGSize(width: VerticallWallWidth, height: UIScreen.main.bounds.height)
        let rightWall = SKSpriteNode(color: UIColor.blue, size: rightWallSize)
        rightWall.position.x = UIScreen.main.bounds.width/2 + rightWallSize.width/2 + wallOffset
        rightWall.physicsBody = createWallPhysics(categoryBitMask: RightWallBitMask, wallSize: rightWallSize)
        addChild(rightWall)

        // Layout left wall
        let leftWallSize = CGSize(width: VerticallWallWidth, height: UIScreen.main.bounds.height)
        let leftWall = SKSpriteNode(color: UIColor.blue, size: leftWallSize)
        leftWall.position.x = -UIScreen.main.bounds.width/2 - leftWallSize.width/2 - wallOffset
        leftWall.physicsBody = createWallPhysics(categoryBitMask: LeftWallBitMask, wallSize: leftWallSize)
        addChild(leftWall)
    }


    fileprivate func createWallPhysics(categoryBitMask: UInt32, wallSize: CGSize) -> SKPhysicsBody {
        // Create new physics body for wall
        let physicsBody = SKPhysicsBody(edgeLoopFrom: CGRect(x: -wallSize.width/2, y: -wallSize.height/2, width: wallSize.width, height: wallSize.height))
        physicsBody.isDynamic = true
        physicsBody.friction = 0
        physicsBody.restitution = 1.0
        physicsBody.linearDamping = 0
        physicsBody.angularDamping = 0.0
        physicsBody.categoryBitMask = categoryBitMask

        // Return body
        return physicsBody
    }
}

最佳答案

哪一个看起来更幽灵?

眼睛正在执行“技巧”。我们没有能力处理具有快速移动物体的低 60fps 屏幕。我们通过虚假的视觉暂留维持屏幕上的图像和位置,这样我们的大脑和意识就可以计算出某些东西在屏幕上“移动”的速度有多快。

在现实生活中,我们有近乎无限数量的“帧”来处理运动、深度和各种其他线索,因此我们很少这样做。

我们仍然这样做,但感觉不太明显,因为我们有近乎无限数量的帧可供调用。

下面三张图片做了不同的事情,以不同的方式揭示了这一点。

第一个是线速度,瞬间加速到它的旋转速度并瞬间停止。

第二个有一个斜坡上升和斜坡下降到它的旋转速度,它具有更高的峰值旋转速度。这对大脑有一个有趣的影响,使它能够为即将达到的速度做好准备。

决赛有很多虚假的运动模糊(对于真实世界的运动图形使用来说太多了),这表明模糊在解决这个问题的效果方面是多么有效,以及为什么慢快门速度对电影制作如此重要。

线性旋转速率: enter image description here

加速和减速:

enter image description here

严重模糊:

enter image description here

关于ios - SpriteKit : sprite looks blurry (with ghosting) at high velocity but fine at low velocity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47320322/

相关文章:

ios - Swift 如何在按钮单击时显示 Tabbar

ios - 飞溅动画完成后更改 View Controller

iphone - 当后台任务完成时如何向主 UI 线程指示? (在后台执行选择器)

iPhone AlertView 文本字段键盘不可见

ios - 为什么我不能遍历 NSArray?

ios - 帧速率问题 Apple SpriteKit

ios - 如何从 UI 测试中的标签检索变量数据

ios - NSLayoutConstraint 和 "attach"两个标签互相

ios - 体系结构 x86_64/i386 的 undefined symbol

ios - 如何将一个 SKNode 的坐标转换为另一个 SKNode?