아방스 칼럼



음 이 77ER,


뜬금없이 나타나서 글을 쓰는 것이지만..


중간 중간 끊기는 렉을 줄여보고자 생각을 하고 적용 해 본 바.


적용이 되어 정리 차원에서 여기에 글을 남겨 봅니다.


렉의 원인은 여러가지가 있겠지만 


그 중에서 가장 쉽게 만날 수 있는 그리고 가장 큰 영향을 미치는 것은..


에니메이션 렉, 픽쳐 렉. (코딩은 아무리 아무리 아무리 길어도 어지간해 길지 않는 이상 사람이 체감할 수 없는 것 같습니다.)


에니메이션 렉은 그 렉을 줄여주는 스크립트도 있고 뭐 조금만 손 보고 여차여차 하면 줄일 수 있는데


 에니메이션의 렉의 주 요 원 인중에 하나가 픽쳐를 불러오는 방식 때문입니다.


에니메이션을 실행하기 위해서 해당 에니메이션 폴더의 픽처를 불러오는데 


그때 픽쳐의 프래임이 한 장에 많이 포진되어 있거나 픽쳐가 생각 이상으로 크다면


불러오는 도중에 렉이 생기고 에니메이션 한 프레임 한 프레임을 불러 올 때마다 전체를 반복해서 불러오기 때문에


만약 30개의 프레임을 가진 에니메이션을 연결해서 불러 온다면 30번을 그 해당 픽쳐파일을 반복해서 불러오는 것이고


그 한 프레임 프레임마다 불러오며 끊기기에 30번이나 끊기는 화면이 이어지고 그래서 육안으로 프레임이 끊기는 현상이 나타나는 것 입니다.


그렇다고 에니메이션 각각의 프레임 따로 파일을 만들어 저장시킬 수도 없는 노릇이고 그래서..



해결 방법이 있습니다.


결론부터 말 씀 드리면 실행할 픽쳐 파일을 전부 module에 불러와서 저장시켜버리는 것 이지요.



픽쳐를 불러오는 함수의 예를 하나 보이면,


 def draw_picture(pic_name, x, y, enabled = true)

    bitmap = Cache.picture(pic_name)

    rect = Rect.new(0, 0 , 272, 288)

    contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)

    bitmap.dispose

  end


저기서 문제의 원인인 bitmap = Cache.picture(pic_name)가 보입니다. 저 부분때문에 매번 픽쳐를 새로 불러올 때 다시금 생으로

픽쳐파일을 캐싱해서 느려지게 되는 것 이지요.


이제 방법을 설명드리면..

(초급자 분들은 이해하기 여러울 수도.. 제 실력으로 너무 자세히는 설명은 못합니다.)

(아래 부분은 그냥 예시일 뿐입니다. 포인트를 잡는데 신경을 ㅋ)


만들려는 게임의 스테이지 1에서 필요한 픽쳐 파일이 A B C D라고 가정해 보겠습니다.


일단


module Picload

 temp = [nil,nil,nil,nil]

end


을 만든 후에


스테이지 1이 시작되기 바로 전 단계(게임 로딩화면 정도..)에

Picload::temp[0] = Cache.picture("A") #픽쳐 A의 주소는 0

Picload::temp[1] = Cache.picture("B") #픽쳐 A의 주소는 1

Picload::temp[2] = Cache.picture("C") #픽쳐 A의 주소는 2

Picload::temp[3] = Cache.picture("D") #픽쳐 A의 주소는 3

를 해 준 후


픽쳐 불러오는 함수 부분을

 def draw_picture(pic_num, x, y, enabled = true)

    rect = Rect.new(0, 0 , 272, 288)

    contents.blt(x, y,  Picload::temp[pic_num], rect, enabled ? 255 : translucent_alpha)

  end

로 바꾸어 줍니다. (원래 픽쳐를 불러오는 함수는 해당 픽쳐의 이름으로 불러왔는데 이제는 저장을 시켰으니 주소(번호)로 불러오게 합니다)


그리고 스테이지 1일 끝나는 부분에 있는 def terminate 함수 부분에

for i in 0..3

 Picload::temp[0].dispose

end

를 추가시켜 주는 것 이지요.


위의 rect = Rect.new(0, 0 , 272, 288) 부분은 불러오는 사진의 어떤 부분을 잘라내 보여주는지 해당되는 것이기에 그 부분도 따로

module Picload

 temp_r = [nil,nil,nil,nil]

end

이렇게 만들어서 스테이지 1이 시작되기 바로 전 단계(게임 로딩화면 정도..)에 각각의 사진의 크기의 맞게

Picload::temp_r[0] = Rect.new(0, 0 , 272, 288)

