반응형

캐릭터의 충돌을 감지하고 표시해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
# pygame 세팅
 
player = pygame.image.load("player.png").convert()
player.set_colorkey(player.get_at((00)))
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
player_speed = 4
player_direction = -1
# player 세팅
 
enemy = pygame.image.load("enemy.png").convert()
enemy.set_colorkey(enemy.get_at((00)))
enemy_size = (enemy.get_width()*1.5, enemy.get_height()*1.5)
enemy = pygame.transform.scale(enemy, enemy_size)
enemy_pos = enemy.get_rect(center=(500, screen.get_height()/2))
# enemy 세팅
 
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if player_direction > 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = -1            
        player_pos.move_ip(-player_speed, 0)
    if keys[pygame.K_RIGHT]:
        if player_direction < 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = 1
        player_pos.move_ip(player_speed, 0)
 
    hitbox = player.get_rect(center=player_pos.center)
    hitbox = hitbox.inflate(-10-10)
    # 분명한 충돌 판정을 위해 player hitbox의 범위를 줄여준다.
 
    clip = None
    if hitbox.colliderect(enemy.get_rect(center=enemy_pos.center)):
        print("collide")
        clip = hitbox.clip(enemy.get_rect(center=enemy_pos.center))
        print(clip)
    # player와 enemy가 충돌하면 "collide" 메세지를 출력하고 충돌 영역은
    # clip에 저장한다.
 
    screen.fill("black")
    screen.blit(player, player_pos)
    screen.blit(enemy, enemy_pos)
    if clip is not None:
        pygame.draw.rect(screen, "blue", clip)
    # player와 enemy가 충돌한 영역이 clip에 저장되었다면 파란 사각형으로
    # 표시힌다.
 
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

player.png

 

enemy.png

 

충돌 영역이 파란 사각형으로 표시된다.

 

충돌 영역 좌표가 표시된다.

 

반응형
Posted by J-sean
:
반응형

텍스트(폰트)를 렌더링 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
font = pygame.font.Font(None48)
text = font.render("Super fun game development"True, (128128128))
#text = font.render("Sean loves game", True, "gray")
# 폰트를 지정하고 텍스트를 렌더링 한다.
 
text_pos = text.get_rect()
text_pos.centerx = screen.get_width()/2
text_pos.centery = screen.get_height()/2
#text_pos = text.get_rect(center=(screen.get_width()/2, screen.get_height()/2))
# pygame.Surface.get_rect()에 인수를 주면 인수가 적용된 영역이 반환되어 간단히
# 위치가 지정된 영역을 얻을 수 있다.
 
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
    screen.fill("black")
    screen.blit(text, text_pos)
 
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

텍스트(폰트)가 렌더링 된다.

 

반응형
Posted by J-sean
:
반응형

사운드를 로드하고 플레이 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
player = pygame.image.load("player.png").convert()
player.set_colorkey(player.get_at((00)))
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
 
sound = pygame.mixer.Sound("music.mp3")
# 사운드 리소스를 로드하고 오브젝트를 반환한다.
sound.play()
# 로드한 사운드 오브젝트를 플레이한다.
 
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
 
    screen.fill("black")
    screen.blit(player, player_pos)
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

music.mp3
4.01MB

 

로드한 사운드가 플레이 된다.

 

반응형
Posted by J-sean
:
반응형

이미지를 로드하고 출력해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
player = pygame.image.load("player.png").convert()
# 플레이어 이미지를 로드하고 디스플레이와 일치하는 color format과 depth로 변환한다.
player.set_colorkey(player.get_at((00)))
# 이미지의 (0, 0) 픽셀을 colorkey로 사용한다. (0, 0) 픽셀과 같은 색상은 투명하게
# 표시된다.
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
# 이미지를 1.5배 확대한다.
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
# 이미지의 위치를 화면 중앙으로 설정한다.
 
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
 
    screen.fill("black")
    screen.blit(player, player_pos)
    # 스크린에 이미지를 출력한다.
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

player.png

 

colorkey가 적용되어 이미지가 깔끔하게 출력된다.

 

반응형
Posted by J-sean
:
반응형

