【问题标题】:Spawning a circle in a random spot on screen在屏幕上的随机位置生成一个圆圈
【发布时间】:2015-07-30 19:56:58
【问题描述】:

我一直在绞尽脑汁,到处搜索,试图找出如何在屏幕上生成一个随机位置来生成一个圆圈。我希望这里有人可以帮助我,因为我完全被难住了。基本上,我试图创建一个形状,当用户触摸时,它总是在屏幕上的随机位置生成。

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        let screenSize: CGRect = UIScreen.mainScreen().bounds
        let screenHeight = screenSize.height
        let screenWidth = screenSize.width

        let currentBall = SKShapeNode(circleOfRadius: 100)
        currentBall.position = CGPointMake(CGFloat(arc4random_uniform(UInt32(Float(screenWidth)))), CGFloat(arc4random_uniform(UInt32(Float(screenHeight)))))

        self.removeAllChildren()
        self.addChild(currentBall)
}

如果你们都需要更多我的代码,那么真的没有更多了。但是感谢您提供的任何帮助! (重申一下,这种代码是可行的……但大多数生成的球似乎都在屏幕外生成)

【问题讨论】:

    标签: ios swift random arc4random


    【解决方案1】:

    问题是你的场景比你的屏幕范围大

    let viewMidX = view!.bounds.midX
    let viewMidY = view!.bounds.midY
    print(viewMidX)
    print(viewMidY)
    
    let sceneHeight = view!.scene!.frame.height
    let sceneWidth = view!.scene!.frame.width
    print(sceneWidth)
    print(sceneHeight)
    
    let currentBall = SKShapeNode(circleOfRadius: 100)
    currentBall.fillColor = .green
    
    let x = view!.scene!.frame.midX - viewMidX + CGFloat(arc4random_uniform(UInt32(viewMidX*2)))
    let y = view!.scene!.frame.midY - viewMidY + CGFloat(arc4random_uniform(UInt32(viewMidY*2)))
    print(x)
    print(y)
    
    currentBall.position = CGPoint(x: x, y: y)
    view?.scene?.addChild(currentBall)
    
    self.removeAllChildren()
    self.addChild(currentBall)
    

    【讨论】:

    • 谢谢你,它的工作方式和我想要的完全一样。而且您并没有对我的代码进行太多更改,因此很容易理解。谢谢! (我对 swift 还很陌生,所以这是一个巨大的帮助)
    • @LeoDabus 只想加球怎么办?我不想通过调用 self.removeAll 来丢失以前的球
    • 谢谢,没关系,我这样解决了我的问题: 1) shift = self.frame.width / 2 - view.bounds.width/2 2) let frame = CGRectMake(shift, 0, self.view!.bounds.width, self.view!.bounds.height) 3) 让 sceneBody = SKPhysicsBody(edgeLoopF​​romRect: frame)
    【解决方案2】:

    首先:确定有效的区域。它可能不是超级视图的框架,因为球(我们称之为ballView)可能会被切断。该区域可能是(在伪代码中):

    CGSize( Width of the superview - width of ballView , Height of the superview - height of ballView)
    

    获得该尺寸的视图后,只需将其与origin 0, 0 一起放在屏幕上即可。

    其次:现在您有了一个有效坐标范围。只需使用随机函数(如您正在使用的函数)来选择其中之一。

    使用以下内容创建一个 swift 文件:

    extension Int
    {
        static func random(range: Range<Int>) -> Int
        {
            var offset = 0
    
            if range.startIndex < 0   // allow negative ranges
            {
                offset = abs(range.startIndex)
            }
    
            let mini = UInt32(range.startIndex + offset)
            let maxi = UInt32(range.endIndex   + offset)
    
            return Int(mini + arc4random_uniform(maxi - mini)) - offset
        }
    }
    

    现在你可以指定一个随机数,如下所示:

    Int.random(1...1000) //generate a random number integer somewhere from 1 to 1000.
    

    您现在可以使用此函数生成 x 和 y 坐标的值。

    【讨论】:

    • 不确定从Range&lt;Int&gt; 中提取随机Int 是解决此问题的最佳方法,但如果random(Range&lt;Int&gt;) 是您想要的,有一种方法可以在不冒风险的情况下实现它整数溢出——见this answer
    【解决方案3】:

    给定以下随机生成器:

    public extension CGFloat {
        public static var random: CGFloat { return CGFloat(arc4random()) / CGFloat(UInt32.max) }
    
        public static func random(between x: CGFloat, and y: CGFloat) -> CGFloat {
            let (start, end) = x < y ? (x, y) : (y, x)
            return start + CGFloat.random * (end - start)
        }
    }
    
    public extension CGRect {
        public var randomPoint: CGPoint {
            var point = CGPoint()
            point.x = CGFloat.random(between: origin.x, and: origin.x + width)
            point.y = CGFloat.random(between: origin.y, and: origin.y + height)
            return point
        }
    }
    

    您可以将以下内容粘贴到 Playground 中:

    import XCPlayground
    import SpriteKit
    
    let view = SKView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
    XCPShowView("game", view)
    
    let scene = SKScene(size: view.frame.size)
    view.presentScene(scene)
    
    let wait = SKAction.waitForDuration(0.5)
    let popIn = SKAction.scaleTo(1, duration: 0.25)
    let popOut = SKAction.scaleTo(0, duration: 0.25)
    let remove = SKAction.removeFromParent()
    
    let popInAndOut = SKAction.sequence([popIn, wait, popOut, remove])
    
    let addBall = SKAction.runBlock { [unowned scene] in
        let ballRadius: CGFloat = 25
        let ball = SKShapeNode(circleOfRadius: ballRadius)
        var popInArea = scene.frame
        popInArea.inset(dx: ballRadius, dy: ballRadius)
        ball.position = popInArea.randomPoint
        ball.xScale = 0
        ball.yScale = 0
        ball.runAction(popInAndOut)
        scene.addChild(ball)
    }
    
    scene.runAction(SKAction.repeatActionForever(SKAction.sequence([addBall, wait])))
    

    (请确保也粘贴随机生成器,或者将它们复制到游乐场的Sources,并打开助手编辑器以便您可以看到动画。)

    【讨论】:

    • 虽然我不再需要随机球的帮助,但XCPlayground 是不是有点像 iOS 模拟器的模拟器?比如,它是否允许您像在 iOS 项目中一样打开视图?还是我只是抱有希望?
    • 上面的代码将直接在 Playground 中运行,在 Playground Settings 中选择 OS X 作为平台。这是 SpriteKit 和 CoreGraphics,它在 iOS 应用程序中也应该同样有效(尽管我没有尝试过)。 Playgrounds 也可以在模拟器中运行它,只需在设置中选中“在完整模拟器中运行”复选框...
    猜你喜欢
    • 2014-04-07
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 2011-01-25
    相关资源
    最近更新 更多