CS Project
CS Project
SOFTWARE REQUIREMENT:
1.Python 3.8.10
2.Spyder ide
3.Tetriminos Sprites (PNG Format)
4. Pygame, Math, Pathlib, Random, SYS Modules
5. Anaconda Packages
6. Font if any (.TTF Format)
SYNOPSIS OF THE PROJECT:
Student Names:
1. ANUJ PANDEY
2.YASHASVIE CHANDRA
3. OJAS PEDNEKER
AIM AND OBJECTIVE
Aim:
The primary aim of my Class 12 Computer Science project is to develop a captivating and
functional video game based on the classic Tetris. This project aims to provide an immersive
gaming experience that reflects both creativity and technical proficiency.
Objectives:
1. *Game Development Proficiency: * Demonstrate a comprehensive understanding of
programming languages and game development tools to create a Tetris game from scratch.
2. *Algorithmic Implementation: * Implement the core algorithms and logic required for
Tetris gameplay, including block movement, rotation, and line clearing, while ensuring
efficiency and responsiveness.
3. *User Interface Design: * Design an intuitive and visually appealing user interface that
enhances the overall gaming experience, incorporating elements such as score displays, level
progression, and clear feedback mechanisms.
4. *Scalability: * Develop the game with a focus on scalability, allowing for potential future
enhancements and modifications to the game structure or features.
5. *Code Optimization: * Apply effective coding practices to optimize the performance of the
game, ensuring smooth gameplay even on devices with varying specifications.
copied the report or its any appreciable parts from any other literature
I hereby thank the school and the staff of the computer science
department for all the guidance and support extended to me
during this project.
SETTING.PY:
import pygame as pg
vec = pg.math.Vector2
#FRAMES PER SECOND
FPS = 60
#COLOUR
FIELD_COLOR = (48, 39, 32)
BG_COLOR = (24, 89, 117)
SPRITE_DIR_PATH = 'TETRIS/assets/sprites'
FONT_PATH = 'FREAKSOFNATUREMASSIVE.ttf'
#MILLISECONDS
ANIM_TIME_INTERVAL = 200
FAST_ANIM_TIME_INTERVAL = 15
TILE_SIZE = 50
FIELD_SIZE = FIELD_W, FIELD_H = 10, 20
FIELD_RES = FIELD_W * TILE_SIZE, FIELD_H * TILE_SIZE
import random
super().__init__(tetromino.tetris.sprite_group)
self.image = tetromino.image
self.rect = self.image.get_rect()
self.sfx_image = self.image.copy()
self.sfx_image.set_alpha(110)
self.sfx_speed = random.uniform(0.2, 0.6)
self.sfx_cycles = random.randrange(6, 8)
self.cycle_counter = 0
#SPECIAL EFFECT DURATION
def sfx_end_time(self):
if self.tetromino.tetris.app.anim_trigger:
self.cycle_counter += 1
if self.cycle_counter > self.sfx_cycles:
self.cycle_counter = 0
return True
#SPECIAL EFFECT ANIMATION
def sfx_run(self):
self.image = self.sfx_image
self.pos.y -= self.sfx_speed
self.image = pg.transform.rotate(self.image, pg.time.get_ticks() * self.sfx_speed)
#CHECKING FOR GAME STATE
def is_alive(self):
if not self.alive:
if not self.sfx_end_time():
self.sfx_run()
else:
self.kill()
#ROTATING THE BLOCKS
def rotate(self, pivot_pos):
translated = self.pos - pivot_pos
rotated = translated.rotate(90)
return rotated + pivot_pos
#UPDATING THE POSITION OF THE BLOCKS
def set_rect_pos(self):
pos = [self.next_pos, self.pos][self.tetromino.current]
self.rect.topleft = pos * TILE_SIZE
#RUNNING THE ABOOVE FUNCTION WHILE GAME RUNS
def update(self):
self.is_alive()
self.set_rect_pos()
#CHECKING FOR BLOCK COLLISION WITH BOUNDRIES
def is_collide(self, pos):
x, y = int(pos.x), int(pos.y)
if 0 <= x < FIELD_W and y < FIELD_H and (
y < 0 or not self.tetromino.tetris.field_array[y][x]):
return False
return True
#DEFINING TETROMINO CLASS
class Tetromino:
#INITIALIZING ATTRIBUTES OF TETROMINO CLASS
def __init__(self, tetris, current=True):
self.tetris = tetris
self.shape = random.choice(list(TETROMINOES.keys()))
self.image = random.choice(tetris.app.images)
self.blocks = [Block(self, pos) for pos in TETROMINOES[self.shape]]
self.landing = False
self.current = current
#ROATATING TETROMINO BLOCKS
def rotate(self):
pivot_pos = self.blocks[0].pos
new_block_positions = [block.rotate(pivot_pos) for block in self.blocks]
if not self.is_collide(new_block_positions):
for i, block in enumerate(self.blocks):
block.pos = new_block_positions[i]
#CHECKING FOR TETROMINO COLLISON WITH THE BOUNDRIES
def is_collide(self, block_positions):
return any(map(Block.is_collide, self.blocks, block_positions))
#NEW POSITION OF THE TETROMINO
def move(self, direction):
move_direction = MOVE_DIRECTIONS[direction]
new_block_positions = [block.pos + move_direction for block in self.blocks]
is_collide = self.is_collide(new_block_positions)
if not is_collide:
for block in self.blocks:
block.pos += move_direction
elif direction == 'down':
self.landing = True
#MOVING TETROMINO DOWN
def update(self):
self.move(direction='down')
TETRIS.PY:
Class Tetris:
#INTIALIZING TETRIS CLASS
def __init__(self, app):
self.app = app
self.sprite_group = pg.sprite.Group()
self.field_array = self.get_field_array()
self.tetromino = Tetromino(self)
self.next_tetromino = Tetromino(self, current=False)
self.speed_up = False
self.highscore= 0
self.score = 0
self.full_lines = 0
self.points_per_lines = {0: 0, 1: 10, 2: 30, 3: 70, 4: 150}
#SCORE CALCULATION AND SAVING
def get_score(self):
self.score += self.points_per_lines[self.full_lines]
self.full_lines = 0
#CHECKING FOR FULL LINES FOR SCORE
def check_full_lines(self):
row = FIELD_H - 1
for y in range(FIELD_H - 1, -1, -1):
for x in range(FIELD_W):
self.field_array[row][x] = self.field_array[y][x]
if self.field_array[y][x]:
self.field_array[row][x].pos = vec(x, y)
self.full_lines += 1
#PUTTING TETROMINO BLOCKS IN THE ARRAY
def put_tetromino_blocks_in_array(self):
for block in self.tetromino.blocks:
x, y = int(block.pos.x), int(block.pos.y)
self.field_array[y][x] = block
#CREATING A 2D ARRAY FOR STORING INFORMATION OF LANDED
TETROMINOS
def get_field_array(self):
return [[0 for x in range(FIELD_W)] for y in range(FIELD_H)]
#GAMES= STATE CEHCK FOR GAME OVER
def is_game_over(self):
if self.tetromino.blocks[0].pos.y == INIT_POS_OFFSET[1]:
pg.time.wait(300)
return True
#CHECK FOR LANDING OF TETROMINO
def check_tetromino_landing(self):
if self.tetromino.landing:
if self.is_game_over():
self.__init__(self.app)
else:
self.speed_up = False
self.put_tetromino_blocks_in_array()
self.next_tetromino.current = True
self.tetromino = self.next_tetromino
self.next_tetromino = Tetromino(self, current=False)
#USER INPUT KEYS DEFINITION
def control(self, pressed_key):
if pressed_key == pg.K_LEFT:
self.tetromino.move(direction='left')
elif pressed_key == pg.K_RIGHT:
self.tetromino.move(direction='right')
elif pressed_key == pg.K_UP:
self.tetromino.rotate()
elif pressed_key == pg.K_DOWN:
self.speed_up = True
#CREATING TETROMINO GRID
def draw_grid(self):
for x in range(FIELD_W):
for y in range(FIELD_H):
pg.draw.rect(self.app.screen, 'black',
(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE),
1),pg.RESIZABLE
#UPDATING SCORE,CHECKING FOR LINES,GAME STATE
def update(self):
trigger = [self.app.anim_trigger, self.app.fast_anim_trigger][self.speed_up]
if trigger:
self.check_full_lines()
self.tetromino.update()
self.check_tetromino_landing()
self.get_score()
self.sprite_group.update()
#DISPLAYING TETROMINO IN GRID
def draw(self):
self.draw_grid()
self.sprite_group.draw(self.app.screen)
MAIN.PY:
from TETRIS.settings import *
from TETRIS.tetris import Tetris, Text
import sys
import pathlib