Pygame으로 게임을 개발하기 위한 기본 코드를 작성해 보자. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Example file showing a basic pygame "game loop"
# pygame 기본 셋업
import os
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'= '1'
# pygame 실행시 표시되는 메세지를 보이지 않게 한다.
# pygame을 import 하기 전에 설정해야 한다.
import pygame
 
# pygame setup
pygame.init()
pygame.display.set_caption("Super fun game development")
# 게임창 제목 표시
screen = pygame.display.set_mode((640480))
# 게임창 크기를 640X480으로 설정.
clock = pygame.time.Clock()
running = True
 
while running:
    # poll for events
    # pygame.QUIT event means the user clicked X to close your window
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
    # fill the screen with a color to wipe away anything from last frame
    screen.fill("black")
 
    # RENDER YOUR GAME HERE
    pygame.draw.circle(screen, "gray", screen.get_rect().center, 100)
    # 스크린 중앙에 회색원을 하나 그린다.
 
    # flip() the display to put your work on screen
    pygame.display.flip()
 
    clock.tick(60)  # limits FPS to 60
 
pygame.quit()
 

 

 

코드를 실행하면 검은 배경에 회색 원이 하나 표시된다.

 

PYGAME_HIDE_SUPPORT_PROMPT를 설정하지 않으면 위와 같은 메세지가 표시된다.

 

반응형
Posted by J-sean
:
반응형

레트로파이에 한글 폰트, 게임 마키, 이미지, 플레이 영상, 설명등을 넣어 보자.

 

2020/02/13 - [Raspberry Pi & Arduino] - Raspberry Pi Desktop(Debian), Ubuntu에서 RetroPie 설치하기

 

특별한 설정을 하지 않았다면 레트로파이(아케이드)에 게임 이름 정도만 표시된다. 등록된 게임을 잘 아는 사람은 문제 없겠지만 모르는 사람은 무슨 게임인지 알 수가 없다. 처음 하는 사람도 어떤 게임인지 알 수 있도록 이미지, 플레이 영상, 설명등을 넣어 보자.

 

Cabin-Bold.ttf 가 기본(영문) 폰트다. 한글이 표시 될 수 있도록 원하는 한글 폰트(KATURI.TTF)를 /etc/emulationstation/themes/carbon/art/ 에 복사한다. 

 

/etc/emulationstation/themes/carbon/ 에 있는 'carbon.xml', 'theme.xml' 파일에 설정된 폰트를 변경한다.

 

두 파일을 열고 'Cabin-Bold.ttf'가 나오는 부분을 모두 한글 폰트 이름(KATURI.TTF)으로 바꾼다. (원래 있던 'Cabin-Bold.ttf' 파일을 지우고 한글 폰트 이름을 'Cabin-Bold.ttf'로 바꾸면 두 파일의 내용을 바꾸지 않아도 된다)

 

 

RetroPie를 실행해 보면 바뀐 폰트가 적용되어 있다.

 

/opt/retropie/configs/all/emulationstation/gamelists/arcade/gamelist.xml 에 게임 이름, 이미지, 플레이 영상, 설명등을 등록 할 수 있다.

 

gamelist.xml
5.73MB

 

아래와 같은 형식으로 작성 한다.

 

<?xml version="1.0"?>

<gameList>

<game>

<path>게임 파일 경로</path>

<name>게임 이름</name>

<image>게임 이미지 파일 경로</image>

<video>게임 플레이 영상 파일 경로</video>

<marquee>게임 마키 파일 경로</marquee>

<developer>게임 제작사</developer>

<publisher>게임 판매사</publisher>

<genre>게임 장르</genre>

<players>게임 플레이어 수</players>

<releasedate>게임 발매일</releasedate>

<desc>게임 설명</desc>

</game>

<game>

...

</game>

...

</gameList>

 

'gamelist.xml'에 등록한 파일 경로 및 이름대로 marquee, snap, video 디렉토리를 /home/pi/RetroPie/roms/arcade/ 에 생성하고 각 디렉토리에 맞는 파일을 복사한다.

 

 

마키(marquee)

 

이미지(image)/스냅(snap)

 

영상(video)

 

 

