파이썬-파이게임 제로 (순한맛)
매운맛으로 공부하기Mu에디터 커스텀 버전 다운로드Mu에디터 한글화 프로젝트 참여책관련 Q&A
  • 게임제작하며 프로젝트 기반으로 파이썬 배우기 (순한맛)
  • 1. 파이게임 제로(pygame zero) 라이브러리
  • 2. 개발환경 구축
  • 3. Hello World 프로그램에서 시작하자
  • 4. 게임 루프의 이해
  • 5. 플래피 버드(Flappy bird) 게임 만들기
    • 5.1 화면에 배경 이미지(오브젝트) 나타내기
    • 5.2 화면에 플래피버드(오브젝트) 나타내기와 움직이기
    • 5.3 화면에 플래피버드(오브젝트)의 자연스러운 움직임 만들기
    • 5.4 화면에 파이프(오브젝트) 나타내기와 움직이기
    • 5.5 플래피버드와 파이프의 충돌 구현하기
    • 5.6 플래피버드 게임 추가기능 구현하기 (점수기능)
    • 5.7 플래피버드 게임 추가기능 구현하기 (파이프 위치 랜덤화)
    • 5.8 플래피버드 게임 추가기능 구현하기 (플래피버드 애니메이션)
  • 6. 블록격파(Breakout) 게임만들기
    • 6.1 게임무대에 배경과 배우 등장시키기
    • 6.2 배우들의 움직임 구현하기
    • 6.3 공의 반사와 블록격파 구현하기
    • 6.4 충돌검사시 고려할 것들
    • 6.5 (보너스) 오리지널 게임처럼 만들어 보기
  • 7. 트윈비(TwinBee) 슈팅게임 만들기
    • 7.1 스크롤 배경객체 만들기, 배경음, 배우(적, 주인공) 등장시키기
    • 7.2 배우들의 움직임과 총알 공격 구현하기
    • 7.3 충돌처리 및 기타정보(점수 및 게임종료) 표기
    • 7.4 그 밖에 도전과제
  • 8. 퐁(Pong) 게임 만들기
    • 8.1 절차지향으로 개발하기 1
    • 8.2 절차지향형으로 개발하기 2
    • 8.3 객체지향 개발이론 (객제지향 디자인이란)
    • 8.4 객체지향 개발이론 (사용자 정의 객체 만들기, 상속)
    • 8.5 객체지향으로 개발하기 1
    • 8.6 객체지향으로 개발하기 2
    • 8.7 (보너스) 파이게임제로 예제버전 1
    • 8.8 (보너스) 파이게임제로 예제버전 2
  • 9. 배틀 시티(Battle city) 게임 만들기
    • 9.1 절차지향형으로 개발하기 1
    • 9.2 절차지향형으로 개발하기 2
    • 9.3 객체지향으로 개발하기 1
    • 9.5 객체지향 개발이론 (인터페이스)
    • 9.6 객체지향으로 개발하기 2
    • 9.7 객체지향으로 개발하기 3
    • 9.8 객체지향으로 개발하기 4
  • 10. 퐁(Pong)을 네트워크 게임으로 만들기
    • 10.1 네트워크 게임방식의 이해와 라이브러리 설치
    • 10.2 릴레이 서버 구동과 클라이언트 접속
    • 10.3 네트워크 게임으로 만들기 1
    • 10.4 네트워크 게임으로 만들기 2
  • 부록
    • 게임을 단 한 개의 실행파일로 패키징 하기
    • 뮤 에디터 단축키 모음
Powered by GitBook
On this page

Was this helpful?

  1. 5. 플래피 버드(Flappy bird) 게임 만들기

5.3 화면에 플래피버드(오브젝트)의 자연스러운 움직임 만들기

