├── highscore.txt
├── tetris
└── .idea
│ └── workspace.xml
├── Sounds
├── bip.ogg
├── line clear.ogg
└── Child's Nightmare.ogg
├── fonts
├── icon.png
├── ka1.ttf
├── ARCADE.TTF
├── retro.ttf
├── ARCADE_I.TTF
├── PIXEL CRAFT.ttf
├── Pixelmania.ttf
└── ARCADECLASSIC.TTF
├── __pycache__
├── Block.cpython-311.pyc
├── Blocks.cpython-311.pyc
├── Color.cpython-311.pyc
├── Game.cpython-311.pyc
├── Grid.cpython-311.pyc
└── Position.cpython-311.pyc
├── Position.py
├── .idea
├── vcs.xml
├── .gitignore
├── misc.xml
├── inspectionProfiles
│ ├── profiles_settings.xml
│ └── Project_Default.xml
├── modules.xml
└── Summer1.iml
├── Color.py
├── LICENSE
├── Block.py
├── Grid.py
├── README.md
├── Blocks.py
├── Game.py
└── main.py
/highscore.txt:
--------------------------------------------------------------------------------
1 | 0
--------------------------------------------------------------------------------
/tetris/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Sounds/bip.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/Sounds/bip.ogg
--------------------------------------------------------------------------------
/fonts/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/icon.png
--------------------------------------------------------------------------------
/fonts/ka1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/ka1.ttf
--------------------------------------------------------------------------------
/fonts/ARCADE.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/ARCADE.TTF
--------------------------------------------------------------------------------
/fonts/retro.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/retro.ttf
--------------------------------------------------------------------------------
/fonts/ARCADE_I.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/ARCADE_I.TTF
--------------------------------------------------------------------------------
/Sounds/line clear.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/Sounds/line clear.ogg
--------------------------------------------------------------------------------
/fonts/PIXEL CRAFT.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/PIXEL CRAFT.ttf
--------------------------------------------------------------------------------
/fonts/Pixelmania.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/Pixelmania.ttf
--------------------------------------------------------------------------------
/fonts/ARCADECLASSIC.TTF:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/fonts/ARCADECLASSIC.TTF
--------------------------------------------------------------------------------
/Sounds/Child's Nightmare.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/Sounds/Child's Nightmare.ogg
--------------------------------------------------------------------------------
/__pycache__/Block.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/__pycache__/Block.cpython-311.pyc
--------------------------------------------------------------------------------
/__pycache__/Blocks.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/__pycache__/Blocks.cpython-311.pyc
--------------------------------------------------------------------------------
/__pycache__/Color.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/__pycache__/Color.cpython-311.pyc
--------------------------------------------------------------------------------
/__pycache__/Game.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/__pycache__/Game.cpython-311.pyc
--------------------------------------------------------------------------------
/__pycache__/Grid.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/__pycache__/Grid.cpython-311.pyc
--------------------------------------------------------------------------------
/Position.py:
--------------------------------------------------------------------------------
1 | class Position:
2 | def __init__(self, row, column):
3 | self.row = row
4 | self.column = column
--------------------------------------------------------------------------------
/__pycache__/Position.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Farid-Karimi/Tetris/HEAD/__pycache__/Position.cpython-311.pyc
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/Summer1.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Color.py:
--------------------------------------------------------------------------------
1 | class Colors:
2 | Cells = (0, 91, 150)
3 | green = (89, 209, 2)
4 | red = (249,65,68)
5 | orange = (255, 140, 0)
6 | yellow = (175, 252, 175)
7 | purple = (188, 0, 221)
8 | lime = (255, 237, 0)
9 | blue = (0, 255, 208)
10 | white = (255, 255, 255)
11 | black = (0, 0, 0)
12 | backGround = (1, 31, 75)
13 | boxes = (3, 57, 108)
14 |
15 | @classmethod
16 | def getCellColors(cls):
17 | return [cls.Cells, cls.green, cls.red, cls.orange, cls.yellow, cls.purple, cls.lime, cls.blue]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Farid Karimi
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 |
--------------------------------------------------------------------------------
/Block.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | from Color import Colors
4 | from Position import Position
5 |
6 |
7 | class Block:
8 | def __init__(self, id):
9 | self.id = id
10 | self.cells = {}
11 | self.cellSize = 30
12 | self.rotationState = 0
13 | self.rowOffset = 0
14 | self.columnOffset = 0
15 | self.colors = Colors.getCellColors()
16 |
17 | def move(self, rows, columns):
18 | self.rowOffset += rows
19 | self.columnOffset += columns
20 |
21 | def getCellPositions(self):
22 | tiles = self.cells[self.rotationState]
23 | moved_tiles = []
24 | for position in tiles:
25 | position = Position(position.row + self.rowOffset, position.column + self.columnOffset)
26 | moved_tiles.append(position)
27 | return moved_tiles
28 |
29 | def rotate(self):
30 | self.rotationState += 1
31 | if self.rotationState == len(self.cells):
32 | self.rotationState = 0
33 |
34 | def undoRotation(self):
35 | self.rotationState -= 1
36 | if self.rotationState == -1:
37 | self.rotationState = len(self.cells) - 1
38 |
39 | def draw(self, screen, offset_x, offset_y):
40 | tiles = self.getCellPositions()
41 | for tile in tiles:
42 | tile_rect = pygame.Rect(offset_x + tile.column * self.cellSize,offset_y + tile.row * self.cellSize, self.cellSize - 1, self.cellSize - 1)
43 | pygame.draw.rect(screen, self.colors[self.id], tile_rect)
--------------------------------------------------------------------------------
/Grid.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | from Color import Colors
4 |
5 |
6 | class Grid:
7 | def __init__(self):
8 | self.numberOfRows = 20
9 | self.numberOfColumns = 10
10 | self.cellSize = 30
11 | self.grid = [[0 for j in range(self.numberOfColumns)] for i in range(self.numberOfRows)]
12 | self.colors = Colors.getCellColors()
13 |
14 | def printGrid(self):
15 | for row in range(self.numberOfRows):
16 | for column in range(self.numberOfColumns):
17 | print(self.grid[row][column], end=" ")
18 | print()
19 |
20 | def draw(self, screen):
21 | for row in range(self.numberOfRows):
22 | for column in range(self.numberOfColumns):
23 | cellValue = self.grid[row][column]
24 | cellRect = pygame.Rect(column * self.cellSize + 11, row * self.cellSize + 11, self.cellSize - 1,
25 | self.cellSize - 1)
26 | pygame.draw.rect(screen, self.colors[cellValue], cellRect)
27 |
28 | def isInside(self, row, column):
29 | if row >= 0 and row < self.numberOfRows and column >= 0 and column < self.numberOfColumns:
30 | return True
31 | return False
32 |
33 | def isEmpty(self, row, column):
34 | if self.grid[row][column] == 0:
35 | return True
36 | return False
37 |
38 | def isRowFull(self, row):
39 | for column in range(self.numberOfColumns):
40 | if self.grid[row][column] == 0:
41 | return False
42 | return True
43 |
44 | def clearRow(self, row):
45 | for column in range(self.numberOfColumns):
46 | self.grid[row][column] = 0
47 |
48 | def moveRowDown(self, row, numberOfRows):
49 | for column in range(self.numberOfColumns):
50 | self.grid[row + numberOfRows][column] = self.grid[row][column]
51 | self.grid[row][column] = 0
52 |
53 | def clearFullRows(self):
54 | completed = 0
55 | for row in range(self.numberOfRows - 1, 0, -1):
56 | if self.isRowFull(row):
57 | self.clearRow(row)
58 | completed += 1
59 | elif completed > 0:
60 | self.moveRowDown(row, completed)
61 | return completed
62 |
63 | def reset(self):
64 | for row in range(self.numberOfRows):
65 | for column in range(self.numberOfColumns):
66 | self.grid[row][column] = 0
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🕹️ Python Tetris
2 |
3 | ## Introduction
4 | This project is my first endeavor in game development using the Pygame library.
5 | The primary goal of this project was to gain hands-on experience with Pygame, strengthen my understanding of Python syntax, and improve my overall programming skills.
6 | The project involved implementing the popular game "Tetris" in Python.
7 |
8 | ## Technologies Used
9 | - Python programming language
10 | - Pygame library
11 |
12 | ## Project Scope
13 | The project focused on building a functional Tetris game using object-oriented programming (OOP) principles, specifically leveraging the concept of inheritance.
14 | The inheritance structure allowed for the creation of modular and reusable code components, enhancing the game's maintainability and scalability.
15 |
16 | ## Design and Visuals
17 | To enhance the visual appeal of the game, I made deliberate design choices and utilized a color palette to create an engaging and aesthetically pleasing user interface. The color palette selection aimed to ensure good contrast, readability, and an enjoyable gaming experience for players.
18 |
19 | ## Learning Outcomes
20 | Through the development of this project, I achieved several learning outcomes, including:
21 | - Gained proficiency in using the Pygame library to create interactive games.
22 | - Deepened my understanding of object-oriented programming (OOP) concepts and their application in game development.
23 | - Strengthened my grasp of Python syntax, including control flow, event handling, and graphics rendering.
24 | - Developed skills in designing and implementing game mechanics, such as block movement, rotation, and collision detection.
25 | - Gained experience in managing game states, such as pausing and game over conditions.
26 | - Improved problem-solving skills by tackling challenges specific to game development.
27 |
28 | ## Conclusion
29 | In conclusion, the Python Tetris project served as an excellent opportunity for me to explore game development, refine my programming skills, and gain practical experience in utilizing the Pygame library.
30 | This project has provided a solid foundation for future game development endeavors and has been instrumental in enhancing my understanding of Python syntax, OOP principles, and design choices.
31 | I look forward to further expanding my knowledge and skills in game development through future projects.
32 |
33 | ## Screenshots
34 | 
35 |
36 |
--------------------------------------------------------------------------------
/Blocks.py:
--------------------------------------------------------------------------------
1 | from Block import Block
2 | from Position import Position
3 |
4 |
5 | class LBlock(Block):
6 | def __init__(self):
7 | super().__init__(id=1)
8 | self.cells = {
9 | 0: [Position(0, 2), Position(1, 0), Position(1, 1), Position(1, 2)],
10 | 1: [Position(0, 1), Position(1, 1), Position(2, 1), Position(2, 2)],
11 | 2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 0)],
12 | 3: [Position(0, 0), Position(0, 1), Position(1, 1), Position(2, 1)]
13 | }
14 | self.move(0, 3)
15 |
16 |
17 | class JBlock(Block):
18 | def __init__(self):
19 | super().__init__(id=2)
20 | self.cells = {
21 | 0: [Position(0, 0), Position(1, 0), Position(1, 1), Position(1, 2)],
22 | 1: [Position(0, 1), Position(0, 2), Position(1, 1), Position(2, 1)],
23 | 2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 2)],
24 | 3: [Position(0, 1), Position(1, 1), Position(2, 0), Position(2, 1)]
25 | }
26 | self.move(0, 3)
27 |
28 |
29 | class IBlock(Block):
30 | def __init__(self):
31 | super().__init__(id=3)
32 | self.cells = {
33 | 0: [Position(1, 0), Position(1, 1), Position(1, 2), Position(1, 3)],
34 | 1: [Position(0, 2), Position(1, 2), Position(2, 2), Position(3, 2)],
35 | 2: [Position(2, 0), Position(2, 1), Position(2, 2), Position(2, 3)],
36 | 3: [Position(0, 1), Position(1, 1), Position(2, 1), Position(3, 1)]
37 | }
38 | self.move(-1, 3)
39 |
40 |
41 | class OBlock(Block):
42 | def __init__(self):
43 | super().__init__(id=4)
44 | self.cells = {
45 | 0: [Position(0, 0), Position(0, 1), Position(1, 0), Position(1, 1)]
46 | }
47 | self.move(0, 4)
48 |
49 |
50 | class SBlock(Block):
51 | def __init__(self):
52 | super().__init__(id=5)
53 | self.cells = {
54 | 0: [Position(0, 1), Position(0, 2), Position(1, 0), Position(1, 1)],
55 | 1: [Position(0, 1), Position(1, 1), Position(1, 2), Position(2, 2)],
56 | 2: [Position(1, 1), Position(1, 2), Position(2, 0), Position(2, 1)],
57 | 3: [Position(0, 0), Position(1, 0), Position(1, 1), Position(2, 1)]
58 | }
59 | self.move(0, 3)
60 |
61 |
62 | class TBlock(Block):
63 | def __init__(self):
64 | super().__init__(id=6)
65 | self.cells = {
66 | 0: [Position(0, 1), Position(1, 0), Position(1, 1), Position(1, 2)],
67 | 1: [Position(0, 1), Position(1, 1), Position(1, 2), Position(2, 1)],
68 | 2: [Position(1, 0), Position(1, 1), Position(1, 2), Position(2, 1)],
69 | 3: [Position(0, 1), Position(1, 0), Position(1, 1), Position(2, 1)]
70 | }
71 | self.move(0, 3)
72 |
73 |
74 | class ZBlock(Block):
75 | def __init__(self):
76 | super().__init__(id=7)
77 | self.cells = {
78 | 0: [Position(0, 0), Position(0, 1), Position(1, 1), Position(1, 2)],
79 | 1: [Position(0, 2), Position(1, 1), Position(1, 2), Position(2, 1)],
80 | 2: [Position(1, 0), Position(1, 1), Position(2, 1), Position(2, 2)],
81 | 3: [Position(0, 1), Position(1, 0), Position(1, 1), Position(2, 0)]
82 | }
83 | self.move(0, 3)
84 |
--------------------------------------------------------------------------------
/Game.py:
--------------------------------------------------------------------------------
1 | import random
2 | import pygame
3 | from Blocks import *
4 | from Grid import Grid
5 |
6 |
7 | class Game:
8 | def __init__(self):
9 | self.grid = Grid()
10 | self.blocks = [IBlock(), JBlock(), LBlock(), OBlock(), SBlock(), TBlock(), ZBlock()]
11 | self.currentBlock = self.getRandomBlock()
12 | self.nextBlock = self.getRandomBlock()
13 | self.gameOver = False
14 | self.score = 0
15 | self.rotate_sound = pygame.mixer.Sound("Sounds/bip.ogg")
16 | self.clear_sound = pygame.mixer.Sound("Sounds/line clear.ogg")
17 | pygame.mixer.music.load("Sounds/Child's Nightmare.ogg")
18 | pygame.mixer.music.play(-1)
19 |
20 | def updateScore(self, linesCleared, moveDownPoints):
21 | if linesCleared == 1:
22 | self.score += 100
23 | elif linesCleared == 2:
24 | self.score += 300
25 | elif linesCleared == 3:
26 | self.score += 500
27 | self.score += moveDownPoints
28 |
29 | def getRandomBlock(self):
30 | if len(self.blocks) == 0:
31 | self.blocks = [IBlock(), JBlock(), LBlock(), OBlock(), SBlock(), TBlock(), ZBlock()]
32 | block = random.choice(self.blocks)
33 | self.blocks.remove(block)
34 | return block
35 |
36 | def moveLeft(self):
37 | self.currentBlock.move(0, -1)
38 | if self.blockInside() == False or self.blockFits() == False:
39 | self.currentBlock.move(0, 1)
40 |
41 | def moveRight(self):
42 | self.currentBlock.move(0, 1)
43 | if self.blockInside() == False or self.blockFits() == False:
44 | self.currentBlock.move(0, -1)
45 |
46 | def moveDown(self):
47 | self.currentBlock.move(1, 0)
48 | if self.blockInside() == False or self.blockFits() == False:
49 | self.currentBlock.move(-1, 0)
50 | self.lockBlock()
51 |
52 | def lockBlock(self):
53 | tiles = self.currentBlock.getCellPositions()
54 | for position in tiles:
55 | self.grid.grid[position.row][position.column] = self.currentBlock.id
56 | self.currentBlock = self.nextBlock
57 | self.nextBlock = self.getRandomBlock()
58 | rowsCleared = self.grid.clearFullRows()
59 | if rowsCleared > 0:
60 | self.clear_sound.play()
61 | self.updateScore(rowsCleared, 0)
62 | if not self.blockFits():
63 | self.gameOver = True
64 |
65 | def reset(self):
66 | self.grid.reset()
67 | self.blocks = [IBlock(), JBlock(), LBlock(), OBlock(), SBlock(), TBlock(), ZBlock()]
68 | self.currentBlock = self.getRandomBlock()
69 | self.nextBlock = self.getRandomBlock()
70 | self.score = 0
71 |
72 | def blockFits(self):
73 | tiles = self.currentBlock.getCellPositions()
74 | for tile in tiles:
75 | if not self.grid.isEmpty(tile.row, tile.column):
76 | return False
77 | return True
78 |
79 | def rotate(self):
80 | self.currentBlock.rotate()
81 | if self.blockInside() == False or self.blockFits() == False:
82 | self.currentBlock.undoRotation()
83 | else:
84 | self.rotate_sound.play()
85 |
86 | def blockInside(self):
87 | tiles = self.currentBlock.getCellPositions()
88 | for tile in tiles:
89 | if not self.grid.isInside(tile.row, tile.column):
90 | return False
91 | return True
92 |
93 | def draw(self, screen):
94 | self.grid.draw(screen)
95 | self.currentBlock.draw(screen, 11, 11)
96 |
97 | if self.nextBlock.id == 3:
98 | self.nextBlock.draw(screen, 255, 290)
99 | elif self.nextBlock.id == 4:
100 | self.nextBlock.draw(screen, 255, 280)
101 | else:
102 | self.nextBlock.draw(screen, 270, 270)
103 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import pygame
3 |
4 | from Color import Colors
5 | from Game import Game
6 |
7 | pygame.init()
8 | titleFont = pygame.font.Font("fonts/ARCADECLASSIC.TTF", 40)
9 | titleFontForHS = pygame.font.Font("fonts/ARCADECLASSIC.TTF", 30)
10 | titleFontForPause = pygame.font.Font("fonts/ARCADECLASSIC.TTF", 60)
11 | scoreSurface = titleFont.render("Score", True, Colors.white)
12 | nextSurface = titleFont.render("Next", True, Colors.white)
13 | gameOverSurface = titleFontForPause.render("GAME OVER", True, Colors.white)
14 | pauseSurface = titleFontForPause.render("PAUSED", True, Colors.white)
15 | highScoreSurface = titleFontForHS.render("High Score", True, Colors.white)
16 |
17 | scoreRect = pygame.Rect(320, 55, 170, 60)
18 | nextRect = pygame.Rect(320, 215, 170, 180)
19 | highScoreRect = pygame.Rect(320, 500, 170, 60)
20 |
21 | screen = pygame.display.set_mode((500, 620))
22 | pygame.display.set_caption("Python Tetris")
23 | img = pygame.image.load('fonts/icon.png')
24 | pygame.display.set_icon(img)
25 |
26 | clock = pygame.time.Clock()
27 |
28 | game = Game()
29 |
30 | gameUpdate = pygame.USEREVENT
31 | pygame.time.set_timer(gameUpdate, 250)
32 |
33 | paused = False
34 |
35 | dim_surface = pygame.Surface(screen.get_size())
36 | dim_surface.set_alpha(100)
37 | dim_surface.fill(Colors.black)
38 |
39 | # Load highscore from a text file
40 | def load_highscore():
41 | try:
42 | with open("highscore.txt", "r") as file:
43 | highscore = int(file.read())
44 | except FileNotFoundError:
45 | highscore = 0
46 | return highscore
47 |
48 | # Save highscore to a text file
49 | def save_highscore(highscore):
50 | with open("highscore.txt", "w") as file:
51 | file.write(str(highscore))
52 |
53 | highscore = load_highscore()
54 |
55 | while True:
56 | for event in pygame.event.get():
57 | if event.type == pygame.QUIT:
58 | # Save highscore before exiting the game
59 | save_highscore(highscore)
60 | pygame.quit()
61 | sys.exit()
62 | if event.type == pygame.KEYDOWN:
63 | if event.key == pygame.K_p:
64 | paused = not paused
65 | if game.gameOver:
66 | game.gameOver = False
67 | game.reset()
68 | if not paused:
69 | if event.key == pygame.K_LEFT and game.gameOver == False:
70 | game.moveLeft()
71 | if event.key == pygame.K_RIGHT and game.gameOver == False:
72 | game.moveRight()
73 | if event.key == pygame.K_DOWN and game.gameOver == False:
74 | game.moveDown()
75 | game.updateScore(0, 1)
76 | if event.key == pygame.K_UP and game.gameOver == False:
77 | game.rotate()
78 | if event.type == gameUpdate and game.gameOver == False and not paused:
79 | game.moveDown()
80 |
81 | scoreValueSurface = titleFont.render(str(game.score), True, Colors.white)
82 | highscoreNum = titleFont.render(str(highscore), True, Colors.white)
83 |
84 | screen.fill(Colors.backGround)
85 |
86 | pygame.draw.rect(screen, Colors.boxes, scoreRect, 0, 15)
87 | screen.blit(scoreValueSurface, scoreValueSurface.get_rect(centerx=scoreRect.centerx, centery=scoreRect.centery))
88 | pygame.draw.rect(screen, Colors.boxes, nextRect, 0, 15)
89 | pygame.draw.rect(screen, Colors.boxes, highScoreRect, 0, 15)
90 | game.draw(screen)
91 |
92 | if game.gameOver:
93 | screen.blit(dim_surface, (0, 0))
94 | screen.blit(gameOverSurface, ((screen.get_width() - gameOverSurface.get_width()) // 2 ,
95 | (screen.get_height() - gameOverSurface.get_height()) // 2))
96 | # Update highscore if the current score is higher
97 | if game.score > highscore:
98 | highscore = game.score
99 | if paused:
100 | screen.blit(dim_surface, (0, 0))
101 | screen.blit(pauseSurface, ((screen.get_width() - pauseSurface.get_width()) // 2,
102 | (screen.get_height() - pauseSurface.get_height()) // 2))
103 |
104 | screen.blit(scoreSurface, (352, 15, 50, 50))
105 | screen.blit(nextSurface, (367, 175, 50, 50))
106 | screen.blit(highScoreSurface, (325, 460, 50, 50))
107 | screen.blit(highscoreNum, highscoreNum.get_rect(centerx=highScoreRect.centerx, centery=highScoreRect.centery))
108 |
109 | pygame.display.update()
110 | clock.tick(60)
111 |
--------------------------------------------------------------------------------