2015-11-01 93 views
9

通過使用SpriteKit 2D遊戲引擎繪製grid like this的最佳方式是什麼? 要求:用SpriteKit繪製網格

  • 以編程方式輸入列數和行數(5x5,10x3,3x4等)。
  • 使用類似SKSpriteNodeSKShapeNode的程序來繪製它,因爲只使用square like this的圖像對我來說似乎不是很有效。
  • 廣場應該有一個固定的大小(假設每個是40x40)。
  • 網格應該在視圖中垂直和水平居中。

我打算使用SKSpriteNode(來自圖片)作爲在此網格中以不同方格移動的玩家。
因此,我將在2維數組中保存每個方塊的中心點(x,y),然後從玩家的當前位置移動到該位置。如果您也有更好的建議,我想聽聽。

我很感謝Swift(最好是2.1)的解決方案,但Objective-C也會這樣做。規劃僅在iPhone設備上使用此功能。
我的問題是關閉to this one。任何幫助表示讚賞。

+0

爲什麼不使用CGContext(Quartz)來畫線?看看CGPaths。唯一需要注意的是確保座標共同引入。畢竟,精靈是精靈... – 2015-11-01 17:27:38

+0

嘿,邁克爾L!感謝您的建議。我不知道如何以有效的方式使用這些CGPath,但0x141E的答案完美無缺。 – Alex

+0

網格是否需要在屏幕上顯示,因爲您應該將屏幕的長度分成所需的網格長度。 – Cing

回答

19

我建議你將網格實現爲SKSpriteNode的紋理,因爲Sprite Kit將在一次繪製調用中呈現網格。這裏有一個如何做一個例子:

class Grid:SKSpriteNode { 
    var rows:Int! 
    var cols:Int! 
    var blockSize:CGFloat! 

    convenience init?(blockSize:CGFloat,rows:Int,cols:Int) { 
     guard let texture = Grid.gridTexture(blockSize: blockSize,rows: rows, cols:cols) else { 
      return nil 
     } 
     self.init(texture: texture, color:SKColor.clear, size: texture.size()) 
     self.blockSize = blockSize 
     self.rows = rows 
     self.cols = cols 
    } 

    class func gridTexture(blockSize:CGFloat,rows:Int,cols:Int) -> SKTexture? { 
     // Add 1 to the height and width to ensure the borders are within the sprite 
     let size = CGSize(width: CGFloat(cols)*blockSize+1.0, height: CGFloat(rows)*blockSize+1.0) 
     UIGraphicsBeginImageContext(size) 

     guard let context = UIGraphicsGetCurrentContext() else { 
      return nil 
     } 
     let bezierPath = UIBezierPath() 
     let offset:CGFloat = 0.5 
     // Draw vertical lines 
     for i in 0...cols { 
      let x = CGFloat(i)*blockSize + offset 
      bezierPath.move(to: CGPoint(x: x, y: 0)) 
      bezierPath.addLine(to: CGPoint(x: x, y: size.height)) 
     } 
     // Draw horizontal lines 
     for i in 0...rows { 
      let y = CGFloat(i)*blockSize + offset 
      bezierPath.move(to: CGPoint(x: 0, y: y)) 
      bezierPath.addLine(to: CGPoint(x: size.width, y: y)) 
     } 
     SKColor.white.setStroke() 
     bezierPath.lineWidth = 1.0 
     bezierPath.stroke() 
     context.addPath(bezierPath.cgPath) 
     let image = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     return SKTexture(image: image!) 
    } 

    func gridPosition(row:Int, col:Int) -> CGPoint { 
     let offset = blockSize/2.0 + 0.5 
     let x = CGFloat(col) * blockSize - (blockSize * CGFloat(cols))/2.0 + offset 
     let y = CGFloat(rows - row - 1) * blockSize - (blockSize * CGFloat(rows))/2.0 + offset 
     return CGPoint(x:x, y:y) 
    } 
} 

,這裏是如何創建一個網格,遊戲件添加到網格

class GameScene: SKScene { 
    override func didMove(to: SKView) { 
     if let grid = Grid(blockSize: 40.0, rows:5, cols:5) { 
      grid.position = CGPoint (x:frame.midX, y:frame.midY) 
      addChild(grid) 

      let gamePiece = SKSpriteNode(imageNamed: "Spaceship") 
      gamePiece.setScale(0.0625) 
      gamePiece.position = grid.gridPosition(row: 1, col: 0) 
      grid.addChild(gamePiece) 
     } 
    } 
} 

更新:

要確定哪些網格廣場被感動,加入這個到init

self.isUserInteractionEnabled = true 

和這個到Grid類:

override func touchesBegan(_ touches: Set<UITouch>, withEvent event: UIEvent?) { 
    for touch in touches { 
     let position = touch.location(in:self) 
     let node = atPoint(position) 
     if node != self { 
      let action = SKAction.rotate(by:CGFloat.pi*2, duration: 1) 
      node.run(action) 
     } 
     else { 
      let x = size.width/2 + position.x 
      let y = size.height/2 - position.y 
      let row = Int(floor(x/blockSize)) 
      let col = Int(floor(y/blockSize)) 
      print("\(row) \(col)") 
     } 
    } 
} 
+1

真的很感謝解決方案,@ 0x141E!這正是我所期待的。真的很酷你如何讓'SpriteKit'在單個繪製中呈現網格。另外感謝'gridPosition'函數,它比我想的要好。 – Alex

+0

你會如何區分網格中的每個框?假設我將skspritenodes添加爲Grid類的子元素,那麼我將如何使用網格中的每個元素開始觸摸? – Boggartfly

+0

添加touchesBegin到'Grid'類不起作用。您需要將其添加到添加到網格的節點實例中。我懷疑這是因爲您要將網格中的框添加爲整個網格精靈的子節點。因此,我們需要在每個盒子的不同類中繼承「SKSpriteNode」,並在其上覆蓋「touchesBegan」。這對我來說很有用。我覺得這很困難。感謝您的回答。 – Boggartfly