Function doesn't work on iPhone 5 with arc4random [duplicate] - swift

This question already has answers here:
Crash when casting the result of arc4random() to Int
(7 answers)
Closed 7 years ago.
I have a problem with one of my function: my application run perfectly on iPhone 5s, 6, etc, but on a iPhone 5 I have a problem with my code. When my function is called, I always have this problem:
switch choixDeCote {
case 1 : //Haut
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 200
SpawnX = UInt32(MaxValue - MinValue)
SpawnX = arc4random_uniform(SpawnX)
SpawnY = UInt32(self.size.height)
directionX = Int(arc4random()) % Int(self.frame.size.width)
print(directionX)
directionY = 0
action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 4)
break
And Xcode says that directionX = Int(arc4random()) % Int(self.frame.size.width) has a problem, but I don't know which one.

arc4random() returns a UInt32. On a 32-bit machine like the iPhone 5, this can overflow an Int.
I would suggest instead:
directionX = Int(Int32(bitPattern: arc4random_uniform(UInt32(self.frame.size.width))))
the Int32(bitPattern:) is only a precaution and isn't really necessary since the self.frame.size.width is much smaller than MAXINT32 so the random number generated won't overflow an Int. You can just do:
directionX = Int(arc4random_uniform(UInt32(self.frame.size.width)))

Related

How to divide screen into a grid using 2d arrays in swift?

Below is my code so far using for loops, and this is what it looks like right now. As you can see it is very condensed
for i in 0...12{
for j in 0...16{
let block = SKSpriteNode(texture: blockImage, size: blockSize)
block.position.x = block.frame.width/2 * CGFloat(j)+1
block.position.y = frame.height - block.frame.height/2 * CGFloat(i)+1
block.zPosition = 1
addChild(block)
}
}
However, I am only trying to have 2 rows of blocks on the top and 1 row of blocks on the bottom. The screen should have a height 12 blocks and a width of 15 blocks.
Is there a way I can create a grid that is 15x12 with a cell size of 64x64 using 2d arrays? Because eventually, I want to add blocks to random cell locations in the grid(besides the fixed top and bottom rows)
I am looking for tutorials on how to do this, but I am finding people that use other open source options that are not included in swift. Please drop any tips or advice you have for me to tackle this I am very new to SpriteKit and Swift, thank you! (lmk if you need more clarification as well)
update:
I got it to look like this now, but I don't know how to remove the rest of the blocks that arent in the top and bottom rows. How would i get the location of each block?
for i in 0...12{
for j in 0...16{
let block = SKSpriteNode(texture: blockImage, size: blockSize)
block.position.x = block.frame.width/2 + CGFloat((64*j))
block.position.y = frame.height - block.frame.height/2 - CGFloat((64*i))
block.zPosition = 1
addChild(block)
}
}
I don't really code for SpriteKit but maybe can offer some tips based on the logic I see.
One way could be to add some logic in the for loop to check if you are currently iterating the first 2 rows or the last row and only in these cases, add the row of blocks.
let rows = 12
let columns = 16
let topBoundary = 1
for i in 0...rows {
for j in 0...columns {
if i <= topBoundary || i == rows {
let block = SKSpriteNode(texture: blockImage, size: blockSize)
block.position.x = block.frame.width/2 + CGFloat((64*j))
block.position.y = frame.height - block.frame.height/2 - CGFloat((64*i))
block.zPosition = 1
addChild(block)
}
}
}

Calculate simple math equation [duplicate]

