Как задать 20 вопросов с множественным выбором на Pygame? - PullRequest
1 голос
/ 14 января 2020

Я пишу очень основную c игру для Pygame для проекта, и основная функция игры - задавать 20 вопросов в зависимости от того, на каком операторе (ах) и на каком уровне выбран пользователь для игры.

Я действительно борюсь с двумя вещами:
во-первых, код, который я написал, действительно производит 20 вопросов с правильным оператором и уровнем сложности, однако я не знаю, как это сделать экран по одному каждый раз, когда пользователь ответил на последний. В настоящее время код показывает только последний вопрос на экране.

Вторая проблема, с которой я столкнулся, - это создание кнопок с несколькими вариантами ответов для каждого вопроса. У меня в игре есть класс «Button», который совпадает с классом «Text», который вы можете видеть в коде, однако он также отслеживает нажатие кнопки.
Для каждого вопроса мне нужно иметь 4 экземпляра класса кнопок на экране, один из которых является правильным ответом на каждый вопрос, а остальные три и случайные числа, и мне нужен код, чтобы рандомизировать, какая кнопка является ответом на каждый вопрос, поэтому ответ не всегда одинаков кнопка.

У меня также есть секундомер в моей игре, и ни один из них не может помешать ему.

    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
        gameBG=pygame.image.load('gameBG.bmp').convert()
        screen.blit(gameBG,(0,0))
        questiontxt= Text((325,45),(question), (white), 80)
        questiontxt.draw(screen)
        ticks=pygame.time.get_ticks()
        if timing == False:
            timing=True
            seconds=0
        seconds=int((ticks/1000%60))
        minutes=int((ticks/60000%24))
        out='{minutes:02d}:{seconds:02d}'.format(minutes=minutes, seconds=seconds)
        timefont.render_to(screen,(855,50),out, green)
        pygame.display.update()
        clock.tick(60)

        while j < 38:
            qnum1=int(numlist[j])
            qnum2=int(numlist[j+1])
            if section == 'mixed':
                mixedno=random.randrange(0,4)
                operators=['addition','subtraction','division','multiplication']
                qsection=operators[mixedno]
            else:
                qsection=section

            if qsection == 'addition':
                question=str(qnum1)+ '+'+ str(qnum2)+' = ?'
                answer= qnum1+qnum2
            elif qsection == 'subtraction':
                question=str(qnum1)+ '-'+ str(qnum2)+' = ?'
                answer= qnum1-qnum2
            elif qsection == 'multiplication':
                question=str(qnum1)+ 'x'+ str(qnum2)+' = ?'
                answer= qnum1*qnum2
            else:
                question=str(qnum1)+'÷'+str(qnum2)+' = ?'
                answer= qnum1/qnum2

            print(question)
            questiontxt= Text((325,45),(question), (white), 80)
            questiontxt.draw(screen)
            j=j+2

1 Ответ

0 голосов
/ 14 января 2020

Давайте начнем с новой, базовой c программы Pygame. Я обычно начинаю так:

import pygame

def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    dt = 0
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        screen.fill(pygame.Color('lightgrey'))
        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

Не так много, чтобы увидеть здесь. Мы создаем окно, закрашиваем его серым цветом, обрабатываем события и отслеживаем дельта-время (время, которое занимает каждый кадр).


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

Вот способ, которым мы могли бы реализовать это:

import pygame
import pygame.freetype

class SimpleScene:

    FONT = None

    def __init__(self, text, next_scene):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))

        if text:
            if SimpleScene.FONT == None:
                SimpleScene.FONT = pygame.freetype.SysFont(None, 32)
            SimpleScene.FONT.render_to(self.background, (120, 180), text, pygame.Color('black'))
            SimpleScene.FONT.render_to(self.background, (119, 179), text, pygame.Color('white'))

        self.next_scene = next_scene

    def start(self):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return self.next_scene

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    dt = 0
    scenes = {
        'TITLE': SimpleScene('PRESS SPACE TO START', 'GAME'),
        'GAME': SimpleScene('Can you press [SPACE]', 'RESULT'),
        'RESULT': SimpleScene('You win! 100 points!', 'TITLE'),
    }
    scene = scenes['TITLE']
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        next_scene = scene.update(events, dt)
        if next_scene:
            scene = scenes[next_scene]
            scene.start()

        scene.draw(screen)

        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here

Теперь мы можем переходить между сценами, нажимая пространство . Как видите, каждая сцена похожа на миниатюрную игру; Конечно, у нас есть только SimpleScene, который только рисует простой текст, поэтому давайте изменим это и реализуем настоящую игру. У нас также есть игровое состояние, поэтому мы должны отслеживать, если оно тоже.

Вот как это может выглядеть:

import pygame
import pygame.freetype
import random

