2015-11-01 20 views
9

Cách tốt nhất để vẽ grid like this bằng cách sử dụng công cụ trò chơi SpriteKit 2D là gì? Yêu cầu:Vẽ một ô lưới với SpriteKit

  • Nhập theo chương trình số cột và hàng (5x5, 10x3, 3x4 v.v.).
  • Vẽ theo chương trình bằng cách sử dụng một cái gì đó như SKSpriteNode hoặc SKShapeNode, vì chỉ sử dụng hình ảnh của square like this có vẻ không hiệu quả đối với tôi.
  • Hình vuông phải có kích thước cố định (giả sử mỗi hình là 40x40).
  • Lưới nên được căn giữa theo chiều dọc và chiều ngang trong chế độ xem.

Tôi định sử dụng SKSpriteNode (từ hình ảnh) khi người chơi di chuyển trong các ô vuông khác nhau trong lưới này.
Vì vậy, tôi sẽ lưu trong mảng 2 chiều điểm trung tâm (x, y) của mỗi ô vuông và sau đó di chuyển từ vị trí hiện tại của người chơi đến vị trí đó. Nếu bạn có một gợi ý tốt hơn cho điều này quá, tôi muốn nghe nó.

Tôi sẽ đánh giá cao một giải pháp trong Swift (tốt nhất là 2.1), nhưng Objective-C cũng sẽ làm như vậy. Lên kế hoạch chỉ sử dụng trên thiết bị iPhone.
Câu hỏi của tôi là đóng to this one. Bất kỳ trợ giúp được đánh giá cao.

+0

Tại sao không sử dụng CGContext (Quartz) để vẽ đường? Nhìn vào CGPaths. Sự chăm sóc duy nhất mà bạn cần thực hiện là đảm bảo rằng các tọa độ đồng khớp. Sau khi tất cả, sprites là sprites ... –

+0

Hey, Michael L! Cám ơn vì sự gợi ý. Tôi không biết cách sử dụng những CGPath đó một cách hiệu quả, nhưng câu trả lời của 0x141E đã làm điều đó một cách hoàn hảo. – Alex

+0

Lưới có cần trên màn hình lỗ hay không vì bạn chỉ cần chia độ dài của màn hình để ném lengt của lưới mà bạn muốn. – Cing

Trả lời

19

Tôi khuyên bạn nên triển khai lưới dưới dạng kết cấu của SKSpriteNode vì Bộ Sprite sẽ hiển thị lưới trong một cuộc gọi vẽ duy nhất. Dưới đây là một ví dụ về cách để làm điều đó:

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) 
    } 
} 

Và dưới đây là cách để tạo ra một mạng lưới và thêm một đoạn trò chơi để lưới

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) 
     } 
    } 
} 

Cập nhật:

Để xác định lưới hình vuông đã được chạm vào, thêm số này vào init

self.isUserInteractionEnabled = true 

và điều này vào lớp 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

Thực sự đánh giá cao giải pháp, @ 0x141E! Đó chính xác là những gì tôi đang tìm kiếm. Thực sự thú vị như thế nào bạn có 'SpriteKit' để render lưới trong một trận hòa duy nhất. Cảm ơn bạn về hàm 'gridPosition', nó tốt hơn những gì tôi nghĩ. – Alex

+0

Bạn phân biệt mọi ô trong lưới như thế nào? Nói rằng tôi thêm skspritenodes như trẻ em của lớp lưới, làm thế nào tôi sẽ sử dụng chạm bắt đầu cho mỗi hộp trong lưới điện? – Boggartfly

+0

Thêm số lần chạm vàoĐến lớp 'Lưới' không hoạt động. Bạn cần phải thêm nó vào trường hợp nút được thêm vào grid.I nghi ngờ điều này là bởi vì bạn đang thêm hộp trong lưới như là một con của toàn bộ lưới điện.Vì vậy, thay vào đó, chúng ta cần kế thừa 'SKSpriteNode' trong một lớp khác cho mỗi hộp và ghi đè' touchesBegan' ở đó. Đó là những gì làm việc cho tôi. Tôi đã tìm ra điều này một cách khó khăn. Cảm ơn câu trả lời của bạn. – Boggartfly

Các vấn đề liên quan