Exemple #1
0
#!/usr/bin/python
import sys
from PyQt4.QtGui import QApplication
from gamewindow import GameWindow
app = QApplication(sys.argv)
w = GameWindow()
w.show()
sys.exit(app.exec_())

class MainWindow(QWidget):
    WIDTH = 800
    HEIGHT = 600

    STATE_NONE = 0
    STATE_GAME_HALL_GAME_LIST = 1
    STATE_GAME_HALL_MAP_LIST = 2
    STATE_GAME_HALL_MAP_SELECTED = 3
    STATE_GAME_HALL_GAME_SELECTED = 4
    STATE_GAME_ROOM_WAITING = 5

    ANIMATION_DEFAULT_AUTO_START = 3000
    ANIMATION_INITIAL_DELAY = 20
    ANIMATION_SHOW_BOTTOM_PANEL_DURATION = 700
    ANIMATION_SHOW_LEFT_PANEL_DURATION = 700
    ANIMATION_SHOW_MAIN_FRAME_DURATION = 700

    def __init__(self):
        super(MainWindow, self).__init__()
        self.setFixedSize(MainWindow.WIDTH, MainWindow.HEIGHT)

        self.mainTitle = Title('Distributed Real-time Risk', 36)
        self.subTitle = Title(' ' * 36 + 'Team 23', 20)

        layout = QGridLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        assert LeftPanel.OFFSET_Y == MainFrame.OFFSET_Y
        assert LeftPanel.HEIGHT == MainFrame.HEIGHT
        assert LeftPanel.OFFSET_Y + LeftPanel.HEIGHT == BottomPanel.OFFSET_Y
        assert BottomPanel.OFFSET_Y + BottomPanel.HEIGHT == MainWindow.HEIGHT
        layout.setRowStretch(0, LeftPanel.OFFSET_Y)
        layout.setRowStretch(1, LeftPanel.HEIGHT)
        layout.setRowStretch(2, BottomPanel.HEIGHT)

        assert LeftPanel.WIDTH + MainFrame.WIDTH == MainWindow.WIDTH
        layout.setColumnStretch(0, LeftPanel.WIDTH)
        layout.setColumnStretch(1, MainFrame.WIDTH)

        self.leftPanel = LeftPanel()
        self.bottomPanel = BottomPanel()
        self.mainFrame = MainFrame()
        layout.addWidget(self.leftPanel, 1, 0)
        layout.addWidget(self.bottomPanel, 2, 0, 1, -1)
        layout.addWidget(self.mainFrame, 1, 1)

        self.bottomPanel.gameHallControl.backButtonClicked.connect(
            self._onBackButtonClicked)
        self.bottomPanel.gameHallControl.createButtonClicked.connect(
            self._onCreateButtonClicked)
        self.bottomPanel.gameHallControl.joinButtonClicked.connect(
            self._onJoinButtonClicked)
        self.bottomPanel.gameRoomControl.backButtonClicked.connect(
            self._onBackButtonClicked)
        self.bottomPanel.gameRoomControl.startButtonClicked.connect(
            self._onStartButtonClicked)
        self.leftPanel.gameHallPanel.mapList.mapSelected.connect(
            self._onMapSelected)
        self.leftPanel.gameHallPanel.gameList.gameSelected.connect(
            self._onGameSelected)

        self.selectedMap = None
        self.selectedGameLoader = None
        self.selectedGame = None

        self.state = MainWindow.STATE_NONE
        self.initialAnimationStarted = False
        QMetaObject.invokeMethod(self, '_startAnimation', Qt.QueuedConnection)

    @Slot()
    def _startAnimation(self):
        self.leftPanel.hide()
        self.bottomPanel.hide()
        self.mainFrame.hide()

        delayAnimation = QPauseAnimation()
        delayAnimation.setDuration(MainWindow.ANIMATION_INITIAL_DELAY)
        delayAnimation.finished.connect(self.bottomPanel.show)

        showBottomPanelAnimation = QPropertyAnimation(self.bottomPanel, 'pos')
        showBottomPanelAnimation.setDuration(
            MainWindow.ANIMATION_SHOW_BOTTOM_PANEL_DURATION)
        showBottomPanelAnimation.setStartValue(
            self.bottomPanel.pos() + QPoint(0, self.bottomPanel.height()))
        showBottomPanelAnimation.setEndValue(self.bottomPanel.pos())
        showBottomPanelAnimation.setEasingCurve(QEasingCurve.OutExpo)
        showBottomPanelAnimation.finished.connect(self.leftPanel.show)
        showBottomPanelAnimation.finished.connect(self.mainFrame.show)

        parallelAnimationGroup = QParallelAnimationGroup()

        showLeftPanelAnimation = QPropertyAnimation(self.leftPanel, 'pos')
        showLeftPanelAnimation.setDuration(
            MainWindow.ANIMATION_SHOW_LEFT_PANEL_DURATION)
        showLeftPanelAnimation.setStartValue(self.leftPanel.pos() -
                                             QPoint(self.leftPanel.width(), 0))
        showLeftPanelAnimation.setEndValue(self.leftPanel.pos())
        showLeftPanelAnimation.setEasingCurve(QEasingCurve.OutBounce)
        parallelAnimationGroup.addAnimation(showLeftPanelAnimation)

        showMainFrameAnimation = QPropertyAnimation(self.mainFrame, 'pos')
        showMainFrameAnimation.setDuration(
            MainWindow.ANIMATION_SHOW_MAIN_FRAME_DURATION)
        showMainFrameAnimation.setStartValue(self.mainFrame.pos() +
                                             QPoint(self.mainFrame.width(), 0))
        showMainFrameAnimation.setEndValue(self.mainFrame.pos())
        showMainFrameAnimation.setEasingCurve(QEasingCurve.OutBounce)
        parallelAnimationGroup.addAnimation(showMainFrameAnimation)

        self.initialAnimationGroup = QSequentialAnimationGroup()
        self.initialAnimationGroup.addAnimation(delayAnimation)
        self.initialAnimationGroup.addAnimation(showBottomPanelAnimation)
        self.initialAnimationGroup.addAnimation(parallelAnimationGroup)
        self.initialAnimationGroup.finished.connect(self._loadGameHall)

        QTimer.singleShot(MainWindow.ANIMATION_DEFAULT_AUTO_START,
                          self._startInitialAnimation)

    def _startInitialAnimation(self):
        if not self.initialAnimationStarted:
            self.initialAnimationStarted = True
            self.initialAnimationGroup.start(
                QAbstractAnimation.DeleteWhenStopped)

    def _setState(self, state, id=None):
        if self.state == MainWindow.STATE_GAME_HALL_MAP_SELECTED:
            if self.selectedMap is not None:
                self.selectedMap.infoUpdated.disconnect()
                self.selectedMap.parseFinished.disconnect()
                self.selectedMap = None
        elif self.state == MainWindow.STATE_GAME_HALL_GAME_SELECTED:
            if self.selectedGameLoader is not None:
                self.selectedGameLoader.loaded.disconnect()
                self.selectedGameLoader = None
        elif self.state == MainWindow.STATE_GAME_ROOM_WAITING:
            assert self.selectedGame is not None
            if self.mainFrame.gameViewFrame.countDown.t > 0:
                self.mainFrame.gameViewFrame.countDown.finished.disconnect()
            try:
                self.selectedGame.gameMap.parseFinished.disconnect()
            except:
                pass
            self.selectedGame.destroy()
            self.selectedGame = None

        if state == MainWindow.STATE_GAME_HALL_GAME_LIST:
            assert self.state == MainWindow.STATE_NONE or \
                   self.state == MainWindow.STATE_GAME_HALL_MAP_LIST or \
                   self.state == MainWindow.STATE_GAME_HALL_MAP_SELECTED or \
                   self.state == MainWindow.STATE_GAME_ROOM_WAITING
            self.leftPanel.gameHallPanel.showGameList()
            self.leftPanel.showGameHallPanel()
            self.mainFrame.introFrame.setTitle('Distribued Real-time Risk')
            self.mainFrame.introFrame.loading.hide()
            self.mainFrame.showIntroFrame()
            self.bottomPanel.gameHallControl.setAllowBack(False)
            self.bottomPanel.gameHallControl.createButton.setEnabled(True)
            self.bottomPanel.gameHallControl.joinButton.setEnabled(False)
            self.bottomPanel.showGameHallControl()
        elif state == MainWindow.STATE_GAME_HALL_MAP_LIST:
            assert self.state == MainWindow.STATE_GAME_HALL_GAME_LIST or \
                   self.state == MainWindow.STATE_GAME_HALL_GAME_SELECTED
            self.leftPanel.gameHallPanel.showMapList()
            self.leftPanel.showGameHallPanel()
            self.mainFrame.introFrame.setTitle('Create Game')
            self.mainFrame.introFrame.loading.hide()
            self.mainFrame.showIntroFrame()
            self.bottomPanel.gameHallControl.setAllowBack(True)
            self.bottomPanel.gameHallControl.createButton.setEnabled(False)
            self.bottomPanel.gameHallControl.joinButton.setEnabled(False)
        elif state == MainWindow.STATE_GAME_HALL_MAP_SELECTED:
            assert self.state == MainWindow.STATE_GAME_HALL_MAP_LIST or \
                   self.state == MainWindow.STATE_GAME_HALL_MAP_SELECTED
            self.selectedMap = GameMap.getGameMap(id)
            self.selectedMap.infoUpdated.connect(
                self.mainFrame.detailFrame.info.updateInfo,
                Qt.QueuedConnection)
            self.selectedMap.parseFinished.connect(
                self.mainFrame.detailFrame.info.loading.hide,
                Qt.QueuedConnection)
            self.selectedMap.parseFinished.connect(
                self.bottomPanel.gameHallControl.createButton.setEnabled,
                Qt.QueuedConnection)
            self.selectedMap.parseAll()
            self.mainFrame.detailFrame.setTitle(self.selectedMap.mapName)
            self.mainFrame.detailFrame.preview.setImage(
                self.selectedMap.background)
            self.mainFrame.detailFrame.info.updateInfo([])
            self.mainFrame.detailFrame.info.loading.show()
            self.mainFrame.showDetailFrame()
            self.bottomPanel.gameHallControl.createButton.setEnabled(False)
        elif state == MainWindow.STATE_GAME_HALL_GAME_SELECTED:
            assert self.state == MainWindow.STATE_GAME_HALL_GAME_LIST or \
                   self.state == MainWindow.STATE_GAME_HALL_GAME_SELECTED
            assert id is not None
            self.selectedGame = None
            name = self.leftPanel.gameHallPanel.gameList.items[id].text()
            mapId = self.leftPanel.gameHallPanel.gameList.items[id].mapId
            self.selectedGameLoader = GameLoader(
                id, name, mapId,
                self.leftPanel.gameHallPanel.playerName.text())
            self.selectedGameLoader.loaded.connect(self._onGameLoaded)
            self.selectedGameLoader.load()
            self.mainFrame.introFrame.setTitle(self.selectedGameLoader.name)
            self.mainFrame.introFrame.loading.show()
            self.mainFrame.showIntroFrame()
            self.bottomPanel.gameHallControl.joinButton.setEnabled(False)
        elif state == MainWindow.STATE_GAME_ROOM_WAITING:
            assert self.state == MainWindow.STATE_GAME_HALL_GAME_SELECTED or \
                   self.state == MainWindow.STATE_GAME_HALL_MAP_SELECTED
            self.selectedGame.playersUpdated.connect(
                self.leftPanel.gameRoomPanel.playerList.setPlayers)
            self.selectedGame.joined.connect(self._onGameJoined)
            self.selectedGame.joinFailed.connect(self._onGameJoinFailed)
            self.selectedGame.started.connect(self._onGameStarted)
            self.selectedGame.gameMap.parseFinished.connect(
                self._onJoinGameParseFinished)
            self.selectedGame.gameMap.parseAll()
            self.leftPanel.gameRoomPanel.playerList.setPlayers(
                self.selectedGame.players)
            self.leftPanel.gameRoomPanel.setGameName(
                self.selectedGame.gameName)
            self.leftPanel.showGameRoomPanel()
            self.mainFrame.gameViewFrame.setTitle(
                self.selectedGame.gameName + ' : ' +
                self.selectedGame.gameMap.mapName)
            self.mainFrame.gameViewFrame.showLoading()
            self.mainFrame.showGameViewFrame()
            self.bottomPanel.gameHallControl.createButton.setEnabled(False)
            self.bottomPanel.gameRoomControl.startButton.setEnabled(False)
            self.bottomPanel.showGameRoomControl()
        else:
            qFatal('Invalid state %d when trying to set state' % state)
        self.state = state

    @Slot()
    def _loadGameHall(self):
        self._setState(MainWindow.STATE_GAME_HALL_GAME_LIST)

    @Slot()
    def _onBackButtonClicked(self):
        assert self.state == MainWindow.STATE_GAME_HALL_MAP_LIST or \
               self.state == MainWindow.STATE_GAME_HALL_MAP_SELECTED or \
               self.state == MainWindow.STATE_GAME_ROOM_WAITING
        self._setState(MainWindow.STATE_GAME_HALL_GAME_LIST)

    @Slot()
    def _onCreateButtonClicked(self):
        if self.state == MainWindow.STATE_GAME_HALL_GAME_LIST or \
           self.state == MainWindow.STATE_GAME_HALL_GAME_SELECTED:
            self._setState(MainWindow.STATE_GAME_HALL_MAP_LIST)
        elif self.state == MainWindow.STATE_GAME_HALL_MAP_SELECTED:
            self.selectedGame = Game(
                -1, Game.randomGameName(), self.selectedMap,
                self.leftPanel.gameHallPanel.playerName.text())
            self.selectedGame.addPlayer(
                Player(-1, self.leftPanel.gameHallPanel.playerName.text()))
            self.selectedGame.createGame()
            self._setState(MainWindow.STATE_GAME_ROOM_WAITING)
        else:
            qFatal('Invalid state %d when create button clicked' % self.state)

    @Slot()
    def _onJoinButtonClicked(self):
        #self.selectedGame.addPlayer(Player(-1, self.leftPanel.gameHallPanel.playerName.text()))
        self._setState(MainWindow.STATE_GAME_ROOM_WAITING)

    @Slot()
    def _onStartButtonClicked(self):
        self.bottomPanel.gameRoomControl.startButton.setEnabled(False)
        self.selectedGame.startGame()

    @Slot(str)
    def _onMapSelected(self, id):
        self._setState(MainWindow.STATE_GAME_HALL_MAP_SELECTED, id)

    @Slot(str)
    def _onGameSelected(self, id):
        self._setState(MainWindow.STATE_GAME_HALL_GAME_SELECTED, id)

    @Slot()
    def _onGameLoaded(self):
        self.selectedGame = self.selectedGameLoader.game
        playersInfo = [('Players', '')]
        for player in self.selectedGameLoader.players:
            playersInfo.append((player, None))
        self.selectedGameLoader = None
        self.mainFrame.showDetailFrame(False)
        self.mainFrame.detailFrame.setTitle(self.selectedGame.gameName +
                                            ' : ' +
                                            self.selectedGame.gameMap.mapName)
        self.mainFrame.detailFrame.preview.setImage(
            self.selectedGame.gameMap.background)
        self.mainFrame.detailFrame.info.updateInfo(playersInfo)
        self.mainFrame.detailFrame.info.loading.hide()
        self.bottomPanel.gameHallControl.joinButton.setEnabled(True)

    def _loadGameView(self):
        self.mainFrame.gameViewFrame.showGameView(self.selectedGame.gameMap)
        self.selectedGame.updateOwner.connect(
            self.mainFrame.gameViewFrame.gameView.setOwner)
        self.selectedGame.updateArmy.connect(
            self.mainFrame.gameViewFrame.gameView.setArmy)
        self.selectedGame.updateAttack.connect(
            self.mainFrame.gameViewFrame.gameView.setAttack)
        self.selectedGame.updateFlash.connect(
            self.mainFrame.gameViewFrame.gameView.setFlash)
        self.bottomPanel.gameRoomControl.startButton.setEnabled(True)

    @Slot()
    def _onGameJoined(self):
        self.mainFrame.gameViewFrame.setTitle(
            self.selectedGame.gameName + ' : ' +
            self.selectedGame.gameMap.mapName)
        self.leftPanel.gameRoomPanel.playerList.setPlayers(
            self.selectedGame.players)
        assert self.selectedGame.gameMap.parsed == 2
        self._loadGameView()

    @Slot()
    def _onGameJoinFailed(self):
        self.mainFrame.gameViewFrame.setTitle(
            'Sorry... Please try join another game')
        self.mainFrame.gameViewFrame.loading.hide()

    @Slot()
    def _onGameStarted(self):
        self.mainFrame.gameViewFrame.showCountDown(self.selectedGame.ob)
        self.mainFrame.gameViewFrame.countDown.finished.connect(
            self._onGameStartCountDownFinished)

    @Slot()
    def _onGameStartCountDownFinished(self):
        self.mainFrame.gameViewFrame.countDown.finished.disconnect()
        self.hide()
        self.selectedGameWindow = GameWindow(
            self.selectedGame, self.mainFrame.gameViewFrame.gameView)
        self.selectedGameWindow.closed.connect(self._onGameWindowClosed)
        self.selectedGameWindow.statBox.setPlayers(self.selectedGame.players)
        self.mainFrame.gameViewFrame.gameView = None
        self.selectedGameWindow.show()

    @Slot()
    def _onGameWindowClosed(self):
        self.selectedGameWindow.deleteLater()
        self.selectedGameWindow = None
        self.show()
        self._setState(MainWindow.STATE_GAME_HALL_GAME_LIST)

    @Slot()
    def _onJoinGameParseFinished(self):
        self.selectedGame.joinGame()

    def keyPressEvent(self, event):
        self._startInitialAnimation()
        super(MainWindow, self).keyPressEvent(event)

    def mousePressEvent(self, event):
        self._startInitialAnimation()
        super(MainWindow, self).mousePressEvent(event)

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)

        # background
        image = QImage(QDir.currentPath() + '/gui/images/background.png')
        image = image.copy(MainFrame.OFFSET_X, MainFrame.OFFSET_Y,
                           MainFrame.WIDTH, MainFrame.HEIGHT)
        image = image.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio,
                             Qt.SmoothTransformation)
        painter.drawImage(0, 0, image)

        # text
        image = self.mainTitle.titleImage()
        painter.drawImage((self.width() - image.width()) / 2,
                          (self.height() - image.height()) / 2 - 50, image)
        image = self.subTitle.titleImage()
        painter.drawImage((self.width() - image.width()) / 2,
                          (self.height() - image.height()) / 2 + 50, image)

        painter.end()

    def show(self):
        super(MainWindow, self).show()
        rect = QStyle.alignedRect(Qt.LeftToRight, Qt.AlignCenter, self.size(),
                                  QApplication.desktop().availableGeometry())
        self.move(rect.x(), rect.y())