Raspberry Pi_Kor_23.5.5 Game을 통한 Python 학습


Published Book on Amazon


All of IOT Starting with the Latest Raspberry Pi from Beginner to Advanced – Volume 1
All of IOT Starting with the Latest Raspberry Pi from Beginner to Advanced – Volume 2


출판된 한글판 도서


최신 라즈베리파이(Raspberry Pi)로 시작하는 사물인터넷(IOT)의 모든 것 – 초보에서 고급까지 (상)
최신 라즈베리파이(Raspberry Pi)로 시작하는 사물인터넷(IOT)의 모든 것 – 초보에서 고급까지 (하)


Original Book Contents


23.5.5  Game을 통한 Python 학습

 

Raspberry Pi 시스템에서는 여러 가지 종류의 게임을 기본으로 제공하고 있다. Raspberry Pi 시스템에서 게임을 제공하는 것은 사용자들이 Raspberry Pi 시스템로 단순히 게임을 즐기는 것 이외에 사용자들을 위한 또 다른 목적을 가지고 있다.

 

Raspberry Pi 시스템에서 게임을 제공하는 것은 게임을 통하여 Python 프로그램을 작성할 수 있는 능력을 키울 수 있는 방법을 제공하는 것에 목적을 두고 있다. 이를 위해 각 게임에 대해서 사용자들이 Python로 게임과 상호 작용을 해 볼 수 있고, 사용자들이 게임 프로그램 source code 내용을 마음대로 수정해서 실행해 볼 수 있는 환경을 제공해 주고 있다.      

 

Python 학습에 사용할 수 있는 game은 다음과 같다.

    Minecraft

    Python Games

 

23.5.5.1    Python Games

 

window 환경에서 Applications Menu MenuàGames을 보면 [Python Games] 메뉴가 있다. 여기서는 Python으로 개발한 많은 게임들을 실행해 볼 수 있고, 동시에 이들에 대한 프로그램 source code를 확인할 수 있으며, 그것들을 사용자가 원하는 대로 수정하여 실행해 볼 수도 있다.


 

 

 


해당 프로그램을 실행하면, 먼저 아래와 같은 확인 화면이 나타난다. 이 화면에서는 소리를 HDMI로 보낼 것인지, 헤드폰으로 보낼 것인지를 결정하는 오디오 설정에 대한 선택을 할 수 있다. 여기서 원하는 항목을 선택하고 [OK] 버튼을 누른다.

 

 

다음으로 실행할 게임 목록을 보여주는 화면이 나타난다. 게임 목록에서 원하는 게임을 선택하고 [OK] 버튼을 누르면 해당 게임이 실행된다


그림 23‑10 Python Games

 

사용자들은 자유롭게 게임을 즐길 수 있다. 여기서 제공되는 모든 게임에 대해서는 프로그램 source code가 제공된다. "/home/pi/python_games" 폴더를 보면 해당 source 코드와 관련 파일들이 있음을 확인할 수 있다.


 


아래는 "Flippy" 게임에 대한 source코드를 Python IDLE를 통해서 조회한 것이다. 사용자들은 게임의 source code가 어떻게 되어 있는지를 학습할 수 있다. 필요하면 해당 source code를 복사한 다음, 내용을 수정하여 실행해 볼 수도 있다. 필요하면 GPIO와 상호작용을 하도록 하거나, 게임이 종료됬을 때 외부 전등이 켜지도록 프로그램을 수정할 수도 있다.

 

 


 

23.5.5.2    Minecraft PI

 

window 환경에서 Applications Menu Menu àGames을 보면 [Minecraft Pi] 메뉴가 있다. 여기서 Raspberry Pi version Minecraft 게임을 즐길 수 있다. Minecraft는 인기가 많은 sandbox open world-building game이다. 사용자들은 이 게임에서 Python code로 명령을 내리거나 간단한 script를 작성하여 게임 내용을 수정하여 즐기면서 Python을 쉽게 배울 수 있다.

 

우리는 여기서 게임을 하는 방법을 설명하고자 하는 것이 아니다. Python을 이용해서 게임을 조정해 보면서 Python이 어떻게 사용되는지를 설명하는 것이 우리의 목적이다.


 


