diff --git a/Open CV Game/bird_sprite.png b/Open CV Game/bird_sprite.png new file mode 100644 index 000000000..f8d23d25e Binary files /dev/null and b/Open CV Game/bird_sprite.png differ diff --git a/Open CV Game/canonical_face_model_uv_visualization.png b/Open CV Game/canonical_face_model_uv_visualization.png new file mode 100644 index 000000000..2acd991eb Binary files /dev/null and b/Open CV Game/canonical_face_model_uv_visualization.png differ diff --git a/Open CV Game/gitignore b/Open CV Game/gitignore new file mode 100644 index 000000000..e43b0f988 --- /dev/null +++ b/Open CV Game/gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/Open CV Game/idea/FlappyBirdCV.iml b/Open CV Game/idea/FlappyBirdCV.iml new file mode 100644 index 000000000..d0876a78d --- /dev/null +++ b/Open CV Game/idea/FlappyBirdCV.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Open CV Game/idea/IncpectionProfiles/profiles_settings.xml b/Open CV Game/idea/IncpectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..105ce2da2 --- /dev/null +++ b/Open CV Game/idea/IncpectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/Open CV Game/idea/misc.xml b/Open CV Game/idea/misc.xml new file mode 100644 index 000000000..d56657add --- /dev/null +++ b/Open CV Game/idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Open CV Game/idea/modules.xml b/Open CV Game/idea/modules.xml new file mode 100644 index 000000000..471b0ea46 --- /dev/null +++ b/Open CV Game/idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Open CV Game/idea/vcs.xml b/Open CV Game/idea/vcs.xml new file mode 100644 index 000000000..288b36b1e --- /dev/null +++ b/Open CV Game/idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Open CV Game/main.py b/Open CV Game/main.py new file mode 100644 index 000000000..4cf44fe2e --- /dev/null +++ b/Open CV Game/main.py @@ -0,0 +1,149 @@ +import sys, time, random, pygame +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 +screen = pygame.display.set_mode(window_size) + +# Bird and pipe init +bird_img = pygame.image.load("bird_sprite.png") +bird_img = pygame.transform.scale(bird_img, (bird_img.get_width() / 6, bird_img.get_height() / 6)) +bird_frame = bird_img.get_rect() +bird_frame.center = (window_size[0] // 6, window_size[1] // 2) +pipe_frames = deque() +pipe_img = pygame.image.load("pipe_sprite_single.png") + +pipe_starting_template = pipe_img.get_rect() +space_between_pipes = 250 + +# Game loop +game_clock = time.time() +stage = 1 +pipeSpawnTimer = 0 +time_between_pipe_spawn = 40 +dist_between_pipes = 500 +pipe_velocity = lambda: dist_between_pipes / time_between_pipe_spawn +level = 0 +score = 0 +didUpdateScore = False +game_is_running = True + +with mp_face_mesh.FaceMesh( + max_num_faces=1, + 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) + screen.blit(text, tr) + pygame.display.update() + pygame.time.wait(2000) + VID_CAP.release() + cv.destroyAllWindows() + 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 + 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 + 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 + + # Mirror frame, swap axes because opencv != pygame + frame = cv.flip(frame, 1).swapaxes(0, 1) + + # 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) + screen.blit(text, tr) + text = pygame.font.SysFont("Helvetica Bold.ttf", 50).render(f'Score: {score}', True, (99, 245, 255)) + tr = text.get_rect() + 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() + diff --git a/Open CV Game/pipe_sprite_single.png b/Open CV Game/pipe_sprite_single.png new file mode 100644 index 000000000..8d24d25de Binary files /dev/null and b/Open CV Game/pipe_sprite_single.png differ