0

Sorry if the title isn't clear, I'm not really sure how to word this. I'm very new to this, so if I'm not clear on something just ask and I can try and word it better.

I am using binary space partitioning for procedural level generation in a 2d game. I have a binary tree where each node contains it's parent, a rectangle named room, childA, and childB. childA.room and childB.room are the results of splitting room. The sum of childA and childB's room sizes is equal to the room's size, but childA and childB's room sizes are not guaranteed to be equal. The axis that the rectangle is cut across will most likely be different each time, but again that's not guaranteed.

So far, all of this is fine. I'm getting rectangles with resulting sizes that I am happy with. Now, I'm stuck on the (seemingly) trivial part of positioning the rectangles. I assume that one of the rectangles doesn't even need to be moved. Below is the closest I've got, it works correctly on the first split but not on any splits after. Again, I'm sorry if I missed any important information or was unclear, just ask.

public List<BinaryNode> SplitNode(BinaryNode nodeToSplit, Vector2 splitParam)
    {
        var nodeList = new List<BinaryNode>();
        var tempSplitParam = new Vector2();
        var TempChildA = new BinaryNode();
        var TempChildB = new BinaryNode();

        TempChildA.parent = nodeToSplit;
        TempChildB.parent = nodeToSplit;

        tempSplitParam = Vector2.zero;
        tempSplitParam.x = Random.Range(splitParam.x, splitParam.y); //select the percentage that each child room gets to keep, somewhere between the splitParams x and y
        tempSplitParam.y = 1 - tempSplitParam.x; //x + y will always = 1. child a gets x%, child b gets y%, all the space is used.

        //randomly decide whether to split on the x or y, only on the FIRST cut.
        if (Random.value > .5 && nodeToSplit.parent == null)//y axis
        {
            TempChildA.room.size = new Vector2(Mathf.Round(nodeToSplit.room.size.x * tempSplitParam.x), nodeToSplit.room.size.y);
            TempChildB.room.size = new Vector2(Mathf.Round(nodeToSplit.room.size.x * tempSplitParam.y), nodeToSplit.room.size.y);
            TempChildB.room.position = new Vector2(TempChildA.room.size.x + TempChildB.room.position.x, TempChildA.room.position.y);
        } else 
        if(nodeToSplit.parent == null)//x axis
        {
            TempChildA.room.size = new Vector2(nodeToSplit.room.size.x, (Mathf.Round(nodeToSplit.room.size.y * tempSplitParam.x)));
            TempChildB.room.size = new Vector2(nodeToSplit.room.size.x, (Mathf.Round(nodeToSplit.room.size.y * tempSplitParam.y)));
            TempChildB.room.position = new Vector2(TempChildB.room.position.x, TempChildA.room.size.y + TempChildB.room.position.x);
        } else 
        if (nodeToSplit.room.width > nodeToSplit.room.height) //cut across the y axis if the room is longer than it is tall
        {
            TempChildA.room.size = new Vector2(Mathf.Round(nodeToSplit.room.size.x * tempSplitParam.x), nodeToSplit.room.size.y);
            TempChildB.room.size = new Vector2(Mathf.Round(nodeToSplit.room.size.x * tempSplitParam.y), nodeToSplit.room.size.y);
            TempChildB.room.position = new Vector2(TempChildA.room.size.x + TempChildB.room.position.x, TempChildA.room.position.y);
        } else //cut across the x axis otherwise
        {
            TempChildA.room.size = new Vector2(nodeToSplit.room.size.x, (Mathf.Round(nodeToSplit.room.size.y * tempSplitParam.x)));
            TempChildB.room.size = new Vector2(nodeToSplit.room.size.x, (Mathf.Round(nodeToSplit.room.size.y * tempSplitParam.y)));
            TempChildB.room.position = new Vector2(TempChildB.room.position.x, TempChildA.room.size.y + TempChildB.room.position.x);
        }

        nodeToSplit.childA = TempChildA;
        nodeToSplit.childB = TempChildB;

        nodeList.Add(TempChildA);
        nodeList.Add(TempChildB);
        return nodeList;
    }
Ben
  • 1
  • 1
  • Assuming you expect exactly two nodes two be created in SplitNodes, then it seems fine, and I suspect the problem is with how SplitNodes is being called. If you are expecting SplitNodes to recursively create a multi level BSP, then the method contains no recursive calls. – Ryan1729 May 26 '20 at 10:21
  • @Ryan1729 SplitNodes isn't recursive, I have a function to get the furthest children in the tree and then I call SplitNodes on them. Here is the function for finding the children. https://pastebin.com/mvtkWkBA – Ben May 28 '20 at 15:27
  • That code seems fine as well, given that all nodes have exactly either 0 or 2 children. When you say that "it works correctly on the first split but not on any splits after", what exactly happens? Does it just not ever split the nodes the second time? Have you tried stepping through the code in a debugger? I suspect that SplitNodes is not being called more than once for some reason. – Ryan1729 May 29 '20 at 01:01
  • SplitNode is being called in a for loop on the furthest children in the tree. I rewrote the function to find children because the last one was not working properly, this one always creates the correct amount of children rooms. I'll print the positions of each final rectangle, alongside their size. Perhaps there is no problem with the rectangles themselves, and I just cant draw the rectangles properly? I'll include screenshots of the outputs and the full code [here](https://imgur.com/a/9Y9Q6N5). – Ben May 30 '20 at 11:21
  • I drew a picture of the coordinates from the second image by hand so I could compare and it seems like only the last two rectangles are getting drawn for some reason? If you directly call DrawRect with four different rects and four different colours does that work? What about if you directly call the method with the rectangles from the printout and only two colours? – Ryan1729 May 30 '20 at 19:24
  • I don't know enough about Unity to see anything wrong with this, and from a quick look at the docs what you did seems right. Since it does seem to be the drawing, I'd suggest trying to make an example that doesn't involve BinaryNode and still that acts unexpectedly and ask a new question about that. – Ryan1729 May 30 '20 at 19:25
  • https://i.gyazo.com/81137db0cac3c894dbe598329ce1bbf7.mp4 I put it into a coroutine to draw the rectangles slower, perhaps this can give some hints? the rectangles are definitely the right size, it just seems that the y position on them is wrong. – Ben May 31 '20 at 06:23

0 Answers0