José María
José María

Reputation: 3083

Create random CGPoint with Swift

So, I'm trying to develop a simple game written in Swift, but I'm having trouble doing a pretty simple thing. I can't manage to create a random CGPoint... When using arc4random, a compiler error shows up telling me that I can't use Int32 in a CGPoint. So, Is there any way to do this? Any workaround? Thanks!

Upvotes: 2

Views: 3661

Answers (4)

Starman
Starman

Reputation: 126

Here is an extension on CGPoint to generate random point based on your x,y closed range.

extension CGPoint {
    static func randPoint(xRange: ClosedRange<CGFloat>, yRange: ClosedRange<CGFloat>) -> Self {
        let x = CGFloat.random(in: xRange)
        let y = CGFloat.random(in: yRange)
        return .init(x: x, y: y)
    }
    
    
}

Upvotes: 0

Evgeniy
Evgeniy

Reputation: 159

Swift 4,5
// Add some range
let minX = 0
let maxX = 100
let minY = 0
let maxY = 100
let randomX = CGFloat.random(in: minX..<maxX)
let randomY = CGFloat.random(in: minY..<maxY)
let random = CGPoint(x: randomX, y: randomY)

Upvotes: 0

Chuck Gaffney
Chuck Gaffney

Reputation: 276

can also maybe make use of Swift's extensions of base types to create a reusable set of overloaded functions of CGPoint. Maybe something like:

extension CGPoint {

    func random()->CGPoint { return CGPoint(x:Int(arc4random()%1000),y:Int(arc4random()%1000))}

    func random(range:Int)->CGPoint { 
         return CGPoint(x:Int(arc4random()%range),y:Int(arc4random()%range))}

    func random(rangeX:Int, rangeY:Int)->CGPoint { 
         return CGPoint(x:Int(arc4random()%rangeX),y:Int(arc4random()%rangeY))} 
}

You can then write random CGPoints like this:

var p = CGPoint.random() 
//random x and y with a range of 1000

or

var p = CGPoint.random(range:100)
//random x and y with a range of 100

or

var p = CGPoint.random(rangeX:200, rangeY:400)
//random x up to 200 and random y with a range of up to 400

Granted, I'm not in the Xcode IDE at the moment to check syntax / if it compiles correctly but hope that could be of help :-)

...

//////////////////

Swift 1.2 Update

//////////////////

Seems these type-level function calls are not allowed anymore with extensions...at least for CGPoint; probably because CGPoint is actually a struct and not a class based on the current IOS documentation.

Here's a more in-depth version of my extension that allows for Range types.

This is confirmed working as of XCode 6.4 Beta

(Github repository with Playground file found here:

https://github.com/princetrunks/Random-CGPoint-Extension)

//creates random CGPoints in Swift as of XCode Beta 6.4 (6E7)
extension CGPoint {

/*private functions that help alleviate the ambiguity of the modulo bias 
   and nested typecasting as well as recycle similar functionality 
     for either Int or Range type parameter inputs */

private func randomInt(num:Int) ->Int{
    return Int(arc4random_uniform(UInt32(num)))
}

private func randomIntFromRange(numRange:Range<Int>) ->Int{
    return Int(arc4random_uniform(UInt32((numRange.endIndex - numRange.startIndex) + numRange.startIndex)))
}

//private variable for the default range
private var defaultRange : Int{
    get{return 1000}
}

//(a) public variable that creates a default random CGPoint
static var randomPoint = CGPoint.zeroPoint.random()


//(b) default random point creation
func random()->CGPoint { return CGPoint(x:randomInt(defaultRange),y:randomInt(defaultRange))}

//(c) using an Int parameter for both the random x and y range
func random(range:Int)->CGPoint {
    return CGPoint(x:randomInt(range),y:randomInt(range))
}

//(d) allows for the specification of the x and y random range
func random(#rangeX:Int, rangeY:Int)->CGPoint {
    return CGPoint(x:randomInt(rangeX),y:randomInt(rangeY))
}

//(e) allows the same functionality as (c) but with a Range<Int> type parameter
func random(range:Range<Int>)->CGPoint {
    return CGPoint(x:randomIntFromRange(range), y:randomIntFromRange(range))
}

//(f) allows the same functionality as (d) but with a Range<Int> type parameter
func random(#rangeX:Range<Int>, rangeY:Range<Int> )->CGPoint {
    return CGPoint(x:randomIntFromRange(rangeX), y:randomIntFromRange(rangeY))
 }

}

Here's how we can test this extension:

//(a)
let r  = CGPoint.randomPoint

//(b)
var anotherRandomPoint = r.random()

//(c)
anotherRandomPoint = r.random(1000)

//(d)
anotherRandomPoint = r.random(0...1000)

//(e)
anotherRandomPoint = r.random(rangeX:90, rangeY: 2000)

//(f)
anotherRandomPoint = r.random(rangeX:0...90, rangeY: 0...2000)


// generates 100 random CGPoints between -1000 and 999
for _ in 0...100 {
    anotherRandomPoint.random(-1000...1000)
}

Upvotes: 3

Christian Dietrich
Christian Dietrich

Reputation: 11868

hi what about constructing an Int? Int(arc4random())

e.g.

var p = CGPoint(x:Int(arc4random()%1000),y:Int(arc4random()%1000))

Upvotes: 2

Related Questions