2014-07-25 19 views
5

Ich habe angefangen, ein kleines Swift/Spritekit-Projekt zu machen, um mich selbst Spiel-Dev zu lehren. Es beginnt mit einer isometrischen Karte, die ich zeichnen konnte. Aber ich habe Probleme, eine genaue Touch-Position auf den verschiedenen Kacheln der Karte zu bekommen. Es funktioniert, ist aber etwas fehl am Platz und scheint nicht konsistent.Swift Spritekit isometrische Karte Touch-Location

Hier sind meine Funktionen:

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

mit:

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

Aber es tut:

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

Und dann habe ich die Fliese I berühren (zum Testen) ausblenden möchten nicht immer die richtige Kachel verstecken. Also, wie soll ich das angehen? Ist mein Code grundsätzlich falsch (möglich)? Oder muss ich den Ort irgendwie in Iso-Koordinaten umwandeln? Oder mit der Fliesen-Bitmaske spielen?

Danke für Ihre Hilfe auf jeden Fall!

Antwort

6

Ich hatte ein ähnliches Problem mit der isometrischen Karte.

Das Problem ist, dass der Knoten, auf den Sie klicken, größer ist als angezeigt (es hat transparente Teile). Eine bessere Erklärung des Problems finden Sie unter my question here.

Hier ist, wie ich es gelöst (sorry Code in Objective-C):

1.Erstellen ein CGPathRef im Anschluss an die Kanten der Fliese (tileSize die Größe der Textur ist). Dieser Code ist für normale isometrische Fliesen, nicht sechseckig, aber die Idee ist die gleiche.

// 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.Create eine Funktion, ob ein gegebener Punkt innerhalb der CGPathRef (textureFrame) ist, überprüft.

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

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

3.Für jeder berührt Knoten, prüfen Sie, welche textureFrame in wir sind.

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

Ich weiß nicht, ob es die beste Lösung ist, aber es funktioniert super. Ich hoffe, es hilft :)

Edit: Added Swift Version des Codes

+0

Großen Dank. Ich werde das bald versuchen, und wenn ich es ausarbeiten kann, wird das Swift-Äquivalent posten. –

+2

Seit ich das geschrieben habe, fing ich an Swift zu lernen. Ich habe meine Antwort aktualisiert;) Ich habe das aus dem Speicher geschrieben und ich kann es jetzt nicht testen, also könnte es einige Fehler geben – Heyfara