플레이어 캐릭터는 활을 겨누면서 360도 방향을 자유롭게 이동합니다. 활은 진행하는 방향을 향하게 되고 진행 방향으로 발사할수 있습니다. 발사된 활은 물체에 닿으면 그 자리에 박힌후 잠시 뒤 사라집니다.

 

멀티 스프라이트로 캐릭터 이미지 만들기

프로젝트뷰에 Player폴더를 만듭니다.  교재를 다운 받으면 이미 폴더가 만들어져 있습니다.

Player.zip
0.03MB

Player폴더의 PlayerImages를 엽니다. 패턴은 32x32 픽셀의 도트이미지 입니다. 타일맵과 동일하게 멀티 스프라이트로 만듭니다. Sprite Mode:Multiple, Pixels Per Unit: 32, Filter Mode: Point 아까 멀티맵처럼 설정합니다.

Sprite Editor를 클릭해 [Slice]탭을 선택하고 Pixel Size:32x32 Pivot:Custom, Custom Pivot x:0.5 Y:0.2로 약간 아래로 내립니다.

화살과 활은 아래와 같이 이동중심으로 옮겨 줍니다.

화살은 Center로 합니다.

설정이 완료되면 위쪽의 APPLY를 클릭합니다.

 

플레이어 캐릭터의 게임 오브젝트 만들기

플레이어의 상하좌우 이동 애니메이션을 만들어야 합니다. 우선 분할된 이미지의 앞 2개를 선택해서 씬뷰로 끌어줍니다.

이름을 PlayerDown 으로 Player 폴더에 저장합니다.

배경 타일맵 보다 위에 보이도록 Order in Layer값을 3으로 설정합니다. 

여기까지 작업후 저장된 애니메이터 컨트롤러 이름을 PlayerAnime으로 합니다. 게임오브젝트의 이름도 Player로 합니다.

* 저는 그냥 Player폴더에 있는 player프리팹을 끌어다 놨습니다. 모든게 이미 설정되어져 있습니다.

플레이어 캐릭터에 Rigidbody2D를 어태치하고 Gravity를 0, Freeze Rotation Z를 체크,

Circle Collider2D를 어태치합니다. 범위를 전체의 반정도로 조정합니다.  Player Tag를 설정하고 Player 레이어를 만들어 설정합니다.  

PlayerDown 애니메이션을 열어 Samples를 4로 설정합니다.

같은 방법으로 PlayerUp(Image2~3), PlayerLeft(Image4~5), PlayerRight(Image6~7)를 만듭니다.

생성된 게임오브젝트는 애니메이션 클립을 만들기 위한 것이므로 실제 사용하지 않습니다. 애니메이션 클립을 저장한 후에는 PlayerUp, PlayerLeft, PlayerRight 애니메이션 컨트롤러와 게임오브젝트는 제거됩니다.

방금만든 PlayerUp, PlayerLeft, PlayerRight 애니메이션을 Animator에 끌어다 놓습니다.

게임오버 애니메이션 만들기

이제 게임오버 애니메이션을 만듭니다.

하이라키에서 Player를 선택하고 애니메이션 창을 엽니다. Crate NewClip을 선택해 PlayerDead라는 이름을 애니메이션 클립을 추가합니다.

[Add Propety] 버튼을 클릭하고 Sprite Renderer > Sprite를 선택해 Sprite를 추가합니다. 빨간색 기록버튼을 누르고 키 프레임으로 등록된 이미지 두개를 PlayerImage_8로 변경합니다. 

Sprite Renderer.Color를 추가하고 마지막 프레임의 Color.a를 0으로 설정합니다.

플레이어 이동 스크립트 만들기

PlayerController라는 스크립트를 Player폴더에 만들고 씬뷰의 Player에 어태치합니다. 7장에서 만든 버추얼패드의 스크립트를 다시사용하고자 이름을 똑같이 했습니다. 

PlayerController.cs
0.01MB

변수

과거 애니메이션과 현재 애니메이션의 이름이 다르면 애니메이션을 변경하는 처리를 합니다.

public float speed = 3.0f;     //이동 속도
//애니메이션 이름
public string upAnime = "PlayerUp";         // 위
public string downAnime = "PlayerDown";     // 아래
public string rightAnime = "PlayerRight";   // 오른쪽
public string leftAnime = "PlayerLeft";     // 왼쪽 
public string deadAnime = "PlayerDead";     // 사망

string nowAnimation = ""; //현재 애니메이션
string oldAnimation = ""; //이전 애니메이션

float axisH;                    //가로 축 값(-1.0 〜 0.0 〜 1.0)
float axisV;                    //세로 축 값(-1.0 〜 0.0 〜 1.0)
public float angleZ = -90.0f;   //회전 각

Rigidbody2D rbody;              //Rigidbody 2D
bool isMoving = false;          //이동 중인지 여부

//데미지 처리
public static int hp = 3;           //플레이어 HP
public static string gameState;     //게임 상태
bool inDamage = false;              //데미지 받는 중인지 여부

Start()

