Как стать автором
Обновить

Простенькая игра Rock-paper-scissors-lizard-Spock на pygame

image
Приветствую хабралюди. Я начал изучать Python курс на Coursera, решил изучить этот чудесный язык, и как 1-й проект нужно было сделать игру по мотивам «The Big Bang Theory» — «Rock-paper-scissors-lizard-Spock». Но это же первый проект, но в Python'e нумерация начинается с 0, и по этому была нулевая неделя с 0-ым проектом типа:

print "We want... a shrubbery!"


Мне захотелось большего и я решил чуток опередить график.

Сначала было яйцо, ой о чем это я, ах да о том что…
Подумав я решил сделать простенькую консольную программку, продумав логику приступил к написанию.
Для хранения жестов, и возможных использовал список вида:

gestures = {'rock': {'win': ['lizard', 'scissors']},
           'paper': {'win': ['rock', 'spock']},
           'scissors': {'win': ['lizard', 'paper']},
           'lizard': {'win': ['paper', 'spock']},
           'spock': {'win': ['rock', 'scissors']}}


Да и процес обработки вышел довольно банальный:

def process(user, comp):
 global user_won, comp_won, draw, won, users, comps
    users = user
    comps = comp
    if user == comp:
        draw += 1
        won = 'Draw'
        return draw
    if gestures.get(user):
        if comp in gestures[user]['win']:
            user_won += 1
            won = 'User Won'
            return texts(user_won, comp_won), hand_set(user, comp)
        else:
            comp_won += 1
            won = 'Computer Won'
            return texts(user_won, comp_won), hand_set(user, comp)
    else:
        raise Exception('Gesture not found in dict.')


За помощь с этой функцией спасибо sadovnychyi.
Думаю давать комментариев что и как не нужно.
Ну и в общем полная консольная версия:

Консольная верся игры
#!/usr/bin/python
import random

print '''
This is "Rock-paper-scissors-lizard-Spock" game
for play you must choose one of gestures(put number):
    0.spock
    1.scissors
    2.lizard
    3.paper
    4.rock
'''

you_won = 0
you_luse = 0
draw = 0


def process(user, comp):
    global you_won, you_luse, draw
    if user == comp:
        draw += 1
        return 'Draw'
    if gestures.get(user):
        if comp in gestures[user]['win']:
            you_won += 1
            return 'You won!'
        else:
            you_luse += 1
            return 'You loser :-('
    else:
        raise Exception('Gesture not found in dict.')


gestures = {'rock': {'win': ['lizard', 'scissors']},
            'paper': {'win': ['rock', 'spock']},
            'scissors': {'win': ['lizard', 'paper']},
            'lizard': {'win': ['paper', 'spock']},
            'spock': {'win': ['rock', 'scissors']}}

while 1:
    try:
        user_gest_inputed = int(raw_input('\nWrite gestures: '))
    except ValueError:
        print 'You must input number'
    else:
        if user_gest_inputed >= 5 or user_gest_inputed < 0:
            print 'You input wrong number(s)'
        else:
            user_gest = gestures.keys()[user_gest_inputed]
            print "User choise:", user_gest

            comp_gest = str(random.sample(gestures.keys(), 1))
            comp_gest = comp_gest[2:-2]
            print "Comp choise:", comp_gest

            result = process(user_gest, comp_gest)
            print result
            print "You won %s, lose %s and draw %s" % (you_won, you_luse, draw)



После этого я подумал, а что если сделать графику, и пальцы забились об клавиатуру в поиске методов как это сделать, и довольно быстро была обнаружена Pygame, после первого взгляда на сайт начало тошнить стало не по себе и в голове прокрутилась мысль: «Как эта библиотека может быть хорошей?», но потом появилась другая: «Стоп, но эти парни не дизайнеры» и пошел процесс изучения игр написанных на этом движке.

И честно говоря я был приятно удивлен количеством не плохих игр. Так как опыт в написании программ я имел не большой, а написать хотелось быстрее и проще — я начал искать туториалы о Pygame, и этот ресурс очень помог. После переваривания инфы начался процесс написания (который не так долго продолжался, больше времени на графику затратил.

Ну что же пришло время посмотреть на говнокод мои решения.

Логику определения победителя я конечно же позаимствовал из консольной версии, которая оказалось может быть еще проще, но сейчас не об этом).

Сначала был нарисован каркас в GIMPe, и добавлен оный вместе с кнопками и подсветкой, сделаными там же:

background = pygame.Surface(screen.get_size())
background = pygame.image.load("src/layout_whitout.jpg").convert()

btnRock = pygame.image.load('src/rock.png').convert_alpha()
btnPaper = pygame.image.load('src/paper.png').convert_alpha()
btnSciss = pygame.image.load('src/scissors.png').convert_alpha()
btnLizard = pygame.image.load('src/lizard.png').convert_alpha()
btnSpock = pygame.image.load('src/spock.png').convert_alpha()

lightBtn = pygame.image.load('src/supernovaBtn.png').convert_alpha()


