Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Powerups have been added #3

Merged
merged 1 commit into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
STAFFPOS = (175, 275, 375, 475, 575)
FPS = 60

probability = 10
obstacle_probability = 10
powerup_probability = 1

# FIXME: Determine the best values for these constants
SPEED_LEVEL = 15
PROB_LEVEL = 30
START_SPEED = 2
BLANK_SPACE = 200

# Staff change sounds
pygame.mixer.init()
Expand All @@ -30,11 +33,12 @@

TOTAL_STAFFS = len(STAFFSOUNDS)
TOTAL_NOTES = 6
TOTAL_POWERUPS = 2


class Direction(Enum):
UP = -1
DOWN = 1


obstacles_group = pygame.sprite.Group()
moving_group = pygame.sprite.Group()
89 changes: 60 additions & 29 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import globals
import obstacles
import logging
import movinglist
import powerups

from pygame.locals import *
from textcontent import *
Expand All @@ -18,7 +20,7 @@
FramePerSec = pygame.time.Clock()

# Setup player and obstacles
game_obstacles = obstacles.ObstacleList()
game_objects = movinglist.MovingList()
player = notes.Player()

# Setup logging
Expand All @@ -42,27 +44,49 @@ def check_collision():
Check for collisions between the player and obstacles. If there is a collision, convert the player sprite to that of the obstacle. After 3 collisions, the game ends.
"""
hits = pygame.sprite.spritecollide(
player, globals.obstacles_group, False, collided=pygame.sprite.collide_mask
player, globals.moving_group, False, collided=pygame.sprite.collide_mask
)
if hits:
logger.info("Collision detected:")
pygame.draw.rect(DISPLAYSURF, (0, 0, 0), (0, 50, globals.WIDTH, 50))
if player.hit_count < 3:
# Increase hit count and display it
player.hit_count += 1
logger.debug("Hit count: " + str(player.hit_count))

# Remove the obstacles from the list
# check if the player is colliding with an obstacle
if isinstance(hits[0], obstacles.Obstacle):
logger.info("Collision detected with obstacle.")
pygame.draw.rect(DISPLAYSURF, (0, 0, 0), (0, 50, globals.WIDTH, 50))
if player.hit_count < 3:
# Increase hit count and display it
player.hit_count += 1
logger.debug("Hit count: " + str(player.hit_count))

# Remove the obstacles from the list
for obj in hits:
game_objects.remove_object(obj)
obj.hide(DISPLAYSURF)

# Convert the player sprite to that of the obstacle
player.convert_to_obstacle(DISPLAYSURF, hits[0])
else:
logger.debug("Game over")
pygame.quit()
sys.exit()

# check if the player is colliding with a powerup
elif isinstance(hits[0], powerups.Powerup):
logger.info("Collision detected with powerup.")
# Remove the powerup from the list
for obj in hits:
game_obstacles.remove_obstacle(obj)
obj.hide_obstacle(DISPLAYSURF)
game_objects.remove_object(obj)
obj.hide(DISPLAYSURF)

# Convert the player sprite to that of the obstacle
player.convert_to_obstacle(DISPLAYSURF, hits[0])
else:
logger.debug("Game over")
pygame.quit()
sys.exit()
# If powerup of type 0, increase the hit count
if hits[0].powerup_type == 0 and player.hit_count > 0:
player.hit_count -= 1
pygame.draw.rect(DISPLAYSURF, (0, 0, 0), (0, 50, globals.WIDTH, 50))
logger.debug("New hit count: " + str(player.hit_count))

# If powerup of type 1, increase the score
elif hits[0].powerup_type == 1:
player.prev_score = player.score
player.score += 10
logger.debug("New score: " + str(player.score))


while True: # main game loop
Expand Down Expand Up @@ -123,30 +147,37 @@ def check_collision():

score_text, score_text_rect = scores_text(player.score)
DISPLAYSURF.blit(score_text, score_text_rect)
prev_score = player.score
player.score += 0.01

# Remove the score from the screen if it changes
if int(prev_score) != int(player.score):
if int(player.prev_score) != int(player.score):
pygame.draw.rect(DISPLAYSURF, (0, 0, 0), (globals.WIDTH - 200, 50, 200, 50))

# Increase the speed of the obstacles every SPEED_LEVEL points
if int(prev_score / globals.SPEED_LEVEL) != int(
if int(player.prev_score / globals.SPEED_LEVEL) != int(
player.score / globals.SPEED_LEVEL
):
game_obstacles.speed += 1
game_objects.speed += 1
globals.obstacle_probability += 1

# Increase the probability of adding an obstacle every PROB_LEVEL points
if int(prev_score / globals.PROB_LEVEL) != int(
if int(player.prev_score / globals.PROB_LEVEL) != int(
player.score / globals.PROB_LEVEL
):
globals.probability += 1
globals.obstacle_probability += 5

# Display and move the obstacles
# Starting probability of adding an obstacle is 10 / 1000
if random.randint(0, 1000) < globals.probability:
game_obstacles.add_obstacle()
game_obstacles.move_obstacles(DISPLAYSURF)
# Starting probability of adding an obstacle is 10%
if random.randint(0, 100) < globals.obstacle_probability:
game_objects.add_obstacle()

# Starting probability of adding a powerup is 1%
if random.randint(0, 100) < globals.powerup_probability:
game_objects.add_powerup()

game_objects.move_objects(DISPLAYSURF)

player.prev_score = player.score
player.score += 0.01

# Display the 5 staff lines at equal intervals in the y direction
staff_lines = [
Expand Down
109 changes: 109 additions & 0 deletions movinglist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import random
import pygame
import sys
import notes
import globals
from obstacles import Obstacle
from powerups import Powerup

from pygame.locals import *


class MovingList:
"""
Class for a list of moving objects (obstacles or powerups)

