game.py 4.66 KB
Newer Older
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 18:34:40 2018

@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""

9
import os
10
11
import logging

12
13
from PyQt5 import QtWidgets
from PyQt5.QtGui import QRegion
Antoine Lima's avatar
Antoine Lima committed
14
15
16
from PyQt5.QtCore import QTime, QTimer, QRect, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
17

18
from player import Side
19
from replay import Replay
20
21
22
23
from module import Module
import modules
from ui.game_ui import Ui_Form as GameWidget

Antoine Lima's avatar
Antoine Lima committed
24
25
26
27
28
29
30
31
class GameOverChecker():
	def __init__(self, conditionType, limit):
		self.conditionType = conditionType
		self.limit = limit
	
	def check(self, time, scores):
		'''
		Checks if a game is over and return the winner if that's the case
32
		Returns the winning side or Side.Undef otherwise
Antoine Lima's avatar
Antoine Lima committed
33
34
35
36
		
		Takes the game time is seconds and a list containing the two scores
		'''
		
37
38
		# Gets the index of the highest scoring player
		bestPlayer = max(scores, key=scores.get)
Antoine Lima's avatar
Antoine Lima committed
39
40
41
42
43
44
		
		if self.conditionType=='score' and scores[bestPlayer]>=self.limit:
			return bestPlayer
		elif self.conditionType=='time' and time>self.limit:
			return bestPlayer
		else:
45
			return Side.Undef
Antoine Lima's avatar
Antoine Lima committed
46
		
47
48
49
50
51
52
53
54
55
class GameModule(Module):
	def __init__(self, parent=None):
		super().__init__(parent, GameWidget())

		# Timer managment
		self.timerUpdateChrono = QTimer(self)
		self.timerUpdateChrono.timeout.connect(self.updateChrono)

		# Button connections
56
57
		self.ui.btnScore1.clicked.connect(lambda: self.goal(Side.Left))
		self.ui.btnScore2.clicked.connect(lambda: self.goal(Side.Right))
58
59
		
		self.replayer = Replay()
Antoine Lima's avatar
Antoine Lima committed
60
	
61
62
63
64
65
	def load(self):
		logging.debug('Loading GameModule')

		self.gameStartTime = QTime.currentTime()
		self.timerUpdateChrono.start(1000)
66
		self.ui.lcdChrono.display(QTime(0,0).toString("hh:mm:ss"))
Antoine Lima's avatar
Antoine Lima committed
67
		
68
		self.showingReplay = False
Antoine Lima's avatar
Antoine Lima committed
69
		self.gameoverChecker = GameOverChecker('score', 10)
70

71
		self.scores = {Side.Left: 0, Side.Right: 0}
72
		self.updateScores()
73
74
75
76
77
78
79
80

	def unload(self):
		logging.debug('Unloading GameModule')
		del self.gameStartTime
		self.timerUpdateChrono.stop()
	
	def other(self, **kwargs):
		logging.debug('Other GameModule')
81
82
83
		
		if 'players' in kwargs:
			self.players = kwargs['players']
84
85
86
	
	def resizeEvent(self, event):
		# 40% of the window width to have (5% margin)-(40% circle)-(10% middle)-(40% circle)-(5% margin)
Antoine Lima's avatar
Antoine Lima committed
87
		btnDiameter = self.mainwin.width()*0.4
88
89
90
91
92
93
94
95
96
97
		region = QRegion(QRect(0, 0, btnDiameter, btnDiameter), QRegion.Ellipse)
		self.ui.btnScore1.setMinimumSize(btnDiameter, btnDiameter)
		self.ui.btnScore2.setMinimumSize(btnDiameter, btnDiameter)
		self.ui.btnScore1.setMask(region)
		self.ui.btnScore2.setMask(region)
		
		QtWidgets.QWidget.resizeEvent(self, event)

	def keyPressEvent(self, e):
		if e.key() == Qt.Key_Escape:
98
			self.handleCancel()
99
		elif e.key() == Qt.Key_Left:
100
			self.goal(Side.Left)
101
		elif e.key() == Qt.Key_Right:
102
			self.goal(Side.Right)
103
104
105

	def updateChrono(self):
		# Updated each second
Antoine Lima's avatar
Antoine Lima committed
106
107
108
109
110
		self.ui.lcdChrono.display(QTime(0,0).addSecs(self.getGameTime()).toString("hh:mm:ss"))
		
		# Don't check scores while showing a replay to avoid closing the engame screen too soon
		if not self.showingReplay:
			self.checkEndGame()
111

Antoine Lima's avatar
Antoine Lima committed
112
113
114
	def getGameTime(self):
		return self.gameStartTime.secsTo(QTime.currentTime())
	
115
	def updateScores(self):
116
117
		self.ui.btnScore1.setText(str(self.scores[Side.Left]))
		self.ui.btnScore2.setText(str(self.scores[Side.Right]))
Antoine Lima's avatar
Antoine Lima committed
118
119
120
		self.checkEndGame()
		
	def goal(self, side):
121
		if side not in Side:
Antoine Lima's avatar
Antoine Lima committed
122
123
124
125
126
127
			logging.error('Wrong goal side: {}'.format(side))
		else:
			self.scores[side] += 1
			
			# Show replay
			# May require `sudo apt-get install qtmultimedia5-examples` in order to install the right libraries
128
			replayFile = self.mainwin.getContent('Replay {}.mp4'.format(side.name))
Antoine Lima's avatar
Antoine Lima committed
129
			
130
			if os.path.exists(replayFile):
131
132
133
134
135
136
137
138
139
140
141
				if True: # Debug Mode
					self.updateScores()
				else:
					self.showingReplay = True
					self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
					self.player.stateChanged.connect(self.endOfReplay)
					self.player.setMuted(True)
					self.player.setVideoOutput(self.ui.videoWidget)
					self.player.setMedia(QMediaContent(QUrl.fromLocalFile(replayFile)))
					self.player.play()
					self.ui.videoWidget.setFullScreen(True)
Antoine Lima's avatar
Antoine Lima committed
142
143
144
145
146
147
148
	
	def endOfReplay(self, status):
		if status!=QMediaPlayer.PlayingState:
			self.ui.videoWidget.setFullScreen(False);
			self.showingReplay = False
			self.updateScores()
			
149

150
	def handleCancel(self):
151
		self.switchModule(modules.MenuModule)
Antoine Lima's avatar
Antoine Lima committed
152
153
		
	def checkEndGame(self):
154
		winSide = self.gameoverChecker.check(self.getGameTime(), self.scores)
Antoine Lima's avatar
Antoine Lima committed
155
		
156
157
		if winSide!=Side.Undef:
			self.send(modules.EndGameModule, players=self.players, winSide=winSide, scores=self.scores, time=self.getGameTime())
Antoine Lima's avatar
Antoine Lima committed
158
			self.switchModule(modules.EndGameModule)