示例#1
0
文件: main.py 项目: Paspasuy/Snake
class MainForm(QMainWindow):
    def __init__(self, database_worker, sound_player):
        super().__init__()
        self.database_worker = database_worker
        self.sound_player = sound_player
        self.player = 'anonymous'
        self.get_name()
        self.status_bar_text = 'Space: pause, Esc: quit'
        self.cell = 40
        self.pause = True
        self.logic = Logic()
        self.timer = QTimer()
        self.theme_worker = ThemeWorker()
        self.play_sounds = True
        self.init_ui()

    def init_ui(self):
        self.status_bar = self.statusBar()
        menubar = self.menuBar()
        self.h = menubar.size().height()
        action_menu = menubar.addMenu('&Actions')
        settings_menu = menubar.addMenu('&Settings')
        play_action = QAction('&Play', self)
        history_action = QAction('&History', self)
        logout_action = QAction('&Log out', self)
        exit_action = QAction('&Exit', self)
        play_action.triggered.connect(self.show_game)
        history_action.triggered.connect(self.show_all)
        logout_action.triggered.connect(self.logout)
        exit_action.triggered.connect(app.exit)
        exit_action.setShortcut('Esc')
        change_theme_action = QAction('&Choose theme', self)
        theme_setup_action = QAction('&Set up custom theme', self)
        change_sounds_action = QAction('&Disable/enable sounds', self)
        change_eye_action = QAction('&Disable/enable eye', self)
        change_theme_action.triggered.connect(self.change_theme)
        theme_setup_action.triggered.connect(self.setup_custom_theme)
        change_sounds_action.triggered.connect(self.change_sounds)
        change_sounds_action.setShortcut('m')
        change_eye_action.triggered.connect(self.change_eye)
        action_menu.addAction(play_action)
        action_menu.addAction(history_action)
        action_menu.addAction(logout_action)
        action_menu.addAction(exit_action)
        settings_menu.addAction(change_theme_action)
        settings_menu.addAction(theme_setup_action)
        settings_menu.addAction(change_sounds_action)
        settings_menu.addAction(change_eye_action)
        self.setFixedSize(
            self.logic.width * self.cell,
            self.logic.height * self.cell + self.h + self.status_bar.height())
        self.canvas = Canvas(self.logic.width * self.cell,
                             self.logic.height * self.cell)
        self.setCentralWidget(self.canvas)
        self.canvas.move(0, self.h)

    def get_name(self):
        name, is_ok = QInputDialog.getText(self, "Enter your name",
                                           "What is your name?")
        name = name.strip()
        if is_ok and name != '':
            self.player = name
        elif is_ok and name == '':
            self.player = 'anonymous'
        return is_ok

    def logout(self):
        self.pause_game()
        if self.get_name():
            self.update()
            self.logic = Logic()

    def show_game(self):
        self.theme_worker.update_colors()
        if self.theme_worker.theme_chooser != None:
            self.theme_worker.set_theme(self.theme_worker.theme_chooser.choose)
        self.theme_worker.write_custom()
        self.canvas = Canvas(self.logic.width * self.cell,
                             self.logic.height * self.cell)
        self.setCentralWidget(self.canvas)

    def start_game(self):
        if self.pause == True:
            self.pause = False
            self.timer.timeout.connect(self.logic_process)
            self.timer.start(100)

    def pause_game(self):
        if self.pause == False:
            self.pause = True
            self.timer.stop()
            self.timer.timeout.disconnect()
            self.update()

    def change_sounds(self):
        self.play_sounds = not self.play_sounds
        self.update()

    def change_theme(self):
        self.pause_game()
        self.theme_worker.init_theme_chooser()
        self.setCentralWidget(self.theme_worker.theme_chooser)

    def setup_custom_theme(self):
        self.pause_game()
        self.theme_worker.init_custom_theme_setup()
        self.setCentralWidget(self.theme_worker.custom_theme_setup)

    def change_eye(self):
        self.theme_worker.change_eye()
        self.update()

    def logic_process(self):
        if not self.pause:
            l1 = len(self.logic.snake.body)
            self.logic.move()
            l2 = len(self.logic.snake.body)
            if self.logic.game_finished:
                self.database_worker.save_result(
                    len(self.logic.snake.body) - 3, self.player)
                if self.play_sounds:
                    self.sound_player.play_lose(self.theme_worker.theme)
                self.show_best()
                self.logic = Logic()
                self.pause_game()
            elif l2 - l1 == 1 and self.play_sounds:
                self.sound_player.play_apple()
        self.update()

    def show_best(self):
        score = len(self.logic.snake.body) - 3
        best_all, best_player = self.database_worker.get_max(self.player)
        s1 = "The best result on this PC:\n" + best_all[0][1] + ": " + str(
            best_all[0][2]) + ' (' + best_all[0][3] + ')\n'
        s2 = "Your best result:\n" + best_player[0][1] + ": " + str(
            best_player[0][2]) + ' (' + best_player[0][3] + ')\n'
        s3 = 'Your result:\n' + str(score) + '\n'
        if score == best_player[0][2]:
            s3 += 'You beat your own record!\n'
        if score == best_all[0][2]:
            s3 += 'You beat your PC record!\n'
        buttonReply = QMessageBox.question(self, 'Best results', s1 + s2 + s3,
                                           QMessageBox.Yes)

    def show_all(self):
        self.pause_game()
        table = DataTable(self.database_worker.get_all())
        central_widget = table
        self.setCentralWidget(central_widget)

    def paintEvent(self, a0: QPaintEvent) -> None:
        self.canvas.painter.begin(self)
        self.canvas.painter.setRenderHints(QPainter.HighQualityAntialiasing)
        self.draw()
        self.canvas.painter.end()

    def draw(self):
        self.draw_background()
        self.draw_grid()
        self.draw_snake()
        self.draw_apple()
        self.draw_text()
        self.status_bar.showMessage(self.status_bar_text)

    def draw_background(self):
        self.canvas.set_color(self.theme_worker.colors[0])
        self.canvas.painter.drawRect(0, 0 + self.h,
                                     self.logic.width * self.cell,
                                     self.logic.height * self.cell)

    def draw_grid(self):
        self.canvas.set_color(self.theme_worker.colors[1])
        for i in range(self.logic.width + 1):
            self.canvas.painter.drawPolygon(*[
                QPoint(i * self.cell, 0 + self.h),
                QPoint(i * self.cell, self.logic.height * self.cell + self.h)
            ])
        for i in range(self.logic.height + 1):
            self.canvas.painter.drawPolygon(*[
                QPoint(0, i * self.cell + self.h),
                QPoint(self.logic.width * self.cell, i * self.cell + self.h)
            ])

    def draw_snake(self):
        self.canvas.set_color(self.theme_worker.colors[2])
        r = self.cell - 4
        for x, y in self.logic.snake.body:
            self.canvas.painter.drawEllipse(self.cell * x + 2,
                                            self.cell * y + 2 + self.h, r, r)
        if self.theme_worker.draw_eye:
            x = self.logic.snake.x
            x = int(
                self.cell *
                (x + 0.25)) + int(self.cell * 0.25) * self.logic.snake.x_dir
            y = self.logic.snake.y
            y = int(
                self.cell *
                (y + 0.25)) + int(self.cell * 0.25) * self.logic.snake.y_dir
            y += self.h
            self.canvas.set_color(self.inv_color(self.theme_worker.colors[2]))
            self.canvas.painter.drawEllipse(x, y, r // 2, r // 2)

    def draw_apple(self):
        self.canvas.set_color(self.theme_worker.colors[3])
        r = self.cell - 4
        self.canvas.painter.drawEllipse(
            self.cell * self.logic.apple_x + 2,
            self.cell * self.logic.apple_y + 2 + self.h, r, r)

    def draw_text(self):
        self.canvas.set_color(self.theme_worker.colors[4])
        self.canvas.painter.setFont(QFont('Arial', 16))
        self.canvas.painter.drawText(0, 0 + self.h, self.cell, self.cell,
                                     Qt.AlignCenter,
                                     str(len(self.logic.snake.body) - 3))
        self.canvas.painter.drawText((self.logic.width - 4) * self.cell,
                                     0 + self.h, 4 * self.cell, self.cell,
                                     Qt.AlignCenter, self.player)
        if not self.play_sounds:
            self.canvas.painter.drawText(
                (self.logic.width - 1) * self.cell,
                (self.logic.height - 1) * self.cell + self.h, self.cell,
                self.cell, Qt.AlignCenter, '🔇')
        else:
            self.canvas.painter.drawText(
                (self.logic.width - 1) * self.cell,
                (self.logic.height - 1) * self.cell + self.h, self.cell,
                self.cell, Qt.AlignCenter, '🔈')
        if self.pause == True:
            self.canvas.painter.setFont(QFont('Arial', 32))
            self.canvas.painter.drawText(
                (self.logic.width // 2 - 4) * self.cell,
                (self.logic.height // 2 - 1) * self.cell + self.h,
                8 * self.cell, self.cell * 4, Qt.AlignCenter, 'PAUSED')

    def keyPressEvent(self, event: QKeyEvent) -> None:
        if event.key() == Qt.Key_Left:
            if self.logic.snake.y_dir:
                self.logic.snake.next_x_dir = -1
                self.logic.snake.next_y_dir = 0
        if event.key() == Qt.Key_Right:
            if self.logic.snake.y_dir:
                self.logic.snake.next_x_dir = 1
                self.logic.snake.next_y_dir = 0
        if event.key() == Qt.Key_Up:
            if self.logic.snake.x_dir:
                self.logic.snake.next_x_dir = 0
                self.logic.snake.next_y_dir = -1
        if event.key() == Qt.Key_Down:
            if self.logic.snake.x_dir:
                self.logic.snake.next_x_dir = 0
                self.logic.snake.next_y_dir = 1
        if event.key() == Qt.Key_Space:
            if self.pause == True:
                self.start_game()
            else:
                self.pause_game()

    def inv_color(self, color):
        return QColor(255 - color.red(), 255 - color.green(),
                      255 - color.blue())