파이썬-파이게임 제로 (순한맛)
매운맛으로 공부하기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. 7. 트윈비(TwinBee) 슈팅게임 만들기

7.2 배우들의 움직임과 총알 공격 구현하기

이번 절부터는 이전 절에서 전체적인 구조적 윤곽을 잡으면서 구현체 없이 빈 함수로 만들어 두었던 각 함수들의 구현체를 채우도록 하겠다.

제일 첫번째로 move_player 함수다. 기존 게임들에서는 마우스로만 조작했던 게임이라 키보드 조작에 대해서는 처음 등장하고 있다. 파이게임제로의 편리한 점은 키보드 조작에 대해 on_key_down 콜백함수를 꼭 쓰지 않더라도, update 콜백함수 안에서 특정 키보드의 키들(예를들어 방향키)에 대해 사전 정의된 변수들(예를 들어, keyboard. up/down/left/right 등)을 통해 키의 눌림을 검사할 수 있다는 것이다. 각 방향키의 눌림에 따라 5픽셀 값 만큼의 이동을 만든다. 주인공 비행기는 전후좌우 사방으로 이동이 가능하나 단, 주어진 화면을 넘어서까지의 이동은 막도록 경계를 두는게 필요하다(10~17라인). 이제 이정도 수준의 코딩은 이미 이전 게임들에서 많이 해봤기 때문에 이해나 구현에는 큰 어려움이 없을 것이다.

def move_player():
    if keyboard.right:
        player.x += 5
    if keyboard.left:
        player.x -= 5
    if keyboard.up:
        player.y -= 5
    if keyboard.down:
        player.y += 5
    if player.right > WIDTH:
        player.right = WIDTH
    if player.left < 0:
        player.left = 0
    if player.bottom > HEIGHT:
        player.bottom = HEIGHT
    if player.top < 0:
        player.top = 0

그 다음, 주인공이 총알발사는 부분인 shoot_bullets 함수를 구현하자. 먼저, 기억해야 할 것은 총알도 크기가 작고 사소해 보여도 총알 한개한개가 다 객체라는 것이다. 사용자가 스페이스바를 눌러 총알을 발생할 때 발생할 수 있는 모든 일련의 작업순서를 생각해보면, 먼저는 총알 발사효과음 내고(3번 라인), 총알 객체를 생성하되(5번 라인), 그 총알의 발사 최초위치는 주인공 비행기에서부터 시작되야 하고(6번 라인), 총날이 날아가야 하는 방향의 각도는 상단전방이다(7번 라인). 총알이 15픽셀씩 이동해 날아가되(10-11라인), 만약, 날아가던 총알이 화면상단 밖으로 넘어가면, 그 총알은 더 이상의 존재의미가 없기 때문에 계속 메모리에 자리를 차지하면서 메모리를 고갈시키지 않도록(참고로 메모리가 full로 다 차면, 프로그램이 갑자기 강제종료될 수 있음) 그런 총알객체는 메모리에서 제거시킨다(12-13번 라인). 메모리에서 제거시키다는 것이 결국 총알객체를 모아놓은 모음인 bullets 리스트 객체 안에서 해당 총알객체를 삭제한다는 것이고, 이를 위해서 리스트 내장메소드 중에 remove 메소드를 사용하면 편리하다(13번 라인).

1회 발사되는 총알개수를 MAX_BULLETS 으로 왜 제약하는지에 궁금할텐데, 그 총알개수 최대값을 검사하는 코드를 제거하고 게임을 실행시켜 보면 왜 그게 필요한지 단번에 이해할게 될 것이다. 우리는 스페이스 바를 아주 잠깐 1회 누른다고 생각하지만, 사실은 update 콜백함수가 초당 60번이나 실행되는(60 FPS) 엄청나게 빠른 속도로 반복해서 불리기 때문에, 스페이스 바가 계속 눌린 상태로 인식되어 생성 총알개수가 순식간에 늘어나 수많은 총알이 한번에 날아가는 것을 볼 수 있다. 이러한 현상은 우리가 적들에게서 지나친 공격적 우위를 점하게 되고, 이는 게임의 난이도를 너무 쉽게 만들어 게임의 재미를 반감시키기 때문에, 게임성을 위해서는 1회 발사되는 총알량을 어느 정도 제한하는 것이 필요하다.

def shoot_bullets():
    if keyboard.space and len(bullets) < MAX_BULLETS:
        sounds.sfx_sounds_interaction25.play()
        bullet = Actor("player_bullet")
        bullet.pos = player.pos
        bullet.angle = 90
        bullets.append(bullet)

    for bullet in bullets:
        bullet.move_forward(15)
        if bullet.y < 0:
            bullets.remove(bullet)

