아방스 칼럼



음 이 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 13970
게임실황살피기 습작의 게임실황 살피기 : RM2k - Beyond The World 1 file 습작 2012.06.30 2390
스크립트이야기 습작의 스크립트 이야기 : 번외편 - 3편 : Starter Kit 6 file 습작 2012.06.30 4523
게임실황살피기 습작의 게임실황 살피기 : RMXP - Aooni Blood Online 3 file 습작 2012.07.09 3476
단   편 RMVX/Ace 맵배치를 논하다 7 file 습작 2012.07.11 3231
게임실황살피기 습작의 게임실황 살피기 : RMXP - 물방울 소리 1 file 습작 2012.07.21 3059
스크립트이야기 습작의 스크립트 이야기 : 비전투스크립트 이야기 - 1편 : RMVX Add-on file 습작 2012.07.27 3566
시 옷 일 기 [시옷일기]네이버 소셜 게임 언라이트의 하이-로우를 구현해 보자 1page 1 file 시옷전사 2012.07.28 4030
스크립트이야기 습작의 스크립트 이야기 : 파이썬과 함께 - 1편 : With Construct Classic 2 file 습작 2012.07.30 3167
XNA게임만들기 XNA 게임 만들기 - 1. 목차 3 file 재훈군 2012.08.04 4148
XNA게임만들기 XNA 게임 만들기 - 2. 게임을 만들기 위한 준비 4 file 재훈군 2012.08.04 3675
XNA게임만들기 XNA 게임 만들기 - 3. 라이브러리 만들기 1 file 재훈군 2012.08.04 3094
XNA게임만들기 XNA 게임 만들기 - 4. 다중 시점 렌더링 5 file 재훈군 2012.08.05 3461
XNA게임만들기 XNA 게임 만들기 - 5. 컨텐츠 관리 (1) 6 file 재훈군 2012.08.05 2845
게임실황살피기 습작의 게임실황 살피기 : RMXP - 아오오니 2Player file 습작 2012.08.11 3093
XNA게임만들기 XNA 게임 만들기 - 6. 컨텐츠 관리 (2)와 JML 그리고 패키지 파일 1 file 재훈군 2012.08.16 2792
XNA게임만들기 XNA 게임 만들기 - 7. 렌더타깃 관리 6 file 재훈군 2012.08.17 2782
XNA게임만들기 XNA 게임 만들기 - 8. 그림을 화면에 & UI 만들기 1 file 재훈군 2012.08.19 3734
단   편 <77ER의 알만툴 스킬> 알만툴에서 픽쳐를 많이 사용하는 스크립트 사용자들의 렉 고민을 풀어보자. (나름 고급자용?) 7 file 77이알 2012.08.31 2797
스크립트이야기 습작의 스크립트 이야기 : 번외편 - 4편 : Ethanon Engine 7 file 습작 2012.10.28 4300
시 옷 일 기 [시옷일기]하이로우 스크립트의 뼈대를 완성하다. 2page 2 file 시옷전사 2012.10.30 2673
시 옷 일 기 [시옷일기]창세기전3의 성장 시스템 3page 6 file 시옷전사 2012.10.30 3682
Board Pagination Prev 1 2 3 4 5 6 7 8 9 Next
/ 9