2017-06-19 1 views
2

Ich versuche, ein Spiel in SpriteKit zu erstellen, und ich brauche eine Möglichkeit, Objekte zu legen, platzieren Sie sie in zufällig generierten Punkte war es nicht für mich zu viel Gruppierung .Poisson Disk Generator schließt drei von vier Ansicht Quadranten

Nach ein paar Recherchen sah ein Poisson Disk Generator so aus, wie ich es brauchte.

Ich habe versucht, meine eigenen zu implementieren. Allerdings sind alle Positionen ausgeschaltet, sie fehlen 3/4 des Displays.

Wohin gehe ich falsch?

min Bei einem Radius von 100.

r = 100

Bei einem Radius von min 10.

r = 10

class GameScene: SKScene { 

    var radius = 100 
    var lookUpCount = 30 
    var grid = [CGPoint?](), ordered = [CGPoint](), active = [CGPoint]() 
    var w = CGFloat() 
    var cols = Int() 
    var rows = Int() 
    var sizeScren = CGSize() 


    override func didMove(to view: SKView) { 
     generate() 

     for item in ordered { 
      let gamePiece = SKSpriteNode(imageNamed: "Spaceship") 
      gamePiece.setScale(0.0625) 
      gamePiece.position = item 
      addChild(gamePiece) 
     } 
    } 

    func distance(p1: CGPoint, p2: CGPoint) -> CGFloat { 
     let dx = p1.x - p2.x 
     let dy = p1.y - p2.y 
     return sqrt(dx * dx + dy * dy) 
    } 

    func generateRandomPointAround(point: CGPoint, minDist: CGFloat) -> CGPoint 
    { 

     let rd1 = CGFloat(Float(arc4random())/Float(UINT32_MAX)) 
     let rd2 = CGFloat(Float(arc4random())/Float(UINT32_MAX)) 

     //random radius 
     let radius = minDist * (rd1 + 1) 
     //random angle 
     let angle = 2 * CGFloat.pi * rd2 

     //new point is generated around the point (x, y) 

     let newX = point.x + radius * cos(angle) 
     let newY = point.y + radius * sin(angle) 
     return CGPoint(x: newX, y: newY) 

    } 


    func generate() { 


     sizeScren = UIScreen.main.bounds.size 

     //create cell 
     w = (CGFloat(Double(radius)/sqrt(2))) 
     cols = Int(floor(sizeScren.height/w)) 
     rows = Int(floor(sizeScren.width/w)) 

     grid = [CGPoint?](repeating: nil, count: (cols * rows)) 

     let x = sizeScren.height/2 
     let y = sizeScren.width/2 
     let i = floor(x/w) 
     let j = floor(y/w) 

     //first posistion 

     let pos = CGPoint (x: frame.midX, y: frame.midY) 
     let index = Int(i + j * CGFloat(cols)) 
     grid[index] = pos 
     active.append(pos) 

     while (active.count > 0) { 
      let randomIndex = Int(arc4random_uniform(UInt32(active.count))) 
      let currentPos = active[randomIndex] 
      var found = false 
      Mainloop: for _ in 0..<Int(lookUpCount) { 

       let samplePoint = generateRandomPointAround(point: currentPos, minDist: CGFloat(radius)) 

       let col = floor(samplePoint.x/w) 
       let row = floor(samplePoint.y/w) 

       //check neighbouring cells are empty and valid, if have a point in already 

       if (col > -1 && row > -1 && CGFloat(col) < CGFloat(cols) && CGFloat(row) < CGFloat(rows) && (grid[Int(col + CGFloat(row) * CGFloat(cols))] == nil)) { 
        var ok = true 
        for index1 in -1...1 { 
         for index2 in -1...1 { 

          //break down complexity for swift compiler 

          let part1 = Int(col + CGFloat(index1)) 
          let part2 = Int(row + CGFloat(index2)) 
          let part3 = part1 + part2 * cols 
          let sampleIndex = part3 

          let isIndexValid = grid.indices.contains(sampleIndex) 

          if isIndexValid { 
           let neighbor = grid[sampleIndex] 

           if neighbor != nil { 
            let distanceAmount = distance(p1: samplePoint, p2: neighbor!) 
            if distanceAmount < CGFloat(radius) { 
             ok = false 
            } 

           } 

          } 
         } 
        } 

        if (ok == true) { 
         found = true 
         grid[Int(col + row * CGFloat(cols))] = samplePoint 
         active.append(samplePoint) 
         ordered.append(samplePoint) 
//      break MainLoop 
        } 
       } 
      } 

      if (!found) { 
       active.remove(at: randomIndex) 
      } 
     } 


    } 
} 
+3

(0, 0) der Mittelpunkt der Bildschirm oder eine der Ecken? Denn wenn es das Zentrum ist, dann ist 'if (col> -1 && reihe> -1 'wird 3 von 4 Quadranten ausschließen) – samgak

+0

(0,0) ist die Mitte, aber ich dachte, es sollte keine Rolle spielen, da es Punkte geben sollte Rund um den Radius gesampelt Ich dachte, mein Problem bestehe eher darin, das 2D-Array auf ein 1D-Array abzubilden. – Magrafear

Antwort

1

(0,0) ist das Zentrum des Bildschirms und samplePoint wird durch eine Division durch w in Zeilen- und Spaltenindizes umgewandelt. Dann filtern Sie alle negativen Zeilen- und Spaltenindizes mit diesem Test aus: if (col > -1 && row > -1 .... samplePoint wird danach nicht angepasst, damit werden 3 von 4 Quadranten effektiv entfernt. Um dies zu beheben können Sie einfach Ihre Indizes wie dieser Versatz:

let col = floor((samplePoint.x + x)/w) 
let row = floor((samplePoint.y + y)/w) 

(x und y wurden bereits als die Hälfte der Bildschirmbreite und Höhe definiert sind)

Verwandte Themen