작업을 시작하기에 앞서 시점을 탑뷰로 할지 쿼터뷰로 할지 고민을 좀 했다.

탑뷰 → https://namu.wiki/w/%ED%83%91%EB%B7%B0

쿼터뷰 → https://namu.wiki/w/%EC%BF%BC%ED%84%B0%EB%B7%B0


이쁘기는 쿼터뷰가 이쁜데 몬스터가 건물을 지나가거나 할때 가려진 부분만 가리고 아닌 부분은 보여주고

이런게 구현하기가 힘들 것 같아서 탑뷰로 만들기로 결정했다.



우선 기본맵을 만들어주기로 했다.

Kenny의 RPG팩의 타일들이 깔끔하고 무난해보여서 이걸로 만들기로 결정했다.



우선은 기본 맵을 만들어 주었다.




이후에 기본 길을 만들어 주었다.

위의 타일을보면 길옆에 데코? 이어주는 타일들을 하나씩 다 따로붙여주어야 하므로 상당한 노가다가 될 것이다.

그래서 지금은 길이 하나지만 이후에 길을 바꾸거나 스테이지를 여러개 만들걸 생각하여 

길에 맞게 자동으로 옆쪽타일을 붙여주게 스크립트를 작성했다.




이후 시작, 끝점과 회전구간만 먼저 예외처리하여 데코를 해주었다.




마지막으로 비어있는 구간에 데코를 붙여서 길을 완성하였다.


길을 이런 모양으로 만든 이유는 여러가지 케이스를 테스트하기 위해

겹치거나 회전할 경우에도 잘 나오는지 확인하기 위해서 이렇게 만들었다.


잘 동작하는거 확인했으니 이제 원했던 대로 한갈래의 길을 만들 것이다.
















기본 맵을 깔아주는 스크립트는 아래와 같다.

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TileMaker : MonoBehaviour {
 
    public static float startX = 0.32f;
    public static float startY = 0.32f;
 
    // Use this for initialization
    void Start () {
        var gameTile = Resources.Load("TileObject"typeof(GameObject)) as GameObject;
 
        // 기본잔디 맵전체에 깔아줌
        for (int i = 1; i < 20; i++)
        {
            for (int j = 1; j < 12; j++)
            {
                makeTile(gameTile, "rpgTile039"new Vector3(startX + (float)i * 0.64f, startY + (float)j * 0.64f, 0), -1);
            }
        }
        // 모서리 4개
        makeTile(gameTile, "rpgTile036"new Vector3(startX, startY, 0), -1);
        makeTile(gameTile, "rpgTile038"new Vector3(startX + 19.0f * 0.64f, startY, 0), -1);
        makeTile(gameTile, "rpgTile000"new Vector3(startX, startY + 11.0f * 0.64f, 0), -1);
        makeTile(gameTile, "rpgTile002"new Vector3(startX + 19.0f * 0.64f, startY + 11.0f * 0.64f, 0), 5);
 
        // 모서리라인 4줄
        for (int i = 1; i < 19; i++)
        {
            makeTile(gameTile, "rpgTile037"new Vector3(startX + (float)i * 0.64f, startY, 0), -1);
            makeTile(gameTile, "rpgTile001"new Vector3(startX + (float)i * 0.64f, startY + 11.0f * 0.64f, 0), 5);
        }
        for (int i = 1; i < 11; i++)
        {
            makeTile(gameTile, "rpgTile018"new Vector3(startX, startY + (float)i * 0.64f, 0), -1);
            makeTile(gameTile, "rpgTile020"new Vector3(startX + 19.0f * 0.64f, startY + (float)i * 0.64f, 0), 5);
        }
    }
 
    public void makeTile(GameObject gameTile, string fileName, Vector3 position, int order)
    {        
        GameObject instance = Instantiate(gameTile);
        SpriteRenderer pRenderer = instance.AddComponent<SpriteRenderer>();
 
        Sprite tile = Resources.Load(fileName, typeof(Sprite)) as Sprite;
        pRenderer.sprite = tile;
        pRenderer.sortingOrder = order;
        instance.transform.position = position;
    }
 
    // Update is called once per frame
    void Update () {
        
    }
}
 
