PACMAN [개인 모작]

UNITY 2021. 9. 5. 02:02
반응형
PACMAN FLEX

맵 지형 데이터

1
2
3
4
5
6
7
8
9
10
11
12
13
MapSize    12    12
1    1    1    1    0    1    1    0    1    1    1    1    
1    0    0    0    0    1    1    0    0    0    0    1    
1    0    1    1    0    0    0    0    1    1    0    1    
1    0    0    1    0    1    1    0    1    0    0    1    
0    0    0    0    0    0    0    0    0    0    0    0    
1    0    1    1    0    1    1    0    1    1    0    1    
1    0    1    1    0    1    1    0    1    1    0    1    
0    0    0    0    0    0    0    0    0    0    0    0    
1    0    0    1    0    1    1    0    1    0    0    1    
1    0    1    1    0    0    0    0    1    1    0    1    
1    0    0    0    0    1    1    0    0    0    0    1    
1    1    1    1    0    1    1    0    1    1    1    1    
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
using UnityEngine;
using System.Collections;
using System.IO;
 
 
public class DataManager : MonoBehaviour
{
    //매니저 하이러시를 사용하기 위한 선언
    [SerializeField]
    private    TileManager    tileManager;
    [SerializeField]
    private ItemManager itemManager;
    [SerializeField]
    private EnemyManager enemyManager;
    [SerializeField]
    private    string        load_data;
 
    void Awake()
    {
        Load_MapData(load_data);
    }
 
    //텍스트 파일 불러오는 함수
    public void Load_MapData(string file_name)
    {
        StreamReader sr = new StreamReader(file_name);
        
 
        //ReadLine으로 불러오고 Split으로 필요없는 데이터 나눕니다.
        //구문을 int로 바꾸어 문자에서 숫자로 형변환
        string        str_map_size    = sr.ReadLine();
        //Split은 \t를 기준으로 문을 끊어준다.
        string[]    size_arr        = str_map_size.Split('\t');
        int            map_x            = int.Parse(size_arr[1]);
        int            map_y            = int.Parse(size_arr[2]);
 
        //ReadLine은 한 구문씩 불러오지만 ReadToEnd는 다 불러옵니다.
        string        str_map_data    = sr.ReadToEnd();
        string[]    str_arr            = str_map_data.Split('\t');
        int[]        int_arr            = new int[str_arr.Length-1];
 
        for ( int i = 0; i < (int)int_arr.Length; ++ i )
        {
            string str = str_arr[i];
            int_arr[i] = int.Parse(str);
        }
 
 
        tileManager.Create_All_Tiles_In_File(map_x, map_y, int_arr);
        itemManager.Create_All_Items_In_File(map_x, map_y, int_arr);
        //적을 관리하는 클래스에서 생성하는 매소드를 실행합니다.
        enemyManager.Create_All_Enemies_In_File(map_x, map_y, int_arr);
        sr.Close();
    }
}
cs

Unity 내 int 클래스에서 제공하는 Parse함수를 통해 읽어온 데이터를 뜯어 지역 배열로 들고 있다가 타일, 아이템, 적 메니저로 정렬된 배열을 뿌려준다.

 

 

1) 아이템 생성 / 제어 적 생산 예측지점 설정

적은 게임 시작 3초 후에 매 4마다 생산된다. 생산되는 위치는 4개의 좌표가 무작위로 설정되며 그 좌표에서 6~10마리의 적이 생산된다.

적 출몰 좌표

EnemyArea

해당 프리팹은 다음 적들이 생성되는 위치를 미리 보여준다. 해당 프리팹은 적이 생산되자마자 삭제되고 다음 생산지점에서 새로 생겨난다. 충돌 값은 없으며 회전만 한다는 것이 특징이며, 적이 생산되면 사라진다.

적은 게임 시작 3초 후에 매 4마다 생산된다. 생산되는 위치는 4개의 좌표가 무작위로 설정되며 그 좌표에서 6~10마리의 적이 생산된다.

 

 

 

2) 적 오브젝트 다수 생성 / 제어_ EnemyManager

최초 적의 수는 10마리가 생성되며, 3초 후 매 4초마다 6~10마리씩 생산된다. 적의 생성과 주석처리를 담당하면서, 이전 코드인 EnemyArea를 관리한다.

 

적과 충돌하면 Life지수가 1차감된다.

 

 

 

3) 카메라 흔들기

