C# Masalah tentang peta ubin sederhana untuk mesin roguelike

Baiklah, pertama-tama, ini adalah postingan pertama saya di sini dan biasanya saya bisa langsung mencari jawabannya, namun karena ini agak spesifik, saya tidak dapat menemukan jawaban untuk yang ini.

Saya agak pemula dalam pengkodean (saya tahu dasar-dasarnya sebagian besar dan telah menonton banyak video dan membaca banyak tutorial tentang C#) dan saya mencoba membuat kode "permainan" konsol ASCII. Semuanya berjalan cukup baik untuk sementara waktu tetapi sekarang saya terjebak pada bagian pemetaan. Pada awalnya, saya pikir saya akan memasukkan semua koordinat secara manual untuk dinding. Namun saya menemukan posting di sini menjelaskan bahwa cara yang lebih Berorientasi Objek dalam melakukannya adalah dengan membuat kelas Tile seperti itu.

public class Tile
{
    public int X { get; set; }
    public int Y { get; set; }
    public bool IsWall { get; set; }
}

dan kemudian mengisi daftar dengan melakukan ini

private static void PopulateTiles()
    {
        for (int x = 1; x < 159; x++)
            for (int y = 3; y < 45; y++)
                Tiles.Add(new Tile { X = x, Y = y });
    }

Alasan nilai awal x dan y yang ganjil adalah karena saya membatasi ubin pada bagian tertentu dari konsol, sisanya digunakan untuk GUI.

Bagaimanapun, kecuali ada cara yang lebih baik (Dan pasti ada, saya tidak tahu apa yang bisa terjadi), saya mencoba mengambil hanya sebagian dari daftar itu untuk mengubah properti ISWALL untuk menyetelnya ke TRUE dan kemudian gunakan ini

    static void DrawObstacles()
    {
        foreach (Tile tile in World.Tiles)
        {
            if (tile.IsWall)
            {
                Console.SetCursorPosition(tile.X, tile.Y);
                Console.Write("#");
            }
        }
    }

Sejauh ini, saya mencoba beberapa solusi berbeda tetapi jelas, saya mengalami masalah dengan masing-masing solusi (saya juga mencoba menghindari memperlambat program, jika memungkinkan, dan menghindari loop lain dengan 1000+ iterasi).

    //Tried this
    private static void SetWalls()
    {
        int[] walls = new int[] { };
        walls += Tiles.GetRange(0, 7); //Fails because I cannot use tiles in an int[]... of course
    }

    //This
    List<Tile> walls = new List<Tile>();
    List<Tile> walls = Tiles.GetRange(0, 7);
    List<Tile> walls = Tiles.GetRange(19, 7; //Doesn't work either but I've no idea why here

    //And finally
    List<Tile> walls = new List<Tile>();
    walls.Add(Tiles[Tiles.GetRange(0, 7)]); //Gives me an error saying that System.Collections.Generic.List<Engine.Tile> cannot be converted to int

Jadi saat ini, saya agak bingung karena saya lebih suka mengulangi daftar, daripada memasukkan setiap koordinat secara manual dalam array 2D... dan kemudian mengulanginya untuk "membangun" dinding.

Pertanyaan saya adalah: Apakah mungkin untuk mengambil hanya beberapa bagian dari daftar (seperti indeks 0 - 7, 19 - 26, 29, 31, 35 - 46) dan kemudian mengulangi daftar ubin utama untuk menggunakan "Daftar Indeks" baru ini " untuk mengubah properti ISWALL ubin pada indeks tersebut... Jika itu masuk akal.

Terima kasih sebelumnya dan jangan ragu untuk memberi tahu saya jika saya membuat kesalahan dalam postingan.


person Schaezar    schedule 24.04.2017    source sumber
comment
Saya tersesat saat membaca ini. Apa sebenarnya Pertanyaan Anda?   -  person Smartis    schedule 24.04.2017
comment
Pada dasarnya, saya ingin dapat mengulangi daftar ubin dan memilih hanya beberapa di antaranya untuk menyetel properti ISWALL ke TRUE. Saya hanya perlu memilih rentang tertentu, seperti ubin 0 - 7, 19 - 26 dan semacamnya. Jika itu masuk akal   -  person Schaezar    schedule 24.04.2017
comment
apakah Anda belum menyimpan ubin Anda dalam format 80x25? meniru keluaran layar? itu akan membuat hidupmu lebih mudah.. karena menurutku kamu sedang mencoba membuat ruangan atm kan? (Saya menghabiskan terlalu banyak hidup saya di game roguelike)   -  person BugFinder    schedule 24.04.2017
comment
Saya tidak yakin saya mengerti apa yang Anda maksud dengan menyimpan ubin dalam format 80*25 tetapi susunan ubin sebenarnya 158*41 karena saya juga mengubah ukuran konsol. Itu (160, 60)   -  person Schaezar    schedule 24.04.2017


Jawaban (1)


Ada banyak informasi yang tidak perlu, sehingga pertanyaannya sulit untuk dipahami. Namun, tampaknya Anda tidak ingin mengulang setiap objek permainan hanya untuk menemukan beberapa. Ini adalah masalah yang Anda alami dalam game, terutama tabrakan. Saya berasumsi Anda membuat game ini di konsol, jadi fitur mesin game apa pun kemungkinan besar tidak dapat Anda gunakan.

Jadi, saya menyarankan agar Anda membagi objek Anda ke dalam daftar berdasarkan kepentingan atau fungsinya. Dengan melakukan ini, Anda hanya perlu mengulang setiap objek game saat startup, dan kemudian menyelamatkan diri Anda dari proses yang melelahkan selama run time.

Misalnya, Anda dapat menginisialisasi semuanya seperti ini:

    List<GameObject> GameObjects { get; set; }
    List<GameObject> Walls { get; set; }
    List<GameObject> Items { get; set; }

    public Map()
    {
        PopulateTiles();
        StructureCollections();
    }

    //Small processing loop
    private void DrawObstacles()
    {
        foreach(var wall in Walls)
        {
            Console.SetCursorPosition(tile.X, tile.Y);
            Console.Write("#");
        }
    }

    //Called only on startup
    private  void PopulateTiles()
    {
        for (int x = 1; x < 159; x++)
            for (int y = 3; y < 45; y++)
                GameObjects.Add(new GameObject() { X = x, Y = y });
    }

    //Called only on starup
    private void StructureCollections()
    {
        foreach(GameObject gameObj in GameObjects)
        {
            if (gameObj.IsWall)
                Walls.Add(gameObj);

            if (gameObj.IsItem)
                Items.Add(gameObj);
        }
    }

Ini bukanlah solusi sempurna, dan semuanya bergantung pada bagaimana Anda berencana menjalankan game Anda. Tapi menurut saya ini adalah awal yang baik untuk sebuah ide.

Pembaruan: Jika Anda ingin menemukan cara yang lebih baik untuk mengatur pembuatan objek game Anda, daripada membuat semuanya dengan tangan, Anda dapat membagi objek Anda menjadi lebih banyak kelas. Misalnya:

public class GameObject
{
    public int X { get; set; }
    public int Y { get; set; }
    public bool IsWall { get; set; }

    public GameObject(int x, int y)
    {
        X = x;
        Y = y;
    }

}

public class Wall : GameObject
{
    public Wall(int x, int y) : base(x,y)
    {
        IsWall = true;
    }
}

Sekarang dalam kasus ini, Anda hanya perlu memanggil new Wall(x, y); baru yang akan menangani semua yang diperlukan untuk beroperasi sebagai dinding, tanpa memerlukan lebih banyak parameter.

PEMBARUAN: Karena ini diterima sebagai jawaban, saya merasa berkewajiban untuk menunjukkan bahwa jawaban ini adalah untuk masalah kecil dan spesifik. Jika Anda akan memiliki banyak objek yang memerlukan kelasnya sendiri, ini bukan metode terbaik (di mana "Dinding" adalah kelasnya sendiri). Jika kita ingin memiliki lebih banyak objek, desain ini kemungkinan besar akan menyebabkan ledakan kelas.

person Toskr    schedule 24.04.2017
comment
Itulah tepatnya yang ingin saya lakukan, namun, saya tidak tahu cara mengubah properti menjadi IsWall (Selain memasukkannya secara manual dengan pernyataan seperti ini: gameObjects.Add(new GameObject(X, Y, true) untuk setiap ubin yang merupakan dinding... yang tidak akan terlalu kering dan akan memakan 100 baris kode untuk setiap pernyataan. - person Schaezar; 24.04.2017