Post

[Jem Clash] 개발일지 #4 - 스프라이트 추가, 액티브 능력 추가

[Jem Clash] 개발일지 #4 - 스프라이트 추가, 액티브 능력 추가

배경, UI 스프라이트 추가

지난 포스팅에 이어 게임에 생기를 불어넣기 위해 스프라이트 몇 개를 추가해 주었습니다

Image

구현한 버튼들에 간단한 스프라이트를 적용해 주는 선에서 끝났었는데, 이번에 배경과 UI도 조금씩 꾸며줬어요

결과물은…

Image

짜잔

버튼의 테두리를 진하게 강조하니까 너무 딱딱해 보이고 레벨 텍스트를 넣을 공간이 부족해서 과감하게 테두리를 없애고, 레벨 텍스트 크기도 조금 키워줬습니다

이렇게 보니까 버튼 디자인을 바꾼 후가 훨씬 나은 것 같네요

UI 왼쪽에 있던 물자와 에너지 현황도 아이콘을 넣어줬고, 오른쪽에 환경설정용으로 마련해 둔 공간에는 게임 배속 버튼과 게임 현황을 확인할 수 있는 버튼, 설정 버튼을 만들어주었습니다

폰트는 갈무리 폰트로 통일해 줬는데 개인적으로 픽셀 폰트 중에서 제일 예쁜 폰트인 것 같네요

배경을 어떻게 꾸밀지 고민하다가, 뭔가 우주 배경을 선택하면 잘 어울릴 것 같았습니다

그렇게 만들면 유닛 소환 포인트는 우주선으로 하면 좋을 것 같고, 마침 자원도 물자와 에너지가 뭔가 우주와 잘 어울리는 것 같고, 넥서스는 행성이나 우주 기지로 바꾸면 좋을 것 같고… 등등 확장성이 좋은 것 같아 일단 우주를 배경으로 세계관 기획을 하게 될 것 같아요

아직 넥서스와 자원을 획득하는 공간을 어떻게 디자인할지 안 정해놔서 다음에 스프라이트를 바꿀 예정입니다

액티브 능력 추가 구현

저번에 구현한 Firework 능력에 이어서 액티브 능력을 추가로 구현했습니다

그전에 플레이어 캐릭터를 자세히 보시면 희미한 테두리가 감싸고 있는 것을 볼 수 있어요

저 범위를 기준으로 플레이어가 유닛들과 상호작용할 수 있도록 할 건데, 크기를 업그레이드할 수 있도록 하기 위해 먼저 범위를 올려주는 업그레이드를 만들었습니다

현재 PlayerBuff의 Update 메서드에서 범위의 반지름을 업데이트하도록 구현해 둔 상태인데, 버튼을 누르면 반지름을 늘려서 적용하게끔 코드 몇 줄 추가했어요

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// PlayerBuff
private void Update()
{
    _circleCollider.radius = buffRadius;
}

// Upgrade
private void IncreaseBuffRange()
{
    if (!EnoughEnergy()) return;

    SpendEnergy();
    GameManager.Instance.player.GetComponentInChildren<PlayerBuff>().ChangeSprite(level);
    GameManager.Instance.player.GetComponentInChildren<PlayerBuff>().buffRadius = upgradeData.counts[level];
    IncrementLevel();
}

범위를 늘릴 때마다 그냥 그대로 늘려주면 스프라이트의 픽셀 사이즈도 안 맞고, 예뻐 보이지도 않아서 반지름별 범위 스프라이트를 각각 만들어주고, ChangeSprite 메서드를 이용해 업그레이드할 때마다 바뀌도록 구현했습니다

Image

버튼 스프라이트는 업그레이드된다는 느낌을 주기 위해 무지개색으로 표현해 주었습니다

확인해 보니 범위가 팍팍 잘 늘어나네요

얜 액티브 능력은 아니라는 점 참고로 말씀드립니다


다음으로 범위 내에 있는 유닛들을 제어하는 UnitControl 능력을 구현해 줄 겁니다

능력을 사용하면 범위 내에 있는 유닛들이 적 넥서스를 향해 돌진하는 능력으로, 많은 숫자의 유닛들을 원하는 방향으로 이동시킬 수 있다는 장점이 있습니다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Upgrade
private void ActivateUnitControl()
{
    if (level == upgradeData.counts.Length)
        GameManager.Instance.abilityManager.GetComponent<UnitControl>().boostMultiplier =
            upgradeData.counts[level - 1];
    else
        GameManager.Instance.abilityManager.GetComponent<UnitControl>().boostMultiplier =
            upgradeData.counts[level];

    GameManager.Instance.abilityManager.GetComponent<UnitControl>().isUnitControl = true;

    StartCoroutine(DeactivateUnitControl(
        GameManager.Instance.abilityManager.GetComponent<UnitControl>().controlTime));
}

