로그인

검색

MoA
조회 수 1317 추천 수 0 댓글 5
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄 첨부
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄 첨부

4_main.png

 

 

 

1. 준비

 

이번엔 펜스를 그려보자. 펜스는 농부가 이동할 수 있는 지역의 경계가 된다. 이 게임의 특징은 펜스나 상점 등의 위치 데이터를 파일에서 가져오는 것이다. 소스 디렉토리에 보면 data 폴더 아래에 level.txt 파일을 열어보자

 

 

FFFFFFFFFF
FLLLLLLLLF
F        F
F   P    F
F       CF
F        F
FW      SF
FFFFFFFFFF

 

 

 

알파벳으로 이루어진 텍스트이다. 게임을 해봤다면 F가 뭔지 L은 뭔지 등을 짐작할 수 있을 것이다. F가 우리가 이 강좌에서 그릴 펜스이다. 파일을 열기 전에 펜스 클래스부터 정의하자.

 

2. Fence 클래스

 

 

class Fence(pygame.sprite.Sprite):

    def __init__(self, x, y):
        self.fence_ = load_img('fence', 'fence_.png')
        self.fence_u = load_img('fence', 'fence_u.png')
        self.fence_d = load_img('fence', 'fence_d.png')
        self.fence_l = load_img('fence', 'fence_l.png')
        self.fence_r = load_img('fence', 'fence_r.png')
        self.fence_ud = load_img('fence', 'fence_ud.png')
        self.fence_ul = load_img('fence', 'fence_ul.png')
        self.fence_ur = load_img('fence', 'fence_ur.png')
        self.fence_dl = load_img('fence', 'fence_dl.png')
        self.fence_dr = load_img('fence', 'fence_dr.png')
        self.fence_lr = load_img('fence', 'fence_lr.png')
        self.fence_udl = load_img('fence', 'fence_udl.png')
        self.fence_udr = load_img('fence', 'fence_udr.png')
        self.fence_ulr = load_img('fence', 'fence_ulr.png')
        self.fence_dlr = load_img('fence', 'fence_dlr.png')
        self.fence_udlr = load_img('fence', 'fence_udlr.png')

        pygame.sprite.Sprite.__init__(self)
        self.image = self.fence_
        self.rect = self.image.get_rect()
        self.rect.topleft = x, y
        fences.append(self)

    def assign_image(self):
        imagename = "fence_"
        if self.rect.move(0, -64).collidelistall(fences) != []: imagename = imagename + "u"
        if self.rect.move(0, 64).collidelistall(fences) != []: imagename = imagename + "d"
        if self.rect.move(-64, 0).collidelistall(fences) != []: imagename = imagename + "l"
        if self.rect.move(64, 0).collidelistall(fences) != []: imagename = imagename + "r"
        exec('self.image = self.%s' % imagename)

 

 

 

3번 강좌에서 본 HUD_Sprite 클래스보다 꽤 복잡하다. 사실 난 이 클래스에 불만이 하나 있다. 펜스를 생성할 때마다 생성자에서 이미지를 16개씩 불러오고 저장하기 때문이다. static 메쏘드나 global 메쏘드로 정의를 하는게 좋을 것 같다. 그리고 펜스 이미지가 16개씩 있는 이유는 이미지를 직접 열어보면 된다. 펜스 자신의 주변에 아무 펜스가 없는 경우, 오른쪽에 펜스가 있는 경우 아래쪽에 펜스가 있는 경우 등등을 다 고려해야 하기 때문이다. 이미지 이름에서 _ 뒤에 있는 문자의 의미는 u = up, d = down, l = left, r = right이다. 자신의 위쪽에 펜스가 있는 경우 u, 아래쪽에 있는 경우 d 등을 붙이는 것이다.

 

생성자에서는 fences 리스트에 자신을 추가한다. 그리고 기본으로는 주변에 펜스가 없는 경우의 이미지를 할당한다. assign_image() 함수는 주변에 펜스가 있는지 없는지를 체크하여 그에 해당하는 이미지를 다시 할당한다. 주변에 펜스가 있는지 없는지는 collidelistall 함수를 이용한다. 이는 파라메터의 리스트 안에 있는 오브젝트들과 충돌 여부를 조사하여 충돌하는 오브젝트들을 모은 리스트를 리턴한다. (collidelistall 함수의 파라메터는 사실 Rect 오브젝트의 리스트여야 하지만 Sprite 클래스의 오브젝트도 가능하다.) 펜스를 상하좌우로 움직여 충돌하는 펜스가 있다면 경우에 따라 이미지 이름의 끝에 u, d, l, r 를 붙인다. 그리고 그 이름의 이미지를 자신의 이미지로 할당한다.

 

3. 맵 데이터 불러오기

 

이제 맵 데이터가 들어가 있는 파일을 불러온다.

 

 

# Sprites/Objects를 생성한다
    fencenum = 1
    blockx = 0
    blocky = 0
    level = open('data/level.txt', 'r')

    for line in level:
        for char in line:
            if char == 'F':
                exec('fence%i = Fence(blockx, blocky)' % fencenum)
                exec('scenerylist.append(fence%i)' % fencenum)
                fencenum += 1
            blockx += 64
        blocky += 64
        blockx = 0
    for fence in fences:
        fence.assign_image()
    
    global allscenery
    allscenery = pygame.sprite.RenderPlain(scenerylist)