예를 들어 marquee 디렉토리의 내용은 위와 같다.

 

RetroPie를 실행해 보자. ARCADE - 메탈 슬러그의 마키, 플레이 영상, 게임 설명등이 디스플레이 된다.

 

스트리트 파이터 2의 내용도 잘 디스플레이 된다.

 

반응형
Posted by J-sean
:
반응형

약 6년전, 동생이 구매했던 노트북이 있다. 삼성 NT900X3G. 지금도 간단한 문서 작업이나 인터넷, 영화 감상용으로는 부족함 없는 노트북이지만 6년이라는 시간동안 많은 일이 있었던 모양이다. 이제는 키보드의 몇몇 키가 눌리지 않고 디스플레이 힌지는 한쪽이 부서져 덜렁거린다. 그 외 컴퓨터라는 기기의 역할에 문제는 없지만 낡아버린 모습에 더 이상 애착이 가지 않았던거 같다. 창고 한쪽 구석에 쳐박혀 버리질 날만 기다리던 이 녀석을 구해 왔다. 조카들에게 괜찮은 장난감으로 바꿔주겠다는 약속을 남기고..

 

이런 스펙의 노트북이라고 한다.

 

우선 노트북 커버를 제거하고 덜렁거리는 디스플레이 및 배터리를 분리한다. 그리고 전원을 연결해 작동 여부를 테스트한다. 그 동안은 KODI를 설치해 영화감상용으로 사용했다.

 

2020/02/01 - [General] - 삼성 노트북 분해, SSD 조립 하기

 

 

영상: 라즈베리 파이 홈미디어 센터(KODI) 만들기

 

주요 부품이 있는 하판을 분리하자. (왼쪽 하단에 2014.01.21이 적혀 있다. 6년 전 구매한 노트북이라는 증거가 될 수 있지 않을까?)

 

프레임, 키보드, 터치패드등 불필요한 부분을 제거하고 작동에 필요한 부분만 남겼다. 디스플레이도 프레임을 제거하려고 했지만 액정 뒤에 붙은 백라이트가 프레임에 접착되어 있어 분리가 불가능했다.

 

 

분리한 부품들만으로 작동 테스트를 해 본다. USB 키보드를 연결하니 입력도 문제 없다. 지금은 스피커가 분리되어 있다.

 

스피커를 연결하고 영상을 플레이하니 소리도 잘 나온다.

 

오락실 게임을 설치하기 위한 소프트웨어 작업을 진행 한다.

운영체제는 라즈비안을 설치 했다. 운영체제 설치 후 레트로 파이를 설치한다.

 

2020/02/13 - [Raspberry Pi & Arduino] - Raspberry Pi Desktop(Debian), Ubuntu에서 RetroPie 설치하기

 

동네 오락실 분위기가 나려면 오락기가 있어야 한다. 진짜 오락실에 설치되어 있는 오락기 사이즈로 만들면 부담스러우므로 테이블에 올려 놓고 사용할 만한 사이즈로 디자인 한다.

전체 디자인은 라즈겜동의 도면을 기본으로, 분해한 노트북에 맞도록(세트 1) 수정했다.

 

 

디자인한 파일을 목재 가공소에 보내서 견적을 받고 작업을 시작 했다.

(가공소에 도착 했을때 진행 중이던 작업. 내가 의뢰한 제품은 아니다)

 

일반 MDF는 접착제에서 포름알데히드가 나오기 때문에 친환경 자재인 컬러보드(블랙)를 사용했다. 덕분에 단가는 거의 2배가 되었지만 석탄같은 색깔 때문이었을까? 자연에 조금 더 가까워지는 느낌을 얻을 수 있었다.

 

가공이 잘 되었는지 확인하기 위해 가조립 해본다. 별 문제 없는거 같다.

 

조이스틱과 버튼을 설치한다.

 

2020/04/09 - [Review] - DIY Sanwa Arcade Joystick Kit - DIY 산와 아케이드 조이스틱 키트

 

 

엔코더와 케이블을 연결한다.

 

그럴듯해 보인다.

 