메뉴에서 프로그램을 실행하면 아래와 같은 화면이 나타난다. 참고사항은 Remote 접속에서는 프로그램이 실행되지 않는다는 것이다. Start Game은 혼자서 하는 게임이고, Join Game은 네트워크 상에서 여러 사람이 같이 하는 게임이다.

그림 23‑11 Minecraft 시작

 

Start Game으로 게임을 실행하면 다음과 같은 화면으로 게임을 시작한다. Minecraft가 실행되고 world가 생성되고 나면, Tab 버튼을 눌러 게임 내에서 focus를 다른 곳으로 옮겨서 마우스를 자유롭게 한다.


 

 

    Remote connection 환경에서의 Minecraft 프로그램 실행

 

주의할 점은 Remote 접속에서는 Minecraft 프로그램이 정상적으로 실행되지 않는 경우가 있다는 것이다. 인터넷에서 여러 곳에서 관련 자료를 찾아 보니, remote 접속 프로그램이  "directly rendered overlay" 기능을 지원하지 않기 때문이라고 한다.

 

최근에 원격 접속 프로그램 <RealVNC>에서 이런 기능을 지원하는 version을 발표하였으니, 필요하면 해당 프로그램을 이용할 수 있다.  


 

   Program Interface를 위한 Python Shell window 실행

 

이제 Minecraft 게임에 연결하여 게임을 조정하기 위해서 Python 프로그램을 시작한다. 아래와 같이 [Menu]에서 Python 3 (IDLE 3)를 이용하여 Python window를 시작한다.

Python 2 in applications menu

 

여러분은 Python Shell window에서 명령을 하나씩 입력하여 곧바로 실행해 볼 수도 있다. 또한 메뉴 File à New window를 이용하여 새로운 화면을 열어서 빈 화면에 전체 내용을 한꺼번에 입력하여 실행하거나, 파일로 저장하여 다음에 다시 사용할 수도 있다


 


 

   Python Minecraft 게임의 연결

 

Python Minecraft를 서로 연결하기 위해서 처음 할 일은 Minecraft library Python으로import하여 게임과 연결하고, 연결상태를 확인하는 것이다. 다음 작업을 한다.

 

from mcpi import minecraft

mc = minecraft.Minecraft.create()

mc.postToChat("Hello world")

 

아래는 Python Shell window에서 위의 명령을 실행한 것이다.


 

아래와 같이 화면에 "Hello world"라는 메시지가 화면에 표시되면 정상 처리된 상태이다.

 

Minecraft Pi with IDLE

   현재 위치 확인

 

현재 위치를 확인하기 위해서 다음 명령을 수행한다.

 

pos = mc.player.getPos()

 

변수 "pos"은 현재 위치 정보를 가지고 있다. "pos.x", "pos.y", "pos.z"를 이용하여 좌표 정보를 알 수 있다.

 

위와는 다르게 좌표를 별도의 변수에 저장하는 좋은 방법은 아래와 같이 Python unpacking 기법을 사용하는 것이다.

 

x, y, z = mc.player.getPos()

 

이제 변수 "x", "y", "z"는 각각 player의 위치에 대한 좌표를 가지고 있다. 변수 "x" "z"는 도보방향(/뒤와 좌/)이고 "y" up/down 방향이다. "getPos()" 함수는 그 시점의 player의 위치정보를 알려 준다는 것에 주의하라만약 위치를 옮겼다면, 새로운 위치에 대한 정보는 함수를 다시 실행해야 알 수 있다.  

 

 

   공중 부양

 

여러분은 현재 위치를 파악할 수 있을 뿐만 아니라 공중 부양할 특정 위치를 지정할 수도 있다.

 

x, y, z = mc.player.getPos()

mc.player.setPos(x, y+100, z)

 

이 문장은 player를 공중에서 "100 space" 지점으로 이동시킨다. 이것은 여러분들이 하늘로 공중 부양했다가, 다시 출발지점으로 추락하는 것을 의미한다. 이제 다른 곳으로 공중부양을 해 보기 바란다.

 


 

   단일 block 설정

 

여러분은 mc.setBlock() 함수를 이용하여 일정한 좌표 집합에 block 하나를 설정할 수 있다.

 

x, y, z = mc.player.getPos()

mc.setBlock(x+1, y, z, 1)

 


