0
func colorBall() {

let colorize1 = SKAction.colorizeWithColor(UIColor.redColor(), colorBlendFactor: 1.0, duration: 0.1)
let colorize2 = SKAction.colorizeWithColor(UIColor.greenColor(), colorBlendFactor: 1.0, duration: 0.1)
let colorize3 = SKAction.colorizeWithColor(UIColor.blueColor(), colorBlendFactor: 1.0, duration: 0.1)

let actions = [colorize1, colorize2, colorize3]
let randomIndex = Int(arc4random_uniform(3))
self.Ball.runAction(actions[randomIndex])


    }
 var colorBucket = [UIColor]()

func randomColor() -> UIColor {

    if colorBucket.isEmpty {
        fillBucket()

    }

    let randomIndex = Int(arc4random_uniform(UInt32(colorBucket.count)))
    let randomColor = colorBucket[randomIndex]
    colorBucket.removeAtIndex(randomIndex)
    return randomColor

}
  func fillBucket() {
    colorBucket = [UIColor.redColor(), UIColor.greenColor(), UIColor.blueColor()]
}

When I run this code in my game, and print out the color value of my ball, it sometimes prints out numbers like this:

 UIDeviceRGBColorSpace 1 2.98023e-08 2.98023e-08 1

Why does it do this? I just want it to say: UIDeviceRGBColorSpace 0 0 1 1 if it's blue, IDeviceRGBColorSpace 1 0 0 1 if it's red, etc.

How can I keep those numbers from going higher than one, or much lower than one? What makes them do that in my code?

Tiptech
  • 177
  • 1
  • 17

2 Answers2

1

2.98023e-08 is 0.0000000298023. If you look up the value 2.98023e-08 on Google or another search engine, you can find several examples of people getting that value because of rounding errors. Rounding errors occur because of how computers treat floating-point numbers.

It's probably a rounding error from the interpolation code that colorizeWithColor uses, and you get it instead of zero. For practical purposes, when talking about color components about to be displayed to an end user, I'd say that anything smaller than 1/256 can be considered to be zero.

You can test if two floating point numbers are "about equal" like this (typed on my phone, not really guaranteed to work):

func areAboutTheSame(a: Double, b: Double) -> Bool {
    let difference = a-b
    return difference < 1/256 && difference > -1/256
}
Community
  • 1
  • 1
zneak
  • 134,922
  • 42
  • 253
  • 328
  • Do you know how to fix it? Or where I could go to find a solution? – Tiptech Jun 20 '16 at 20:23
  • What do you do that relies on getting an exact 0? That might be what you could fix. It's unlikely that you can get Apple's code to return an exact 0. – zneak Jun 20 '16 at 20:24
  • Because I'm comparing two objects color properties. And if they don't share the exact same RGB values, it'll think that the objects are different colors when they are actually the same. – Tiptech Jun 20 '16 at 20:25
  • Instead, you could check that each component falls within 1/256 of another (or any other threshold that works for you). Subtract the two values and check if the result is between -1/256 and 1/256. In general, you should avoid exact comparisons of floating-point numbers because of this type of problem. – zneak Jun 20 '16 at 20:27
1

Based partially on zneak's answer I've made this (no thrills or frills) extension to UIColor which could come in handy:

extension UIColor {
    func isVisuallyEqual(color: UIColor) -> Bool {
        let compareValues = CGColorGetComponents(color.CGColor)
        let values = CGColorGetComponents(self.CGColor)

        let count = CGColorGetNumberOfComponents(self.CGColor)
        if count != CGColorGetNumberOfComponents(color.CGColor) {
            debugPrint("color-parameter has mismatching colorSpace")
            return false
        }
        for index in 0..<count {
            if !fuzzyFloatCompares(values[index], float2: compareValues[index]) {
                return false
            }
        }
        return true
    }

    private func fuzzyFloatCompares(float1: CGFloat, float2: CGFloat) -> Bool {
        let difference = float1 - float2
        return difference >= -1/256 && difference <= 1/256
    }
}
T. Benjamin Larsen
  • 6,373
  • 4
  • 22
  • 32
  • After I create a new .swift file, import UIKit and paste this code, do I need to put anything in my GameScene.swift file? – Tiptech Jun 21 '16 at 21:31
  • Well, any place you are now calling `isEqual:` on a color instance, say `someSprite.color.isEqual(anotherSprite.color)` you should replace the call with `isVisuallyEqual:`. – T. Benjamin Larsen Jun 22 '16 at 03:13