Генерация персонажей-стиль стены


Вот некоторые код, который я написал лет 5 назад и смотрел недавно. Целью было создать стены с текстурами на них. Если есть пересечения в стены, текстуры внутри сжимается незначительно и текстуры снаружи будет слегка расширенной, так что модели правильно плитку и там могут быть специальные шаблоны для углов, которые выстраиваются. Вот пример его использования:

enter image description here

Вот уродство, что реализует основной алгоритм его генерации. Он создает каре 4 очка и отправляет их в QuadGeometry класс, который строит фактический Вертекс/индекс буфера. Кроме того, он создает вершины и края стены (как вы можете видеть из Тодос-я так и не закончила эту часть).

using System.Collections.Generic;
using masques.map;
using masques.util;
using SharpDX;

namespace masques.graphics
{
    public static class WallGeometry
    {
        private static Vector3 vec3(float x, float y, float z) { return new Vector3(x, y, z); }

        private static int lookLeftAndRight(MapWalls walls, int x, int y, int z)
        {
            int c = 0;
            if(x > 0 && walls.X.exists(x - 1, y, z)) c += 1;
            if(x < walls.width && walls.X.exists(x, y, z)) c += 2;
            return c;
        }

        private static int lookUpAndDown(MapWalls walls, int x, int y, int z)
        {
            int c = 0;
            if(y > 0 && walls.Y.exists(x, y - 1, z)) c += 1;
            if(y < walls.height && walls.Y.exists(x, y, z)) c += 2;
            return c;
        }

        private static void adjustCorners(ref float a, ref float b, int corners, float adjustment, bool pushOut)
        {
            if(corners == 1)      { a -= adjustment; if(pushOut) b += adjustment; }
            else if(corners == 2) { b -= adjustment; if(pushOut) a += adjustment; }
            else if(corners == 3) { a -= adjustment; b -= adjustment; }
        }

        // TODO edge and top materials not always the defaults
        // TODO don't put top on wall if wall/tile is above
        public static void build(MapWalls walls, QuadGeometry geo) { build(walls, geo, 0, 0, 0, walls.width, walls.height, walls.layers, MapWalls.EDGE_SIZE, 1, true); }
        public static void build(MapWalls walls, QuadGeometry geo, int x0, int y0, int z0, int x1, int y1, int z1, float edgeSize, float wallHeight, bool includeBorders)
        {
            if(x1 <= x0 || y1 <= y0) return;
            int w = walls.width, h = walls.height;
            const ushort edgeMat = 1;
            const ushort topMat = 1;

            /***********************************************************************************************
             *                                           X WALLS                                           *
             ***********************************************************************************************/

            int y0x = includeBorders ? y0 : y0 + 1;
            int y1x = includeBorders ? y1 + 1 : y1;
            foreach(KeyValuePair<IntPoint, WallSegment> kvp in walls.X)
            {
                int x = kvp.Key.x;
                int y = kvp.Key.y;
                int z = kvp.Key.z;
                if(x < x0 || x >= x1 || y < y0x || y >= y1x || z < z0 || z >= z1)
                    continue;


                WallSegment segment = kvp.Value;
                float px1 = x, px1a = px1, px1b = px1;
                float px2 = x + 1, px2a = px2, px2b = px2;
                float py = y;
                float py1 = py - edgeSize;
                float py2 = py + edgeSize;
                float pz = z;

                int corners1 = lookUpAndDown(walls, x, y, z);
                int corners2 = lookUpAndDown(walls, x + 1, y, z);
                bool isWallStart = x == 0 || !walls.X.exists(x - 1, y, z);
                bool isWallEnd = x == w - 1 || !walls.X.exists(x + 1, y, z);
                adjustCorners(ref px1a, ref px1b, corners1, -edgeSize, isWallStart);
                adjustCorners(ref px2a, ref px2b, corners2, +edgeSize, isWallEnd);
                float tx1a = px1a, tx1b = px1b, tx2a = px2a, tx2b = px2b;

                // if we're the beginning of a wall...
                if(isWallStart)
                {
                    // If there are no Y intersections here, add an edge
                    if(corners1 == 0) geo.add(vec3(px1a, py2, pz), vec3(px1a, py1, pz), vec3(px1a, py2, pz + wallHeight), vec3(px1a, py1, pz + wallHeight), 0, 1, 0, 1, edgeMat);
                }
                else if(corners1 != 3)
                {
                    tx1a = px1;
                    tx1b = px1;
                }

                // if we're at the end of a wall...
                if(isWallEnd)
                {
                    // If there are no Y intersections here, add an edge
                    if(corners2 == 0) geo.add(vec3(px2a, py1, pz), vec3(px2a, py2, pz), vec3(px2a, py1, pz + wallHeight), vec3(px2a, py2, pz + wallHeight), 0, 1, 0, 1, edgeMat);
                }
                else if(corners2 != 3)
                {
                    tx2a = px2;
                    tx2b = px2;
                }

                // top
                if(!walls.X.exists(x, y, z + 1))
                {
                    geo.add(vec3(tx2b, py2, pz + wallHeight), vec3(tx1b, py2, pz + wallHeight), vec3(tx2a, py1, pz + wallHeight), vec3(tx1a, py1, pz + wallHeight), 0, 1, 0, 1, topMat);
                }

                // faces
                geo.add(vec3(px1a, py1, pz),  vec3(px2a, py1, pz),  vec3(px1a, py1, pz + wallHeight), vec3(px2a, py1, pz + wallHeight), x + 1, x, z, z + 1, segment.back);
                geo.add(vec3(px2b, py2, pz),  vec3(px1b, py2, pz),  vec3(px2b, py2, pz + wallHeight), vec3(px1b, py2, pz + wallHeight), w - x, w - x - 1, z, z + 1, segment.front);
            }

            /***********************************************************************************************
             *                                           Y WALLS                                           *
             ***********************************************************************************************/

            int x0y = includeBorders ? x0 : x0 + 1;
            int x1y = includeBorders ? x1 + 1 : x1;
            foreach(KeyValuePair<IntPoint, WallSegment> kvp in walls.Y)
            {
                int x = kvp.Key.x;
                int y = kvp.Key.y;
                int z = kvp.Key.z;
                if(x < x0y || x >= x1y || y < y0 || y >= y1 || z < z0 || z >= z1)
                    continue;

                WallSegment segment = kvp.Value;
                float px = x;
                float px1 = px - edgeSize;
                float px2 = px + edgeSize;
                float py1 = y, py1a = py1, py1b = py1;
                float py2 = py1 + 1, py2a = py2, py2b = py2;
                float pz = z;

                int corners1 = lookLeftAndRight(walls, x, y, z);
                int corners2 = lookLeftAndRight(walls, x, y + 1, z);
                bool isWallStart = y == 0 || !walls.Y.exists(x, y - 1, z);
                bool isWallEnd = y == h - 1 || !walls.Y.exists(x, y + 1, z);
                adjustCorners(ref py1a, ref py1b, corners1, -edgeSize, isWallStart);
                adjustCorners(ref py2a, ref py2b, corners2, +edgeSize, isWallEnd);
                float ty1a = py1a, ty1b = py1b, ty2a = py2a, ty2b = py2b;

                // if we're the beginning of a wall...
                if(isWallStart)
                {
                    // If there are no X intersections here, add an edge
                    if(corners1 == 0) geo.add(vec3(px1, py1a, pz), vec3(px2, py1a, pz), vec3(px1, py1a, pz + wallHeight), vec3(px2, py1a, pz + wallHeight), 0, 1, 0, 1, edgeMat);
                }
                else
                {
                    ty1a = py1;
                    ty1b = py1;
                }

                // if we're at the end of a wall...
                if(isWallEnd)
                {
                    // If there are no X intersections here, add an edge
                    if(corners2 == 0) geo.add(vec3(px2, py2a, pz), vec3(px1, py2a, pz), vec3(px2, py2a, pz + wallHeight), vec3(px1, py2a, pz + wallHeight), 0, 1, 0, 1, edgeMat);
                }
                else
                {
                    ty2a = py2;
                    ty2b = py2;
                }

                // top
                if(!walls.Y.exists(x, y, z + 1))
                {
                    geo.add(vec3(px2, ty2b, pz + wallHeight), vec3(px1, ty2a, pz + wallHeight), vec3(px2, ty1b, pz + wallHeight), vec3(px1, ty1a, pz + wallHeight), 0, 1, 0, 1, topMat);
                }

                // wall faces
                geo.add(vec3(px1, py2a, pz),  vec3(px1, py1a, pz),  vec3(px1, py2a, pz + wallHeight), vec3(px1, py1a, pz + wallHeight), h - y, h - y - 1, z, z + 1, segment.back);
                geo.add(vec3(px2, py1b, pz),  vec3(px2, py2b, pz),  vec3(px2, py1b, pz + wallHeight), vec3(px2, py2b, pz + wallHeight), y + 1, y, z, z + 1, segment.front);
            }
        }
    }
}

Я думал о преобразовании его в Единство, который использует г-вместо З-С это довольно эффективный/простой способ бросить простых зданий, но перед этим имеет смысл немного ее подчистить. В частности, я ищу, если есть хороший способ, чтобы объединить полностью дублируются х стенах и у стен части. Можно решать иным способом (например, генерации всегда на X, после перекачки координаты у стены), хотя это не просто, как это может быть сделано.

Любые предложения, или это исковеркана?



150
8
задан 22 февраля 2018 в 03:02 Источник Поделиться
Комментарии
1 ответ

Что касается CleanCode, это хорошая практика:


  1. обеспечить более четкое имена: в методах lookxxxx, я думаю, что c
    угол?

  2. используйте скобки, если-заявления (даже если есть один
    заявление).

  3. никаких магических чисел; 1 и 2 означают? (методы поиска)

  4. adjustCorners: использовать переключатели вместо Если

  5. гео.добавление строк действительно трудно читать. Почему не разделить их на несколько строк?

  6. Чтобы предотвратить множество параметров, попытаться передать объекты; как стена, а не стена.ширина стены,высота стены.слоев (если вы хотите сохранить текущую метода построения, добавить перегрузку, которая принимает объект стены).

  7. Извлекать несколько методов, чтобы облегчить чтение и понимание. Ваши комментарии являются первыми индикаторами и предложения для названия метода ;-)
    как: // если здесь нет у перекрестков, добавить край

8
ответ дан 22 февраля 2018 в 11:02 Источник Поделиться