This question already has answers here:
How to round a Double to the nearest Int in swift?
(9 answers)
Closed 4 years ago.
I try to use swift code to calculate 10 * 75% = 7.5
var b : Int = 10
var a : Int = 75
// result x is 0
var x = b * (a / 100)
However the result is zero. How to get 7.5 result without changing the type and value of a and b?
UPDATE:
I got it right by:
var x: Double = (Double(b) * (Double(a) / 100)) // x is 7.5
Now, how can I round it to 8 as a Int type?
You're using integer (i.e. whole number) arithmetic, when what you want is floating-point arithmetic. Change one of the types to Float, and Swift will figure out that x is also a Float.
var b : Int = 10
var a : Int = 75
var x = Float(b) * (Float(a) / 100.0) // now x is a Float (.75)
For doing arithmetic in Swift, both sides of the equation must be using the same type. Try using this code:
let b = 10.0
let a = 75.0
let x = b * (a / 100.0
print(x)
7.5
To make it round up, use the built in ceil function
print(ceil(x))
8.0
Ok then you just need to do:
var b : Int = 10
let c = (Double(b) * 0.75)
let restult = ceil(c)

Generate a random number between negative and positive in swift [duplicate]

This question already has an answer here:
How to generate a random number in a range (10...20) using Swift [duplicate]
(1 answer)
Closed 4 years ago.
So I'm trying to generate a random number between negative and positive range because I need to give an object a position on the x axis. I've tried with arc4random and arc4random_uniform but it doesn't work. I need a way to generate a random position on the x axis, negative and positive.
I don't think you can generate negative random number using arc4random directly
let lValue = -10 // (your negative number)
let uValue = 10 //(your positive number)
let result = Int(arc4random_uniform(UInt32(uValue - lValue + 1))) + lValue
print(result)
hope this will work
let min : UInt32 = 10
let max : UInt32 = 50
let randomNumber = arc4random_uniform(max - min) + min
if arc4random_uniform(2) == 0 {
randomNumber = randomNumber * -1
}

M_P is deprecated: Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting in Swift 3.1 [duplicate]

This question already has answers here:
How to get mathemical PI constant in Swift
(3 answers)
Closed 5 years ago.
I have this error when updating my codes to Swift3.1 with Xcode 8.3.1
'M_PI' is deprecated: Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.
My codes under below,
let center = containerShapeView.center
let startAngle = CGFloat(0.0)
let endAngle = CGFloat(M_PI*2)
let radius = containerShapeView.bounds.width * 0.21
CGFloat(M_PI*2) line gives error
How can I resolve it ?
Well, follow the instructions of the error message:
let center = containerShapeView.center
let startAngle = CGFloat(0.0)
let endAngle = CGFloat(Double.pi) * 2
let radius = containerShapeView.bounds.width * 0.21
Or better yet, to avoid the unecessary conversions:
let center = containerShapeView.center
let startAngle: CGFloat = 0
let endAngle = CGFloat.pi * 2
let radius = containerShapeView.bounds.width * 0.21

Displaying 4 textures using for loop

I'm creating a game using Swift 2.0 and Sprite-Kit with Xcode7. I want to implement 4 purple balls that are suppose to resemble lives. So every time the player gets hit he loses one purple ball. They are supposed to appear side by side. I was wondering if instead of hardcoding 4 balls on to the scene I could instead use a for loop to display 4 balls.
let purpleBall = SKSpriteNode(texture: purpleTexture)
purpleBall.position = CGPointMake(self.frame.size.width * 0.65, self.frame.size.height * 0.92)
self.addChild(purpleBall)
I haven't been successful on getting 4 balls to appear on the scene. This was one of my attempts.
for(var i = 0.50; i <= 0.90; i = i + 0.10) {
let purpleBall = SKSpriteNode(texture: purpleTexture)
purpleBall.position = CGPointMake(self.frame.size.width * i, self.frame.size.height * 0.92)
self.addChild(purpleBall)
}
Here I get an error: Binary operator cannot be applied to operands of type 'CGFloat' and 'Double'
Do I have to convert i to CGFloat? and will this code actually place 4 different balls side by side or only move the single one to each new position.
Your code has an off by one error in the for loop. It should be a less than sign rather than less than or equal too. Your current code is going to create five purple balls.
You shouldn't really let i equal anything but an integer it's confusing. You could rewrite the code like this and it would do the same thing, without the worry of the float/double errors you're currently getting. Note that I will also use a constant called maxBalls, and distanceBetweenBalls so that you can easily change the number of balls and the distance without any complicated rewriting:
let maxBalls = 4
for(var i = 0; i < maxBalls; i++) {
let purpleBall = SKSpriteNode(texture: purpleTexture)
let ballXPosition = .50 + (i * .1)
purpleBall.position = CGPointMake(self.frame.size.width * ballXPosition, self.frame.size.height * 0.92)
self.addChild(purpleBall)
This should avoid the issues you were facing before, hope that helps.