После того как что то начало появляться нужно было сделать что бы что то и выполнялось. Подсмотрев в туториале как настроить поведение мышки, сделал подобное:

 if event.type == pygame.QUIT:
            done = True  

        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                pos = pygame.mouse.get_pos()
# Определение координат мышки
                x = pos[0]
                y = pos[1]
# Если ЛКМ нажата - пеередаем координаты на выполнение у функцию, что бы определить на какую кнопку нажато
                position(x, y)
                mouse_click = True
                print("Click ", pos, "Grid coordinates: ", x, y)

#Все тоже самое только передается при движении в функцию для создания подсветки
        elif event.type == pygame.MOUSEMOTION:
            pos = event.pos
            x = pos[0]
            y = pos[1]
            blur_pos(x, y)


Здесь происходит определение на какую кнопку нажато:

def position(x, y):
    comp_gest = str(random.sample(gestures.keys(), 1))
    comp_gest = comp_gest[2: -2]
    print "Comp choise:", comp_gest
    if y > 500:
        if x in range(btnRock_x, btnRock_x + 92):
            user_gest = 'rock'
            process(user_gest, comp_gest)
            print 'User choise: rock'

        elif x in range(btnPaper_x, btnPaper_x + 92):
            user_gest = 'paper'
            process(user_gest, comp_gest)
            print 'User choise: paper' . . .


Потом еще прикрутил что бы выводило на экран очки игроков, кто выиграл и проиграл, а главное жесты рук (которые делал в blender 3d).

Версия из GUI
#!/usr/bin/python
import pygame
import random


# Initialize the game engine
pygame.init()

# Define the colors we will use in RGB format
black = [0, 0, 0]

#Dict with elems
gestures = {'rock': {'win': ['lizard', 'scissors']},
            'paper': {'win': ['rock', 'spock']},
            'scissors': {'win': ['lizard', 'paper']},
            'lizard': {'win': ['paper', 'spock']},
            'spock': {'win': ['rock', 'scissors']}}

#Score
user_won = 0
comp_won = 0
draw = 0
won = ""

#Var for visible won label
mouse_click = False

#Var for hands
users = ''
comps = ''

#Location on screen
x = 0
y = 0

#Labels
font = pygame.font.SysFont("Comic Sans MS", 18)
font_won = pygame.font.SysFont("Comic Sans MS", 32)
label_comp_score = font.render("User Win: " + str(comp_won), 1, black)
label_user_score = font.render("Comp Win: " + str(user_won), 1, black)
label_draw_score = font.render("Draw: " + str(user_won), 1, black)
label_won = font_won.render(str(won), 1, black)

# Set the height and width of the screen
size = [800, 600]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Rock-paper-scissors-lizard-Spock game")

#Loop until the user clicks the close button.
done = False
clock = pygame.time.Clock()

#Set background picture
background = pygame.Surface(screen.get_size())
background = pygame.image.load("src/layout_whitout.jpg").convert()

#Set picture for buttons
btnRock = pygame.image.load('src/rock.png').convert_alpha()
btnPaper = pygame.image.load('src/paper.png').convert_alpha()
btnSciss = pygame.image.load('src/scissors.png').convert_alpha()
btnLizard = pygame.image.load('src/lizard.png').convert_alpha()
btnSpock = pygame.image.load('src/spock.png').convert_alpha()

lightBtn = pygame.image.load('src/supernovaBtn.png').convert_alpha()
pushBtn = pygame.image.load('src/lightBtn.png').convert_alpha()

#Set hands
lHadn_rock = pygame.image.load('src/lRock.png').convert_alpha()
lHadn_paper = pygame.image.load('src/lPaper.png').convert_alpha()
lHadn_sciss = pygame.image.load('src/lScissors.png').convert_alpha()
lHadn_lizard = pygame.image.load('src/lLizard.png').convert_alpha()
lHadn_spock = pygame.image.load('src/lSpock.png').convert_alpha()

rotated = pygame.transform.rotate(lHadn_rock, 0)

rHand_rock = pygame.transform.flip(lHadn_rock, True, False)
rHadn_paper = pygame.transform.flip(lHadn_paper, True, False)
rHadn_sciss = pygame.transform.flip(lHadn_sciss, True, False)
rHadn_lizard = pygame.transform.flip(lHadn_lizard, True, False)
rHadn_spock = pygame.transform.flip(lHadn_spock, True, False)

#Set btn possition x-axis
btnRock_x = 50
btnPaper_x = 200
btnSciss_x = 350
btnLizard_x = 500
btnSpock_x = 650


def win_screen():
    global label_won
    if mouse_click:
        #set win label
        label_won_rect = label_won.get_rect()
        label_won_x = screen.get_width() / 2 - label_won_rect.width / 2
        label_won_y = screen.get_height() / 2 - label_won_rect.height / 2
        screen.blit(label_won, [label_won_x, label_won_y])
        label_won = font_won.render(str(won), 1, black)


def texts(user_won, comp_won):
    #Set fount and label
    global label_comp_score, label_user_score, label_draw_score
    label_comp_score = font.render("User Win: " + str(comp_won), 1, black)
    label_user_score = font.render("Comp Win: " + str(user_won), 1, black)
    label_draw_score = font.render("Draw: " + str(draw), 1, black)


