├── LICENSE ├── README.md ├── game.py └── sprites ├── cacti-big.png ├── cacti-small.png ├── checkPoint.wav ├── cloud.png ├── die.wav ├── dino.png ├── dino_ducking.png ├── game_over.png ├── ground.png ├── jump.wav ├── logo.png ├── logo.psd ├── logoa.png ├── numbers.png ├── offline-sprite-2x-black.png ├── ptera.png └── replay_button.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 khvmaths 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DinoRun-PyQt-PyGame 2 | Integration between Pygame and PyQt5 for Dino Run Game 3 | 4 | # Support me 5 | Buy Me A Coffee 6 | 7 | # Concept 8 | ## Concept of the game and the design flow. 9 | This game is purely designed with PyGame library. To link two different GUIs is not possible. As such, a simple trick is done. It is started with initializing the PyGame library to run a GUI (pygame.init()). Since the GUI created by PyGame is supposed to be ‘embedded’ into PyQt, the PyGame’s GUI is ‘hidden’ by setting it’s windows coordinate out of the screen, using os library with the command `os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (-300,-300)`. 10 | 11 | As such, the PyGame window shall started at x=-300 and y=-300, which is out of the screen, or ‘hidden’ from user. The next step is to capturing every frame created by PyGame and show it in the PyQt windows. So, at the end of the gameplay function (situated in class App), the four lines below is used. 12 | 13 | ```python 14 | data=screen.get_buffer().raw 15 | image=QtGui.QImage(data,width,height,QtGui.QImage.Format_RGB32) 16 | pixmap = QPixmap.fromImage(image) 17 | win.setPixmap(pixmap) 18 | ``` 19 | First, the data variable get the PyGame’s screen raw buffer. By utilizing ```QtGui.QImage```, the raw buffer is converted into RGB32 format image. With the help of ```QPixmap```, the image is then set to map the label and shown in the label. 20 | 21 | The second problem is the keyboard event. Since the game is developed in PyGame, thus the keyboard event is defined in PyGame. By the help of PyQt key press event, every key is captured and stored in act variable which is then used to compare and made the right move. 22 | 23 | The OpenCV is implemented. The technique used is morphological transformations. It is used to detect an object and track. It tends to come in pairs. Erosion is used to erode the edge and Dilation is used to do the opposite of erosion. This is used to analyses sequential video frames and outputs the movement of targets between the frame. 24 | 25 | ## How to play the game? 26 | Choose the desired game mode and press space to start the game. Use space bar or up arrow to jump and down arrow to duck. 27 | 28 | 29 | Main game reference from **Rohit Rane** 30 | -------------------------------------------------------------------------------- /game.py: -------------------------------------------------------------------------------- 1 | __author__ = "Koay Hong Vin" 2 | __MatricNo__ = "KIE160111" 3 | __Title__ = "Assignment 2" 4 | __GitHub__ = "https://github.com/khvmaths" 5 | 6 | import sys 7 | from PyQt5 import QtCore,QtGui,QtWidgets 8 | from PyQt5.QtCore import QThread 9 | from PyQt5.QtGui import QImage, QPixmap 10 | from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QLabel, QPushButton 11 | 12 | import cv2 13 | import numpy as np 14 | import math 15 | import pygame 16 | import random 17 | import os 18 | import time 19 | 20 | os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (-300,-300) 21 | 22 | from collections import deque 23 | import argparse 24 | #import gamegui 25 | 26 | """GUI""" 27 | class Ui_Dialog(object): 28 | def setupUi(self, Dialog): 29 | Dialog.setObjectName("Dialog") 30 | Dialog.resize(637, 317) 31 | self.groupBox = QtWidgets.QGroupBox(Dialog) 32 | self.groupBox.setGeometry(QtCore.QRect(640, 10, 251, 301)) 33 | self.groupBox.setObjectName("groupBox") 34 | self.label = QtWidgets.QLabel(self.groupBox) 35 | self.label.setGeometry(QtCore.QRect(20, 20, 101, 16)) 36 | self.label.setObjectName("label") 37 | self.label_4 = QtWidgets.QLabel(self.groupBox) 38 | self.label_4.setGeometry(QtCore.QRect(20, 200, 141, 16)) 39 | self.label_4.setObjectName("label_4") 40 | self.label_5 = QtWidgets.QLabel(self.groupBox) 41 | self.label_5.setGeometry(QtCore.QRect(20, 220, 211, 31)) 42 | font = QtGui.QFont() 43 | font.setPointSize(14) 44 | font.setBold(True) 45 | font.setWeight(75) 46 | self.label_5.setFont(font) 47 | self.label_5.setText("") 48 | self.label_5.setObjectName("label_5") 49 | self.label_7 = QtWidgets.QLabel(self.groupBox) 50 | self.label_7.setGeometry(QtCore.QRect(20, 40, 221, 151)) 51 | self.label_7.setText("") 52 | self.label_7.setObjectName("label_7") 53 | self.pushButton_5 = QtWidgets.QPushButton(self.groupBox) 54 | self.pushButton_5.setGeometry(QtCore.QRect(60, 260, 131, 31)) 55 | font = QtGui.QFont() 56 | font.setPointSize(10) 57 | font.setBold(True) 58 | font.setWeight(75) 59 | self.pushButton_5.setFont(font) 60 | self.pushButton_5.setAutoDefault(False) 61 | self.pushButton_5.setObjectName("pushButton_5") 62 | self.groupBox_3 = QtWidgets.QGroupBox(Dialog) 63 | self.groupBox_3.setGeometry(QtCore.QRect(10, 210, 141, 71)) 64 | self.groupBox_3.setObjectName("groupBox_3") 65 | self.label_6 = QtWidgets.QLabel(self.groupBox_3) 66 | self.label_6.setGeometry(QtCore.QRect(10, 20, 121, 51)) 67 | font = QtGui.QFont() 68 | font.setFamily("MS Serif") 69 | font.setPointSize(16) 70 | font.setBold(True) 71 | font.setWeight(75) 72 | self.label_6.setFont(font) 73 | self.label_6.setText("") 74 | self.label_6.setObjectName("label_6") 75 | self.pushButton_3 = QtWidgets.QPushButton(Dialog) 76 | self.pushButton_3.setGeometry(QtCore.QRect(350, 220, 131, 61)) 77 | font = QtGui.QFont() 78 | font.setPointSize(10) 79 | font.setBold(True) 80 | font.setWeight(75) 81 | self.pushButton_3.setFont(font) 82 | self.pushButton_3.setAutoDefault(True) 83 | self.pushButton_3.setDefault(True) 84 | self.pushButton_3.setFlat(False) 85 | self.pushButton_3.setObjectName("pushButton_3") 86 | self.groupBox_2 = QtWidgets.QGroupBox(Dialog) 87 | self.groupBox_2.setGeometry(QtCore.QRect(10, 10, 621, 181)) 88 | self.groupBox_2.setObjectName("groupBox_2") 89 | self.label_2 = QtWidgets.QLabel(self.groupBox_2) 90 | self.label_2.setGeometry(QtCore.QRect(10, 20, 601, 151)) 91 | self.label_2.setObjectName("label_2") 92 | self.pushButton_4 = QtWidgets.QPushButton(Dialog) 93 | self.pushButton_4.setGeometry(QtCore.QRect(490, 220, 131, 61)) 94 | font = QtGui.QFont() 95 | font.setPointSize(10) 96 | font.setBold(True) 97 | font.setWeight(75) 98 | self.pushButton_4.setFont(font) 99 | self.pushButton_4.setAutoDefault(False) 100 | self.pushButton_4.setObjectName("pushButton_4") 101 | self.label_9 = QtWidgets.QLabel(Dialog) 102 | self.label_9.setGeometry(QtCore.QRect(20, 290, 171, 16)) 103 | self.label_9.setObjectName("label_9") 104 | self.groupBox_4 = QtWidgets.QGroupBox(Dialog) 105 | self.groupBox_4.setGeometry(QtCore.QRect(160, 210, 141, 71)) 106 | self.groupBox_4.setObjectName("groupBox_4") 107 | self.label_10 = QtWidgets.QLabel(self.groupBox_4) 108 | self.label_10.setGeometry(QtCore.QRect(10, 20, 121, 51)) 109 | font = QtGui.QFont() 110 | font.setFamily("MS Serif") 111 | font.setPointSize(16) 112 | font.setBold(True) 113 | font.setWeight(75) 114 | self.label_10.setFont(font) 115 | self.label_10.setText("") 116 | self.label_10.setObjectName("label_10") 117 | self.label_3 = QtWidgets.QLabel(Dialog) 118 | self.label_3.setGeometry(QtCore.QRect(340, 290, 291, 20)) 119 | self.label_3.setTextFormat(QtCore.Qt.RichText) 120 | self.label_3.setObjectName("label_3") 121 | 122 | self.retranslateUi(Dialog) 123 | QtCore.QMetaObject.connectSlotsByName(Dialog) 124 | 125 | def retranslateUi(self, Dialog): 126 | _translate = QtCore.QCoreApplication.translate 127 | Dialog.setWindowTitle(_translate("Dialog", "Dino Run")) 128 | self.groupBox.setTitle(_translate("Dialog", "OpenCV Processing")) 129 | self.label.setText(_translate("Dialog", "Original Image")) 130 | self.label_4.setText(_translate("Dialog", "Processed Information")) 131 | self.pushButton_5.setText(_translate("Dialog", "Stop CV")) 132 | self.groupBox_3.setTitle(_translate("Dialog", "Score Board")) 133 | self.pushButton_3.setText(_translate("Dialog", "Normal Start")) 134 | self.groupBox_2.setTitle(_translate("Dialog", "Game Area")) 135 | self.label_2.setText(_translate("Dialog", "TextLabel")) 136 | self.pushButton_4.setText(_translate("Dialog", "Start with CV")) 137 | self.label_9.setText(_translate("Dialog", "TextLabel")) 138 | self.groupBox_4.setTitle(_translate("Dialog", "High Score")) 139 | self.label_3.setText(_translate("Dialog", "