Rigidbody2D 컴포넌트 참조를 저장하고, oldAnimation을 downAnime으로 하고 gameState를 "playing"으로 설정합니다.

// Use this for initialization
void Start()
{
    //Rigidbody2D 가져오기
    rbody = GetComponent<Rigidbody2D>();
    //애니메이션
    oldAnimation = downAnime;
    //게임 상태를 플레이 중으로 변경
    gameState = "playing";
}

Update()

키입력으로 방향을 정하고 애니메이션을 결정

// Update is called once per frame
void Update()  {
    //게임중이 아니거나 데미지 받는 중엔 아무것도 하지 않음
    if (gameState != "playing" || inDamage)  {
        return;
    }
    if (isMoving == false)  {
        axisH = Input.GetAxisRaw("Horizontal"); //좌우 키 입력
        axisV = Input.GetAxisRaw("Vertical");   //상하 키 입력
    }
    //키 입력으로 이동 각도 구하기
    Vector2 fromPt = transform.position;
    Vector2 toPt = new Vector2(fromPt.x + axisH, fromPt.y + axisV);
    angleZ = GetAngle(fromPt, toPt);
    //이동 각도에서 방향과 애니메이션 변경
    if (angleZ >= -45 && angleZ < 45)   {
        //오른쪽
        nowAnimation = rightAnime;
    }  else if (angleZ >= 45 && angleZ <= 135)   {
        //위쪽
        nowAnimation = upAnime;
    }   else if (angleZ >= -135 && angleZ <= -45)  {
        //아래쪽
        nowAnimation = downAnime;
    }  else {
        //왼쪽
        nowAnimation = leftAnime;
    }
    // 애니메이션 변경하
    if (nowAnimation != oldAnimation) {
        oldAnimation = nowAnimation;
        GetComponent<Animator>().Play(nowAnimation);
    }
}

FixedUpdate()

 inDamage상태이면 SpriteRendere.enable = true, false로 변경하면서 점멸시킨다. 이동속도도 변경시킨다.

void FixedUpdate()  {
    //게임 중이 아니면 아무것도 하지 않음
    if (gameState != "playing")   {
        return;
    }
    if (inDamage)  {
        //데미지 받는 중엔 점멸 시키기
        float val = Mathf.Sin(Time.time * 50);
        Debug.Log(val);
        if (val > 0)   {
            //스프라이트 표시
            gameObject.GetComponent<SpriteRenderer>().enabled = true;
        } else {
            //스프라이트 비표시
            gameObject.GetComponent<SpriteRenderer>().enabled = false;
        }
        return; //데미지 받는 중엔 조작을 할수 없게하기
    }
    //이동 속도 변경하기
    rbody.velocity = new Vector2(axisH, axisV) * speed;
}

SetAxis() 

버추얼패드에서 호출해서 키보드대신 axisH와 axisV를 설정해줍니다.

public void SetAxis(float h, float v) {
    axisH = h;
    axisV = v;
    if (axisH == 0 && axisV == 0)   {
        isMoving = false;
    }   else {
        isMoving = true;
    }
}

GetAngle()

p1,p2사이의 각도를 Atan2를 이용해 구합니다.

float GetAngle(Vector2 p1, Vector2 p2) {
    float angle;
    if (axisH != 0 || axisV != 0) {
        //이동 중이면 각도를 변경
        //p1과 p2차이 구하기(원점을 0으로 하기 위해)
        float dx = p2.x - p1.x;
        float dy = p2.y - p1.y;
        //아크 탄젠트 함수로 각도(라디안) 구하기
        float rad = Mathf.Atan2(dy, dx);
        //라디안 각으로 변환하여 반환
        angle = rad * Mathf.Rad2Deg;
    }   else {
        //정지중이면 이전 각도를 유지
        angle = angleZ;
    }
    return angle;
}

OnCollisionEnter2D() 

Enemy와 충돌하면 대미지처리를 합니다.

private void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.tag == "Enemy")
    {
        GetDamage(collision.gameObject);
    }
}

GameOver()

플레이어의 hp가 0이되면 GameOver()처리를 합니다.

void GameOver()
{
    Debug.Log("게임 오버!");
    gameState = "gameover";
    //=====================
    //게임 오버 연출
    //=====================
    //플레이어 충돌 판정 비활성
    GetComponent<CircleCollider2D>().enabled = false;
    //이동 중지
    rbody.velocity = new Vector2(0, 0);
    //중력을 적용하여 플레이어를 위로 튀어오르게하는 연출
    rbody.gravityScale = 1;
    rbody.AddForce(new Vector2(0, 5), ForceMode2D.Impulse);
    // 애니메이션 변경하기
    GetComponent<Animator>().Play(deadAnime);
    //1초후에 플레이어 캐릭터 제거하기
    Destroy(gameObject, 1.0f);
}

Player에 어태치해서 실행해보면 WASD키를 누르면 상하좌우로 잘 움직입니다.  교재에는 활을 표시해주는  Arrow Shoot 스크립트가 어태치되어 있어 활도 표시되었습니다 이건 뒤에서 공부합니다.

 

+ Recent posts