Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Generace bludiště v políčkové grafice

Aktivity
Avatar
matesax
Tvůrce
Avatar
matesax:20.10.2012 21:48

Dobrý den,
zdá se, že se mi podařilo splácat funkční algoritmus, ale jaksi to má menší háček - cesty se budují pohledem na příští políčka. (Jejich náhodným výběrem a kontrolu.) Takže mezi políčky mi nevznikají mezery. (stěny) Když se ale budu dívat jak o jedno kolem, tak i o dva kolem - a pak tam dělat nějaké podmínky - či tak, tak to asi nebude dobré řešení... :) Jak na to? Děkuji.

public List<Vector2> GenerateMaze(Rectangle bounds)
{
    List<Vector2>
        paths = new List<Vector2>(),
        potential = new List<Vector2> { new Vector2(0, 0) };

    Vector2[] neighbors = new Vector2[] { new Vector2(1, 0), new Vector2(-1, 0), new Vector2(0, 1), new Vector2(0, -1) };

    while (paths.Count < (bounds.Width / 32) * (bounds.Height / 32))
    {
        Vector2 doc = potential[r.Next(potential.Count - 1)];

        if (!paths.Contains(doc))
        {
            foreach (Vector2 neighbor in neighbors)
                if (!paths.Contains(doc + neighbor))
                    potential.Insert(r.Next(potential.Count), doc + neighbor);

            paths.Add(doc);
        }

        potential.Remove(doc);
    }

    return paths;
}

Proč je tam "if (!paths.Conta­ins(doc))"? To proto, že to chci maximálně náhodné - takže když si nějaké políčko zabere cestu, ale jiné mu ji překazí, tak by došlo k selhání. Takže jsem to mohl zarazit v jedné podmínce - zde:

if (!paths.Conta­ins(doc + neighbor))

Ale jak píši - chtěl bych to co nejnáhodnější...

Editováno 20.10.2012 21:51
 
Odpovědět
20.10.2012 21:48
Avatar
matesax
Tvůrce
Avatar
matesax:20.10.2012 22:02

Pro jistotu to ještě nakreslím. :)

Základ:

000000...
000000...
000000...
000000...
.........

Moje dělá:

111111...
111111...
111100...
111111...
.........

Potřebuji:

100100...
110111...
101100...
111000...
.........

 
Nahoru Odpovědět
20.10.2012 22:02
Avatar
matesax
Tvůrce
Avatar
matesax:21.10.2012 13:34

Tak opět sám. :)

using System.Collections.Generic;
using Microsoft.Xna.Framework;
using System;

public class MazeGenerator
{
    private Random r = new Random();

    public List<Vector2> GenerateMaze(Rectangle bounds)
    {
        List<Vector2> paths = new List<Vector2>() { new Vector2(0, 0) };

        Dictionary<Vector2, int> potential =  new Dictionary<Vector2,int>();

        Vector2[] neighbors = new Vector2[] { new Vector2(1, 0), new Vector2(-1, 0), new Vector2(0, 1), new Vector2(0, -1) };

        for (int index = 0; index < 4; index++)
            potential.Add(neighbors[index], index);

        while (paths.Count < 1000)
        {
            Vector2
                oldItem = new Vector2(),
                newItem = new Vector2();
            int
                index = r.Next(potential.Count),
                direction = 0;

            foreach (Vector2 item in potential.Keys)
                if (index == 1)
                {
                    oldItem = item;
                    direction = potential[item];
                    newItem = oldItem + neighbors[direction];
                    break;
                }
                else
                    index--;

            if (!paths.Contains(newItem))
            {
                paths.Add(oldItem);
                paths.Add(newItem);

                for (int index2 = 0; index2 < 4; index2++)
                    if (!paths.Contains(newItem + neighbors[index2]) && !potential.ContainsKey(newItem + neighbors[index2]))
                        potential.Add(newItem + neighbors[index2], index2);
            }

            potential.Remove(oldItem);
        }

        return paths;
    }
}
 
Nahoru Odpovědět
21.10.2012 13:34
Avatar
Kit
Tvůrce
Avatar
Odpovídá na matesax
Kit:21.10.2012 13:38

My bychom ti občas rádi poradili, kdybychom ti rozuměli.

Nahoru Odpovědět
21.10.2012 13:38
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
matesax
Tvůrce
Avatar
Odpovídá na Kit
matesax:21.10.2012 13:49

Já sám jsem to nechápal - proto jsem se obrátil sem... :)

Nyní mi to je již jasné - bral jsem to tak, že si z každého volného konce vyberu náhodného souseda (nikam nezasahujícího) a toho přidám do proměnné s cestami v bludišti. Ale je to tak že každý volný konec má jen jeden směr - vstoupí-li mu někdo jiný do cesty, tak se jednoduše vymaže. Tím tedy každý konec má svůj pevně daný směr - a v něm stačí kontrolovat každé příští políčko...