Developed by Koay Hong Vin (KIE160111)

")) 140 | 141 | 142 | """THE CV IS HIGHLY DEPENDENT ON ENVIRONMENT/NOISE""" 143 | threshold = 60 # BINARY threshold 144 | blurValue = 41 # GaussianBlur parameter 145 | Lower_bound=np.array([110,50,50]) 146 | Upper_bound=np.array([130,255,255]) 147 | pts=deque(maxlen=64) 148 | 149 | """OPENCV PART == TODO: Change the whole idea of detecting movement""" 150 | class FrameThread(QThread,Ui_Dialog): 151 | imgLab = None 152 | device = None 153 | 154 | def __init__(self,deviceIndex,imgLab,action): 155 | QThread.__init__(self) 156 | self.imgLab = imgLab 157 | self.action=action 158 | self.deviceIndex = deviceIndex 159 | 160 | self.device = cv2.VideoCapture(self.deviceIndex) 161 | self.device.set(cv2.CAP_PROP_FRAME_WIDTH, 1600) 162 | self.device.set(cv2.CAP_PROP_FRAME_HEIGHT, 1200) 163 | 164 | def run(self): 165 | if self.device.isOpened(): 166 | last_center=(0,0) 167 | try: 168 | while True: 169 | ret, frame = self.device.read() 170 | height, width, bytesPerComponent = frame.shape 171 | bytesPerLine = bytesPerComponent * width 172 | 173 | cv2.cvtColor(frame, cv2.COLOR_BGR2RGB, frame) 174 | 175 | 176 | hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV) 177 | kernel=np.ones((5,5),np.uint8) 178 | mask=cv2.inRange(hsv,Lower_bound,Upper_bound) 179 | mask=cv2.erode(mask,kernel,iterations=2) 180 | mask=cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel) 181 | mask=cv2.dilate(mask,kernel,iterations=1) 182 | res=cv2.bitwise_and(frame,frame,mask=mask) 183 | cnts,heir=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2:] 184 | center=None 185 | 186 | if len(cnts)>0: 187 | c=max(cnts,key=cv2.contourArea) 188 | ((x,y),radius)=cv2.minEnclosingCircle(c) 189 | M=cv2.moments(c) 190 | center=(int(M["m10"]/M["m00"]),int(M["m01"]/M["m00"])) 191 | print(center) 192 | 193 | if radius>5: 194 | cv2.circle(frame,(int(x),int(y)),int(radius),(0,255,255),2) 195 | cv2.circle(frame,center,5,(0,0,255),-1) 196 | pts.appendleft(center) 197 | 198 | for i in range(1,len(pts)): 199 | if pts[i-1] is None or pts[i] is None: 200 | continue 201 | thick=int(np.sqrt(len(pts)/float(i+1))*2.5) 202 | cv2.line(frame,pts[i-1],pts[i],(0,0,255),thick) 203 | 204 | flipped=cv2.flip(frame,1) 205 | image = QImage(flipped, width, height, bytesPerLine, QImage.Format_RGB888) 206 | pixmap = QPixmap.fromImage(image) 207 | pixmap = pixmap.scaled(221, 191, QtCore.Qt.KeepAspectRatio) 208 | 209 | if (center==None): 210 | continue 211 | else: 212 | if(abs(center[0]-last_center[0])>5 and abs(center[1]-last_center[1]<20)): 213 | if(center[0]>last_center[0]): 214 | pass 215 | else: 216 | pass 217 | elif(abs(center[1]-last_center[1]))>10: 218 | if(center[1]>last_center[1]): 219 | act='Down' 220 | else: 221 | act='Up' 222 | else: 223 | act='No action' 224 | last_center=center 225 | 226 | self.imgLab.setPixmap(pixmap) 227 | self.action.setText(act) 228 | except: 229 | pass 230 | 231 | 232 | 233 | def destoryed(self,QObject=None): 234 | self.device.release() 235 | 236 | 237 | """MAIN GAME TRESHOLD""" 238 | pygame.init() 239 | 240 | scr_size = (width,height) = (600,150) 241 | FPS = 60 242 | gravity = 0.6 243 | 244 | black = (0,0,0) 245 | white = (255,255,255) 246 | background_col = (235,235,235) 247 | 248 | high_score = 0 249 | 250 | screen = pygame.display.set_mode(scr_size) 251 | clock = pygame.time.Clock() 252 | pygame.display.set_caption("Dino Run ") 253 | 254 | jump_sound = pygame.mixer.Sound('sprites/jump.wav') 255 | die_sound = pygame.mixer.Sound('sprites/die.wav') 256 | checkPoint_sound = pygame.mixer.Sound('sprites/checkPoint.wav') 257 | 258 | def load_image( 259 | name, 260 | sizex=-1, 261 | sizey=-1, 262 | colorkey=None, 263 | ): 264 | 265 | fullname = os.path.join('sprites', name) 266 | image = pygame.image.load(fullname) 267 | image = image.convert() 268 | if colorkey is not None: 269 | if colorkey is -1: 270 | colorkey = image.get_at((0, 0)) 271 | image.set_colorkey(colorkey, pygame.RLEACCEL) 272 | 273 | if sizex != -1 or sizey != -1: 274 | image = pygame.transform.scale(image, (sizex, sizey)) 275 | 276 | return (image, image.get_rect()) 277 | 278 | def load_sprite_sheet( 279 | sheetname, 280 | nx, 281 | ny, 282 | scalex = -1, 283 | scaley = -1, 284 | colorkey = None, 285 | ): 286 | fullname = os.path.join('sprites',sheetname) 287 | sheet = pygame.image.load(fullname) 288 | sheet = sheet.convert() 289 | 290 | sheet_rect = sheet.get_rect() 291 | 292 | sprites = [] 293 | 294 | sizex = sheet_rect.width/nx 295 | sizey = sheet_rect.height/ny 296 | 297 | for i in range(0,ny): 298 | for j in range(0,nx): 299 | rect = pygame.Rect((j*sizex,i*sizey,sizex,sizey)) 300 | image = pygame.Surface(rect.size) 301 | image = image.convert() 302 | image.blit(sheet,(0,0),rect) 303 | 304 | if colorkey is not None: 305 | if colorkey is -1: 306 | colorkey = image.get_at((0,0)) 307 | image.set_colorkey(colorkey,pygame.RLEACCEL) 308 | 309 | if scalex != -1 or scaley != -1: 310 | image = pygame.transform.scale(image,(scalex,scaley)) 311 | 312 | sprites.append(image) 313 | 314 | sprite_rect = sprites[0].get_rect() 315 | 316 | return sprites,sprite_rect 317 | 318 | def disp_gameOver_msg(retbutton_image,gameover_image): 319 | retbutton_rect = retbutton_image.get_rect() 320 | retbutton_rect.centerx = width / 2 321 | retbutton_rect.top = height*0.52 322 | 323 | gameover_rect = gameover_image.get_rect() 324 | gameover_rect.centerx = width / 2 325 | gameover_rect.centery = height*0.35 326 | 327 | screen.blit(retbutton_image, retbutton_rect) 328 | screen.blit(gameover_image, gameover_rect) 329 | 330 | def extractDigits(number): 331 | if number > -1: 332 | digits = [] 333 | i = 0 334 | while(number/10 != 0): 335 | digits.append(number%10) 336 | number = int(number/10) 337 | 338 | digits.append(number%10) 339 | for i in range(len(digits),5): 340 | digits.append(0) 341 | digits.reverse() 342 | return digits 343 | 344 | class Dino(): 345 | def __init__(self,sizex=-1,sizey=-1): 346 | self.images,self.rect = load_sprite_sheet('dino.png',5,1,sizex,sizey,-1) 347 | self.images1,self.rect1 = load_sprite_sheet('dino_ducking.png',2,1,59,sizey,-1) 348 | self.rect.bottom = int(0.98*height) 349 | self.rect.left = width/15 350 | self.image = self.images[0] 351 | self.index = 0 352 | self.counter = 0 353 | self.score = 0 354 | self.isJumping = False 355 | self.isDead = False 356 | self.isDucking = False 357 | self.isBlinking = False 358 | self.movement = [0,0] 359 | self.jumpSpeed = 11.5 360 | 361 | self.stand_pos_width = self.rect.width 362 | self.duck_pos_width = self.rect1.width 363 | 364 | def draw(self): 365 | screen.blit(self.image,self.rect) 366 | 367 | def checkbounds(self): 368 | if self.rect.bottom > int(0.98*height): 369 | self.rect.bottom = int(0.98*height) 370 | self.isJumping = False 371 | 372 | def update(self): 373 | if self.isJumping: 374 | self.movement[1] = self.movement[1] + gravity 375 | 376 | if self.isJumping: 377 | self.index = 0 378 | elif self.isBlinking: 379 | if self.index == 0: 380 | if self.counter % 400 == 399: 381 | self.index = (self.index + 1)%2 382 | else: 383 | if self.counter % 20 == 19: 384 | self.index = (self.index + 1)%2 385 | 386 | elif self.isDucking: 387 | if self.counter % 5 == 0: 388 | self.index = (self.index + 1)%2 389 | else: 390 | if self.counter % 5 == 0: 391 | self.index = (self.index + 1)%2 + 2 392 | 393 | if self.isDead: 394 | self.index = 4 395 | 396 | if not self.isDucking: 397 | self.image = self.images[self.index] 398 | self.rect.width = self.stand_pos_width 399 | else: 400 | self.image = self.images1[(self.index)%2] 401 | self.rect.width = self.duck_pos_width 402 | 403 | self.rect = self.rect.move(self.movement) 404 | self.checkbounds() 405 | 406 | if not self.isDead and self.counter % 7 == 6 and self.isBlinking == False: 407 | self.score += 1 408 | if self.score % 100 == 0 and self.score != 0: 409 | if pygame.mixer.get_init() != None: 410 | checkPoint_sound.play() 411 | 412 | self.counter = (self.counter + 1) 413 | 414 | class Cactus(pygame.sprite.Sprite): 415 | def __init__(self,speed=5,sizex=-1,sizey=-1): 416 | pygame.sprite.Sprite.__init__(self,self.containers) 417 | self.images,self.rect = load_sprite_sheet('cacti-small.png',3,1,sizex,sizey,-1) 418 | self.rect.bottom = int(0.98*height) 419 | self.rect.left = width + self.rect.width 420 | self.image = self.images[random.randrange(0,3)] 421 | self.movement = [-1*speed,0] 422 | 423 | def draw(self): 424 | screen.blit(self.image,self.rect) 425 | 426 | def update(self): 427 | self.rect = self.rect.move(self.movement) 428 | 429 | if self.rect.right < 0: 430 | self.kill() 431 | 432 | class Ptera(pygame.sprite.Sprite): 433 | def __init__(self,speed=5,sizex=-1,sizey=-1): 434 | pygame.sprite.Sprite.__init__(self,self.containers) 435 | self.images,self.rect = load_sprite_sheet('ptera.png',2,1,sizex,sizey,-1) 436 | self.ptera_height = [height*0.82,height*0.75,height*0.60] 437 | self.rect.centery = self.ptera_height[random.randrange(0,3)] 438 | self.rect.left = width + self.rect.width 439 | self.image = self.images[0] 440 | self.movement = [-1*speed,0] 441 | self.index = 0 442 | self.counter = 0 443 | 444 | def draw(self): 445 | screen.blit(self.image,self.rect) 446 | 447 | def update(self): 448 | if self.counter % 10 == 0: 449 | self.index = (self.index+1)%2 450 | self.image = self.images[self.index] 451 | self.rect = self.rect.move(self.movement) 452 | self.counter = (self.counter + 1) 453 | if self.rect.right < 0: 454 | self.kill() 455 | 456 | class Ground(): 457 | def __init__(self,speed=-5): 458 | self.image,self.rect = load_image('ground.png',-1,-1,-1) 459 | self.image1,self.rect1 = load_image('ground.png',-1,-1,-1) 460 | self.rect.bottom = height 461 | self.rect1.bottom = height 462 | self.rect1.left = self.rect.right 463 | self.speed = speed 464 | 465 | def draw(self): 466 | screen.blit(self.image,self.rect) 467 | screen.blit(self.image1,self.rect1) 468 | 469 | def update(self): 470 | self.rect.left += self.speed 471 | self.rect1.left += self.speed 472 | 473 | if self.rect.right < 0: 474 | self.rect.left = self.rect1.right 475 | 476 | if self.rect1.right < 0: 477 | self.rect1.left = self.rect.right 478 | 479 | class Cloud(pygame.sprite.Sprite): 480 | def __init__(self,x,y): 481 | pygame.sprite.Sprite.__init__(self,self.containers) 482 | self.image,self.rect = load_image('cloud.png',int(90*30/42),30,-1) 483 | self.speed = 1 484 | self.rect.left = x 485 | self.rect.top = y 486 | self.movement = [-1*self.speed,0] 487 | 488 | def draw(self): 489 | screen.blit(self.image,self.rect) 490 | 491 | def update(self): 492 | self.rect = self.rect.move(self.movement) 493 | if self.rect.right < 0: 494 | self.kill() 495 | 496 | class Scoreboard(): 497 | def __init__(self,x=-1,y=-1): 498 | self.score = 0 499 | self.tempimages,self.temprect = load_sprite_sheet('numbers.png',12,1,11,int(11*6/5),-1) 500 | self.image = pygame.Surface((55,int(11*6/5))) 501 | self.rect = self.image.get_rect() 502 | if x == -1: 503 | self.rect.left = width*0.89 504 | else: 505 | self.rect.left = x 506 | if y == -1: 507 | self.rect.top = height*0.1 508 | else: 509 | self.rect.top = y 510 | 511 | def draw(self): 512 | screen.blit(self.image,self.rect) 513 | 514 | def update(self,score): 515 | score_digits = extractDigits(score) 516 | self.image.fill(background_col) 517 | for s in score_digits: 518 | self.image.blit(self.tempimages[s],self.temprect) 519 | self.temprect.left += self.temprect.width 520 | self.temprect.left = 0 521 | 522 | class App(QtWidgets.QMainWindow, Ui_Dialog): 523 | def __init__(self): 524 | #pygame.display.iconify() 525 | self.act='' 526 | super(self.__class__,self).__init__() 527 | self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) 528 | self.setupUi(self) 529 | self.frameThread = FrameThread(0,self.label_7,self.label_5) 530 | 531 | self.pushButton_4.clicked.connect(self.on_click) 532 | self.pushButton_3.clicked.connect(self.start_game) 533 | self.pushButton_5.clicked.connect(self.stop_cv) 534 | self.pushButton_5.setEnabled(False) 535 | 536 | self.timer = QtCore.QTimer(self) 537 | self.timer.setInterval(1000) 538 | self.timer.timeout.connect(self.displayTime) 539 | self.timer.start() 540 | 541 | self.label_2.setPixmap(QtGui.QPixmap("sprites/logo.png")) 542 | 543 | def on_click(self): 544 | self.resize(905,317) 545 | self.pushButton_3.setEnabled(False) 546 | self.pushButton_4.setEnabled(False) 547 | self.pushButton_5.setEnabled(True) 548 | self.frameThread.start() 549 | isGameQuit = self.introscreen(self.label_2) 550 | if not isGameQuit: 551 | self.gameplay(self.label_2,self.label_6,self.label_10) 552 | pygame.display.flip() 553 | 554 | def stop_cv(self): 555 | self.resize(637,317) 556 | self.frameThread.destoryed() 557 | self.label_5.setText('') 558 | self.pushButton_3.setEnabled(True) 559 | self.pushButton_4.setEnabled(True) 560 | self.pushButton_5.setEnabled(False) 561 | 562 | def start_game(self): 563 | self.resize(637,317) 564 | self.pushButton_3.setEnabled(False) 565 | self.pushButton_4.setEnabled(False) 566 | self.pushButton_5.setEnabled(False) 567 | isGameQuit = self.introscreen(self.label_2) 568 | if not isGameQuit: 569 | self.gameplay(self.label_2,self.label_6,self.label_10) 570 | pygame.display.flip() 571 | 572 | def keyPressEvent(self,event): 573 | key=event.key() 574 | if key==QtCore.Qt.Key_Up or (event.type()==QtCore.QEvent.KeyPress and key==QtCore.Qt.Key_Space): 575 | self.act='space' 576 | if key==QtCore.Qt.Key_Down: 577 | self.act='down' 578 | 579 | def displayTime(self): 580 | self.label_9.setText(QtCore.QDateTime.currentDateTime().toString()) 581 | 582 | def introscreen(self,win): 583 | temp_dino = Dino(44,47) 584 | temp_dino.isBlinking = True 585 | gameStart = False 586 | 587 | temp_ground,temp_ground_rect = load_sprite_sheet('ground.png',15,1,-1,-1,-1) 588 | temp_ground_rect.left = width/20 589 | temp_ground_rect.bottom = height 590 | 591 | logo,logo_rect = load_image('logoa.png',300,140,-1) 592 | logo_rect.centerx = width*0.6 593 | logo_rect.centery = height*0.6 594 | while not gameStart: 595 | if pygame.display.get_surface() == None: 596 | print("Couldn't load display surface") 597 | return True 598 | else: 599 | if self.act=='space': 600 | temp_dino.isJumping=True 601 | temp_dino.isBlinking=False 602 | temp_dino.movement[1]=-1*temp_dino.jumpSpeed 603 | self.act='' 604 | 605 | for event in pygame.event.get(): 606 | if event.type == pygame.QUIT: 607 | return True 608 | if event.type == pygame.KEYDOWN: 609 | if event.key == pygame.K_SPACE or event.key == pygame.K_UP: 610 | temp_dino.isJumping = True 611 | temp_dino.isBlinking = False 612 | temp_dino.movement[1] = -1*temp_dino.jumpSpeed 613 | 614 | temp_dino.update() 615 | 616 | if pygame.display.get_surface() != None: 617 | screen.fill(background_col) 618 | screen.blit(temp_ground[0],temp_ground_rect) 619 | if temp_dino.isBlinking: 620 | screen.blit(logo,logo_rect) 621 | temp_dino.draw() 622 | 623 | pygame.display.update() 624 | 625 | data=screen.get_buffer().raw 626 | image=QtGui.QImage(data,width,height,QtGui.QImage.Format_RGB32) 627 | pixmap = QPixmap.fromImage(image) 628 | win.setPixmap(pixmap) 629 | 630 | clock.tick(FPS) 631 | if temp_dino.isJumping == False and temp_dino.isBlinking == False: 632 | gameStart = True 633 | 634 | def gameplay(self,win,score,hscore): 635 | self.pushButton_3.setEnabled(False) 636 | self.pushButton_4.setEnabled(False) 637 | global high_score 638 | lastduck=0 639 | currentscr=0 640 | gamespeed = 4 641 | startMenu = False 642 | gameOver = False 643 | gameQuit = False 644 | playerDino = Dino(44,47) 645 | new_ground = Ground(-1*gamespeed) 646 | scb = Scoreboard() 647 | highsc = Scoreboard(width*0.78) 648 | counter = 0 649 | 650 | cacti = pygame.sprite.Group() 651 | pteras = pygame.sprite.Group() 652 | clouds = pygame.sprite.Group() 653 | last_obstacle = pygame.sprite.Group() 654 | 655 | Cactus.containers = cacti 656 | Ptera.containers = pteras 657 | Cloud.containers = clouds 658 | 659 | retbutton_image,retbutton_rect = load_image('replay_button.png',35,31,-1) 660 | gameover_image,gameover_rect = load_image('game_over.png',190,11,-1) 661 | 662 | temp_images,temp_rect = load_sprite_sheet('numbers.png',12,1,11,int(11*6/5),-1) 663 | HI_image = pygame.Surface((22,int(11*6/5))) 664 | HI_rect = HI_image.get_rect() 665 | HI_image.fill(background_col) 666 | HI_image.blit(temp_images[10],temp_rect) 667 | temp_rect.left += temp_rect.width 668 | HI_image.blit(temp_images[11],temp_rect) 669 | HI_rect.top = height*0.1 670 | HI_rect.left = width*0.73 671 | 672 | while not gameQuit: 673 | while startMenu: 674 | pass 675 | while not gameOver: 676 | if pygame.display.get_surface() == None: 677 | print("Couldn't load display surface") 678 | gameQuit = True 679 | gameOver = True 680 | else: 681 | if(self.label_5.text()!=''): 682 | if(self.label_5.text()=='Up'): 683 | self.act='space' 684 | if(self.label_5.text()=='Down'): 685 | self.act='down' 686 | #KEYBOARD COMMAND FROM PYQT 687 | currentscr=playerDino.score 688 | if self.act=='space': 689 | if playerDino.rect.bottom==int(0.98*height): 690 | playerDino.isJumping=True 691 | if pygame.mixer.get_init()!=None: 692 | jump_sound.play() 693 | playerDino.movement[1]=-1*playerDino.jumpSpeed 694 | self.act='' 695 | if self.act=='down': 696 | if not (playerDino.isJumping and playerDino.isDead): 697 | playerDino.isDucking=True 698 | self.act='' 699 | lastduck=playerDino.score 700 | if not currentscr==0 and not lastduck ==0 and currentscr-lastduck>=0 and currentscr-lastduck<=1: 701 | playerDino.isDucking=True 702 | else: 703 | playerDino.isDucking=False 704 | 705 | #KEYBOARD COMMAND FROM PYGAME 706 | for event in pygame.event.get(): 707 | if event.type == pygame.QUIT: 708 | gameQuit = True 709 | gameOver = True 710 | 711 | if event.type == pygame.KEYDOWN: 712 | if event.key == pygame.K_SPACE: 713 | if playerDino.rect.bottom == int(0.98*height): 714 | playerDino.isJumping = True 715 | if pygame.mixer.get_init() != None: 716 | jump_sound.play() 717 | playerDino.movement[1] = -1*playerDino.jumpSpeed 718 | 719 | if event.key == pygame.K_DOWN: 720 | if not (playerDino.isJumping and playerDino.isDead): 721 | playerDino.isDucking = True 722 | 723 | if event.type == pygame.KEYUP: 724 | if event.key == pygame.K_DOWN: 725 | playerDino.isDucking = False 726 | for c in cacti: 727 | c.movement[0] = -1*gamespeed 728 | if pygame.sprite.collide_mask(playerDino,c): 729 | playerDino.isDead = True 730 | if pygame.mixer.get_init() != None: 731 | die_sound.play() 732 | 733 | for p in pteras: 734 | p.movement[0] = -1*gamespeed 735 | if pygame.sprite.collide_mask(playerDino,p): 736 | playerDino.isDead = True 737 | if pygame.mixer.get_init() != None: 738 | die_sound.play() 739 | 740 | if len(cacti) < 2: 741 | if len(cacti) == 0: 742 | last_obstacle.empty() 743 | last_obstacle.add(Cactus(gamespeed,40,40)) 744 | else: 745 | for l in last_obstacle: 746 | if l.rect.right < width*0.7 and random.randrange(0,50) == 10: 747 | last_obstacle.empty() 748 | last_obstacle.add(Cactus(gamespeed, 40, 40)) 749 | 750 | if len(pteras) == 0 and random.randrange(0,200) == 10 and counter > 500: 751 | for l in last_obstacle: 752 | if l.rect.right < width*0.8: 753 | last_obstacle.empty() 754 | last_obstacle.add(Ptera(gamespeed, 46, 40)) 755 | 756 | if len(clouds) < 5 and random.randrange(0,300) == 10: 757 | Cloud(width,random.randrange(height/5,height/2)) 758 | 759 | playerDino.update() 760 | cacti.update() 761 | pteras.update() 762 | clouds.update() 763 | new_ground.update() 764 | scb.update(playerDino.score) 765 | score.setText(str(playerDino.score)) 766 | highsc.update(high_score) 767 | 768 | if pygame.display.get_surface() != None: 769 | screen.fill(background_col) 770 | new_ground.draw() 771 | clouds.draw(screen) 772 | scb.draw() 773 | if high_score != 0: 774 | highsc.draw() 775 | screen.blit(HI_image,HI_rect) 776 | cacti.draw(screen) 777 | pteras.draw(screen) 778 | playerDino.draw() 779 | 780 | pygame.display.update() 781 | 782 | #Add to the Qt 783 | data=screen.get_buffer().raw 784 | image=QtGui.QImage(data,width,height,QtGui.QImage.Format_RGB32) 785 | pixmap = QPixmap.fromImage(image) 786 | win.setPixmap(pixmap) 787 | 788 | clock.tick(FPS) 789 | 790 | if playerDino.isDead: 791 | gameOver = True 792 | if playerDino.score > high_score: 793 | high_score = playerDino.score 794 | hscore.setText(str(high_score)) 795 | 796 | if counter%700 == 699: 797 | new_ground.speed -= 1 798 | gamespeed += 1 799 | 800 | counter = (counter + 1) 801 | 802 | if gameQuit: 803 | break 804 | 805 | while gameOver: 806 | if pygame.display.get_surface() == None: 807 | print("Couldn't load display surface") 808 | gameQuit = True 809 | gameOver = False 810 | else: 811 | self.pushButton_3.setEnabled(True) 812 | self.pushButton_4.setEnabled(True) 813 | if self.act=='space': 814 | gameOver=False 815 | self.gameplay(win,score,hscore) 816 | act='' 817 | 818 | for event in pygame.event.get(): 819 | if event.type == pygame.QUIT: 820 | gameQuit = True 821 | gameOver = False 822 | if event.type == pygame.KEYDOWN: 823 | if event.key == pygame.K_ESCAPE: 824 | gameQuit = True 825 | gameOver = False 826 | 827 | if event.key == pygame.K_RETURN or event.key == pygame.K_SPACE: 828 | gameOver = False 829 | self.gameplay(win,score,hscore) 830 | highsc.update(high_score) 831 | if pygame.display.get_surface() != None: 832 | disp_gameOver_msg(retbutton_image,gameover_image) 833 | if high_score != 0: 834 | highsc.draw() 835 | screen.blit(HI_image,HI_rect) 836 | pygame.display.update() 837 | data=screen.get_buffer().raw 838 | image=QtGui.QImage(data,width,height,QtGui.QImage.Format_RGB32) 839 | pixmap = QPixmap.fromImage(image) 840 | win.setPixmap(pixmap) 841 | clock.tick(FPS) 842 | 843 | 844 | def main(): 845 | app=QtWidgets.QApplication(sys.argv) 846 | form=App() 847 | form.show() 848 | app.exec_() 849 | 850 | if __name__ == '__main__': 851 | main() 852 | 853 | """GAME REFERENCE by Rohit Rane""" -------------------------------------------------------------------------------- /sprites/cacti-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/cacti-big.png -------------------------------------------------------------------------------- /sprites/cacti-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/cacti-small.png -------------------------------------------------------------------------------- /sprites/checkPoint.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/checkPoint.wav -------------------------------------------------------------------------------- /sprites/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/cloud.png -------------------------------------------------------------------------------- /sprites/die.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/die.wav -------------------------------------------------------------------------------- /sprites/dino.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/dino.png -------------------------------------------------------------------------------- /sprites/dino_ducking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/dino_ducking.png -------------------------------------------------------------------------------- /sprites/game_over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/game_over.png -------------------------------------------------------------------------------- /sprites/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/ground.png -------------------------------------------------------------------------------- /sprites/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/jump.wav -------------------------------------------------------------------------------- /sprites/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/logo.png -------------------------------------------------------------------------------- /sprites/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/logo.psd -------------------------------------------------------------------------------- /sprites/logoa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/logoa.png -------------------------------------------------------------------------------- /sprites/numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/numbers.png -------------------------------------------------------------------------------- /sprites/offline-sprite-2x-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/offline-sprite-2x-black.png -------------------------------------------------------------------------------- /sprites/ptera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/ptera.png -------------------------------------------------------------------------------- /sprites/replay_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongvin/DinoRun-PyQt-PyGame/c6f35f7e00e994ae9f570dc90575967ecca20f33/sprites/replay_button.png --------------------------------------------------------------------------------