Geração aleatória de mapas no estilo Zelda


9

Estou tentando gerar aleatoriamente um mapa de salas conectadas por portas e consegui gerar uma usando este código:

public void generate(GameContainer gc) {
        rooms = new ArrayList<Room>();
        startingRoom = new Room(0);
        startingRoom.setPosition(viewport.getCenterX(), viewport.getCenterY());
        lastRoom = startingRoom;
        rooms.add(startingRoom);
        int roomsize = 25;

        for (int i = 0; i <= (1000 + Math.random() * 4000); i++) {
            Room room = new Room(i + 1);
            int direction = (int) (Math.random() * (4));

            switch (direction) {
                case 0:
                    room.setPosition(lastRoom.x, lastRoom.y - roomsize);
                    break;
                case 1:
                    room.setPosition(lastRoom.x, lastRoom.y + roomsize);
                    break;
                case 2:
                    room.setPosition(lastRoom.x + roomsize, lastRoom.y);
                    break;
                case 3:
                    room.setPosition(lastRoom.x - roomsize, lastRoom.y);
                    break;
                default:
                    room.setPosition(lastRoom.x, lastRoom.y - roomsize);
                    break;
            }
            rooms.add(room);
            lastRoom = room;
        }
    } 

No entanto, isso não me permite descobrir quais portas o quarto tem. Eu preciso ser capaz de descobrir isso para que eu possa colocar as portas nos lugares corretos para que possam ser usadas em salas adjacentes. Esse tipo de "mapa inteligente" é possível com meu algoritmo atual ou devo começar de novo? Que etapas posso tomar para que isso funcione?

Estou usando Slick2d e Java para isso

Obrigado.


Por que você não une os quartos primeiro e cria as portas necessárias para conectá-los?
petervaz

É isso que eu quero fazer, mas acho que não posso com esse algoritmo, porque não há como contabilizar salas que aparecem ao lado de salas existentes que não são sua fonte, o que pode significar que a porta não está há. Tenho certeza de que neste momento precisarei escrever algo completamente novo. Estou apontando para um sistema de mapas como The Binding of Isaac's, se isso ajudar.
user1500452

Parece que você precisa ter os quartos facilmente pesquisáveis ​​por sua posição. Eu sugeriria um Mapa <Vector2d, Quarto> para ser rápido e sujo, mas você pode querer montar uma matriz classificada de matrizes ordenadas.
rebocadores

dê uma olhada aqui: pcg.wikidot.com/pcg-algorithm:dungeon-generation (does not responder a sua pergunta, mas pode ajudar)
tigrou

Pode não ser uma opção, mas você pode tentar algo como: Gere cada sala com 4 pontos abertos (1 para cada parede) e, em seguida, coloque aleatoriamente uma porta aberta, porta fechada, parede etc. em cada uma das conexões da sala.
Supericy 19/03/2013

Respostas:


1

Acho que essa pergunta é bastante aberta, já que existem alguns trechos de código que você precisará para poder vincular as salas adequadamente e como você codifica isso depende muito de como as coisas fazem sentido para você.

Dito isto, posso fazer algumas recomendações para ajudá-lo a ir na direção certa.

Primeiro de tudo, se os tamanhos dos quartos forem constantes, recomendo criar um sistema de coordenadas de nível mais alto para os quartos. Algo que seria assim:

 _____ _____ _____ _____ _____
|     |     |     |     |     |
|-2,-1|-1,-1| 0,-1| 1,-1| 2,-1|
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|-2,0 |-1,0 | 0,0 | 1,0 | 2,0 |
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|-2,1 |-1,1 | 0,1 | 1,1 | 2,1 |
|_____|_____|_____|_____|_____|

A idéia é que, quando você está abrindo espaço (0,0), você pergunta aos quartos (-1,0) (0, -1) (1,0) e (0,1) onde estão as portas adjacentes. Se você precisar de cordas de tela, deve ser fácil adicionar um método GetScreenCoords ou uma matriz de transformação, se você preferir.

Em seguida, você poderá consultar a lista de quartos. Passar por todas as salas da sua lista (até 5000!) Apenas para encontrar as salas vizinhas ficará caro. Para uma maneira rápida de colocar as coisas em funcionamento, eu recomendo usar um HashMap<coord, Room> rooms. Dessa forma, quando você está abrindo espaço (0,0), solicita quartos vizinhos existentes, simplesmente solicita rooms.get((1,0))etc., e adiciona sua sala recém-gerada em (0,0) que faria rooms.put((0,0), newroom) Se isso se tornar muito lento, poderá vale a pena olhar para listas ordenadas. Talvez uma lista classificada (x) de listas ordenadas (y).

Finalmente, você precisará adicionar uma maneira de obter a posição da porta nas salas vizinhas. Um novo método como int GetSouthDoor()deve fazer o truque.

Tenho certeza de que haverá muito mais trabalho para você codificar uma solução completa. Espero que isso ajude você a começar.


Extremamente útil, as informações sobre os hashmaps são exatamente o que eu precisava para me levar na direção certa. Obrigado!
user1500452

2

Duas coisas:

1) Em seu comentário, você diz que deseja algo como a Encadernação de Isaque. Esse jogo tem portas no meio de cada peça, garantindo que elas estejam alinhadas. Se você seguir o exemplo, tudo se resume a decidir com que tipo de porta conectá-las (aberta, trancada, bowall, etc.).

2) Seu código parece iniciar em um local e gerar processualmente novos blocos em uma direção. Em sua declaração switch, no entanto, você não está representando a direção você está vindo de . Se você continuar com esse algoritmo, considere acompanhar também o último canal, para que os blocos não se substituam.


0

Use um algoritmo de geração de labirinto

Use uma forma modificada do algoritmo de Prim para criar um labirinto básico de 20 quartos ou mais. Escolha duas salas para serem as salas inicial e final, garantindo que o final seja sempre alcançável. Bloqueie portas aleatórias com diferentes tipos de portas e adicione portas aleatoriamente onde duas salas adjacentes não estejam conectadas (com baixa probabilidade)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.