Skip to content
Open
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
118 changes: 72 additions & 46 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,104 +2,130 @@
import mediapipe as mp
import numpy as np
import time

import random

# Initialize webcam
#1
cap = cv2.VideoCapture(0) # 1

# Initialize hand tracking
#2
mp_hands = mp.solutions.hands
hands = mp_hands.Hands() # 2

# Initialize paddle and puck positions
#3
paddle_x, paddle_y = 320, 480 # Initial paddle position # 3
puck_x, puck_y = 320, 240 # Initial puck position # 3

# Initial velocity
initial_puck_velocity = [10, 10]
initial_puck_velocity = [15, 15]
puck_velocity = initial_puck_velocity.copy()

# Load target image and resize it to 30,30
#4
# Load target image and resize it to 30x30
target_image = cv2.imread("ERC-Assignment-4/target.png", cv2.IMREAD_UNCHANGED) # 4
target_image = cv2.resize(target_image, (30, 30)) # 4

# Initialize 5 target positions randomly(remember assignment 2!!)
#5
# Initialize 5 target positions randomly
target_positions = [(random.randint(50, 590), random.randint(50, 430)) for _ in range(5)] # 5

# Initialize score
#6
score = 0 # 6

# Initialize timer variables
start_time = time.time()
game_duration = 30 # 1/2 minute in seconds

# Function to check if the puck is within a 5% acceptance region of a target
def is_within_acceptance(puck, target, acceptance_percent=5):
#complete the function
#7
return (
0#make changes here!! #8
)
# Calculate the distance between puck and target
distance = np.sqrt((puck[0] - target[0]) ** 2 + (puck[1] - target[1]) ** 2) # 7

# Check if the distance is within the acceptance region
return distance <= (acceptance_percent / 100) * max(target_image.shape[:2]) # 8

while True:
# Calculate remaining time and elapsed time in minutes and seconds
#9

# Calculate remaining time and elapsed time in minutes and seconds
elapsed_time = time.time() - start_time # 9
remaining_time = max(0, game_duration - elapsed_time) # 9
minutes, seconds = divmod(int(remaining_time), 60) # 9

# Read a frame from the webcam
#10
ret, frame = cap.read() # 10

# Flip the frame horizontally for a later selfie-view display
#11
frame = cv2.flip(frame, 1) # 11

# Convert the BGR image to RGB
#12
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 12

# Process the frame with mediapipe hands
#13
results = hands.process(frame_rgb) # 13

# Update paddle position based on index finger tip
#14
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
index_finger = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
paddle_x, paddle_y = int(index_finger.x * frame.shape[1]), int(index_finger.y * frame.shape[0]) # 14

# Update puck position based on its velocity
#15
puck_x += puck_velocity[0] # 15
puck_y += puck_velocity[1] # 15

# Check for collisions with the walls
#16
if puck_x <= 0 or puck_x >= frame.shape[1]:
puck_velocity[0] *= -1 # 16
if puck_y <= 0 or puck_y >= frame.shape[0]:
puck_velocity[1] *= -1 # 16

# Check for collisions with the paddle
#17

# Check for collisions with the targets(use is_within_acceptance)
#18
if (
paddle_x < puck_x < paddle_x + 100
and paddle_y < puck_y < paddle_y + 20
):
puck_velocity[1] *= -1 # 17

# Check for collisions with the targets
for target_position in target_positions:
if is_within_acceptance([puck_x, puck_y], target_position):
# Increase the player's score
score += 1

# Remove the hit target
# Increase puck velocity after each hit by 2(you will have to increase both x and y velocities
target_positions.remove(target_position)

# Increase puck velocity after each hit by 2 (both x and y velocities)
puck_velocity[0] += 2
puck_velocity[1] += 2

# Draw paddle, puck, and targets on the frame and overlay target image on frame
#19

# FOR REFERENCE:
# for target_position in target_positions:
# target_roi = frame[target_position[1]:target_position[1] + target_image.shape[0],
# target_position[0]:target_position[0] + target_image.shape[1]]
# alpha = target_image[:, :, 3] / 255.0
# beta = 1.0 - alpha
# for c in range(0, 3):
# target_roi[:, :, c] = (alpha * target_image[:, :, c] +
# beta * target_roi[:, :, c])
frame = cv2.rectangle(frame, (paddle_x, paddle_y), (paddle_x + 100, paddle_y + 20), (255, 0, 0), -1) # 19
frame = cv2.circle(frame, (int(puck_x), int(puck_y)), 10, (255, 255, 255), -1) # 19

for target_position in target_positions:
frame_roi = frame[
target_position[1] : target_position[1] + target_image.shape[0],
target_position[0] : target_position[0] + target_image.shape[1],
]
alpha = target_image[:, :, 3] / 255.0
beta = 1.0 - alpha
for c in range(0, 3):
frame_roi[:, :, c] = (alpha * target_image[:, :, c] + beta * frame_roi[:, :, c])

# Display the player's score on the frame
#20
cv2.putText(frame, f"Score: {score}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) # 20

# Display the remaining time on the frame
#21
cv2.putText(frame, f"Time: {minutes:02d}:{seconds:02d}", (frame.shape[1] - 200, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) # 21

# Check if all targets are hit or time is up
#22
if not target_positions or remaining_time == 0: # 22
break

# Display the resulting frame
#23
cv2.imshow("Virtual Air Hockey", frame) # 23

# Exit the game when 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# Release the webcam and close all windows
#24
cap.release() # 24
cv2.destroyAllWindows() # 24