open('data/level.txt', 'r') 문장은 data폴더의 level.txt 파일을 읽기모드로 연다. 그 결과 level에는 level.txt 파일 내용이 들어가 있다. for 문을 통해 각 라인에 있는 문자를 하나씩 하나씩 읽어 들인다. F라는 문자가 보이면 exec 함수를 이용하여 펜스 클래스의 오브젝트를 생성한다. 그리고 여기에 blockx, blocky 변수를 이용하여 펜스의 x,y 위치를 넣어준다. 두 번째 exec 문장은 개발자가 게임을 만들다 말았다는 것을 보여준다. scenerylist에 펜스뿐만 아니라 다른 장애물도 넣으려 한 것으로 보인다. 하지만 장애물은 펜스밖에 없다. 펜스 클래스에서 초기화할 때 자신을 펜스 리스트에도 넣어주므로 사실은 필요 없는 문장.

 

또한 읽은 문자가 F가 아니더라도 blockx 즉 오브젝트의 위치는 64씩 증가한다. F가 아닌 문자에 대해서는 아무 처리도 안했으므로 오브젝트가 생성되지 않은 상태로 blockx 가 증가한다. 공백도 문자임에 유의하자.

 

펜스를 다 읽은 후 assign_image 함수로 적절한 이미지를 할당하는 것도 확인하자.

 

그 외 부분은 이전 강의에서 언급한 내용이므로 충분히 이해할 수 있을 것이다. 여기서 펜스를 화면에 그리는 부분은 설명하지 않았는데 어디에 어떻게 펜스 그리는 코드를 넣어야할지 생각해보자. 첨부한 코드에 답이 있다.

 

덧 : 이 코드에는 에러 처리하는 부분이 없다. 이 게임은 640x640 해상도의 게임이고 하나의 타일은 64x64픽셀이므로 맵데이터가 10x10개의 텍스트가 아니면 화면을 다 못채우거나 화면 밖으로 그려질 수도 있다. 다른 사람들에게 게임을 공개하려면 이런 경우의 에러 처리가 있어야 한다.

 

 

 

 

 

 

 

 

 

 

 

?
  • ?
    큰돼지 2014.04.30 13:47
    팬스 종류 총 16개 중에 안쓰는게 많네요.
    게임 만들다가 만건가여?
  • ?
    큰돼지 2014.04.30 15:48
    올ㄷㄷㄷ 충돌 함수 어려워요
  • profile
    MoA 2014.04.30 15:17

    그런거지.
    맵 데이터 바꾸면 다른 모양이 나오긴 할거야.

  • ?
    큰돼지 2014.04.30 18:39
    오 펜스 완전 신기하네여 ㄷㄷㄷ
    level.txt 바꾸니까 알아서 그려주네요 ㄷㄷㄷ
  • ?
    큰돼지 2014.04.30 18:39
    개신기

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
공지 Tool/etc Programming 게시판 관련 2 MoA 2014.11.01 5311
288 API/MFC 후킹 링크 MoA 2013.07.28 1498
287 Python 화면 캡쳐 소스 MoA 2014.01.14 1382
286 API/MFC 프린터 출력하기 MoA 2013.10.16 4404
285 API/MFC 프로세스 - 생성과 종료 그리고 이것 저것 너울 2011.10.12 2175
284 API/MFC 프로그램 배포용으로 만드는 과정 너울 2012.01.20 1612
283 Site 프로그래밍 관련 사이트 MoA 2012.08.02 641
282 C/C++ 파일 입출력 MoA 2013.07.28 1177
281 Python 파이썬에서 C모듈 사용하기 MoA 2014.02.10 2544
280 Deeplearning 파이썬 머신러닝 무료 강의 (7시간) OBG 2022.07.06 460
279 Site 특정 자료형의 데이터를 binary(hex값, 2진수값)으로 변환 Naya 2012.11.15 1112
278 Tool/etc 텍스트 에디터 Sublime Text 2 너울 2012.03.30 1134
277 API/MFC 태스크 대화상자 (Task Dialog) MoA 2013.10.22 998
276 Algorithm 큰 수 구하기 알고리즘 Naya 2012.08.02 1320
275 Tool/etc 쿠버네티스 클러스터 OBG 2022.11.11 1113
274 C/C++ 코드 실행 시간 계산 Naya 2012.08.02 743
273 C/C++ 코드 실행 시간 계산 Naya 2012.09.27 1261
272 Tool/etc 컨텍스트 스위칭 (Context Switching) MoA 2013.07.28 1799
271 Web 카카오톡 웹버전 만들기 OBG 2022.11.09 754
270 Deeplearning 추천(Recommendation) 시스템 - 알고리즘 Trend 정리 OBG 2021.08.03 734
269 Deeplearning 추천 시스템 OBG 2023.03.30 934
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 15 Next
/ 15