2차 프로토까지 하고나서 플레이어가 건물을 어디에 건설해야 할 지에 대한 동기부여가 전혀 되지 않는 것을 발견함.

(걍 아무데나 막 짓게 됨)


고민해보니 시작자원이 없는거나 마찬가지여서 그런 것 같더라.


시작지점 주위에 있는 자원들을 유저가 알면 거기에 건물을 지음으로서 첫번째 게임 플레이가 시작되는데


걍 자원을 랜덤하게 돌에 섞어서 흩뿌려 두었으니 유저는 걍 아무데나 마구 까는게 전부였지.



그래서 자원을 덩어리지게 배치하고, 광산을 추가하였음.



viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73ced85fa11d02831a10d3d354cfd31ab73f93ab078cb9d8e0aba70f9e79b6f4e8d7f490733ac41ccece598d999d7b8d6bed6d7c1c33fcb

(오른쪽에 노란게 광산. 광산에서 구리광물을 뽑아내고, 옆에 공장들은 구리괴로 가공하고 있다)



펄린 노이즈 쓰다가 시간낭비하는 것 같아서 걍 랜덤하게 대충 뿌려주었다.


절차생성은 강력하지만 맵이 작다거나 하면 원하는 형태로 뽑기 매우 어려움.


많은 시행착오와 수치조정이 필요한데 ㅅㅂ 그럴 시간이 어딨어?