나사를 이용해 나무판들을 고정한다. 나사에 맞는 드릴 비트가 없어 조심히 작업했지만 모서리 가까운곳에서는 약간씩 갈라졌다. 순간접착제로 보강해준다.

 

뒷판은 쉽게 열고 닫을 수 있도록 경첩을 달아 준다. 오른쪽 경첩의 나사 하나가 부러져 적당히 고정만 시켰다.

노트북 전원 단자도 문제 없이 나온다.

 

 

뒷판이 고정 될 수 있도록 자석 도어 캐치를 달아준다. (설치하고 보니 좀 약하다)

 

노트북 기판에서 디스플레이까지 연결되는 케이블과 전원 단자 케이블은 충분히 길지는 않지만 문제가 되지는 않았다. 하지만 전원 버튼은 기판에 붙어 있기 때문에 오락기 케이스 외부로 빼내기 위해 케이블에 납땜하고 연장 해야했다. (빨간색, 검정색 케이블과 노란색 푸시버튼)

 

작업한 노트북 기판을 오락기 내부에 설치한다. (대충.. 쇼트나지 않도록 적당히 잘 넣는다)

 

디스플레이도 노출된 회로를 적당히 처리하고 붙여준다.

 

 

오른쪽엔 코인기를 설치하기 위한 구멍이 있다.

 

이 코인기를 설치한다.

 

생각해 보니 조카들의 반발이 예상되어 일단 그냥 막아둔다.

 

이제 뒷문을 닫고 노트북 어댑터를 연결한다.

 

 

미리 설치해둔 운영체제와 레트로 파이가 문제없이 작동된다. 노란색 푸시버튼은 문제가 있어 다른 디자인의 검정색 푸시버튼으로 바꿨다. 푸시버튼 양 옆으로 노트북에서 분리한 스피커를 설치하기 위한 네모난 홈이 보인다. 하지만 스피커가 케이스 내부에 있어도 소리가 잘 들리므로 그냥 두기로 한다. (스피커를 케이스 밖으로 빼려면 케이블을 잘라서 연장해야 하는데 그게 귀찮아서 그랬던건 아니다) 

 

메탈 슬러그도 잘 된다.

 

스트리트 파이터도 잘 된다.

 

컬러보드도 표면이 거칠다보니 약간의 마무리 작업이 필요하다. 조카들에게 주기전에 시트지를 붙이거나 바니쉬를 발라줘야겠다. 조립하기 전에 미리 했으면 좋았을텐데..

 

반응형
Posted by J-sean
:
반응형

가끔 조카들이 놀러 오면 같이 놀기 위해 오래된 컴퓨터에 레트로파이를 설치하고 예전 오락실 게임이나 콘솔 게임을 플레이 할 수 있도록 만들었다. 


2020/02/13 - [Raspberry Pi] - Raspberry Pi Desktop(Debian), Ubuntu에서 RetroPie 설치하기


이 컴퓨터는 거실에 두고 모니터보다 훨씬 큰 TV에 연결 했으니 이렇게만 만들어도 충분히 게임을 즐길 수 있지만 왠지 예전 게임기 느낌이 살지는 않는거 같아 살짝 아쉬운 마음이 들었다. 그래서 구입한 RETROFLAG의 SUPERPi Case-J.


제조: RETROFLAG

판매: Amazon


공식 판매처인 미국 아마존에서 구입이 가능하지만 게임패드가 포함되지 않은 모델의 경우에도 제품과 배송비를 합쳐 약 $26의 비용이 든다. 국내에서 사는게 더 비싸다면 배송 기간도 고려해서 아마존 구매를 생각해 보겠지만 디바이스마트에서 \16,500에 파는걸 보고 바로 주문했다.


그리고 이틀 후 도착한 내 소중한 케이스...


상자 앞 면


상자 뒷 면


상자 옆 면


겉 상자를 열면 안에 다시 속 상자가 들어 있다.



속 상자에 들어 있는 케이스. 모든 부품이 케이스 안에 다 들어 있다.


케이스 뒷 면


조립 메뉴얼


조립 메뉴얼



상자 안에 들어 있는 부품들


