代码之家  ›  专栏  ›  技术社区  ›  E. Huckabee

BSP地牢生成器出现不可修复错误

  •  1
  • E. Huckabee  · 技术社区  · 6 年前

    我在做翻译 this ActionScript tutorial 二进制空间划分成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!
    }
    

    这是我的翻译代码(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代码完全相同(据我所知)。但这给了我一个错误。这个 左撇子 右孩子 变量未在我的中初始化 init 方法。当我移动 split() -> Bool 功能进入 方法它不允许我使用该函数,给我一个错误“类型Leaf的值没有成员split()”。卸下 l if (l.spit()) 行给出了第二个错误“在声明之前使用局部变量‘split’”。这个 split() 函数必须在初始化范围之外。

    左撇子 右孩子 像这样:

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

    它创建了一个无限循环,最终导致崩溃。

    代码应该正在初始化 左撇子 右孩子 拆分()->布尔 但我不认为这是它的工作方式在斯威夫特。你应该能够复制/粘贴到一个Swift文件,并得到相同的错误。

    为什么会这样?我的代码写得不好吗?我怎样才能解决这个问题?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Dávid Pásztor    6 年前

    在ActionScript中,未初始化的变量将自动使用特殊值进行计算 undefined ; 另外,在ActionScript中, undefined == null ,这就是为什么 if (leftChild != null || rightChild != null) 作品。

    在Swift中,您需要明确地 allow 你的变量是零。你担心的变量需要从 nil (如果您允许,通过将其类型设置为 Optional

    var leftChild:Leaf?
    var rightChild:Leaf?