2차 프로토까지 하고나서 플레이어가 건물을 어디에 건설해야 할 지에 대한 동기부여가 전혀 되지 않는 것을 발견함.
(걍 아무데나 막 짓게 됨)
고민해보니 시작자원이 없는거나 마찬가지여서 그런 것 같더라.
시작지점 주위에 있는 자원들을 유저가 알면 거기에 건물을 지음으로서 첫번째 게임 플레이가 시작되는데
걍 자원을 랜덤하게 돌에 섞어서 흩뿌려 두었으니 유저는 걍 아무데나 마구 까는게 전부였지.
그래서 자원을 덩어리지게 배치하고, 광산을 추가하였음.
(오른쪽에 노란게 광산. 광산에서 구리광물을 뽑아내고, 옆에 공장들은 구리괴로 가공하고 있다)
펄린 노이즈 쓰다가 시간낭비하는 것 같아서 걍 랜덤하게 대충 뿌려주었다.
절차생성은 강력하지만 맵이 작다거나 하면 원하는 형태로 뽑기 매우 어려움.
많은 시행착오와 수치조정이 필요한데 ㅅㅂ 그럴 시간이 어딨어?
묻고 대충으로 가!
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, 2, 3); SetResourceData(ironMapTemplate.ResourceName, ironMapTemplate.PileCountPerChunk, ironMapTemplate.PileRadiusMin, ironMapTemplate.PileRadiusMax); var coalItemTemplate = TemplateDic.GetItemTemplate("coal"); var coalMapTemplate = new ResourcePileTemplate(coalItemTemplate.ItemTypeNumber, coalItemTemplate.Name, 0.7f, 2, 3); SetResourceData(coalMapTemplate.ResourceName, coalMapTemplate.PileCountPerChunk, coalMapTemplate.PileRadiusMin, coalMapTemplate.PileRadiusMax); var copperItemTemplate = TemplateDic.GetItemTemplate("copperOre"); var copperMapTemplate = new ResourcePileTemplate(copperItemTemplate.ItemTypeNumber, copperItemTemplate.Name, 0.6f, 2, 3); SetResourceData(copperMapTemplate.ResourceName, copperMapTemplate.PileCountPerChunk, copperMapTemplate.PileRadiusMin, copperMapTemplate.PileRadiusMax); var silverItemTemplate = TemplateDic.GetItemTemplate("silverOre"); var silverMapTemplate = new ResourcePileTemplate(silverItemTemplate.ItemTypeNumber, silverItemTemplate.Name, 0.3f, 1, 2); SetResourceData(silverMapTemplate.ResourceName, silverMapTemplate.PileCountPerChunk, silverMapTemplate.PileRadiusMin, silverMapTemplate.PileRadiusMax); var goldItemTemplate = TemplateDic.GetItemTemplate("goldOre"); var goldMapTemplate = new ResourcePileTemplate(goldItemTemplate.ItemTypeNumber, goldItemTemplate.Name, 0.3f, 1, 2); 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 |
(대충 만든다면서 클래스까지 따로 만들어 쓰는 정신병 초기증세)
(요런 자원이 뿌려졌다. 대충대충이라 지들끼리 막 덮이고 난리도 아님. 그래도 이거면 충분하고 넘침...)
광물이 있는 곳의 땅을 깐 후, 광산을 설치하면
백수들이 우루루 뛰어가서 광산에서 일하면서 광물을 계속해서 뱉어낸다.
프로토이므로 광물은 고갈되지 않음. 스타 무한맵이라고 보면 됨.
다음은 식량이나 산소 만들어야징.
팩토리오 같네
빽또리오랑 뜨로삐꼬 쓰까놓은 겜이 될 것 같음. 쓰까~묵자~
펄린 노이즈 내가 적용한 방식 정리해서 글로 올려봄.
햄보캐
저거 어떻게 씀? 코드 줄 만드는거
https://colorscripter.com/
모든 타일들의 정보는 어떻게 관리함? 리스트에 몰아넣고?
걍 이차배열에 때려넣음. 맵을 20*20 짜리 청크로 나눠서 청크별로 딕셔너리로 관리 ResourceDataDic = new Dictionary<ChunkIndex>();
아 딕셔너리군. 알려줘서 ㄱㅅㄱㅅ