class SimpleScene:

    FONT = None

    def __init__(self, next_scene, *text):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))

        y = 80
        if text:
            if SimpleScene.FONT == None:
                SimpleScene.FONT = pygame.freetype.SysFont(None, 32)
            for line in text:
                SimpleScene.FONT.render_to(self.background, (120, y), line, pygame.Color('black'))
                SimpleScene.FONT.render_to(self.background, (119, y-1), line, pygame.Color('white'))
                y += 50

        self.next_scene = next_scene
        self.additional_text = None

    def start(self, text):
        self.additional_text = text

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        if self.additional_text:
            y = 180
            for line in self.additional_text:
                SimpleScene.FONT.render_to(screen, (120, y), line, pygame.Color('black'))
                SimpleScene.FONT.render_to(screen, (119, y-1), line, pygame.Color('white'))
                y += 50

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return (self.next_scene, None)

class GameState:
    def __init__(self, difficulty):
        self.difficulty = difficulty
        self.questions = [
            ('How many legs has a cow?', 4),
            ('How many legs has a bird?', 2),
            ('What is 1 x 1 ?', 1)
        ]
        self.current_question = None
        self.right = 0
        self.wrong = 0

    def pop_question(self):
        q = random.choice(self.questions)
        self.questions.remove(q)
        self.current_question = q
        return q

    def answer(self, answer):
        if answer == self.current_question[1]:
            self.right += 1
        else:
            self.wrong += 1

    def get_result(self):
        return f'{self.right} answers correct', f'{self.wrong} answers wrong', '', 'Good!' if self.right > self.wrong else 'You can do better!'

class SettingScene:

    def __init__(self):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))

        if SimpleScene.FONT == None:
            SimpleScene.FONT = pygame.freetype.SysFont(None, 32)

        SimpleScene.FONT.render_to(self.background, (120, 50), 'Select your difficulty level', pygame.Color('black'))
        SimpleScene.FONT.render_to(self.background, (119, 49), 'Select your difficulty level', pygame.Color('white'))

        self.rects = []
        x = 120
        y = 120
        for n in range(4):
            rect = pygame.Rect(x, y, 80, 80)
            self.rects.append(rect)
            x += 100

    def start(self, *args):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        n = 1
        for rect in self.rects:
            if rect.collidepoint(pygame.mouse.get_pos()):
                pygame.draw.rect(screen, pygame.Color('darkgrey'), rect)
            pygame.draw.rect(screen, pygame.Color('darkgrey'), rect, 5)                
            SimpleScene.FONT.render_to(screen, (rect.x+30, rect.y+30), str(n), pygame.Color('black'))
            SimpleScene.FONT.render_to(screen, (rect.x+29, rect.y+29), str(n), pygame.Color('white'))
            n+=1

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                n = 1
                for rect in self.rects:
                    if rect.collidepoint(event.pos):
                        return ('GAME', GameState(n))
                    n += 1

class GameScene:
    def __init__(self):
        if SimpleScene.FONT == None:
            SimpleScene.FONT = pygame.freetype.SysFont(None, 32)

        self.rects = []
        x = 120
        y = 120
        for n in range(4):
            rect = pygame.Rect(x, y, 80, 80)
            self.rects.append(rect)
            x += 100

    def start(self, gamestate):
        self.background = pygame.Surface((640, 480))
        self.background.fill(pygame.Color('lightgrey'))
        self.gamestate = gamestate
        question, answer = gamestate.pop_question()
        SimpleScene.FONT.render_to(self.background, (120, 50), question, pygame.Color('black'))
        SimpleScene.FONT.render_to(self.background, (119, 49), question, pygame.Color('white'))


    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        n = 1
        for rect in self.rects:
            if rect.collidepoint(pygame.mouse.get_pos()):
                pygame.draw.rect(screen, pygame.Color('darkgrey'), rect)
            pygame.draw.rect(screen, pygame.Color('darkgrey'), rect, 5)
            SimpleScene.FONT.render_to(screen, (rect.x+30, rect.y+30), str(n), pygame.Color('black'))
            SimpleScene.FONT.render_to(screen, (rect.x+29, rect.y+29), str(n), pygame.Color('white'))
            n+=1

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                n = 1
                for rect in self.rects:
                    if rect.collidepoint(event.pos):
                        self.gamestate.answer(n)
                        if self.gamestate.questions:
                            return ('GAME', self.gamestate)
                        else:
                            return ('RESULT', self.gamestate.get_result())
                    n += 1

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    dt = 0
    scenes = {
        'TITLE':    SimpleScene('SETTING', 'Welcome to the quiz', '', '', '', 'press [SPACE] to start'),
        'SETTING':  SettingScene(),
        'GAME':     GameScene(),
        'RESULT':   SimpleScene('TITLE', 'Here is your result:'),
    }
    scene = scenes['TITLE']
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        result = scene.update(events, dt)
        if result:
            next_scene, state = result
            if next_scene:
                scene = scenes[next_scene]
                scene.start(state)

        scene.draw(screen)

        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here

Конечно, он не закончен на 100%, но он должен дать вам представление о том, как структурировать вашу игру, чтобы получить то, что вы хотите.

Как вы можете видеть, каждая сцена обрабатывает свой собственный аспект игра, и игровая сцена переходит в себя при прохождении игрового состояния. Чтобы добавить таймер, вы можете просто сохранить текущее игровое время (например, pygame.time.get_ticks ()) в состоянии игры при первом вызове его функции start и рассчитать оставшееся время в функции update сцена. Если таймер истекает, перейдите к сцене, которая отображает результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...