Attributes:
obj_list : list of Obstacle/Powerup objects
rightmost_occupied_px: list of int (rightmost pixel occupied by an obstacle on each staff line)

Methods:
add_obstacle() : adds an obstacle to the list
add_powerup() : adds a powerup to the list
remove_object(): removes an obstacle/powerup from the list
move_objects() : moves all objects in the list
"""

RIGHT_LIMIT = globals.WIDTH - globals.BLANK_SPACE

def __init__(self):
"""
Initialize an empty list of moving objects
"""
self.obj_list = []
self.rightmost_occupied_px = [0, 0, 0, 0, 0]
self.speed = globals.START_SPEED

def add_obstacle(self):
"""
Add an obstacle to the list to an empty position on the staff
"""
# Out of all unoccupied staff lines, randomly choose one.
# If any 4 or all are occupied, return False
unoccupied_cnt = self.rightmost_occupied_px.count(0)
if unoccupied_cnt == 0 or unoccupied_cnt == 1:
return False

unoccupied = [i for i, x in enumerate(self.rightmost_occupied_px) if x == 0]
s_loc = random.choice(unoccupied)

# randomly generate a number
n_type = random.randint(0, globals.TOTAL_NOTES - 1)

obstacle = Obstacle(note_type=n_type, staff_loc=s_loc)
# print("Adding obstacle at staff line", s_loc)
self.obj_list.append(obstacle)
globals.moving_group.add(obstacle)
self.rightmost_occupied_px[s_loc] = obstacle.x + obstacle.rect.width / 2

return True

def add_powerup(self):
"""
Add a powerup to the list to an empty position on the staff
"""
# Out of staff lines 1 and 2, randomly choose one which is not occupied.
# If both are occupied, return False
if self.rightmost_occupied_px[1] == 0 and self.rightmost_occupied_px[2] == 0:
s_loc = random.randint(1, 2)
elif self.rightmost_occupied_px[1] == 0:
s_loc = 1
elif self.rightmost_occupied_px[2] == 0:
s_loc = 2
else:
return False

n_type = s_loc - 1
powerup = Powerup(powerup_type=n_type)
# print("Adding obstacle at staff line", s_loc)
self.obj_list.append(powerup)
globals.moving_group.add(powerup)
self.rightmost_occupied_px[s_loc] = powerup.x + powerup.rect.width / 2

return True

def remove_object(self, moving_object):
"""
Remove the moving object from the list
"""
self.obj_list.remove(moving_object)
globals.moving_group.remove(moving_object)

def move_objects(self, surface):
"""
Move all objects in the list, while updating the occupied staff lines
"""
for moving_object in self.obj_list:
moving_object.move_left(surface, self.speed)
w = moving_object.rect.width
if moving_object.x + moving_object.offset_x + w / 2 < 0:
self.remove_object(moving_object)

for i in range(0, 5):
if self.rightmost_occupied_px[i] != 0:
self.rightmost_occupied_px[i] -= 1
if (
self.rightmost_occupied_px[i] < self.RIGHT_LIMIT
and self.rightmost_occupied_px[i] != 0
):
self.rightmost_occupied_px[i] = 0
1 change: 1 addition & 0 deletions notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def __init__(
self.color_player()
self.hit_count = 0
self.score = 0
self.prev_score = 0

def color_player(self):
colorImage = pygame.Surface(self.orig_image.get_size()).convert_alpha()
Expand Down
78 changes: 2 additions & 76 deletions obstacles.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Obstacle(notes.Note):

Methods:
move_left() : moves obstacles across the screen
hide() : hides the obstacle by drawing a black rectangle over it
"""

