Реализация собственного SKTileGroupRule для визуализации стрелок для отображения перемещения символов в SKTileMapNode - PullRequest
0 голосов
/ 26 марта 2019

В настоящее время я работаю над новой игрой, в которой у меня есть SKTileMapNode с именем background в качестве игровой площадки, на которой персонажи могут переходить от плитки к плитке. В дополнение к этому у меня есть еще один SKTileMapNode с именем objects, который отображается поверх background (в направлении z), где у меня есть различные препятствия для движения персонажей, таких как деревья или камни. My Scene содержит курсор и игровой контроллер с кнопками вверх, вниз, влево, вправо, A и B.
Я уже реализовал в логике, где я могу переместить курсор поверх символа и выбрать его. После выбора я могу выбрать плитку для перемещения выбранного персонажа, если нет препятствий. Все до этого момента работает как надо.
Теперь я хочу реализовать способ, позволяющий игроку видеть стрелку после выбора персонажа, который отображает плитки, по которым персонаж должен пройти, чтобы добраться до плитки, на которой находится курсор, прежде чем выбрать эту плитку в качестве места назначения. .
У меня была идея создать собственный SKTileGroupRule для object или новый SKTileMapNode поверх обоих, который автоматически выбирает правильное SKTileDefinition для отображения текстуры стрелки вправо. Также следует автоматически исправить стрелку, если игрок переместил курсор в обход желаемой плитки и обнаружил препятствия для рисования.
Поэтому мой вопрос: как я могу реализовать свою собственную SKTileGroup с этими данными правилами. Пожалуйста, не стесняйтесь отвечать, даже если у вас есть только идея создать SKTileGroupRule только для рисования вокруг препятствий TileDefinitions или автозамены на обходах, как упоминалось ранее.

Картинка другой игры с той же логикой:

A picture of another game with the same logic

import SpriteKit

