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
120 changes: 71 additions & 49 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,105 +1,127 @@
import cv2
import mediapipe as mp
import numpy as np
import time

# Import necessary libraries
import mediapipe as mp # for hand tracking
import numpy as np # for numerical operations
import time # for time-related functions
import random # for generating random target positions
import cv2 # for computer vision and image processing

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

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

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

# 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
target_image = cv2.imread("ERC-Assignment-4/target.png", cv2.IMREAD_UNCHANGED)
target_image = cv2.resize(target_image, (30, 30))

# 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)]

# Initialize score
#6
score = 0

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

# 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
)
distance = np.sqrt((puck[0] - target[0]) ** 2 + (puck[1] - target[1]) ** 2)
return distance <= (acceptance_percent / 100) * max(target_image.shape[:2])

# Main game loop
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
remaining_time = max(0, game_duration - elapsed_time)
minutes, seconds = divmod(int(remaining_time), 60)

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

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

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

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

# 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])

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

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

# Check for collisions with the paddle
#17
if paddle_x < puck_x < paddle_x + 100 and paddle_y < puck_y < paddle_y + 20:
puck_velocity[1] *= -1

# Check for collisions with the targets(use is_within_acceptance)
#18
# 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)
frame = cv2.circle(frame, (int(puck_x), int(puck_y)), 10, (255, 255, 255), -1)

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)

# 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)

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

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

# 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()
cv2.destroyAllWindows()