BSP Dungeon Generator выдаёт неустранимую ошибку - PullRequest
0 голосов
/ 01 октября 2018

Я работаю над переводом этого руководства по ActionScript по разбиению двоичного пространства на Swift, чтобы я мог использовать его в своей игре, похожей на мошенника.Я наткнулся на заминку.

В этой статье писатель инициализирует свой класс следующим образом:

public function Leaf(X:int, Y:int, Width:int, Height:int)
{
    // initialize our leaf
    x = X;
    y = Y;
    width = Width;
    height = Height;
}

Когда я перевел это на Swift, я столкнулся с ошибкой.Приведенный выше код не инициализирует все объявленные значения.Это приводит меня к невозможной ошибке, которую я не могу исправить.Каким-то образом автор статьи инициализирует свои переменные leftChild и rightChild с помощью этой функции, которая находится за пределами области инициализации.

public function split():Boolean
{
    // begin splitting the leaf into two children
    if (leftChild != null || rightChild != null)
        return false; // we're already split! Abort!

    // determine direction of split
    // if the width is >25% larger than height, we split vertically
    // if the height is >25% larger than the width, we split horizontally
    // otherwise we split randomly
    var splitH:Boolean = FlxG.random() > 0.5;
    if (width > height && width / height >= 1.25)
        splitH = false;
    else if (height > width && height / width >= 1.25)
        splitH = true;

    var max:int = (splitH ? height : width) - MIN_LEAF_SIZE; // determine the maximum height or width
    if (max <= MIN_LEAF_SIZE)
        return false; // the area is too small to split any more...

    var split:int = Registry.randomNumber(MIN_LEAF_SIZE, max); // determine where we're going to split

    // create our left and right children based on the direction of the split
    if (splitH)
    {
        leftChild = new Leaf(x, y, width, split);
        rightChild = new Leaf(x, y + split, width, height - split);
    }
    else
    {
        leftChild = new Leaf(x, y, split, height);
        rightChild = new Leaf(x + split, y, width - split, height);
    }
    return true; // split successful!
}

Что-то нормально в ActionScript, но в Swift это приводит меня к моей проблеме.

Вот мой переведенный код (Swift):

private let mapWidth:Int = 50
private let mapHeight:Int = 50

class Leaf {
    var leftLeaf = [Leaf]()
    var rightLeaf = [Leaf]()

    var minLeafSize:Int = 6
    var x, y, width, height: Int

    var leftChild:Leaf
    var rightChild:Leaf

    init (X:Int, Y:Int, W:Int, H:Int) {

        x = Y
        y = Y

        width = W
        height = H

        let maxLeafSize:UInt = 20

        var leaves = [Leaf]()

        // first, create a Leaf to be the 'root' of all Leafs.
        let root = Leaf(X: 0, Y: 0, W: mapWidth, H: mapHeight)
        leaves.append(root)

        var didSplit:Bool = true
        // we loop through every Leaf in our Vector over and over again, until no more Leafs can be split.
        while (didSplit) {
            didSplit = false
            for l in leaves {
                if l.leftLeaf.isEmpty == true && l.rightLeaf.isEmpty == true {
                    // if this Leaf is too big, or 75% chance...
                    if l.width > maxLeafSize || l.height > maxLeafSize || Int(arc4random_uniform(100)) > 25 {
                        if (l.split()) {
                            // if we did split, push the child leafs to the Vector so we can loop into them next
                            leaves.append(l.leftChild)
                            leaves.append(l.rightChild)
                            didSplit = true
                        }
                    }
                }
            }
        }
    }
    func split() -> Bool {
        if leftLeaf.isEmpty == true || rightLeaf.isEmpty == true {
            return false
        }

        var splitH = arc4random_uniform(100) > 50 ? true : false

        if width > height && Double(width / height) >= 1.25 {
            splitH = false
        }
        if height > width && Double(height / width) >= 1.25 {
            splitH = true
        }

        let max:Int = (splitH ? height : width) - minLeafSize // determine the maximum height or width
        if max <= minLeafSize { return false }

        let split:Int = Int(arc4random_uniform(UInt32(minLeafSize - max) + UInt32(max)))

        if (splitH) {
            leftChild = Leaf(X: x, Y: y, W: width, H: split)
            rightChild = Leaf(X: x, Y: y + split, W: width, H: height - split)

            leftLeaf.append(leftChild)
            rightLeaf.append(rightChild)
        } else {
            leftChild = Leaf(X: x, Y: y, W: split, H: height)
            rightChild = Leaf(X: x + split, Y: y, W: width - split, H: height);

            leftLeaf.append(leftChild)
            rightLeaf.append(rightChild)
        }
        return true
    }
}

Он идентичен (насколько я понимаю) коду ActionScript в статье.Но это дает мне ошибку.Переменные leftChild и rightChild не инициализируются в моем методе init.Когда я перемещаю функцию split() -> Bool в метод init, она не позволяет мне использовать эту функцию, что выдает ошибку «Значение типа Leaf не имеет члена split ()».Удаление l из строки if (l.spit()) дает мне вторую ошибку "Использование локальной переменной 'split' перед ее объявлением".Функция split() должна находиться за пределами области инициализации.

Если я попытаюсь инициализировать leftChild и rightChild примерно так:

init (X:Int, Y:Int, W:Int, H:Int) {

    x = Y
    y = Y

    width = W
    height = H

    leftChild = Leaf(X: x, Y: y, W: width, H: height)
    rightChild = Leaf(X: x, Y: y, W: width, H: height)
}

Она создает бесконечный цикл, который в конечном итогевызывает сбой.

Код должен инициализировать leftChild и rightChild в функции split() -> Bool, но я не думаю, что это работает в Swift.Вы должны иметь возможность скопировать / вставить его в файл Swift и получить те же ошибки.

Почему это происходит?Мой код плохо написан?Как я могу это исправить?

1 Ответ

0 голосов
/ 01 октября 2018

В ActionScript неинициализированные переменные автоматически оцениваются специальным значением undefined;также в ActionScript undefined == null, поэтому if (leftChild != null || rightChild != null) работает.

В Swift вам необходимо явно разрешить вашим переменным быть нулевыми.Переменные, о которых вы беспокоитесь, должны начинаться с nil (что они автоматически сделают, если вы позволите им, установив для их типа значение Optional - отметьте знак вопроса):

var leftChild:Leaf?
var rightChild:Leaf?
...