조금 더 역동적인 플레이를 위해 채용했다. 적에게 피격 시 화면이 흔들린다.

화면이 잠깐 움직이기 때문에 사진에서는 제대로 보이지 않는다.

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
using UnityEngine;
using System.Collections;
 
 
//비행기 피격 시 화면이 흔들립니다.
//참고 주소: https://gist.github.com/ftvs/5822103
 
public class CameraShake : MonoBehaviour
{
 
    // Transform of the camera to shake. Grabs the gameObject's transform 
    // if null. 
 
    //카메라 좌표, 흔들림 절대시간,
    //흔들림 양, 흔들림 상대시간, 카메라 절대 좌표
 
    public Transform camTransform;
    public static float shakeDuration = 0f;
    public float shakeAmount = 0.1f;
    public float decreaseFactor = 0.5f;
    Vector3 originalPos;
 
    //카메라를 좌표화 시켜 저장합니다.
    void Awake()
    {
        if (camTransform == null)
        {
            camTransform = GetComponent(typeof(Transform)) as Transform;
        }
    }
 
    //해당 메소드는 저장이 이루어졌을 경우 실행되며
    //산출된 좌표는 절대 좌표이므로 orginalPos에 저장합니다.
    void OnEnable()
    {
        originalPos = camTransform.localPosition;
    }
 
    void Update()
    {
        //흔들림 절대시간을 부여하면서 연출이 시작됩니다.
        //insideUintSphere 는 구 안에 무작위 좌표를 찍어 산출합니다.
        //연출 시간은 델타타임을 활용합니다.
        if (shakeDuration > 0)
        {
            camTransform.localPosition = originalPos + Random.insideUnitSphere * shakeAmount;
            shakeDuration -= Time.deltaTime * decreaseFactor;
        }
 
        //연출 시간 소멸 시 끝나게 되며 좌표는 다시
        //절대 좌표로 돌아가게 됩니다.
        else
        {
            shakeDuration = 0f;
            camTransform.localPosition = originalPos;
        }
    }
}
cs

Camera Update 구현부

 

 

 

4) 수호기모드

적이 생성되지만 플레이어는 게임 시작과 동시에 공격을 할 수 없다. 게임 시작 후 혹은 피버모드가 다 지난 후 일정 시간이 흐르면(5) 수호기 모드가 발동된다. 수호기 모드에서 스페이스를 누르고 있으면 유도탄을 발사할 수 있다.

팩맨 주위 노란색 마름모의 출현이 수호기 모드가 발동됐음을 알려준다.

GuardMode

수호기 모드가 활성화되면 스페이스를 누를 시 총알을 발사할 수 있는데 이때 노란색 마름모가 점멸한다. 수호기 모드 활성화 후에도 스페이스를 누르지 않으면 점멸하지 않는다.

 

 

 

5) 유도탄 발사

수호기 상태에서 스페이스를 누르면 유도탄이 발사된다. 탄알 연속 발사는 0.8초에 한 발씩 쏜다. 단, 탄알은 맵 밖으로 나가면 사라진다.

 

유도탄이 발사 후 체공 중인 모습

 

 

 

6) 드링크

수호기 상태 시 유도탄을 발사하여 적을 잡게 되면 일정확률로 드링크가 등장한다. 이 드링크를 습득하게 되면 플레이어는 피버모드로 전환된다.

 

피격 후 남아있는 드링크

 

 

 

7) 피버모드

수호기 모드에서 드링크를 습득하였을 때에만, 피버모드로 전환된다. 이 모드로 전환되면 적과 부딪혔을 때 수가 증가하며 무적상태가 된다. 또한 적과 플레이어의 속도가 증가하며, 기존의 노란 아이템을 습득할 수는 없다.

 

드링크 습득 후 피버모드로 전환된 모습. 붉은 사각형이 점멸하고 배경음악도 바뀐다.

 

 

8) 부족한 점

레벨 디자인이 부족한 것 같다. 확실히 영상(두 번째 판)에서도 확인 가능한 부분이 피버모드 시 스폰지역에 머무르거나 문때면 순식간에 적들이 사라지는 것을 볼 수 있다. 즉, 적들이 한 번에 너무 많아지고 적어진다는 점, 러닝타임의 초기와 후기의 격차가 꽤 크다는 점이 부족한 점이다.

 

반응형
Posted by Kestone Black Box
,