Vraag Teken een raster met SpriteKit


Wat zou de beste manier zijn om een ​​te tekenen rooster zoals deze door de SpriteKit 2D-game-engine te gebruiken? Vereisten:

  • Programmeer het aantal kolommen en rijen (5x5, 10x3, 3x4 etc.).
  • Teken het programmatisch met zoiets SKSpriteNode of SKShapeNode, omdat alleen afbeeldingen van a vierkant zoals dit lijkt me niet erg efficiënt.
  • De vierkanten moeten een vaste grootte hebben (laten we zeggen dat elk vierkant 40x40 is).
  • Het raster moet verticaal en horizontaal worden gecentreerd in het beeld.

Ik ben van plan om een ​​te gebruiken SKSpriteNode (van een afbeelding) als een speler die in verschillende vakjes in dit raster beweegt.
Dus, ik sla in een tweedimensionale array het centrale punt (x, y) van elk vierkant op en ga dan van de huidige positie van de speler naar die positie. Als je hier ook een betere suggestie voor hebt, zou ik het graag willen horen.

Ik zou een oplossing in Swift waarderen (bij voorkeur 2.1), maar Objective-C zou dat ook doen. Van plan om dit alleen op iPhone-apparaten te gebruiken.
Mijn vraag is dichtbij voor deze. Alle hulp wordt gewaardeerd.


13
2017-11-01 17:22


oorsprong


antwoorden:


Ik stel voor dat je het raster implementeert als een textuur van een SKSpriteNode omdat Sprite Kit het raster in één draw-call rendert. Hier is een voorbeeld van hoe dat te doen:

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

En hier is hoe je een raster kunt maken en een spelstuk aan het raster kunt toevoegen

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

Bijwerken:

Om te bepalen welk raster vierkant is aangeraakt, voeg dit toe aan init

self.isUserInteractionEnabled = true

en dit voor de Grid klasse:

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

23
2017-11-02 06:16