Game Development, 게임개발/배경지식

Scroll, 스크롤에 대한 것

게임이 더 좋아 2021. 11. 11. 14:08
반응형
728x170

 

비교적 간단한 2D게임은 한 화면에 들어가지만

복잡한 2D 게임은 한 화면 안에 모든 것을 보여주기 그럴 때가 있다.

스크롤에도 여러가지가 있는데 알아보자

**여기서 코드는 의사코드로 표현했다. 어차피 다 자기 플랫폼에 맞춰서 짜면 된다.

 


 

-단일 축 스크롤

단일 축 스크롤 게임은 대표적으로 슈팅게임이 많이 있다.

횡스크롤, 종스크롤이 바로 그것을 말하는 것인데

1945나 텐가이 같은 게임이 종, 횡 스크롤 게임이다.

 

단일 축에 대해 구현하는 것은 그렇게 어렵지는 않다.

만약 모든 배경이미지를 한꺼번에 메모리로 로드할 수 있다면 간단한 알고리즘으로 구현이 가능하다.

제일 쉬운 방법이 화면 크기대로 배경을 나누는 것이다.

그래놓고 순서대로 Load하면 그만이다.

//의사 코드에 가깝게 그냥 쓰면
const int screenWidth = 960 // 화면의 넓이

string backgrounds [] = {"bg1.png", ......}

int hCount = 0
foreach string s in backgrounds
	Sprite bgSprite
    bgSprite.image.Loads(s)
    
    bgSprite.x = hCount * screenWidth// -> 횡스크롤 일 때
    bgSprite.y = 0// 높이는 변하지 않고
    bgSpriteList.Add(bgSprite) //계속 Load하고 추가함.
    hCount++
 loop

그냥 화면에 횡방향으로 쭉~ Load하면 되는 것이다.

그리고 카메라 Movement만 설정해주면 횡스크롤은 끝이다.

 

플레이어의 위치에 따라 카메라의 Movement를 조절하고

Camera는 배경을 벗어나서는 안된다.

횡스크롤로 따지면 가장 왼쪽 배경과 가장 오른쪽 배경에서 플레이어가 끝에 붙었을 때

어떻게 하느냐가 중요할 것이다.

 

여기서는 Clamp를 써서 최대 최소 값을 지정해주는 것도 나쁘지 않다.

가장 왼쪽과 가장 오른쪽을 지정해주는 것이다.

 

카메라 위치만 일단 정해지면 카메라의 위치를 기준으로 표시할 배경 조각을 정할 수 있다.

camera.x = clamp(player.x, screenWidth/2, hCount * screenWidth - ScreenWidth / 2)
//즉, player.x를 가지면서 최소는 가장 왼쪽 배경의 절반, 최대는 가장 오른쪽의 절반이라고 생각하면 된다.

Iterator i = bgSpriteList.begin()
while i != bgSpriteList.end()
    Sprite s = i.value()
    //배경을 비춤
    if(camera.x - s.x) < screenWidth
        draw s at (s.x - camera.x + screenWidth/2, 0)
        //플레이어가 화면 절반을 넘어가면 다음화면이 보일 수도 있으니 그리는 것이다.
        i ++
        s = i.value()
        draw s at (s.x - camera.x + screenWidth/2, 0)
        break
    end
    i++
loop

 


 

슈팅게임 같은 경우

최종 보스를 끝냈을 때, 게임이 끝나지 않고 무한모드란 것이 존재한다.

즉, 난이도만 계속 높아질 뿐 끝나지 않는 게임이다.

이럴 때 게임의 배경을 무한대로 이어줄 수는 없다. 왜냐면 한계가 있기 때문이다.

다만 무한한 배경처럼 보이게 할 수는 있다.

 

- 그것이 바로 무한 스크롤이다.

무한 스크롤은 화면크기의 배경 3개만 있으면 된다.

플레이어가 1을 지나고 있을 때 2는 어느정도 로딩이 되어야하고

2를 지나고 있을 때는 3이 어느정도 로딩이 되어야 하고

3을 지날 때는 다시 1을 로딩시켜주면 된다.

즉, 3개만으로도 무한한 배경을 만들 수 있다.

다만 1,2,3이 배경이 비슷하지 않거나 너무 다를경우.. 위화감이 들 수도 있다.