이제 여러분이 서 있는 곳 옆에 "stone" block이 나타난다. 그것이 여러분 앞에 있지 않으면, 옆이나 뒤에 있을 수도 있다. Minecraft window로 돌아가서, 여러분 앞에 회색 block이 보일 때까지 마우스로 그 장소를 여기저기 돌아다녀 보도록 한다.

 

 

"setBlock" 함수에 전달되는 인수는 "x", "y", "z" "id"이다. "x", "y", "z" world에서의 위치 (우리는 "x+1"을 이용해서 player가 있는 곳에서부터 1 block 떨어진 곳을 지정했다)를 가리키고, "id"는 만들고자 하는 block의 유형을 가리키는데, "1" 값은 "stone"을 의미한다. 아래의 다른 block도 시도해 보기 바란다.

    Air             -- 0

    Stone          -- 1

    Grass          -- 2

    Dirt            -- 3


 

이제 나타난 block을 이용해서 그것을 다른 것으로 변경해 보자.

 

mc.setBlock(x+1, y, z, 2)

 

여러분들은 이제 회색 "stone" block이 여러분 눈앞에서 변경되는 것을 볼 수 있다.


 

 

   Block을 변수(variable)로 저장

 

변수(variable) "id"를 저장하면 코드를 더 읽기 쉽게 만들 수 있다."id" block을 사용하여 설정할 수 있고, 이미 "id"에 대한 값을 알고 있다면, 직접 지정할 수도 있다.

 

dirt = block.DIRT.id

mc.setBlock(x, y, z, dirt)

 

dirt = 3

mc.setBlock(x, y, z, dirt)

 


 

   특수 block

 

색상을 지정하기 위한 추가 설정항목이 있는 "wool"처럼 별도의 특성을 가진 block들이 있다. 이러한 것을 설정하기 위해서는 "setBlock()" 함수에서 네 번째의 선택적 parameter를 사용할 수 있다.

 

wool = 35

mc.setBlock(x, y, z, wool, 1)

 

여기서 네 번째 parameter "1" "wool"의 색상을 오렌지색으로 바꿔준다. 네 번째 parameter가 없다면, 그 값은 default zero(0)로 설정되는데, 이것은 흰색을 의미한다. 다음은 다른 색상에 대한 값이다.

    1    -- White

    2    -- Magenta

    3    -- Light Blue

    4    -- Yellow

 

다른 숫자를 사용하여 block이 어떻게 변하는지 시도해 보자. 추가 특성을 가지고 있는 다른 block으로는 다음과 같은 것이 있다. 상세한 내용에 대해서는 API reference를 참조하기 바란다.

    wood         -- 17     -- oak, spruce, birch

    tall grass     -- 31     -- shrub, grass, fern

    torch          -- 50     -- east, west, north, south

 


 

   복수 block 설정

 

"setBlock" 함수로 block 하나를 설정할 수 있지만, "setBlocks" 함수를 이용하면 한번에 일정 공간에 block으로 채울 수도 있다.

 

stone = 1

x, y, z = mc.player.getPos()

mc.setBlocks(x+1, y+1, z+1, x+11, y+11, z+11, stone)

 

code 10 x 10 x 10 정육면체 형태의 단단한 stone으로 block을 만들게 된다. "setBlocks" function으로 더 큰 block을 만들 수도 있지만, 그러면 더 많은 시간이 걸릴 것이다.


 


 

   걸어 가면서 block 떨어 뜨리기

 

다음 code는 여러분이 걸어 갈 때 여러분 뒤로 꽃을 떨어 뜨리게 할 것이다.

 

from mcpi import minecraft

from time import sleep

 

mc = minecraft.Minecraft.create()

 

flower = 38

 

while True:

    x, y, z = mc.player.getPos()

    mc.setBlock(x, y, z, flower)

    sleep(0.1)

 

이제 잠시 앞으로 걸어가고, 뒤돌아 가면서 뒤에 꽃이 있는지 확인해 보기 바란다. 우리는 while True loop를 사용했기 때문에 이 동작은 영원히 계속될 것이다. 멈추기 위해서는 Python window에서 Ctrl + C를 누른다.


 

 

 

 

 

 

 

 

공중으로 비행해 보고 공중에 꽃이 뿌려지는지 확인해 보기 바란다.


 