private IEnumerator DeactivateUnitControl(float delay)
{
    yield return new WaitForSeconds(delay);
    GameManager.Instance.abilityManager.GetComponent<UnitControl>().isUnitControl = false;
}

우선 Upgrade 스크립트의 코드입니다

맨 위의 if else 문은 유닛의 속도를 높이는 boostMultiplier 값을 upgradeData에서 가져오는 코드인데, 만렙을 찍었을 때도 계속 값을 가져와야 해서 그때는 배열의 가장 마지막 값을 가져오기 위해 경우를 나눠줬어요

이후엔 UnitControl 클래스의 isUnitControl 변수를 true로 설정하고, controlTime 뒤에 유닛 제어를 멈추도록 코루틴을 넣어주었습니다

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
// PlayerBuff
private void OnTriggerEnter2D(Collider2D other)
    {
        ActivateUnitControl(other);
    }

    private void OnTriggerStay2D(Collider2D other)
    {
        ActivateUnitControl(other);
    }

    private void ActivateUnitControl(Collider2D other)
    {
        if (!other.CompareTag("Unit")) return;

        GameManager.Instance.abilityManager.GetComponent<UnitControl>().ActivateUnitControl(other);
    }

// UnitControl
public class UnitControl : MonoBehaviour
{
    public float controlTime;
    public bool isUnitControl;
    public float boostMultiplier;

    private void Awake()
    {
        isUnitControl = false;
    }

    public void ActivateUnitControl(Collider2D other)
    {
        UnitStats otherStats = other.GetComponent<UnitStats>();
        if (otherStats.isAlly == -1) return; // 적군이면 리턴

        if (!isUnitControl) return;

        // 상대 넥서스 방향으로 이동
        UnitMovement unitMovement = other.GetComponent<UnitMovement>();
        unitMovement.HeadToEnemyNexus();

        StartCoroutine(BoostUnitSpeed(unitMovement, boostMultiplier));
    }

    private IEnumerator BoostUnitSpeed(UnitMovement unitMovement, float mult)
    {
        float originalSpeed = unitMovement.rb.velocity.magnitude;
        unitMovement.rb.velocity *= mult;

        yield return new WaitForSeconds(controlTime);

        Vector2 currentVec = unitMovement.rb.velocity.normalized;
        unitMovement.rb.velocity = currentVec * originalSpeed;
    }
}

다음으로 PlayerBuff와 UnitControl 스크립트입니다

PlayerBuff의 범위 트리거에 오브젝트가 들어오면 유닛인지 확인하고, 맞으면 UnitControl의 ActivateUnitControl 메서드로 오브젝트를 넘겨줍니다

ActivateUnitControl 메서드에서 아군 유닛일 경우 UnitMovement 스크립트의 HeadToEnemyNexus 메서드를 이용해 적 넥서스를 향하도록 velocity를 설정해 주고, BoostUnitSpeed 코루틴을 시작해 유닛의 이동 속도를 올려줍니다

이후 controlTime이 흐르면 유닛은 기존에 이동하던 속력으로 복귀하게 되며 능력이 종료됩니다

Image

버튼 스프라이트는 저격용 총의 스코프 느낌으로 디자인해 줬습니다

버튼을 누르면 범위 안의 아군 유닛이 적 넥서스로 발사되는 걸 볼 수 있네요

다만 유닛이 많아지면 이동한다는 걸 눈으로 확인하기 어려울 것 같아서 나중에 눈에 띄는 이펙트를 추가하면 좋을 것 같습니다


아직 소개할 액티브 능력이 2개 정도 남았는데, 분량이 길어져서 다음 포스팅으로 올리도록 하겠습니다

이게 포스팅을 바로바로 올리지 않다 보니 쌓여있는 진행 상황을 올리는 과정에서 빠뜨리는 부분도 많고, 상세하게 다루지 못해서 글의 퀄리티가 떨어지게 되는 것 같네요

앞으로는 분량이 다소 짧더라도 자주 올리는 게 지금까지 어떻게 진행했는지 보기도 좋고, 퀄리티를 올리기에도 좋을 것 같습니다

그럼 다음 포스팅에서 뵐게요 👋

This post is licensed under CC BY 4.0 by the author.