SpriteKit: the sprite looks blurry (with a halo) at high speed, but excellent at low speed

When used in SpriteKit high speed (linear or angular), sprites look vague, as if ghosts accompanied the "ghosts". Sprite looks great at low speeds.

Below is a screenshot and GIF illustrating the blur / halo problem with high linear velocity, but the problem also occurs with the angularVelocity property .

Ball (use SKScene below to reproduce the blur):

    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

Looks nice:

ball.physicsBody?.velocity.dy = -200

Looks blurry:

ball.physicsBody?.velocity.dy = -1200

Screenshot:

enter image description here

GIF:

enter image description here

SKScene (run the project and the real scene to see the blur):

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
    }
}
+4
source share
1 answer

?

"" . 60 . , , - "" .

"" , .

, , .

, -.

- , .

, . , , .

( ), , , .

: enter image description here

:

enter image description here

:

enter image description here

+2

Source: https://habr.com/ru/post/1689349/


All Articles