라즈베리 파이를 조립하기 전에 SD 카드를 분리해야 한다. 굳이 분리할 필요가 있을까 생각 했지만 분리하지 않으면 라즈베리 파이가 케이스에 제대로 들어가지 않는다.


조립에 필요한 부품들


케이스 위에 설치 할 롬 카트리지. 진짜 롬 카트리지는 아니고 SD 카드를 보관 할 수 있는 케이스다.



드라이버가 포함되어 있다.


Power/Reset/SAFE SHUTDOWN 스위치, 전면 USB포트 연결 케이블, GPIO연결 커넥터등이 보인다.





설치 과정 영상 추가 예정..................

SAFE SHUTDOWN 설치 영상 추가 예정............






영상에서 볼 수 있듯이 SAFE SHUTDOWN기능은 터미널에서 아래 명령어만 입력해 주면 간단히 설치 가능 하다.


wget -O - "https://raw.githubusercontent.com/RetroFlag/retroflag-picase/master/install.sh" | sudo bash


참고로 레트로파이에서 키보드 설정을 바꾸지 않았다면 영국 키보드로 지정되어 있다. 우리가 일반적으로 사용하는 키보드와는 키배열이 약간 다르므로 아래 그림을 참고 하자.


영국 키보드


그럼 install.sh에는 어떤 내용이 있어 SAFE SHUTOWN 기능이 설치 되는지 살펴 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/bin/bash
 
 
#Step 1) Check if root--------------------------------------
if [[ $EUID -ne 0 ]]; then
   echo "Please execute script as root." 
   exit 1
fi
#-----------------------------------------------------------
 
#Step 2) enable UART----------------------------------------
cd /boot/
File=config.txt
if grep -"enable_uart=1" "$File";
    then
        echo "UART already enabled. Doing nothing."
    else
        echo "enable_uart=1" >> $File
        echo "UART enabled."
fi
#-----------------------------------------------------------
 
#Step 3) Update repository----------------------------------
sudo apt-get update -y
#-----------------------------------------------------------
 
#Step 4) Install gpiozero module----------------------------
sudo apt-get install -y python3-gpiozero
#-----------------------------------------------------------
 
#Step 5) Download Python script-----------------------------
cd /opt/
sudo mkdir RetroFlag
cd /opt/RetroFlag
script=SafeShutdown.py
 
if [ -e $script ];
    then
        echo "Script SafeShutdown.py already exists. Doing nothing."
    else
        wget "https://raw.githubusercontent.com/RetroFlag/retroflag-picase/master/SafeShutdown.py"
fi
#-----------------------------------------------------------
 
#Step 6) Enable Python script to run on start up------------
cd /etc/
RC=rc.local
 
if grep -"sudo python3 \/opt\/RetroFlag\/SafeShutdown.py \&" "$RC";
    then
        echo "File /etc/rc.local already configured. Doing nothing."
    else
        sed --"s/^exit 0/sudo python3 \/opt\/RetroFlag\/SafeShutdown.py \&\n&/g" "$RC"
        echo "File /etc/rc.local configured."
fi
#-----------------------------------------------------------
 
#Step 7) Reboot to apply changes----------------------------
echo "RetroFlag Pi Case installation done. Will now reboot after 3 seconds."
sleep 3
sudo reboot
#-----------------------------------------------------------




스크립트 분석 추가 예정..................






그럼 Safeshutdown.py의 내용을 확인해 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python3
from gpiozero import Button, LED
import os 
from signal import pause
 
powerPin = 3 
resetPin = 2 
ledPin = 14 
powerenPin = 4 
hold = 1
led = LED(ledPin)
led.on()
power = LED(powerenPin)
power.on()
 
#functions that handle button events
def when_pressed():
  led.blink(.2,.2)
  os.system("sudo killall emulationstation && sleep 5s && sudo shutdown -h now")
def when_released():
  led.on()
def reboot(): 
  os.system("sudo killall emulationstation && sleep 5s && sudo reboot")
  
btn = Button(powerPin, hold_time=hold)
rebootBtn = Button(resetPin)
rebootBtn.when_pressed = reboot 
btn.when_pressed = when_pressed
btn.when_released = when_released
pause()




스크립트 분석 추가 예정......







반응형
Posted by J-sean
: