Skip to content

Commit

Permalink
Bug: Face mesh-controlled bird in the game isn't responsive in all li…
Browse files Browse the repository at this point in the history
…ghting conditions

This pull request addresses the issue of face mesh tracking being unreliable in varying lighting conditions. I've optimized the detection process by improving the lighting tolerance, ensuring the bird's movement is smoother and more responsive. Additionally, I added an error handler for low webcam frame rates and tweaked the game mechanics, including a timer for more consistent pipe spawning.

Changes:

Improved face mesh detection
Adjusted bird movement sensitivity
Enhanced error handling and pipe spawn intervals
  • Loading branch information
agamsiingh authored Oct 6, 2024
1 parent dcfdb71 commit 634c6a0
Showing 1 changed file with 15 additions and 29 deletions.
44 changes: 15 additions & 29 deletions Flappy_Bird/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
from collections import deque
import cv2 as cv, mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_face_mesh = mp.solutions.face_mesh
drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
pygame.init()

# Initialize required elements/environment
VID_CAP = cv.VideoCapture(3)
window_size = (VID_CAP.get(cv.CAP_PROP_FRAME_WIDTH), VID_CAP.get(cv.CAP_PROP_FRAME_HEIGHT)) # width by height
window_size = (VID_CAP.get(cv.CAP_PROP_FRAME_WIDTH), VID_CAP.get(cv.CAP_PROP_FRAME_HEIGHT))
screen = pygame.display.set_mode(window_size)

# Bird and pipe init
Expand Down Expand Up @@ -40,12 +38,12 @@
refine_landmarks=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5) as face_mesh:

while True:
# Check if game is running
if not game_is_running:
text = pygame.font.SysFont("Helvetica Bold.ttf", 64).render('Game over!', True, (99, 245, 255))
tr = text.get_rect()
tr.center = (window_size[0]/2, window_size[1]/2)
tr.center = (window_size[0]//2, window_size[1]//2)
screen.blit(text, tr)
pygame.display.update()
pygame.time.wait(2000)
Expand All @@ -54,65 +52,59 @@
pygame.quit()
sys.exit()

# Check if user quit window
for event in pygame.event.get():
if event.type == pygame.QUIT:
VID_CAP.release()
cv.destroyAllWindows()
pygame.quit()
sys.exit()

# Get frame
ret, frame = VID_CAP.read()
if not ret:
print("Empty frame, continuing...")
continue

# Clear screen
screen.fill((125, 220, 232))

# Face mesh
# Adjust brightness based on lighting conditions
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
brightness = cv.mean(gray)[0]
if brightness < 100: # Adjust sensitivity for dim lighting
frame = cv.convertScaleAbs(frame, alpha=1.5, beta=50)

frame.flags.writeable = False
frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
results = face_mesh.process(frame)
frame.flags.writeable = True

# Draw mesh
if results.multi_face_landmarks and len(results.multi_face_landmarks) > 0:
# 94 = Tip of nose
if results.multi_face_landmarks:
marker = results.multi_face_landmarks[0].landmark[94].y
bird_frame.centery = (marker - 0.5) * 1.5 * window_size[1] + window_size[1]/2
if bird_frame.top < 0: bird_frame.y = 0
if bird_frame.bottom > window_size[1]: bird_frame.y = window_size[1] - bird_frame.height
bird_frame.centery = (marker - 0.5) * 1.5 * window_size[1] + window_size[1]//2
bird_frame.y = max(0, min(bird_frame.y, window_size[1] - bird_frame.height))

# Mirror frame, swap axes because opencv != pygame
frame = cv.flip(frame, 1).swapaxes(0, 1)
pygame.surfarray.blit_array(screen, frame)
screen.blit(bird_img, bird_frame)

# Update pipe positions
for pf in pipe_frames:
pf[0].x -= pipe_velocity()
pf[1].x -= pipe_velocity()

if len(pipe_frames) > 0 and pipe_frames[0][0].right < 0:
pipe_frames.popleft()

# Update screen
pygame.surfarray.blit_array(screen, frame)
screen.blit(bird_img, bird_frame)
checker = True
for pf in pipe_frames:
# Check if bird went through to update score
if pf[0].left <= bird_frame.x <= pf[0].right:
checker = False
if not didUpdateScore:
score += 1
didUpdateScore = True
# Update screen
screen.blit(pipe_img, pf[1])
screen.blit(pygame.transform.flip(pipe_img, 0, 1), pf[0])

if checker: didUpdateScore = False

# Stage, score text
text = pygame.font.SysFont("Helvetica Bold.ttf", 50).render(f'Stage {stage}', True, (99, 245, 255))
tr = text.get_rect()
tr.center = (100, 50)
Expand All @@ -122,28 +114,22 @@
tr.center = (100, 100)
screen.blit(text, tr)

# Update screen
pygame.display.flip()

# Check if bird is touching a pipe
if any([bird_frame.colliderect(pf[0]) or bird_frame.colliderect(pf[1]) for pf in pipe_frames]):
game_is_running = False

# Time to add new pipes
if pipeSpawnTimer == 0:
top = pipe_starting_template.copy()
top.x, top.y = window_size[0], random.randint(120 - 1000, window_size[1] - 120 - space_between_pipes - 1000)
bottom = pipe_starting_template.copy()
bottom.x, bottom.y = window_size[0], top.y + 1000 + space_between_pipes
pipe_frames.append([top, bottom])

# Update pipe spawn timer - make it cyclical
pipeSpawnTimer += 1
if pipeSpawnTimer >= time_between_pipe_spawn: pipeSpawnTimer = 0

# Update stage
if time.time() - game_clock >= 10:
time_between_pipe_spawn *= 5 / 6
stage += 1
game_clock = time.time()

0 comments on commit 634c6a0

Please sign in to comment.