우리 눈에 플래피버드의 움직임이 자연스럽지 않았던 건 자연에 존재하는 실제 물리법칙 즉 중력과 유사하게 만들지 않았기 때문이다라고도 할 수도 있다. 그래서, 움직임을 실제 중력과 유사하게 구현해 보도록 하자. 우리가 아는 상식에서의 중력은 고정된 일정한 힘이며, 중력에 의해서 물체가 낙하할 때, 물체는 일정한 속도로 낙하하는게 아니라, 가속도가 붙어서 떨어질 때는 점점더 빠르게 떨어진다는 것이다. 따라서 우리도 이 두 가지(중력과 떨어지는 속도)를 두 가지 변수를 사용해 분리하자.

TITLE = 'Flappy Bird'
WIDTH = 400
HEIGHT = 708

GRAVITY = 0.3
drop_speed = 0

flappy_bird = Actor('bird1', (75, 350))

def draw():
    screen.blit('background', (0, 0))
    flappy_bird.draw()

def update():
    global drop_speed
    drop_speed += GRAVITY
    flappy_bird.y += drop_speed

def on_mouse_down():
    global drop_speed
    drop_speed = -6.5

이처럼 drop_speed 값의 사용처는 update 함수와 on_mouse_down 함수 두 곳에서 함께 사용되고 있다는 것을 알 수 있고, 이러한 이유 때문에 해당 변수는 함수들 바깥쪽 영역에 정의되었다. 이 변수를 사용하는 함수에서의 활용을 유심히 살펴 본다면, 함수 밖에 있는 변수이고 함수 안쪽에서 그 값을 수정하려면 변수명 앞에 global 이라는 키워드(keyword)를 붙혀 함수 도입부분에서 변수명을 선언해야 하는 파이썬 문법이 존재하는 것을 발견할 수 있을 것이다. 그렇다. 파이썬 문법에서는 함수 밖에 존재하는 변수를 활용하고 있다는 의미를 명확하게 하기 위해 변수명 앞에 global(말 그대로 코드전체에서 사용가능한 변수의 의미로)를 붙히게 되어있다는 것을 기억하자. 이러한 변수들을 지칭하는 용어도 global 변수라고 불린다는 것도 함께 기억하자.

참고로 여기서 주의할 것이 있는데 파이썬이 갖는 엄밀히 문법을 따지지 않는 유연성이 장점이면서 동시에 때론 단점인데, 때로는 global 이라는 키워드를 명확히 쓰지 않았음에도 불구하고 실행시 에러없이 잘 실행되기때문에 이 경우, 왜 원하는데로 동작하지 않는지의 논리적 오류를 발견하기가 쉽지 않은 상황은 만날 수도 있으니 주의하도록 하자.

지금까지 플래피버드의 자연스러운 움직임을 만들기 위한 테크닉 적용에 대해 살펴보았고, 이를 통해 새로운 것들(파이썬 문법, 코딩관습 등)을 배울 수 있었다. 이제 다음장에서는 우리 게임무대의 두번째 Actor(배우)인 파이프 객체들을 생성하고 출현시켜 보자.

Previous5.2 화면에 플래피버드(오브젝트) 나타내기와 움직이기Next5.4 화면에 파이프(오브젝트) 나타내기와 움직이기

Last updated 6 months ago

Was this helpful?

위에서 언급한 것처럼 자연스럽게 나는 모습을 구현하기 위해서는 몇 가지 추가적인 변수를 도입할 필요가 있다. 플래피버드가 자연낙하하게 하는 중력(아래방향으로 당기는 힘)이라는 변하지 않는 고정된 힘의 크기를 5번 라인에서 GRAVITY 라는 변수명과 함께 그 크기를 0.3이라고 정했다. 여기서 중력의 힘의 크기를 일부러 변수를 담아놓아다는 것에 주목하자. 이렇게 하는 의도는 앞으로 해당 값은 변수이름을 통해서 읽어 오겠다는 것이다. 이런 식의 테크닉을 구사하는데는 두 가지 목적이 있다.