def __init__(
Expand Down Expand Up @@ -64,83 +65,8 @@ def move_left(self, surface, speed=1):
# draw the obstacle at its new position
self.draw(surface)

def hide_obstacle(self, surface):
def hide(self, surface):
"""
Hide the obstacle
"""
pygame.draw.rect(surface, (0, 0, 0), self.rect)


class ObstacleList:
"""
Class for a list of obstacles

Attributes:
obstacles : list of Obstacle objects
rightmost_occupied_px: list of int (rightmost pixel occupied by an obstacle on each staff line)

Methods:
add_obstacle() : adds an obstacle to the list
remove_obstacle(): removes an obstacle from the list
move_obstacles() : moves all obstacles in the list
"""

RIGHT_LIMIT = globals.WIDTH / 2

def __init__(self):
"""
Initialize an empty list of obstacles
"""
self.obstacles = []
self.rightmost_occupied_px = [0, 0, 0, 0, 0]
self.speed = 1

def add_obstacle(self):
"""
Add an obstacle to the list to an empty position on the staff
"""
# if no staff line has righmost pixel as zero, that means all staff lines are occupied, so return False
if all(x != 0 for x in self.rightmost_occupied_px):
return False

# randomly generate a number
n_type = random.randint(0, globals.TOTAL_NOTES - 1)
# randomly generate a staff location
while True:
s_loc = random.randint(0, globals.TOTAL_STAFFS - 1)
if self.rightmost_occupied_px[s_loc] == 0:
break

obstacle = Obstacle(note_type=n_type, staff_loc=s_loc)
# print("Adding obstacle at staff line", s_loc)
self.obstacles.append(obstacle)
globals.obstacles_group.add(obstacle)
self.rightmost_occupied_px[s_loc] = obstacle.x + obstacle.rect.width / 2

return True

def remove_obstacle(self, obstacle):
"""
Remove an obstacle from the list
"""
self.obstacles.remove(obstacle)
globals.obstacles_group.remove(obstacle)

def move_obstacles(self, surface):
"""
Move all obstacles in the list, while updating the occupied staff lines
"""
for obstacle in self.obstacles:
obstacle.move_left(surface, self.speed)
w = obstacle.rect.width
if obstacle.x + obstacle.offset_x + w / 2 < 0:
self.remove_obstacle(obstacle)

for i in range(0, 5):
if self.rightmost_occupied_px[i] != 0:
self.rightmost_occupied_px[i] -= 1
if (
self.rightmost_occupied_px[i] < self.RIGHT_LIMIT
and self.rightmost_occupied_px[i] != 0
):
self.rightmost_occupied_px[i] = 0
Loading