때문에 3개의 배경을 주되 해당 Color감을 바꾸는 식으로도 배경을 여러 개가 무한히 있는 것럼 바꿀 수 있다.

 

**분명 어렸을 때는 지구에 도착하면 외계인이 죽겠지 상상했지만..?

내가 5분동안 기다려본 결과 지구에 도착하지 않는다.

우주에서 지구로 다이빙한 사람이 5분 채 걸리지 않았지만 메탈슬러그의 세계관은 지구가 아닌가보다.

가 아니라... 무한스크롤을 배경으로 썼기 때문이다.

 

더군다나 보스의 패턴에 따라 색도 바뀌게 하여 무한 스크롤이 위화감 없이 진행되었다.

 

 


 

또한 스크롤링을 이용하여 원근감을 줄 수도 있다.

차가 아무리 빨리 달려도 태양이 제자리에 있는 것처럼

멀리 있는 것은 내가 아무리 빨리 이동하더라도 느리게 움직인다.

반면에 내 가까이 있는 것은 내가 빨리 이동하는 만큼 빨리 움직인다.

 

즉, 배경에서 저 멀리있는 산은 내가 움직여도 천천히 움직일 것이고

당장 내 앞에 있는 나무들은 내가 움직이는 만큼 빨리 움직일 것이다.

 

-그것이 Parallax Scrolling이다.

 

이것은 배경마다 Layer를 조정하여 적용한다.

위의 메탈슬러그 같은 경우

멀리 있는 구름은 느리게 흘러가고

가까이 있는 구름은 빠르게 흘러가는 식으로 만들 수 있다.

즉, Layer마다 심도(depth)를 정한다면 Depth에 비례해서 속도를 바꿀 수 있다.

float speedFactor = 0.3f;
float depth = spriteBg.depth; // 심도
draw s at (s.x - (camera.x - screenWidth/2) * speedFactor * 1/depth, 0)

 

심도에 따라 배경이 어디까지 그려져야하는지 달라지는 것이다.

 


 

횡스크롤, 종스크롤만 있어?? 둘다 합친 것은??

물론 있다.

-네 방향 스크롤게임은 정말 많다. 

당장 메이플만 해도 그렇다.

그 옛날의 메이플... 구경하다가 죽어서 엘리니아로 돌아갔는데..ㅋㅋㅋ

 

물론 메이플은 종횡스크롤이면서도 포탈로 맵이 나누어져 있어서

굳이 배경을 미리 로딩못할 것도 없다.

즉, 카메라가 해당 배경만 벗어나지 않게 수정만 해도 된다.

다시 말해서 카메라의 x축, y축의 최대 최솟값을 적절히 정해주면 된다는 말이다.

어렵지 않다.

 


 

-젤다의전설 같이 TIle Map을 이용한 스크롤 방법도 있다.

 

이미 구현해봤지만 이것 또한 미리 로딩시켜놓고 조작한다.

다만 모든 땅에 대해서 하나하나씩 로딩하는 것이 아니라.

해당 타일을 어디다 위치시킬 것인지만 결정하면 모든 것이 해결된다.

즉, 나무 타일이 0번이면 0의 위치만 정해주면 Map에 나무타일이 생겨 맵이 구성되는 것이다.

하지만 좀 더 복잡하게 하기 위해 Random으로 나무타일 5개 중 1개를 뽑아 넣거나 해서

맵을 미리 만들지 않고도 항상 새로운 맵을 만드는데 사용되기도 한다.

즉, 타일에 들어가는 문짝도 랜덤으로 배치하여 해당 문을 통과했을 때, 런타임에 해당 맵을 만들기도 한다.

우리가 코딩테스트에서

5,5

1,1,1,1,0

0,0,0,1,0

0,0,0,0,0

1,1,1,0,1

0,0,0,0,1

과 같은 것도 사실 타일맵이라 보면 된다.

0이 갈 수 있는 타일, 1이 벽 타일 

 


 

스크롤은 사실 배경이나 맵에 정말 많이 쓰인다.

카메라 이동과 플레이어 이동과 가장 밀접하게 관련되어 있다.

생각해보면 우리는 이미 경험적으로 다 알고 있다.

다만 게임개발자는 알고 있는 것을 게임에 넣을 수 있느냐

그것도 효율적으로 넣을 수 있느냐를 연구해서 만들어내는 매력적인 일을 한다.

 

반응형
그리드형