파이게임제로에서 Actor객체의 angle 속성값을 설정할 때의 각도와 direction 속성값을 설정할 때의 각도는 동일한 의미를 갖기 때문에 코드에서 random.randint(-100, -80) 의 의미는 화면 정하단방향(-90도) 주변으로 10도씩 약간의 랜덤한 움직임을 주려는 목적인 것이다.

def create_enemies():
    if random.randint(0, 1000) > 980:
        enemy = Actor("enemy1_1")
        enemy.images = ["enemy1_1", "enemy1_2"]
        enemy.fps = 5
        enemy.y = -50
        enemy.x = random.randint(100, WIDTH - 100)
        enemy.direction = random.randint(-100, -80)
        enemies.append(enemy)

    for enemy in enemies:
        enemy.move_in_direction(4)
        enemy.animate()
        if enemy.top > HEIGHT:
            enemies.remove(enemy)
        if random.randint(0, 1000) > 990:
            bullet = Actor("enemy_bullet")
            bullet.pos = enemy.pos
            bullet.angle = random.randint(0, 359)
            enemy_bullets.append(bullet)

    for bullet in enemy_bullets:
        bullet.move_forward(5)
        if bullet.x < 0 or bullet.x > WIDTH or bullet.y < 0 or bullet.y > HEIGHT:
            enemy_bullets.remove(bullet)
Previous7.1 스크롤 배경객체 만들기, 배경음, 배우(적, 주인공) 등장시키기Next7.3 충돌처리 및 기타정보(점수 및 게임종료) 표기

Last updated 6 months ago

Was this helpful?

6번 라인에서 등장한 angle 속성값은 우리가 에서 이미 익혔던 내용으로, 90도 값을 설정한 것은 화면 상단방향으로 총알이 움직이게 하려는 목적이다. 만약, 를 거쳐오지 않은 독자가 있을 수 있어 아래에 angle 값의 의미에 대한 추가 설명 이미지를 첨부한다.

그 다음으로는 적 비행기들을 출현시켜는 함수는 create_enemies 를 구현해보자. 적 비행기가 출연하고 이후 공격을 위해 총알을 쏘는 모든 일련의 작업순서를 생각해보면, 먼저는 적 비행기는 눈에 보이지 않는 화면 상단에서(6번 라인) 랜덤하게 생성해(7번 라인) 화면 아래방향으로 랜덤하게(8번 라인) 날아가도록 해야할 것이다(12번 라인). 8번 라인에서 에서 우리가 이미 익혔던 angle과 거의 유사하나 개념이 조금 다른 direction 이라는 속성값이 등장했는데, 엔트리 블록코딩 거쳐온 독자라면 이미 익숙할텐데 엔트리에 방향/이동방향이란 두 가지 값이 존재했었고, 두 값의 차이는 실제 오브젝트 자체를 회전시키느냐와 오브젝트 자체에 대한 회전이 아닌 오브젝트가 움직일 때의 그 움직임의 방향만 바꾸냐의 차이가 존재했다. 여기서 direction은 후자의 경우이다.

적 비행기가 날아갈 때, 애니메이션을 가미하여(4번, 13번 라인) 게임성을 더했다는 것도 기억해두자. 파이게임제로에서 Actor객체의 애니메이션을 만드는 법에 대해선에서 이미 학습했기 때문에 자세한 설명은 하지 않겠고, 추가 학습이 필요한 분은 이전 서의 내용을 참조하면 좋겠다. 적 비행기는 가만히 날아가는 것이 아니고, 날아가면서 총알공격을 하기 때문에 이 부분을 구현해야 하며, 쏜 총알이 날아가는 방향은 360도 전방위로 랜덤하게(19번 라인), 5픽셀 속도로 날아가게(23번 라인) 하였다. 그밖에 적 비행기든 총알이든 화면 밖을 빠져나가게 되면, 메모리에서 제거하는 코드는 여전히 항상 필요하다 하겠다(14-15번 라인, 24-25번 라인).

나머지 2개 함수(check_collision, draw_text)에 대해서는 다음 절에서 계속 설명을 이어나가도록 하겠다. 만약, 공부하다가 코드에 대한 추가적인 문의가 생긴다면, 함께 을 준비해 두었으니 언제든 그곳을 통해 의문점을 함께 해결해 나갈 수 있다는 것을 기억하자.

소통할 채널
이전 서
이전 서
이전 서
이전 서