Picload::temp_r[1] = Rect.new(0, 0 , 50, 50)

Picload::temp_r[2] = Rect.new(96, 96 , 96, 96)

Picload::temp_r[3] = Rect.new(0, 0 , 100, 100)

이렇게 해 주고

 def draw_picture(pic_num, x, y, enabled = true)

    contents.blt(x, y,  Picload::temp[pic_num],  Picload::temp_r[pic_num] , enabled ? 255 : translucent_alpha)

  end

위에처럼 해 버려도 됩니다.


근데 module은 임시캐쉬같은 것이니 때문에 세이브하고 로딩하면 다 날아가버린다는게 문제 입니다.

하지만 이것의 해결 방법은 또한 간단합니다. 각각의 스테이지별로 로딩할 때 그 부분에 필요한 픽쳐를

Picload::temp[0] = Cache.picture("A") #픽쳐 A의 주소는 0

Picload::temp[1] = Cache.picture("B") #픽쳐 A의 주소는 1

Picload::temp[2] = Cache.picture("C") #픽쳐 A의 주소는 2

Picload::temp[3] = Cache.picture("D") #픽쳐 A의 주소는 3

위의 식으로 다시 불러오는 코드를 입력하면 됩니다.

아마 세이브 전에 

for i in 0..3

 Picload::temp[0].dispose

end

이 필요할 지도 모르겠군요.


놀랍게 부분 부분 끊기고 렉이 생기던 것이 싹 사리집니다.

별로 어렵지 않은 방법이지만 어렵지 않은 방법을 생각해 내는데 참 오래도 걸리더군요.


에니메이션에서 사용되는 방법은 좀 조작이 필요하지만 위 의 방법으로 수정을 잘 하면 동일하게 수행이 가능 합니다.


위의 방법은 픽쳐를 쓰는 어느 곳이던 간에 응용이 가능 합니다. 렉 때문에 짜증나던 것이 사라지니 알만툴의 신세계를 경험하는 느낌이 들더군요...


또 다른 렉의 문제점 하나는 픽쳐를 너무 많이 사용해서 입니다. 그것을 줄이는 방법으로는 여러 픽쳐를 통일시켜 버리는 겁니다. 화면에 두 개의 픽쳐를 표시하려고 하는데 그냥 한 개의 픽쳐에 두개의 픽쳐를 붙여넣어 두개의 픽쳐가 보이게 해 버리는 것 이지요.


생각나는데로 막 썼기 때문에 이해하기 어려울지 모르나 제가 말하고자 하는 포인트를 잡을 수 있으리라 보여집니다.



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

VVV위 방법을 사용했을 때와 하지 않았을 때 비교 동영상VVV

(여타 다른 코딩 등에는 전혀 변화를 주지 않음.)

(캡쳐한 동영상이라 실제로는 더 부드러움. 확연한 차이를 비교하는게 주요.)



기존의 draw_picture 방식으로 사용 하였을 경우

1.png








수정된 방식으로 사용 하였을 경우

2.png

3.png



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////



다음 번에는 단 한개의 변수를 사용하여 무한 변수를 생성하여 사용하는 방법을 설명해 보겠습니다. 관심도를 봐서 ㅋ