class Spielfeld: SKScene {

var x: Int = 0     // columns
var y: Int = 0     // rows
var background: SKTileMapNode = SKTileMapNode()
var 

objects: SKTileMapNode = SKTileMapNode()

enum State {
    case initial
    case selected
    case menu
}

var state: State = .initial // Initial state

var selected: Charakter!

var menu: Menu = Menu(0)

var up: SKSpriteNode = SKSpriteNode()
var down: SKSpriteNode = SKSpriteNode()
var left: SKSpriteNode = SKSpriteNode()
var right: SKSpriteNode = SKSpriteNode()
var buttonA: SKSpriteNode = SKSpriteNode()
var buttonB: SKSpriteNode = SKSpriteNode()

let cursor: SKSpriteNode = SKSpriteNode(imageNamed: "Cursor1Blue")
var cursor_x: Int = 0
var cursor_y: Int = 0

let charInfo: SKNode = SKNode()
let charInfoBG: SKSpriteNode = SKSpriteNode(imageNamed: "CharInfo")
let charInfoLabel: SKLabelNode = SKLabelNode()

var reach: [SKSpriteNode] = []

let ike: Ike = Ike()
let boyd: Boyd = Boyd()

override func sceneDidLoad() {
    background = self.childNode(withName: "Background") as! SKTileMapNode
    objects = self.childNode(withName: "Objects") as! SKTileMapNode

    calibrateMap()

    addController()
    addCursor()

    ike.position = objects.centerOfTile(atColumn: 0, row: 1)
    ike.x = 0
    ike.y = 1
    objects.addChild(ike)

    boyd.position = objects.centerOfTile(atColumn: 6, row: 3)
    boyd.x = 6
    boyd.y = 3
    boyd.team = 2
    objects.addChild(boyd)

    initCharInfo()
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch:UITouch = touches.first! as UITouch
    let positionInScene = touch.location(in: self)
    let touchedNode = self.atPoint(positionInScene)
    print(touchedNode.name!)
    if(touchedNode.name == "Objects") {
        let map = touchedNode as! (SKTileMapNode)
        let positionInMap = touch.location(in: map)
    } else if(isCursor(touchedNode.name!)) {
        switch state {
        case .initial, .selected:
            moveCursor(button: touchedNode.name!)
            if let char = atCursor() {
                print(char.name!)
                changeCursorColor(team: char.team)
                charInfoLabel.text = char.getInfo()
                charInfo.isHidden = false
            } else {
                changeCursorColor(team: 0)
                charInfo.isHidden = true
            }
        case .menu:
            switch touchedNode.name! {
            case "Up":
                menu.moveUp()
            case "Down":
                menu.moveDown()
            default:
                break
            }
        }
    } else if(touchedNode.name == "ButtonA") {
        print("Button A pressed")
        buttonAPressed()
    } else if(touchedNode.name == "ButtonB") {
        print("Button B pressed")
        buttonBPressed()
    }
}

func calibrateMap() {
    background.position.x += (background.mapSize.width/2 - 32)
    background.position.y += (background.mapSize.width/2 - 5 * 32)
    objects.position.x += (background.mapSize.width/2 - 32)
    objects.position.y += (background.mapSize.width/2 - 5 * 32)
}

func addController() {
    up = self.childNode(withName: "Up") as! SKSpriteNode
    down = self.childNode(withName: "Down") as! SKSpriteNode
    left = self.childNode(withName: "Left") as! SKSpriteNode
    right = self.childNode(withName: "Right") as! SKSpriteNode
    buttonA = self.childNode(withName: "ButtonA") as! SKSpriteNode
    buttonB = self.childNode(withName: "ButtonB") as! SKSpriteNode
}

func addCursor() {
    cursor_x = 0
    cursor_y = 1
    cursor.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
    cursor.zPosition = 2
    cursor.name = "Cursor"
    self.addChild(cursor)

    var cursorTextures: [SKTexture] = Array(repeating: SKTexture(), count: 3)
    cursorTextures[0] = SKTexture(imageNamed: "Cursor1Blue")
    cursorTextures[1] = SKTexture(imageNamed: "Cursor2Blue")
    cursorTextures[2] = SKTexture(imageNamed: "Cursor3Blue")

    var cursorAnimation = SKAction.animate(with: cursorTextures, timePerFrame: 0.5)
    cursorAnimation = SKAction.repeatForever(cursorAnimation)

    cursor.run(cursorAnimation, withKey: "CursorAnimation")
}

func isCursor(_ name: String) -> Bool {
    if(name == "Up" || name == "Down" || name == "Left" || name == "Right") {
        return true
    } else {
        return false
    }
}

func moveCursor(button: String) {
    if(button == "Up" && cursor_y != y-1) {
        cursor_y += 1
        background.position.y -= 64
        objects.position.y -= 64
    } else if(button == "Down" && cursor_y != 0) {
        cursor_y -= 1
        background.position.y += 64
        objects.position.y += 64
    } else if(button == "Left" && cursor_x != 0) {
        cursor_x -= 1
        background.position.x += 64
        objects.position.x += 64
    } else if(button == "Right" && cursor_x != x-1) {
        cursor_x += 1
        background.position.x -= 64
        objects.position.x -= 64
    }
}

func atCursor() -> Charakter? {
    let char = self.atPoint(cursor.position) as? Charakter
    return char
}

func changeCursorColor(team: Int) {
    cursor.removeAction(forKey: "CursorAnimation")

    var cursorTextures: [SKTexture] = Array(repeating: SKTexture(), count: 3)

    switch team {
    case 0:
        cursorTextures[0] = SKTexture(imageNamed: "Cursor1White")
        cursorTextures[1] = SKTexture(imageNamed: "Cursor2White")
        cursorTextures[2] = SKTexture(imageNamed: "Cursor3White")
    case 1:
        cursorTextures[0] = SKTexture(imageNamed: "Cursor1Blue")
        cursorTextures[1] = SKTexture(imageNamed: "Cursor2Blue")
        cursorTextures[2] = SKTexture(imageNamed: "Cursor3Blue")
    case 2:
        cursorTextures[0] = SKTexture(imageNamed: "Cursor1Red")
        cursorTextures[1] = SKTexture(imageNamed: "Cursor2Red")
        cursorTextures[2] = SKTexture(imageNamed: "Cursor3Red")
    case 3:
        cursorTextures[0] = SKTexture(imageNamed: "Cursor1Green")
        cursorTextures[1] = SKTexture(imageNamed: "Cursor2Green")
        cursorTextures[2] = SKTexture(imageNamed: "Cursor3Green")
    case 4:
        cursorTextures[0] = SKTexture(imageNamed: "Cursor1Yellow")
        cursorTextures[1] = SKTexture(imageNamed: "Cursor2Yellow")
        cursorTextures[2] = SKTexture(imageNamed: "Cursor3Yellow")
    default:
        print("Team doesnt exist!")
    }

    var cursorAnimation = SKAction.animate(with: cursorTextures, timePerFrame: 0.5)
    cursorAnimation = SKAction.repeatForever(cursorAnimation)

    cursor.run(cursorAnimation, withKey: "CursorAnimation")
}

func buttonAPressed() {
    switch state {
    case .initial:
        if let char = atCursor() {
            selected = char
            state = .selected
            showReach(char)
        }
    case .selected:
        if selected.inReach(x: cursor_x, y: cursor_y) {
            if let _ = atCursor() {

            } else {
                let isTree = objects.tileDefinition(atColumn: cursor_x, row: cursor_y)?.userData?["isTree"] as? Bool
                if(isTree == true) {
                    print("tree!")
                } else {
                    state = .menu
                    menu = Menu(3)
                    menu.position = CGPoint(x: self.size.width/2 + 128, y: self.size.height/2)
                    self.addChild(menu)
                }
            }
        }

    case .menu:
        switch menu.getSelectedOption() {
        case.warten:
            selected.move(to: background.centerOfTile(atColumn: cursor_x, row: cursor_y))
            selected.x = cursor_x
            selected.y = cursor_y
            state = .initial
            background.removeChildren(in: reach)
            reach = []
            self.removeChildren(in: [menu])
        default: break
        }
    }
}

func buttonBPressed() {
    switch state {
    case .selected:
        state = .initial
        background.removeChildren(in: reach)
        reach = []
    case .menu:
        state = .selected
        self.removeChildren(in: [menu])
    default:
        break
    }
}

func initCharInfo() {
    charInfoBG.name = "CharInfoBG"
    charInfoBG.anchorPoint = CGPoint(x: 0, y: 1)
    charInfoBG.zPosition = 3
    charInfo.addChild(charInfoBG)

    charInfoLabel.name = "CharInfoLabel"
    charInfoLabel.text = ike.getInfo()
    charInfoLabel.horizontalAlignmentMode = .left
    charInfoLabel.fontName = "Papyrus"
    charInfoLabel.fontColor = .black
    charInfoLabel.fontSize = 22
    charInfoLabel.position = CGPoint(x: 23, y: -33)
    charInfoLabel.zPosition = 4
    charInfo.addChild(charInfoLabel)

    charInfo.name = "CharInfo"
    charInfo.position = CGPoint(x: 0, y: 375)
    self.addChild(charInfo)
}

func showReach(_ char: Charakter) {
    background.removeChildren(in: reach)
    reach = []
    let node: SKSpriteNode = SKSpriteNode(color: .blue, size: CGSize(width: 64, height: 64))
    node.zPosition = 2
    node.alpha = 0.25
    reach.append(node.copy() as! SKSpriteNode)
    reach.last!.position = background.centerOfTile(atColumn: char.x, row: char.y)
    reach.last?.name = "Reichweite"
    background.addChild(reach.last!)
    for i in 1...char.bew {
        if(char.x+i <= x-1) {
            let isTree = objects.tileDefinition(atColumn: char.x+i, row: char.y)?.userData?["isTree"] as? Bool
            if (isTree == false || isTree == nil) {
                reach.append(node.copy() as! SKSpriteNode)
                reach.last!.position = background.centerOfTile(atColumn: char.x+i, row: char.y)
                reach.last?.name = "Reichweite"
                background.addChild(reach.last!)
            }
        }
        if(char.x-i >= 0) {
            let isTree = objects.tileDefinition(atColumn: char.x-i, row: char.y)?.userData?["isTree"] as? Bool
            if (isTree == false || isTree == nil) {
                reach.append(node.copy() as! SKSpriteNode)
                reach.last!.position = background.centerOfTile(atColumn: char.x-i, row: char.y)
                background.addChild(reach.last!)
                reach.last?.name = "Reichweite"
            }
        }
        if(char.y+i <= y-1) {
            let isTree = objects.tileDefinition(atColumn: char.x, row: char.y+i)?.userData?["isTree"] as? Bool
            if (isTree == false || isTree == nil) {
                reach.append(node.copy() as! SKSpriteNode)
                reach.last!.position = background.centerOfTile(atColumn: char.x, row: char.y+i)
                background.addChild(reach.last!)
                reach.last?.name = "Reichweite"
            }
        }
        if(char.y-i >= 0) {
            let isTree = objects.tileDefinition(atColumn: char.x, row: char.y-i)?.userData?["isTree"] as? Bool
            if (isTree == false || isTree == nil) {
                reach.append(node.copy() as! SKSpriteNode)
                reach.last!.position = background.centerOfTile(atColumn: char.x, row: char.y-i)
                background.addChild(reach.last!)
                reach.last?.name = "Reichweite"
            }
        }
        for j in 0...char.bew-i {
            if(j == 0) {
                continue
            }
            if(char.x+i <= x-1) {
                if(char.y+j <= y-1) {
                    let isTree = objects.tileDefinition(atColumn: char.x+i, row: char.y+j)?.userData?["isTree"] as? Bool
                    if (isTree == false || isTree == nil) {
                        reach.append(node.copy() as! SKSpriteNode)
                        reach.last!.position = background.centerOfTile(atColumn: char.x+i, row: char.y+j)
                        background.addChild(reach.last!)
                        reach.last?.name = "Reichweite"
                    }
                }
                if(char.y-j >= 0) {
                    let isTree = objects.tileDefinition(atColumn: char.x+i, row: char.y-j)?.userData?["isTree"] as? Bool
                    if (isTree == false || isTree == nil) {
                        reach.append(node.copy() as! SKSpriteNode)
                        reach.last!.position = background.centerOfTile(atColumn: char.x+i, row: char.y-j)
                        background.addChild(reach.last!)
                        reach.last?.name = "Reichweite"
                    }
                }
            }
            if(char.x-i >= 0) {
                if(char.y-j >= 0) {
                    let isTree = objects.tileDefinition(atColumn: char.x-i, row: char.y-j)?.userData?["isTree"] as? Bool
                    if (isTree == false || isTree == nil) {
                        reach.append(node.copy() as! SKSpriteNode)
                        reach.last!.position = background.centerOfTile(atColumn: char.x-i, row: char.y-j)
                        background.addChild(reach.last!)
                        reach.last?.name = "Reichweite"
                    }
                }
                if(char.y+j <= y-1) {
                    let isTree = objects.tileDefinition(atColumn: char.x-i, row: char.y+j)?.userData?["isTree"] as? Bool
                    if (isTree == false || isTree == nil) {
                        reach.append(node.copy() as! SKSpriteNode)
                        reach.last!.position = background.centerOfTile(atColumn: char.x-i, row: char.y+j)
                        background.addChild(reach.last!)
                        reach.last?.name = "Reichweite"
                    }
                }
            }
        }
    }
}

}

...