diff --git a/CollisionBox.py b/CollisionBox.py new file mode 100644 index 0000000..77ce5fc --- /dev/null +++ b/CollisionBox.py @@ -0,0 +1,21 @@ +""" +CollisionBox entity class +""" + +import pygame + + +class CollisionBox(pygame.sprite.Sprite): + def __init__(self, offsetX, offsetY, width, height, center): + pygame.sprite.Sprite.__init__(self) + + self.offset = (offsetX, offsetY) + self.size = (width, height) + self.rect = pygame.Rect(0, 0, width, height) + self.rect.center = center + + self.rect.x += self.offset[0] + self.rect.y += self.offset[1] + + def setY(self, y): + self.rect.y = y + self.offset[1] diff --git a/Drakora.pyw b/Drakora.pyw index f478570..a7938a1 100644 --- a/Drakora.pyw +++ b/Drakora.pyw @@ -15,6 +15,7 @@ from StandingEnemy import StandingEnemy from FlyingEnemy import FlyingEnemy from Cloud import Cloud from Floor import Floor +from EndSceen import EndSceen class Drakora(): @@ -57,6 +58,13 @@ class Drakora(): self.speedUp() self.speedUpLabelCD = self.targetFps + def getFont(self): + return self.font + + + def getTime(self): + return self.time + def newGame(self): self.background = Background(self) @@ -91,6 +99,9 @@ class Drakora(): self.speedDownCheatLabelCD = 0 self.speedResetCheatLabelCD = 0 + self.time = 0 + self.endSceen.newEndScreen() + def __init__(self): random.seed() @@ -124,10 +135,10 @@ class Drakora(): self.isGodmode = False self.drawBoxes = False - font = pygame.font.match_font('liberation mono') - self.fontScore = pygame.font.Font(font, 32) - self.fontMessage = pygame.font.Font(font, 56) - self.fontGodmode = pygame.font.Font(font, 12) + self.font = pygame.font.match_font('liberation mono') + self.fontScore = pygame.font.Font(self.font, 32) + self.fontMessage = pygame.font.Font(self.font, 56) + self.fontGodmode = pygame.font.Font(self.font, 12) self.charKeys = { pygame.K_a:'a', pygame.K_b:'b', pygame.K_c:'c', pygame.K_d:'d', @@ -141,6 +152,8 @@ class Drakora(): self.pressedKeys = deque(maxlen=10) self.isPressedKeysUpdated = True + self.endSceen = EndSceen(self) + self.newGame() @@ -165,29 +178,30 @@ class Drakora(): if self.drawBoxes: for player in self.players: - pygame.draw.rect(self.screen, (255, 0, 0), player.rect, 1) + for collision in self.player.getCollisionBoxes(): + pygame.draw.rect(self.screen, (255, 0, 0), collision.rect, 1) + # pygame.draw.rect(self.screen, (255, 0, 0), player.rect, 1) for enemy in self.enemies: pygame.draw.rect(self.screen, (255, 0, 0), enemy.rect, 1) for floor in self.floors: pygame.draw.rect(self.screen, (255, 0, 0), floor.rect, 1) - self.renderText('%d'%(self.__score), - self.fontScore, (255, 255, 255), - (self.getScreenWidth()/2,20)) - if self.isGameOver: - self.renderText('GAME OVER', - self.fontMessage, (255, 255, 255), - tuple(i/2 for i in self.screenSize)) - elif self.isPaused: - self.renderText('PAUSED', - self.fontMessage, (255, 255, 255), - tuple(i/2 for i in self.screenSize)) - elif self.speedUpLabelCD > 0: - self.speedUpLabelCD -= 1 - self.renderText('SPEED UP', - self.fontMessage, (255, 255, 255), - tuple(i/2 for i in self.screenSize)) + self.endSceen.render(); + else: + self.renderText('%d'%(self.__score), + self.fontScore, (255, 255, 255), + (self.getScreenWidth()/2,20)) + + if self.isPaused: + self.renderText('PAUSED', + self.fontMessage, (255, 255, 255), + tuple(i/2 for i in self.screenSize)) + elif self.speedUpLabelCD > 0: + self.speedUpLabelCD -= 1 + self.renderText('SPEED UP', + self.fontMessage, (255, 255, 255), + tuple(i/2 for i in self.screenSize)) if self.isGodmode: self.renderText('godmode', @@ -229,7 +243,7 @@ class Drakora(): def collideCheck(self): - if pygame.sprite.spritecollideany(self.player, self.enemies): + if sum([1 if pygame.sprite.spritecollideany(i, self.enemies) else 0 for i in self.player.getCollisionBoxes()]): if not self.isGodmode: self.isGameOver = True if self.player.isOnFloor: @@ -246,6 +260,7 @@ class Drakora(): def doCheats(self): + self.drawBoxes = True if self.isPressedKeysUpdated: pressedKeysStr = ''.join(self.pressedKeys) @@ -271,6 +286,7 @@ class Drakora(): for event in pygame.event.get(): self.player.control(event) + self.endSceen.control(event) if event.type == pygame.QUIT: return False @@ -279,7 +295,7 @@ class Drakora(): if event.key in self.buttonsQuit: return False elif event.key in self.buttonsNewGame: - if self.isGameOver or self.isGodmode: self.newGame() + if self.isGodmode: self.newGame() elif event.key in self.buttonsPause: self.isPaused = not self.isPaused @@ -291,7 +307,9 @@ class Drakora(): self.doCheats() if not self.isGameOver and not self.isPaused: + self.time += 1/self.targetFps self.background.update() + for cloudGroup in self.cloudGroups: cloudGroup.update() self.enemies.update() self.players.update() diff --git a/EndSceen.py b/EndSceen.py new file mode 100644 index 0000000..a2aa7d2 --- /dev/null +++ b/EndSceen.py @@ -0,0 +1,184 @@ +""" +Enemy entity class +""" + + +import pygame + + +class EndSceen(): + def __init__(self, mainGameClass): + self.fontGameOver = pygame.font.Font(mainGameClass.getFont(), 56) + self.fontLeaderBoard = pygame.font.Font(mainGameClass.getFont(), 30) + self.fontLeaderBoardActive = pygame.font.Font(mainGameClass.getFont(), 30) + self.fontLeaderBoardActive.underline = True + self.fontError = pygame.font.Font(mainGameClass.getFont(), 15) + + self.game = mainGameClass + + def newEndScreen(self): + self.endScreenTimer = 0; + self.playerName = 'Player' + + self.scoresFromFile = [] + self.data = [] + + self.isBackButton = True + + fileWithData = open('leaders.txt') + + for line in fileWithData: + oneStr = line.split() + + if (len(oneStr) == 3): + self.data.append([oneStr[0][:10], int(oneStr[1]), float(oneStr[2])]) + + fileWithData.close() + + self.sortedDataByScores = sorted(enumerate(self.data), key=lambda i: i[1][1], reverse=True) + + + def renderText(self, text, font, color, center, backColor=None): + render = font.render(text, True, color, backColor) + rect = render.get_rect() + rect.center = center + self.game.screen.blit(render, rect) + + def drawTableLB(self, number): + j = 1 + placeFlag = False + + for i in [i[0] for i in self.sortedDataByScores[:number]]: + # print(self.data[i]) + + if (self.game.getScore() > self.data[i][1] and not placeFlag): + self.renderText('>{0:3} {1:^10} {2:6d} {3:8.2f} '.format(j, self.playerName[:10], self.game.getScore(), self.game.getTime()), + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + j*50)) + j += 1 + placeFlag = True + + if (j > number): + break + + formatDataForOnePlayer = ' {0:3} {1:^10} {2:6d} {3:8.2f} '.format(j, *self.data[i]) + + self.renderText(formatDataForOnePlayer, + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + j*50)) + + j += 1 + + if (j > number): + break + + if not placeFlag and j <= number: + self.renderText('>{0:3} {1:^10} {2:6d} {3:8.2f} '.format(j, self.playerName[:10], self.game.getScore(), self.game.getTime()), + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + j*50)) + + + self.renderText(' {0:>3} {1:^10} {2:>6} {3:>8} '.format('..','.....', '..', '.....'), + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + (number + 1)*50)) + + # for i in rows: + + def getScorePosition(self, score): + counter = 1 + for i in self.sortedDataByScores: + if i[1][1] < score: + return counter + else: + counter += 1 + return counter + + + def render(self): + backGround = pygame.Surface(self.game.screenSize, pygame.SRCALPHA) + backGround.fill((0,0,0,200)) + self.game.screen.blit(backGround, (0,0)) + + self.renderText('GAME OVER', + self.fontGameOver, (255, 255, 255), + (self.game.getScreenWidth()/2,50)) + + self.renderText('Leaderboard', + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100)) + + self.drawTableLB(5) + + cursorChar = ' ' + if self.endScreenTimer > self.game.targetFps / 3: + cursorChar = '_' + + if self.endScreenTimer > 2 * self.game.targetFps / 3: + self.endScreenTimer = 0 + + self.endScreenTimer += 1 + + if len(self.playerName) > 0: + self.renderText(' {0:3d} {1:^10} {2:6d} {3:8.2f} '.format(self.getScorePosition(self.game.getScore()), self.playerName[:10] + (cursorChar if len(self.playerName) < 10 else ''), self.game.getScore(), self.game.getTime()), + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + (5 + 2)*50)) + else: + self.renderText(' {0:3d} {1:^10} {2:6d} {3:8.2f} '.format(self.getScorePosition(self.game.getScore()), self.playerName[:10] + (cursorChar if len(self.playerName) < 10 else ''), self.game.getScore(), self.game.getTime()), + self.fontLeaderBoard, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + (5 + 2)*50), (200, 20, 20)) + + self.renderText(' {0:^30} '.format('Missing player name'), + self.fontError, (255, 255, 255), + (self.game.getScreenWidth()/2,100 + (5 + 2)*50 + 25)) + + self.renderText('Back', + self.fontLeaderBoard if not self.isBackButton else self.fontLeaderBoardActive, (255, 255, 255), + (self.game.getScreenWidth()/2 - 100, self.game.getScreenHeight() - 80)) + + self.renderText('Continue', + self.fontLeaderBoard if self.isBackButton else self.fontLeaderBoardActive, (255, 255, 255), + (self.game.getScreenWidth()/2 + 100, self.game.getScreenHeight() - 80)) + + def control(self, event): + if event.type == pygame.KEYDOWN and self.game.isGameOver: + if event.key == pygame.K_RIGHT: + self.isBackButton = False + + elif event.key == pygame.K_LEFT: + self.isBackButton = True + + elif event.key == pygame.K_RETURN: + if len(self.playerName) > 0: + self.saveResults() + + if self.isBackButton: + self.game.newGame() + else: + self.game.newGame() + + elif event.key == pygame.K_BACKSPACE: + self.playerName = self.playerName[:len(self.playerName) - 1] + + elif len(pygame.key.name(event.key)) == 1 and len(self.playerName) < 10: + if pygame.key.get_mods() & pygame.KMOD_LSHIFT: + self.playerName += pygame.key.name(event.key).upper() + else: + self.playerName += pygame.key.name(event.key).lower() + # self.playerName += self.game.charKeys[event.key] + + def saveResults(self): + with open ('leaders.txt', 'r') as fileWithData: + tmpData = fileWithData.readlines() + fileWithData.close() + + newData = [] + for line in tmpData: + if len(line.split()) == 3: + if not (line.split()[0].rstrip() == self.playerName.rstrip()): + newData.append(line) + + newData.append('{0} {1} {2:.2f}\n'.format(self.playerName, self.game.getScore(), self.game.getTime())) + + with open ('leaders.txt', 'w') as fileWithData: + fileWithData.writelines(newData) + fileWithData.close() diff --git a/Player.py b/Player.py index 52594db..7ebfdfa 100644 --- a/Player.py +++ b/Player.py @@ -6,6 +6,7 @@ Player entity class import pygame import math import os +from CollisionBox import CollisionBox class Player(pygame.sprite.Sprite): @@ -39,6 +40,8 @@ class Player(pygame.sprite.Sprite): for image in array: image.set_colorkey((255,0,255)) + def getCollisionBoxes(self): + return self.collisionBoxes def __init__(self): pygame.sprite.Sprite.__init__(self) @@ -64,18 +67,33 @@ class Player(pygame.sprite.Sprite): self.gameSpeed = 1 self.updateCount = 0 + self.collisionBoxes = [] + + collision = CollisionBox(0, 20, 60, 20, self.rect.center) + self.collisionBoxes.append(collision) + collision = CollisionBox(-10, 5, 30, 20, self.rect.center) + self.collisionBoxes.append(collision) + collision = CollisionBox(0, 35, 25, 40, self.rect.center) + self.collisionBoxes.append(collision) + def crouch(self): if not self.isCrouching: self.isCrouching = True self.rect = self.rect.inflate(0, -32) + for i in self.collisionBoxes: + i.rect.y -= 32 + def standup(self): if self.isCrouching: self.isCrouching = False self.rect = self.rect.inflate(0, 32) + for i in self.collisionBoxes: + i.rect.y += 32 + def updateSpeed(self, newGameSpeed): self.gameSpeed = newGameSpeed @@ -134,6 +152,9 @@ class Player(pygame.sprite.Sprite): self.rect.y += self.speed + for i in self.collisionBoxes: + i.setY(self.rect.y) + if self.updateCount >= 22 - math.log2(self.gameSpeed) * 2: if self.isOnFloor: if self.isCrouching: diff --git a/leaders.txt b/leaders.txt new file mode 100644 index 0000000..d1a8b6c --- /dev/null +++ b/leaders.txt @@ -0,0 +1,6 @@ +Kolya 1 11.37 +Coolguy 1 10.75 +Wow 74 185.72 +Cheater 1000 0.01 +New-Kolya 2 15.20 +1 1 10.02