cs




길을 만드는 스크립트

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class MakePath : MonoBehaviour {
    
    public class MovePath
    {
        public int x = 0;
        public int y = 0;
        public MovePath(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
    public static List<MovePath> movePath = new List<MovePath>();
 
    // 데이터를 저장할 배열
    // 1은 길, 2는 시작.끝점, 3은 꺾이는점, 4는 사이드, 5는 회전닫아주는것.
    public int[] map = new int[240];
 
    // Use this for initialization
    void Start () {
        // 배열 초기화
        for(int i=0; i<240; i++)
        {
            map[i] = 0;
        }
 
        // 길
        movePath.Add(new MovePath(06));
        movePath.Add(new MovePath(16));
        movePath.Add(new MovePath(26));
        movePath.Add(new MovePath(36));
        movePath.Add(new MovePath(46));
        movePath.Add(new MovePath(56));
        movePath.Add(new MovePath(66));
        movePath.Add(new MovePath(76));
        movePath.Add(new MovePath(86));
 
        movePath.Add(new MovePath(87));
        movePath.Add(new MovePath(88));
 
        movePath.Add(new MovePath(98));
        movePath.Add(new MovePath(108));
        movePath.Add(new MovePath(118));
        movePath.Add(new MovePath(128));
 
        movePath.Add(new MovePath(127));
        movePath.Add(new MovePath(126));
        movePath.Add(new MovePath(125));
        movePath.Add(new MovePath(124));
 
        movePath.Add(new MovePath(114));
        movePath.Add(new MovePath(104));
        movePath.Add(new MovePath(94));
        movePath.Add(new MovePath(84));
        movePath.Add(new MovePath(85));
 
        movePath.Add(new MovePath(136));
        movePath.Add(new MovePath(146));
        movePath.Add(new MovePath(156));
        movePath.Add(new MovePath(166));
        movePath.Add(new MovePath(176));
        movePath.Add(new MovePath(186));
        movePath.Add(new MovePath(196));
 
        movePath.Add(new MovePath(109));
        movePath.Add(new MovePath(119));
        movePath.Add(new MovePath(1010));
        movePath.Add(new MovePath(1011));
 
        movePath.Add(new MovePath(103));
        movePath.Add(new MovePath(102));
        movePath.Add(new MovePath(101));
        movePath.Add(new MovePath(100));
        movePath.Add(new MovePath(100));
 
 
        // 일단 길만들기
        foreach (MovePath path in movePath)
        {
            // 마지막은 자연스러운 삭제를 위해 추가한 경로이므로 맵생성 x
            if (path != movePath[movePath.Count - 1])
            {
                makeTile(path, "rpgTile024"5);
                map[path.y * 20 + path.x] = 1;
            }
        }
 
        // 시작길, 꺾이는길 먼저 만들기
        foreach (MovePath path in movePath)
        {
            if (path != movePath[movePath.Count - 1])
            {
                makeSpecialTile(path, 1);
            }
        }
 
        // 이제 남은 자리에 사이드 타일 붙이기
        foreach (MovePath path in movePath)
        {
            if (path != movePath[movePath.Count - 1])
            {
                makeSideTile(path, 1);
            }
        }
    }
 
    public void makeSpecialTile(MovePath path, int order)
    {
        // 시작점과 끝점이면 양옆 다른 타일 생성
 
        // 왼쪽시작점 위아래 타일생성
        if (path.x <= 0 && path.y > 0 && path.y < 12)
        {
            MovePath upPath = new MovePath(path.x, path.y + 1);
            MovePath downPath = new MovePath(path.x, path.y - 1);
            makeTile(upPath, "rpgTile036", order + 2);
            makeTile(downPath, "rpgTile000", order + 2);
 
            map[(path.y + 1* 20 + path.x] = 2;
            map[(path.y - 1* 20 + path.x] = 2;
        }
        // 오른쪽 시작점 위아래 타일생성
        else if (path.x >= 19 && path.y > 0 && path.y < 12)
        {
            MovePath upPath = new MovePath(path.x, path.y + 1);
            MovePath downPath = new MovePath(path.x, path.y - 1);
            makeTile(upPath, "rpgTile038", order + 2);
            makeTile(downPath, "rpgTile002", order + 2);
 
            map[(path.y + 1* 20 + path.x] = 2;
            map[(path.y - 1* 20 + path.x] = 2;
        }
        // 위시작점 좌우 타일생성
        else if (path.y >= 11 && path.x > 0 && path.x < 20)
        {
            MovePath rightPath = new MovePath(path.x + 1, path.y);
            MovePath leftPath = new MovePath(path.x - 1, path.y);
            makeTile(leftPath, "rpgTile002", order + 2);
            makeTile(rightPath, "rpgTile000", order + 2);
 
            map[path.y * 20 + path.x - 1= 2;
            map[path.y * 20 + path.x + 1= 2;
        }
        // 아래시작점 좌우 타일생성
        else if (path.y <= 0 && path.x > 0 && path.x < 20)
        {
            MovePath rightPath = new MovePath(path.x + 1, path.y);
            MovePath leftPath = new MovePath(path.x - 1, path.y);
            makeTile(leftPath, "rpgTile038", order + 2);
            makeTile(rightPath, "rpgTile036", order + 2);
 
            map[path.y * 20 + path.x - 1= 2;
            map[path.y * 20 + path.x + 1= 2;
        }
        
 
        // 시작, 끝점이 아닐때만 나머지검사
        if (path.x > 0 && path.x < 19 && path.y > 0 && path.y < 12)
        {
            // 꺾이는 부분이면 꺾이는 블럭생성. 근데 꺾이는부분 오더 우선
            // 위와 왼쪽이 있으면(┘ 모양)
            if (map[(path.y + 1* 20 + path.x] == 1 && map[path.y * 20 + path.x - 1== 1)
            {
                MovePath leftupPath = new MovePath(path.x - 1, path.y + 1);
                MovePath rightdownPath = new MovePath(path.x + 1, path.y - 1);
 
                // 땅이 없는 자리에만 생성
                if (map[(path.y + 1* 20 + path.x - 1!= 1)
                {
                    makeTile(leftupPath, "rpgTile038", order + 2);
                    map[(path.y + 1* 20 + path.x - 1= 3;
                }
                if (map[(path.y - 1* 20 + path.x + 1!= 1)
                {
                    makeTile(rightdownPath, "rpgTile022", order);
                    map[(path.y - 1* 20 + path.x + 1= 5;
                }
            }
            // 위와 오른쪽이 있으면(└ 모양)
            if (map[(path.y + 1* 20 + path.x] == 1 && map[path.y * 20 + path.x + 1== 1)
            {
                MovePath rightupPath = new MovePath(path.x + 1, path.y + 1);
                MovePath leftdownPath = new MovePath(path.x - 1, path.y - 1);
 
                // 땅이 없는 자리에만 생성
                if (map[(path.y + 1* 20 + path.x + 1!= 1)
                {
                    makeTile(rightupPath, "rpgTile036", order + 2);
                    map[(path.y + 1* 20 + path.x + 1= 3;
                }
                if (map[(path.y - 1* 20 + path.x - 1!= 1)
                {
                    makeTile(leftdownPath, "rpgTile021", order);
                    map[(path.y - 1* 20 + path.x - 1= 5;
                }
            }
            // 아래와 왼쪽이 있으면(┐ 모양)
            if (map[(path.y - 1* 20 + path.x] == 1 && map[path.y * 20 + path.x - 1== 1)
            {
                MovePath leftdownPath = new MovePath(path.x - 1, path.y - 1);
                MovePath rightupPath = new MovePath(path.x + 1, path.y + 1);
 
                // 땅이 없는 자리에만 생성
                if (map[(path.y - 1* 20 + path.x - 1!= 1)
                {
                    makeTile(leftdownPath, "rpgTile002", order + 2);
                    map[(path.y - 1* 20 + path.x - 1= 3;
                }
                if (map[(path.y + 1* 20 + path.x + 1!= 1)
                {
                    makeTile(rightupPath, "rpgTile004", order);
                    map[(path.y + 1* 20 + path.x + 1= 5;
                }
            }
            // 아래와 오른쪽이 있으면(┌ 모양)
            if (map[(path.y - 1* 20 + path.x] == 1 && map[path.y * 20 + path.x + 1== 1)
            {
                MovePath rightdownPath = new MovePath(path.x + 1, path.y - 1);
                MovePath leftupPath = new MovePath(path.x - 1, path.y + 1);
 
                // 땅이 없는 자리에만 생성
                if (map[(path.y - 1* 20 + path.x + 1!= 1)
                {
                    makeTile(rightdownPath, "rpgTile000", order + 2);
                    map[(path.y - 1* 20 + path.x + 1= 3;
                }
                if (map[(path.y + 1* 20 + path.x - 1!= 1)
                {
                    makeTile(leftupPath, "rpgTile003", order);
                    map[(path.y + 1* 20 + path.x - 1= 5;
                }                
            }
        }
    }
 
    public void makeSideTile(MovePath path, int order)
    {
        // 시작, 끝점이 아닐때만 나머지검사
        if (path.x > 0 && path.x < 19 && path.y > 0 && path.y < 11)
        {
            // 상하좌우검사
            // 비어있거나 회전닫는블럭이면 덮어씌우고 사이드 생성
            if (map[(path.y + 1* 20 + path.x] == 0 || map[(path.y + 1* 20 + path.x] == 5)
            {
                MovePath upPath = new MovePath(path.x, path.y + 1);
                makeTile(upPath, "rpgTile037", order + 1);
                map[(path.y + 1* 20 + path.x] = 4;
            }
            if (map[(path.y - 1* 20 + path.x] == 0 || map[(path.y - 1* 20 + path.x] == 5)
            {
                MovePath downPath = new MovePath(path.x, path.y - 1);
                makeTile(downPath, "rpgTile001", order + 1);
                map[(path.y - 1* 20 + path.x] = 4;
            }
            if (map[path.y * 20 + path.x - 1== 0 || map[path.y * 20 + path.x - 1== 5)
            {
                MovePath leftPath = new MovePath(path.x - 1, path.y);
                makeTile(leftPath, "rpgTile020", order + 1);
                map[path.y * 20 + path.x - 1= 4;
            }
            if (map[path.y * 20 + path.x + 1== 0 || map[path.y * 20 + path.x + 1== 5)
            {
                MovePath rightPath = new MovePath(path.x + 1, path.y);
                makeTile(rightPath, "rpgTile018", order + 1);
                map[path.y * 20 + path.x + 1= 4;
            }
        }
    }
    
    public void makeTile(MovePath path, string fileName, int order)
    {
        var gameTile = Resources.Load("TileObject"typeof(GameObject)) as GameObject;
        GameObject instance = Instantiate(gameTile);
        SpriteRenderer pRenderer = instance.AddComponent<SpriteRenderer>();
 
        Sprite tile = Resources.Load(fileName, typeof(Sprite)) as Sprite;
        pRenderer.sprite = tile;
        pRenderer.sortingOrder = order;
        // 시작 x, y는 0.32로 똑같으므로
        instance.transform.position = new Vector3(TileMaker.startX + path.x * 0.64f, TileMaker.startY + path.y * 0.64f);
    }
 
    // Update is called once per frame
    void Update () {
        
    }
}
cs

MovePath라는 클래스를 만들어 List로 관리하였다.

그 이유는 타일의 1칸은 가로 세로 64픽셀이지만 1단위로 관리하기위해서 편의를 위해 만들었다.

그리고 map이라는 배열을 만들어 맵 위치에 무엇이 들어있는지를 저장하여 맵을 관리하였다.

Posted by misty_
,