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)")
}
}
}
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 ... –
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
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