Done as [DASS] Design and analysis of software systems' Assignment-2 | spring 2021
- extended version here
an arcade game in Python3 (terminal-based), inspired from the old classic brick breaker similar to this. The player will be using a paddle with a bouncing ball to smash a wall of bricks and make high scores! The objective of the game is to break all the bricks as fast as possible and beat the highest score! You lose a life when the ball touches the ground below the paddle.
- you have 5 lives or 200 secs for game.
- a life losses if you cross the lower boundary.
- you can take advantages of some powerups for 20 secs or some exploding bricks.
- score increases by 1 if a brick exploded completely(different bricks have different strengths - 1,2,3,infinity and these are in different colours).
The board class creates a 40*100 board for gameplay, with all four boundaries. render function in this class is for printing our board(that 2-d matrix which we are updating).
The Object class is the parent class based on which some entities of the game are inherited (bricks , paddle , ball , exploding bricks , powerups).
The Ball class has all the variables and functions of ball, this includes the shoot, movement, collisions. It is inherited from Object class and has additional functionality. It also represents polymorphism as the render() function has been changed.
The paddle class is inherited from the Object class and has function to move .
The powerups class is inherited from Object class, it has function that check for collisions of powerups with paddle.
The bricks class is inherited from Object class, it has function to check collisions of ball and bricks.
The exploding bricks class is inherited from Object class, it has function to check collisions of ball and bricks.
Inheritance allows us to define a class that inherits all the methods and properties from another class.
A base class Object
has been declared from which multiple elements are inherited.
class Objects():
def __init__(self , obj , xpos , ypos):
self.position_x = xpos
self.position_y = ypos
self.height = len(obj)
self.width = len(obj[0])
self.shape = obj
Polymorphism allows us to define methods in the child class with the same name as defined in their parent class.
class Objects():
...
def clear(self):
for i in range(self.width):
for j in range(self.height):
global_variables.main_board.matrix[j+self.position_y][i+self.position_x] = " "
def render(self):
if global_variables.active_powerupflag[4] == 1 and global_variables.active_powerupflag[1] == 0:
self.shape = config.shrink_p
self.width = len(config.shrink_p[0])
for i in range(self.width):
for j in range(self.height):
global_variables.main_board.matrix[j+self.position_y][i+self.position_x] =( Back.CYAN + Fore.CYAN + self.shape[j][i] )
elif global_variables.active_powerupflag[1] == 1 and global_variables.active_powerupflag[4] == 0:
self.shape = config.expand_p
self.width = len(config.expand_p[0])
# self.position_x -=1
for i in range(self.width):
for j in range(self.height):
global_variables.main_board.matrix[j+self.position_y][i+self.position_x] =( Back.CYAN + Fore.CYAN + self.shape[j][i] )
elif (global_variables.active_powerupflag[1] == 1 and global_variables.active_powerupflag[4] == 1) or (global_variables.active_powerupflag[1] == 0 and global_variables.active_powerupflag[4] == 0):
self.shape = config.paddle
self.width = len(config.paddle[0])
for i in range(self.width):
for j in range(self.height):
global_variables.main_board.matrix[j+self.position_y][i+self.position_x] =( Back.CYAN + Fore.CYAN + self.shape[j][i] )
class Ball(Objects):
def clear(self):
for i in range(self.width):
for j in range(self.height):
global_variables.main_board.matrix[j+self.position_y][i+self.position_x] = " "
def render(self):
if global_variables.active_powerupflag[2] == 1 and self.onetimetempflag == 0:
if self.speed_x < 0:
self.speed_x -=1
else:
self.speed_x += 1
self.onetimetempflag = 1
self.collision_with_wall()
self.collision_with_paddle()
self.position_x += self.speed_x
self.position_y -= self.speed_y
for i in range(self.width):
for j in range(self.height):
global_variables.main_board.matrix[j+self.position_y][i+self.position_x] = self.shape[j][i]
The idea of wrapping data and the methods that work on data within one unit. Prevents accidental modification of data. Implemented many classes and objects for the same.
Abstraction means hiding the complexity and only showing the essential features of the object.
class Ball(Objects):
...
def speed(self):
self.speed_x = global_variables.ball_privious_speed_x
self.speed_y = global_variables.ball_privious_speed_y
.speed() is an abstraction
- Run the following code to start the game.
python3 main.py
- 'a, d' use these controls for left, and right.
- use 'x' to shoot.
- press 'q' to quit.
- Python3
- colorama==0.4.4
- numpy==1.18.1
For mac:
brew cask update
sudo brew cask install python3
For Linux:
sudo apt-get update
sudo apt-get install python3
Both developers and non-developers are invited to contribute to this project by adding a PR. If genuine, the changes would be approved and added to the master branch.
As of now, according to the problem statement a powerup(ball multiplier) is left, also you can contribute anything you like to do.
- ball-multiplier powerup
- exploding bricks modifications
- side collision with bricks (using trajectory of ball)
- increment of speed of ball in y-direction
- anything else you can find intresting, open for suggestions.