첫째, 중력힘의 값을 변수명이 아닌 숫자값 그대로 사용했다고 하면, 당장은 몰라도 시간이 지나 나중에 나 자신 또는 내 코드를 읽게 되는 다른 동료의 코드 가독성(해독성)을 떨어뜨리게 된다. 코드를 해독하기 위해 눈으로 한 라인 한 라인 읽어나가다가 갑자기 등장한 숫자(0.3)을 보고, 그 숫자값은 도데체 어떤 값을 의미하는 숫자인지 잠시 고민하는 시간이 필요하고, 이렇게 한눈에 한번에 빠르게 읽어나가지 못하고 멈추게 하는 그 지점이 바로 가독성을 떨어뜨리는 지점인 것이다. 그런데, 우리가 이런 식으로 그 숫자값을 중력이라는 의미를 부여한 변수이름(GRAVITY)과 매칭해 놓았다면, 우리는 변수이름만 보고() 곧바로, 그 숫자값의 의미를 파악할 수 있다. 또 의도적으로 변수이름을 대문자로 표현한 것도 특징인데, 물론 변수가 변화하는 값을 저장하는 기본적인 목적이 있으나, 이 경우는 그러한 목적보다는 특정값을 대치하는 용도로서의 용도가 더 크기 때문에 그 의미를 부여하기 위해 대문자 표기를 하였다. 참고로 이는 일종의 프로그래머들 사이의 관습적 표현()이므로 적극 활용하면 좋을 것이다.

둘째 이렇게 할 경우, 또다른 장점은 무엇이 있을까? 나중에 어떤 이유에 의해서(에서 언급했지만, 소프트웨어 특성상 생각보다 자주 코드수정이 빈번하고) 우리 게임에 새로운 요구사항이 와서 게임의 난이도를 높이기 위해 더 센 중력의 힘을 요구한다고 하자 그리고, 우리는 이에 맞춰 전반적인 코드의 재수정이 필요하다. 우리는 이미 똑똑하게 이러한 가능성을 대비해 해당 값을 변수명을 통해 코딩해 놓았지 않는가? 따라서, 이 값(GRAVITY)의 현재 값인 0.3을 예를들어 0.5으로만 바꿈으로써 이러한 코드 수정 요구사항의 빠른 대응이 가능하게 되는 것이다.

6번 라인에 도입한 drop_speed 변수는 말 그대로 값이 계속 변화하는 값이 적용되는 변수로서의 용도이기 때문에 의도적으로 소문자로만 변수명을 적었다는 것을 기억하자. 이렇게 대문자/소문자의 구분표기만으로도 그 용도가 쉽게 들어나는 용이성이 있다. drop_speed 라는 이름을 부여한 것에서 알 수 있듯이, 낙하를 만드는 힘(중력)은 고정된 것이나 실제 낙하할 때 속도는 시간이 지남에 따라 가속도가 붙어 더 빠른 속도로 증가하게 되고, 이를 표현한 값인 것이다. 해당 변수의 목적과 용도는 이해했다. 자 그런데 이번엔 전체 코드영역에서 이 변수의 정의(definition)가 어디에 위치하고 있느냐에 관한 것으로 왜 함수 안쪽 영역(scope)에 존재하지 않고, 함수 바깥쪽 영역에 존재해야 하는가에 대해 알아볼 필요가 있다. 이는 변수를 만드는 규칙에 관한 것으로, 특정 함수 안에서만 사용되는 변수는 해당 함수 안쪽에서 정의하고, 여러 함수에 걸쳐 공통으로 함께 사용해야 하는 변수는 이처럼 함수들 바깥쪽 영역에 정의하게 된다.

21번 라인에서 사용자가 마우스버튼을 눌러 플래피버드를 부상하려고 할 때, 낙하하는 속도를 의도적으로 음수값을 통해 뒤로 되돌림으로써 플래피버드가 상승하는 효과를 만들고 있다.

🔢
🔢
🔢
Conding conventions
이전 서에서 언급했지만, 그래서 변수이름을 의미있 잘 짓는 것이 중요!
이전 서