Comment '7'
  • profile
    습작 2012.08.31 14:37

    * 관리자에 의해 카테고리가 수정되었습니다. 일단 '자유연재'로 판단하여 수정하였으니, '단편'인 경우라면 [단편] 카테고리로 수정부탁드립니다. '기획연재'의 경우 '기획연재 안내 및 신청' 게시물을 참고해주세요.^^

  • ?
    77이알 2012.09.01 11:35
    단편으로 수정 했습니다 ~
  • ?
    허걱 2012.09.01 00:51
    음...저는 Picload 모듈이 왜 필요한지 모르겠네요;
    Picload 나 Cache 나 둘다 모듈이고 하는 기능은 동일하게 보입니다.
    Cache 역시 한번이상 불러온 파일은 메모리에 저장시켜 놓고 있죠.
    위와 같이 하게 된다면 Picload 를 통해서 의미없는 처리만 더 늘어나는게 아닐까요?
  • ?
    77이알 2012.09.01 09:18



    이건 실제 개인적으로 해 봐서요 . 저렇게 하고 안하고의 차이는 확실히 눈으로 확인이 가능 했거든요.


    위 처럼 안 하고 기존의 방식대로 하면 픽쳐 파일이 크다면 draw_picture함수를 연속적으로 사용할 때마다 딱딱 끊깁니다.


    하지만 수정된 방식대로하면 이상하게도 끊김현상이 완전히 사라집니다.


    작성 글을 다시 보시면 비교 동영상을 첨부했습니다.


      #--------------------------------------------------------------------------

      # ● 캐쉬 존재 체크

      #--------------------------------------------------------------------------

      def self.include?(key)

        @cache[key] && !@cache[key].disposed?

      end


    위 부분을 보니 Cache.picture(..이렇게 반복적으로 해도 불러왔던 파일은 안 불러오는 것을 확인 가능했으나


    만약 그렇다고 해도 위에 끊김현상이 사라지는 것은 논리적으로 이해가 안되기도 합니다.


    제가 지식이 짧기 때문에 경험적 효과로만 해 보고 올린거라서 확실한 알고리즘은 틀릴 수도 있겠네요.


    draw_picture 함수 내의 bitmap.dispose 때문인 것 같기도 하고...


    생각해 보니 이 작업은 딱히 모듈을 새로 만들기보다는 클래스 자체 내에서 만들어 처리해 버리는 게 좋을 듯도 하네요.

    Cache에 저장한 픽쳐의 주소만을 저장하는 것 이니까요.

  • ?
    허걱 2012.09.04 20:36
    draw_picture 함수는 직접 만드신건가요?
    translucent_alpha 메소드를 사용한걸 보면 Ace 같은데 draw_picture 함수는 기본적으로 없던데...
    (본문에 사용 툴이 표시되면 좀 더 좋을것 같네요^^;)

    그리고 Cache 모듈을 사용해서 비트맵을 불러올 경우 dispose는 딱히 필요없을듯 하네요.
    (아마 dispose 해주면서 메모리에서 삭제하니깐 Cache 모듈에서 다시 불러오고 불러오고 하면서 느려지는듯)
  • ?
    77이알 2012.09.04 21:20

    VX/VX ACE에 원래 있는 def draw_face 에서 face만 picture로 수정한 겁니다.

    def draw_face(face_name, face_index, x, y, enabled = true)
    bitmap = Cache.face(face_name)
    rect = Rect.new(face_index % 4 * 96, face_index / 4 * 96, 96, 96)
    contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
    bitmap.dispose
    end

    def draw_face 함수 안에도 bitmap.dispose 있네요.

    근데 dispose때문이 아닌 것 같습니다.

    저 bitmap.dispose를 지워줘도 똑같이 끊기더군요.

    bitmap = Cache... 이 부분이 있으면 무조건 느려져요.

    원래 Cache 모듈에는 불러왔던 것은 다시 안 불러오게하는 함수가 있는 것 같은데

    그 코드가 작동을 잘 안 하지 않나 생각 해 봅니다. ㅋ^^;;

  • ?
    77이알 2012.09.01 10:06

    아 그리고 위의 방법은

    실제로  새로 픽쳐를 불러 올 때마나 끊기기 때문에 게임 중간에 불러오지 말고 

    게임에서 해당하는 파트 부분에 필요로 하는 전 픽쳐를 일단 불러와 놓고 시작하는데에는 효과적이라고 보여집니다.


    예를 들어 첫번째 스테이지가 시작되기 전에


    for i in 0..필요갯수만큼

     ...Cache.picture("필요파일이름_"+i)..

    end


List of Articles
분류 제목 글쓴이 날짜 조회 수
공   지 칼럼 게시판 이용 안내 6 습작 2012.07.09 13995
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 5 7 2013.07.10 2822
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 4 9 2013.07.05 2625
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 3 11 2013.06.22 3151
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 20 13 file 2015.09.03 1745
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 2 8 2013.06.02 3083
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 1~50 요약본 4 file 2013.10.08 1988
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 19 4 file 2015.06.04 1251
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 18 6 file 2015.03.01 1740
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 17 9 file 2014.07.07 3514
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 16 file 2014.03.29 2341
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 15 9 file 2014.02.12 2478
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 14 7 file 2014.01.18 2921
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 13 4 file 2013.11.20 2357
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 12 9 file 2013.10.23 2469
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 11 14 file 2013.10.16 2284
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 10 21 file 2013.09.26 3041
게임실황넋두리 국산 게이ㅁ들을 실황해오면서 느낀 잡썰 1 7 2013.05.29 3429
단   편 공포게임을 하면서 참 부족했던 점. 3 2034 2014.09.28 1276
단   편 게임제작을 포기하는 이유. 11 file 스리아씨 2013.10.25 1845
자 유 연 재 게임이란 무엇인가? - 3. 부가요소 5 제스터 2014.04.18 1209
자 유 연 재 게임이란 무엇인가? - 2. 핵심 요소 제스터 2014.04.17 1402
Board Pagination Prev 1 2 3 4 5 6 7 8 9 Next
/ 9