Jediné co mi vrtá hlavou - jak mám zařídit, aby se mi vyplnila určitá plocha?

 
Nahoru Odpovědět
21.10.2012 13:49
Avatar
David Hartinger
Vlastník
Avatar
Nahoru Odpovědět
21.10.2012 14:05
You are the greatest project you will ever work on.
Avatar
matesax
Tvůrce
Avatar
Odpovídá na David Hartinger
matesax:21.10.2012 14:11

Vždyť to již mám - a způsobů je snad nekonečně mnoho... :) (A ten můj je pro mě lepší - potřebuji alespoň jednu 100% průchozí cestu...) A snad jsem i vymyslel, jek jím vyplnit předem zadanou plochu...

 
Nahoru Odpovědět
21.10.2012 14:11
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na matesax
David Hartinger:21.10.2012 14:19

Tuhle věc jsem řešil i tak, že jsem naházel na plochu několik obdélníkových místností a ty poté propojil náhodně generovanou chodbou. Bylo to jako had, který se náhodně pohybuje (ale nemůže dozadu) a kolem něj se staví zdi. Dělalo to docela hezké dungeony, bohužel jsem to nikdy nedodělal.

Nahoru Odpovědět
21.10.2012 14:19
You are the greatest project you will ever work on.
Avatar
matesax
Tvůrce
Avatar
Odpovídá na David Hartinger
matesax:21.10.2012 14:31

Cyklus se mi nechce ukončit - přitom podmínky jsou myslím správně:

using System.Collections.Generic;
using Microsoft.Xna.Framework;
using System;

public class MazeGenerator
{
    private Random r = new Random();

    public List<Vector2> GenerateMaze(Rectangle bounds)
    {
        List<Vector2> paths = new List<Vector2>() { new Vector2(0, 0) };

        Dictionary<Vector2, int> potential = new Dictionary<Vector2, int>() { { new Vector2(1, 0), 0 }, { new Vector2(0, 1), 2 } };

        Vector2[] neighbors = new Vector2[] { new Vector2(1, 0), new Vector2(-1, 0), new Vector2(0, 1), new Vector2(0, -1) };

        while (potential.Count > 0)
        {
            Vector2
                oldItem = new Vector2(),
                newItem = new Vector2();
            int
                index = r.Next(potential.Count),
                direction = 0;

            foreach (Vector2 item in potential.Keys)
                if (index == 1)
                {
                    oldItem = item;
                    direction = potential[item];
                    newItem = oldItem + neighbors[direction];
                    break;
                }
                else
                    index--;

            if (!paths.Contains(newItem))
            {
                paths.Add(oldItem);
                paths.Add(newItem);

                for (int index2 = 0; index2 < 4; index2++)
                {
                    Vector2 total = newItem + neighbors[index2];

                    if (!paths.Contains(total) && !potential.ContainsKey(total) && total.X > 0 && total.Y > 0 && total.X < (bounds.Width / 32) && total.Y < (bounds.Height / 32))
                        potential.Add(total, index2);
                }
            }

            potential.Remove(oldItem);
        }

        return paths;
    }
}

V čem vidíš problém? Děkuji.

Editováno 21.10.2012 14:32
 
Nahoru Odpovědět
21.10.2012 14:31
Avatar
matesax
Tvůrce
Avatar
Odpovídá na David Hartinger
matesax:21.10.2012 17:53

A jak bych to měl naklonit podle X - asi to mám správně:

using System;
using Microsoft.Xna.Framework;

public class Camera2D
{
    public float Zoom { get; set; }

    public float Rotation { get; set; }

    public Vector2 Position { get; set; }

    public Camera2D()
    {
        Zoom = 2;
        Rotation = 0.001F;
        Position = new Vector2(-400, 240);
    }

    public void Move(Vector2 amount)
    {
        Position += amount;
    }

    public Matrix GetTransformation(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphicsDevice)
    {
        return Matrix.CreateTranslation(
            new Vector3(Position.X, -Position.Y, 0))
            *
            Matrix.CreateRotationX(Rotation)
            *
            Matrix.CreateScale(new Vector3(Zoom, Zoom, 1))
            *
            Matrix.CreateTranslation(new Vector3(graphicsDevice.Viewport.Width * 0.5f, graphicsDevice.Viewport.Height * 0.5f, 0));
    }
}

Ale problém vidím ve vykreslení 3D objektu - místo 2D. Tak jako tak bych ty zdi 3D mít chtěl - zatím bez textury. Ovšem Texture3D se vykreslit nedá - co jsem nejčastěji viděl - dělá se to přes postupné vykreslování Meshů. Ovšem dává mi to dost zabrat - dát do dokupy - jak píši - zatím by to bylo jen v nějaké modré barvě. Děkuji za případnou pomoc.

 
Nahoru Odpovědět
21.10.2012 17:53
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.