2014-07-25 11 views
5

Ho iniziato a fare un piccolo progetto swift/spritekit per insegnare a me stesso game dev. Inizia con una mappa isometrica, che sono riuscito a disegnare. Ma non riesco a trovare una posizione di tocco precisa sulle diverse tessere della mappa. Funziona, ma è leggermente fuori posto e non sembra coerente.Swift Spritekit mappa isometrica touch location

Qui sono le mie funzioni:

class PlayScene: SKScene { 

let map = SKNode() 
    override func didMoveToView(view: SKView) { 

     let origin = view.frame.origin 
     let mapOrigin = CGPointMake(origin.x + self.frame.width/4, origin.y - self.frame.height/4) 


     let mapConfig: Int[][] = 

     [[0, 0, 0, 0, 1, 0, 0, 0], 
     [0, 0, 0, 0, 1, 0, 0, 0], 
     [0, 0, 0, 0, 1, 0, 0, 0], 
     [2, 2, 2, 2, 1, 2, 2, 2], 
     [0, 0, 0, 0, 1, 0, 0, 0], 
     [0, 0, 0, 0, 1, 0, 0, 0], 
     [0, 0, 0, 0, 1, 0, 0, 0], 
     [0, 0, 0, 0, 1, 0, 0, 0]] 

    drawMap(mapConfig, mapOrigin: mapOrigin) 
} 

Con:

func drawMap(mapConfig:Int[][], mapOrigin:CGPoint) 
{ 
    let tileHeight:CGFloat = 25.5 
    let numColumns:Int = 8 
    let numRows:Int = 8 

    var position = mapOrigin 
    var column: Int = 0 
    var row: Int = 0 

    for column = 0; column < numColumns; column++ 
    { 
     for row = 0; row < numRows; row++ 
     { 
      position.x = mapOrigin.x + CGFloat(column) * tileHeight 
      position.y = mapOrigin.y + CGFloat(row) * tileHeight 
      let isoPosition = twoDToIso(position) 
      placeTile(isoPosition, mapConfig: mapConfig[row][column]) 
     } 
    } 
    self.addChild(map) 
} 

func placeTile(position:CGPoint, mapConfig:Int) 
{ 
switch mapConfig 
    { 
    case 0: 
     let sprite = SKSpriteNode(imageNamed:"grassTile") 
     sprite.position = position 
     sprite.setScale(0.1) 
     sprite.name = "\(position)" 
     self.map.addChild(sprite) 
    case 1: 
     let sprite = SKSpriteNode(imageNamed:"roadTile") 
     sprite.position = position 
     sprite.setScale(0.1) 
     sprite.name = "\(position)" 
     self.map.addChild(sprite) 
    default: 
     let sprite = SKSpriteNode(imageNamed:"roadTileLTR") 
     sprite.position = position 
     sprite.setScale(0.1) 
     sprite.name = "\(position)" 
     self.map.addChild(sprite) 
    } 
} 

e poi voglio nascondere la piastrella tocco (per le prove):

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) 
{ 
    for touch: AnyObject in touches 
    { 
     let locationNode = touch.locationInNode(self) 
     nodeAtPoint(locationNode).hidden = true 
    } 
} 

ma lo fa non nascondere sempre la tessera corretta. Quindi come dovrei affrontare questo? Il mio codice è fondamentalmente sbagliato (possibile)? O devo convertire la posizione in coordinate ISO in qualche modo? O giocare con il tile bitmask?

Grazie per il vostro aiuto in ogni caso!

risposta

6

Ho avuto un problema simile con la mappa isometrica.

Il problema è che il nodo su cui si fa clic è più grande di quello visualizzato (ha parti trasparenti). Vedere my question here per una migliore spiegazione del problema.

Ecco come ho risolto (codice dispiace è in Objective-C):

1.Creare un CGPathRef seguendo i bordi della piastrella (tileSize è la dimensione della texture). Questo codice è per le tessere isometriche regolari, non esagonali ma l'idea è la stessa.

// ObjC 
-(CGPathRef)createTextureFrame:(CGSize)tileSize 
{ 
    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathMoveToPoint(path, NULL, 0, -(self.tileSize.height/2)); 
    CGPathAddLineToPoint(path, NULL, (self.tileSize.width/2), 0); 
    CGPathAddLineToPoint(path, NULL, 0, (self.tileSize.height/2)); 
    CGPathAddLineToPoint(path, NULL, -(self.tileSize.width/2), 0); 
    CGPathCloseSubpath(path); 
    return path; 
} 

// Swift 
func createTextureFrame(tileSize:CGSize) -> CGPathRef { 
    CGMutablePathRef path = CGPathCreateMutable() 
    CGPathMoveToPoint(path, nil, 0, -(self.tileSize.height/2)) 
    CGPathAddLineToPoint(path, nil, (self.tileSize.width/2), 0) 
    CGPathAddLineToPoint(path, nil, 0, (self.tileSize.height/2)) 
    CGPathAddLineToPoint(path, nil, -(self.tileSize.width/2), 0) 
    CGPathCloseSubpath(path) 
    return path 
} 

2.Creare una funzione che verifica se un determinato punto si trova all'interno di CGPathRef (textureFrame).

// ObjC 
-(BOOL)isPointOnNode:(CGPoint)point 
{ 
    return CGPathContainsPoint(textureFrame, NULL, point, YES); 
} 

// Swift 
func isPointOnNode(point:CGPoint) -> Bool { 
    return CGPathContainsPoint(textureFrame, nil, point, YES) 
} 

3.Per ogni toccato nodi, verificare quali textureFrame siamo in.

// ObjC 
UITouch *touch = [touches anyObject]; 
NSArray *nodes = [self nodesAtPoint:[touch locationInNode:self]]; 
for (SKNode *node in nodes) 
{ 
    CGPoint locationInNode = [touch locationInNode:node]; 
    if ([node isPointOnNode:locationInNode]) 
    { 
     node.hidden = YES; 
    } 
} 

// Swift 
var touch = touches.anyObject() as UITouch 
var nodes = self.nodesAtPoint(touch.locationInNode(self)) 
for node in nodes as [SKNode] { 
    var locationInNode = touch.locationInNode(node) 

    if node.isPointOnNode() { 
     node.hidden = true 
    } 
} 

Non so se è la soluzione migliore, ma funziona benissimo. Spero che aiuta :)

Edit: versione Aggiunto Swift del codice

+0

Grande, grazie. Ci proverò presto, e se riuscirò a risolverlo, pubblicherò l'equivalente di Swift. –

+2

Da quando ho postato questo ho iniziato a imparare Swift. Ho aggiornato la mia risposta;) L'ho scritto a memoria e non posso testarlo adesso, quindi potrebbero esserci degli errori – Heyfara

Problemi correlati