우리가 "grass" 위에서 걸을 때만 꽃을 뿌리기 원하면 어떻게 해야 할까? 현재 block이 어떤 유형인지를 알고 싶으면 "getBlock" 함수를 사용한다. 이것은 여러분이 서 있는 block를 알려 줄 것이다. (air block에서는 "0"이 된다).

 

x, y, z = mc.player.getPos()  # player position (x, y, z)

this_block = mc.getBlock(x, y, z)  # block ID

print(this_block)

 

우리는 우리가 서있는 block 유형을 알고 싶다. 이를 위해 "y" 값에서 "1"을 뺀 다음, "getBlock()" 함수를 사용하면, 우리가 서 있는 block의 유형을 결정할 수 있다.

 

x, y, z = mc.player.getpos()  # player position (x, y, z)

block_beneath = mc.getBlock(x, y-1, z)  # block ID

print(block_beneath)

 

위 문장은 우리가 서 있는 block ID를 알려 준다. loop 문을 사용하여 우리가 서 있는 block ID를 계속 인쇄하여 테스트 해보기 바란다

 

while True:

    x, y, z = mc.player.getPos()

    block_beneath = mc.getBlock(x, y-1, z)

    print(block_beneath)


 

현재 우리가 꽃을 심을 곳을 결정하기 위해서 "if" 문을 사용할 수 있다. 다음은 block 유형이 "grass"인 경우에만 꽃을 뿌린다.

 

grass = 2

flower = 38

 

while True:

    x, y, z = mc.player.getPos()  # player position (x, y, z)

    block_beneath = mc.getBlock(x, y-1, z)  # block ID

 

    if block_beneath == grass:

        mc.setBlock(x, y, z, flower)

    sleep(0.1)

 

다음은 우리가 서 있는 block "grass"가 아니면, 이것을 "grass"로 변경해 준다.  

 

if block_beneath == grass:

    mc.setBlock(x, y, z, flower)

else:

    mc.setBlock(x, y-1, z, grass)

 


 

이제 앞으로 걸어가면서, 만약 "grass" block 위를 걷고 있다면, 우리 뒤로 꽃이 뿌려 질 것이다. 만약 현재 위치가 "grass"가 아니라면, 그 위치가 "grass"로 변경될 것이다. 우리가 돌아다니다가 나중에 되돌아 가면, 그 자리가 "grass"로 변경되어 있으므로, 이번에는 꽃이 뿌려지게 될 것이다.


 

 

 

 


 

   TNT block

 

다른 재미있는 block "TNT"이다. 정상적인 "TNT" block을 만들려면 다음 문장을 사용한다.

 

tnt = 46

mc.setBlock(x, y, z, tnt)


 

하지만 이 상태의 "TNT" block은 상당히 지루하다. 그래서 data "1"을 적용한다. 그런 다음 이제 "sword"()을 선택하고, "TNT" block을 왼쪽 마우스로 click 해 본다. 그러면 이것이 활성화되어 몇 초안에 폭발할 것이다.

 

tnt = 46

mc.setBlock(x, y, z, tnt, 1)

 


 

다음으로는 이제 커다란 육면체의 TNT blocks을 만들어 보자

 

tnt = 46

mc.setBlocks(x+1, y+1, z+1, x+11, y+11, z+11, tnt, 1)


 

이제 커다란 육면체의 "TNT" blocks이 나타난다. 계속해서 block 하나를 활성화하고, 멀리 달아나서 어떤 일이 일어나는지 지켜보자. 그러면 화면에서 많은 것들이 한꺼번에 변하기 때문에 그래픽을 렌더링하는 것이 정말 느릴 것이다.

 



   network game

 

만약 여러 사람들이 각자의 Raspberry Pi를 같은 LAN에 연결해 두었다면, 그 사람들은 동일한 Minecraft world에 참가하면서 게임을 즐길 수 있다. 각각의 player들은 Minecraft world에서 서로를 볼 수 있다.

 

 

   API reference

 

functions에 대한 더 광범위한 문서나 block ID에 대한 전체 목록을 알고 싶으면, 다음에서 API reference 자료를 참고하기 바란다.  

    http://www.stuffaboutcode.com/p/minecraft-api-reference.html

 

 

 


 

Leave a Reply