KEYDOWN가사용되었지만,아직도이게임이완전한图形界面가아닌것처럼보이는이유는图形用户界面가입력은없고오직출력(프린트)하는데에만사용되었기때문이다。Gui에서의입력이란특정한위치에서의마우스이벤트를처리하는것이다。HP를증가시키거나감소시키는버튼2개를만드는것은어떨까?

../../../../_images/AdvancedInputOutput11.gif
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 320, 240
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("AdvancedInputOutput1.gif")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()
../../../../_images/AdvancedInputOutput21.gif
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 320, 240
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("AdvancedInputOutput2.gif")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()

버튼2개를만드는것은쉽다.버튼을보면,뭔가특이한효과가적용되어있음을알우있다.어떻게한것인다?이전의아이디어처럼단순하다.첫째,큰정사각형을그린다.둘째,내용은없고두께만있는작은정사각형을그린다.하지만이버튼들은아직출력용이다.이버튼들을위한클릭가능공간을만들어야한다.

../../../../_images/AdvancedInputOutput31.gif
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 320, 240
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("AdvancedInputOutput3.gif")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()
../../../../_images/AdvancedInputOutput41.gif
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 320, 240
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("AdvancedInputOutput4.gif")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()
../../../../_images/AdvancedInputOutput51.gif
 1import sys, pygame
 2pygame.init()
 3
 4size = width, height = 320, 240
 5speed = [2, 2]
 6black = 0, 0, 0
 7
 8screen = pygame.display.set_mode(size)
 9
10ball = pygame.image.load("AdvancedInputOutput5.gif")
11ballrect = ball.get_rect()
12
13while True:
14    for event in pygame.event.get():
15        if event.type == pygame.QUIT: sys.exit()
16
17    ballrect = ballrect.move(speed)
18    if ballrect.left < 0 or ballrect.right > width:
19        speed[0] = -speed[0]
20    if ballrect.top < 0 or ballrect.bottom > height:
21        speed[1] = -speed[1]
22
23    screen.fill(black)
24    screen.blit(ball, ballrect)
25    pygame.display.flip()

이제Event문에MOUSEBUTTONUP이추가되었다。마우스가up된것은키보드가down된것과동일한의미를가진다.만약MOUSEBUTTONUP이활성화되면,Event.pos는x값과y값을기록해야하는데,이것은클릭지점을나타낸다.그러므로,클릭이특정정사각형내부에서일어났는지아닌지는碰撞点를확인하면된다。만약내부였다면,“사용자가특정영역내부를클릭했다”를의미하게된다.그다음,변수를업데이트하는적절한처리만이필요하게된다.입력을위한두변수가존재하고,(事件문에있음)(270,425,45,45)와(325,425,45,45)。출력을위한두변수도존재함을확인하라.(绘图按钮에있음)(页边距,高度-r-10,r,r)과(页边距+r+r_页边距,高度-r-10,r,r)。버튼의경우,입력영역과출력영역이동일해야한다.그렇지않다면,버튼의판정범위가사기가된다!변수(출력용)들을구체적인계산을통해상수(입력용)값을알아내기싫다면,이변수들을동일한변수로두는것이좋은생각일것이다.두영역을하나로묶을수있는함수는없으므로,이점은항상신경써야한다.

<참고코드>::

import pygame, sys
from pygame.locals import*

maxHP = 10
white = (255,255,255)
gray = (127,127,127)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
pygame.init()
pygame.display.set_caption("Array buttons Project")
width = 640
height = 480
myScreen = pygame.display.set_mode((width, height))
myTextFont = pygame.font.Font("HoonWhitecatR.ttf", 32)
myText = myTextFont.render((str(maxHP) + "/" + str(maxHP)), True, red, gray)
myTextArea = myText.get_rect()
myTextArea.center = (width/2, height/2)
fpsClock = pygame.time.Clock()

def main():
    HP = 5

    while True:
        myText = myTextFont.render((str(HP) + "/" + str(maxHP)), True, red, gray)

        myScreen.fill(gray)

        myScreen.blit(myText, myTextArea)
        drawHP(HP)
        drawButtons()

        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_UP:
                    if HP != 10:
                        HP = HP + 1
                elif event.key == K_DOWN:
                    if HP != 0:
                        HP = HP - 1
            elif event.type == MOUSEBUTTONUP: #1
                x, y = event.pos
                if pygame.Rect(270, 425, 45, 45).collidepoint(x, y):
                    if HP != 10:
                        HP = HP + 1
                elif pygame.Rect(325, 425, 45, 45).collidepoint(x, y):
                    if HP != 0:
                        HP = HP - 1

        pygame.display.update()
        fpsClock.tick(60)

def drawHP(HP):
    r = int((height - 40) / maxHP)

    pygame.draw.rect(myScreen, black, (20, 20, 20, 20 + ((maxHP - 0.5) * r)))

    for i in range(maxHP):
        if HP >= (maxHP - i):
            pygame.draw.rect(myScreen, red, (20, 20 + (i * r), 20, r))
        pygame.draw.rect(myScreen, white, (20, 20 + (i * r), 20, r), 1)

    return

def drawButtons():
    r = 45
    r_margin = 10
    colors = [red, black]

    num = 2
    margin = int((width - ((r * num) + (r_margin * (num - 1)))) / 2)
    for i in range(0, num):
        left = margin + (i * r) + (i * r_margin)
        up = height - r - 10
        pygame.draw.rect(myScreen, colors[i], (left, up, r, r))
        pygame.draw.rect(myScreen, gray, (left + 2, up + 2, r - 4, r - 4), 2)

if __name__ == '__main__':
    main()



Edit on GitHub