묻고 대충으로 가!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class MapGenExample
{
    [Inject] private readonly ChunkQuery _chunkQuery;
    [Inject] private readonly EventManager _eventManager;
    [Inject] private readonly GameSetting _gameSetting;
    [Inject] private readonly IMapQuery _mapQuery;
    public void Initialize()
    {
        //SpawnStoneMap();
        SpawnResourceMap();
        //SpawnFogOfWarMap();
        //자원량 출력
        var resourceString = string.Join(", ", _mapQuery.GetResourceAmounts().Select(dic => dic.Key.ToString() + ":" + dic.Value.ToString()));
        Debug.Log($"resources :{resourceString}");
    }
    /// 
    ///     자원맵은 굉장히 심플하게 생성하는데 (막짜임) 펄린 노이즈를 쓰지 않고 단순하게 랜덤으로 흩뿌린다. 더 단순한 방법이 있다면 그걸 쓰고 싶다. 프로토 기능이니까.
    ///     1. 총 몇개의 덩어리를 배치할지 정한다
    ///     2. 청크의 순서를 섞는다
    ///     3. 청크별로 랜덤한 지점에 자원생성점을 배치한다. (청크개수보다 자원개수가 많으면 루프한다)
    ///     4. 자원생성점의 주변 x radius 의 coord를 찾아낸다
    ///     5. 해당 coords를 전부 해당 자원으로 세팅한다
    ///     6. 다음 자원으로 넘어가 1부터 반복한다
    ///     7. 결과적으로 나중에 생성되는 자원일수록 다른 자원을 '덮어쓸 수 ' 있다. 그래서 처음 자원은 조금 더 많아야 할 수도 있음
    ///     8. 최종적으로 자원의 개수를 세어 로그로 출력한다.
    ///     todo : 위 수치들을 템플릿으로 뽑아도 좋을 것이다.
    ///     hack : 이 메소드는 리소스맵에 즉시 써버림.
    ///     warn : 이미 존재하는 자원맵에 덮어쓰는 것이다.
    /// 
    public void SetResourceData(string resourceName, float resourcePileCountPerChunk, int pileRadiusMin, int pileRadiusMax)
    {
        var resourceTemplate = TemplateDic.GetItemTemplate(resourceName);
        var resourceNumber = resourceTemplate.ItemTypeNumber;
        Debug.Assert(_mapQuery.ResourceDataDic.Any());
        //청크 인덱스들을 섞는다.
        var chunkIndexs = _mapQuery.ResourceDataDic.Keys.ToList();
        chunkIndexs.Shuffle();
        var pileCount = (int)Math.Round(resourcePileCountPerChunk * chunkIndexs.Count);
        //자원 덩어리 개수만큼
        for (var i = 0; i < pileCount; i++)
        {
            //청크를 고르고, 청크안의 랜덤한 점을 찾고, 그 점 주위로 원형의 자원을 세팅한다.
            var selectedChunk = chunkIndexs[i % chunkIndexs.Count];
            var randomPileSpawnPoint = (TRandom.Range(0, _gameSetting.TilePerChunkX), TRandom.Range(0, _gameSetting.TilePerChunkY));
            var spawnCoordCenter = _chunkQuery.ChunkPositionToCoord(new ChunkPosition(selectedChunk, randomPileSpawnPoint.Item1, randomPileSpawnPoint.Item2));
            var resourcePileCoords = _mapQuery.GetRadiusCoordsWithSpiral(TRandom.Range(pileRadiusMin, pileRadiusMax + 1), spawnCoordCenter);
            foreach (var resouceCoord in resourcePileCoords)
            {
                //맵 안에 있어야 하며, 지표면보다는 낮아야 함.
                if (_mapQuery.IsInMap(resouceCoord) && resouceCoord.Y < _chunkQuery.SurfaceCenter.Y)
                {
                    //자원을 실제로 세팅하는 부분.
                    _mapQuery.SetResourceData(resouceCoord, resourceNumber, resourceTemplate.TileName);
                }
            }
        }
    }
    private void SpawnResourceMap()
    {
        var ironItemTemplate = TemplateDic.GetItemTemplate("ironOre");
        var ironMapTemplate = new ResourcePileTemplate(ironItemTemplate.ItemTypeNumber, ironItemTemplate.Name, 0.8f, 23);
        SetResourceData(ironMapTemplate.ResourceName, ironMapTemplate.PileCountPerChunk, ironMapTemplate.PileRadiusMin, ironMapTemplate.PileRadiusMax);
        var coalItemTemplate = TemplateDic.GetItemTemplate("coal");
        var coalMapTemplate = new ResourcePileTemplate(coalItemTemplate.ItemTypeNumber, coalItemTemplate.Name, 0.7f, 23);
        SetResourceData(coalMapTemplate.ResourceName, coalMapTemplate.PileCountPerChunk, coalMapTemplate.PileRadiusMin, coalMapTemplate.PileRadiusMax);
        var copperItemTemplate = TemplateDic.GetItemTemplate("copperOre");
        var copperMapTemplate = new ResourcePileTemplate(copperItemTemplate.ItemTypeNumber, copperItemTemplate.Name, 0.6f, 23);
        SetResourceData(copperMapTemplate.ResourceName, copperMapTemplate.PileCountPerChunk, copperMapTemplate.PileRadiusMin, copperMapTemplate.PileRadiusMax);
        var silverItemTemplate = TemplateDic.GetItemTemplate("silverOre");
        var silverMapTemplate = new ResourcePileTemplate(silverItemTemplate.ItemTypeNumber, silverItemTemplate.Name, 0.3f, 12);
        SetResourceData(silverMapTemplate.ResourceName, silverMapTemplate.PileCountPerChunk, silverMapTemplate.PileRadiusMin, silverMapTemplate.PileRadiusMax);
        var goldItemTemplate = TemplateDic.GetItemTemplate("goldOre");
        var goldMapTemplate = new ResourcePileTemplate(goldItemTemplate.ItemTypeNumber, goldItemTemplate.Name, 0.3f, 12);
        SetResourceData(goldMapTemplate.ResourceName, goldMapTemplate.PileCountPerChunk, goldMapTemplate.PileRadiusMin, goldMapTemplate.PileRadiusMax);
    }
    
    public class ResourcePileTemplate
    {
        public float PileCountPerChunk;
        public int PileRadiusMax;
        public int PileRadiusMin;
        public byte ResourceByteNumber;
        public string ResourceName;
        public ResourcePileTemplate(byte resourceByteNumber, string resourceName, float pileCountPerChunk, int pileRadiusMin, int pileRadiusMax)
        {
            ResourceByteNumber = resourceByteNumber;
            ResourceName = resourceName;
            PileCountPerChunk = pileCountPerChunk;
            PileRadiusMin = pileRadiusMin;
            PileRadiusMax = pileRadiusMax;
        }
    }
}
cs


(대충 만든다면서 클래스까지 따로 만들어 쓰는 정신병 초기증세)




viewimage.php?id=2abcdd23dad63db0&no=24b0d769e1d32ca73ced85fa11d02831a10d3d354cfd31ab73f93ab078cb9d8e0aba70f9e79b6f4ec82b1b035dad49c98737b742f491060846a0e13da1ca393db43864a3

(요런 자원이 뿌려졌다. 대충대충이라 지들끼리 막 덮이고 난리도 아님. 그래도 이거면 충분하고 넘침...)



광물이 있는 곳의 땅을 깐 후, 광산을 설치하면 


백수들이 우루루 뛰어가서 광산에서 일하면서 광물을 계속해서 뱉어낸다.


프로토이므로 광물은 고갈되지 않음. 스타 무한맵이라고 보면 됨.



다음은 식량이나 산소 만들어야징.