def process(user, comp):
    global user_won, comp_won, draw, won, users, comps
    users = user
    comps = comp
    if user == comp:
        draw += 1
        won = 'Draw'
        return draw
    if gestures.get(user):
        if comp in gestures[user]['win']:
            user_won += 1
            won = 'User Won'
            return texts(user_won, comp_won), hand_set(user, comp)
        else:
            comp_won += 1
            won = 'Computer Won'
            return texts(user_won, comp_won), hand_set(user, comp)
    else:
        raise Exception('Gesture not found in dict.')


#Set users and comp hands
def hand_set(user, comp):
    if won == '':
        screen.blit(lHadn_rock, [5, 200])
        screen.blit(rHand_rock, [540, 200])

    if user == 'rock':
        screen.blit(lHadn_rock, [5, 200])
    elif user == 'paper':
        screen.blit(lHadn_paper, [5, 200])
    elif user == 'scissors':
        screen.blit(lHadn_sciss, [5, 200])
    elif user == 'lizard':
        screen.blit(lHadn_lizard, [5, 200])
    elif user == 'spock':
        screen.blit(lHadn_spock, [5, 200])

    if comp == 'rock':
        screen.blit(rHand_rock, [540, 200])
    elif comp == 'paper':
        screen.blit(rHadn_paper, [400, 200])
    elif comp == 'scissors':
        screen.blit(rHadn_sciss, [400, 200])
    elif comp == 'lizard':
        screen.blit(rHadn_lizard, [400, 200])
    elif comp == 'spock':
        screen.blit(rHadn_spock, [400, 200])


def position(x, y):
    comp_gest = str(random.sample(gestures.keys(), 1))
    comp_gest = comp_gest[2: -2]
    print "Comp choise:", comp_gest
    if y > 500:
        if x in range(btnRock_x, btnRock_x + 92):
            user_gest = 'rock'
            process(user_gest, comp_gest)
            print 'User choise: rock'

        elif x in range(btnPaper_x, btnPaper_x + 92):
            user_gest = 'paper'
            process(user_gest, comp_gest)
            print 'User choise: paper'

        elif x in range(btnSciss_x, btnSciss_x + 92):
            user_gest = 'scissors'
            process(user_gest, comp_gest)
            print 'User choise: scissor'

        elif x in range(btnLizard_x, btnLizard_x + 92):
            user_gest = 'lizard'
            process(user_gest, comp_gest)
            print 'User choise: lizard'

        elif x in range(btnSpock_x, btnSpock_x + 92):
            user_gest = 'spock'
            process(user_gest, comp_gest)
            print 'User choise: spock'

def blur_pos(x, y):
    global blur_rock, blur_paper, blur_scissor, blur_lizard, blur_spock
    if y > 500:
        if x in range(btnRock_x, btnRock_x + 92):
            screen.blit(lightBtn, [btnRock_x, 500])

        elif x in range(btnPaper_x, btnPaper_x + 92):
            screen.blit(lightBtn, [btnPaper_x, 500])

        elif x in range(btnSciss_x, btnSciss_x + 92):
            screen.blit(lightBtn, [btnSciss_x, 500])

        elif x in range(btnLizard_x, btnLizard_x + 92):
            screen.blit(lightBtn, [btnLizard_x, 500])

        elif x in range(btnSpock_x, btnSpock_x + 92):
            screen.blit(lightBtn, [btnSpock_x, 500])


while done == False:
    global x, y
    clock.tick(10)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True  # Flag that we are done so we exit this loop

        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                pos = pygame.mouse.get_pos()
                # Change the x/y screen coordinates to grid coordinates
                x = pos[0]
                y = pos[1]
                # Pass values to function
                position(x, y)
                mouse_click = True
                print("Click ", pos, "Grid coordinates: ", x, y)

        elif event.type == pygame.MOUSEMOTION:
            pos = event.pos
            x = pos[0]
            y = pos[1]
            blur_pos(x, y)

    #set background
    screen.blit(background, [0, 0])

    #set buttons
    screen.blit(btnRock, [btnRock_x, 500])
    screen.blit(btnPaper, [btnPaper_x, 500])
    screen.blit(btnSciss, [btnSciss_x, 500])
    screen.blit(btnLizard, [btnLizard_x, 500])
    screen.blit(btnSpock, [btnSpock_x, 500])

    #set light for buttons
    blur_pos(x, y)

    #set labels
    screen.blit(label_comp_score, (70, 40))
    screen.blit(label_user_score, (575, 42))
    screen.blit(label_draw_score, (375, 42))

    hand_set(users, comps)
    win_screen()
    mouse_click = False

    pygame.display.flip()

pygame.quit()



Вот, к стати, скрин того что вышло:

image

P.S. После того как открылся для реализации проект на Coursera, я понял что можно было обойтись более простой логикой и без использования словарей.

Кому интересно вот полный проект со всеми ресурсами: ubuntuone.com/7IcRcnTyQEPaciOIuTGrOl
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.