ios - Draw a grid with SpriteKit -
what best way draw grid this using spritekit 2d game engine? requirements:
- input programatically number of columns , rows (5x5, 10x3, 3x4 etc.).
- draw programmatically using
skspritenode
orskshapenode
, since using images of square this doesn't seem efficient me. - the squares should have fixed size (let's each 40x40).
- the grid should vertically , horizontally centred in view.
i'm planning use skspritenode
(from image) player moving in different squares in grid.
so, i'll save in 2 dimensional array central point (x,y) of each square , move player's current position position. if have better suggestion too, i'd hear it.
i appreciate solution in swift (preferably 2.1), objective-c too. planning on using on iphone devices.
question close to one. appreciated.
i suggest implement grid texture of skspritenode
because sprite kit renders grid in single draw call. here's example of how that:
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 height , width ensure borders within 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 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 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) } }
and here's how create grid , add game piece grid
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) } } }
update:
to determine grid square touched, add init
self.isuserinteractionenabled = true
and grid
class:
override func touchesbegan(_ touches: set<uitouch>, withevent event: uievent?) { 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)") } } }
Comments
Post a Comment