在 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
截图:
动图:
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 屏幕。我们通过虚假的视觉暂留维持屏幕上的图像和位置,这样我们的大脑和意识就可以计算出某些东西在屏幕上“移动”的速度有多快。
在现实生活中,我们有近乎无限数量的“帧”来处理运动、深度和各种其他线索,因此我们很少这样做。
我们仍然这样做,但感觉不太明显,因为我们有近乎无限数量的帧可供调用。
下面三张图片做了不同的事情,以不同的方式揭示了这一点。
第一个是线速度,瞬间加速到它的旋转速度并瞬间停止。
第二个有一个斜坡上升和斜坡下降到它的旋转速度,它具有更高的峰值旋转速度。这对大脑有一个有趣的影响,使它能够为即将达到的速度做好准备。
决赛有很多虚假的运动模糊(对于真实世界的运动图形使用来说太多了),这表明模糊在解决这个问题的效果方面是多么有效,以及为什么慢快门速度对电影制作如此重要。
加速和减速:
严重模糊:
关于ios - SpriteKit : sprite looks blurry (with ghosting) at high velocity but fine at low velocity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47320322/