diff --git a/Project Overview.pdf b/Project Overview.pdf new file mode 100644 index 00000000..f43b7056 Binary files /dev/null and b/Project Overview.pdf differ diff --git a/ProjectProposal b/ProjectProposal new file mode 100644 index 00000000..ed93f4ed --- /dev/null +++ b/ProjectProposal @@ -0,0 +1,16 @@ +Our main idea is to create a two-player pong game with hand gestures as the main way of playing. +We will explore OpenCV and try to implement gesture recognition so it can serve as the main controller +for the game. Our minimum viable will be designing the game interface and getting the gesture recognition +to successfully detect gestures so the components of the game will all work individually. Our stretch goal would be 3D pong. + +Anna's Learning Goal: I want to become more familiar with pygame and explore OpenCV's capabilities in depth. +Shyheim's Learning Goal: I want to design something that is nastolgic through pygame and learn to peer program more. + +We plan on using Pygame library for one and the OpenCV library, we do not know how to use them yet but +we plan on exploring their differnt abilities. We want to use OpenCV in order to use the camera to recognize +hand gestures while using pygame to actually design the game. + + +We want to get the layout of the game working and have it working with the mouse and/or keyboard commands. +The biggest risk we may face is taking on too much in the amount of time we have or trying to figure out +OpenCV since neither of us have any experience with it diff --git a/ProjectProposal.ipynb b/ProjectProposal.ipynb new file mode 100644 index 00000000..260cabaf --- /dev/null +++ b/ProjectProposal.ipynb @@ -0,0 +1,46 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Our main idea is to create a two-player pong game with hand gestures as the main way of playing. We will explore OpenCV and try to implement gesture recognition so it can serve as the main controller for the game. Our minimum viable will be designing the game interface and getting the gesture recognition to successfully detect gestures so the components of the game will all work individually. Our stretch goal would be 3D pong. \n", + " Anna's Learning Goal: I want to become more familiar with pygame and explore OpenCV's capabilities in depth.\n", + " Shyheim's Learning Goal: I want to design something that is nastolgic through pygame and learn to peer program more.\n", + " We plan on using Pygame library for one and the OpenCV library, we do not know how to use them yet but we plan on exploring their differnt abilities. We want to use OpenCV in order to use the camera to recognize hand gestures while using pygame to actually design the game.\n", + " We want to get the layout of the game working and have it working with the mouse and/or keyboard commands.\n", + " The biggest risk we may face is taking on too much in the amount of time we have or trying to figure out OpenCV since neither of us have any experience with it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/README.md b/README.md index 5f822327..64ce5e7c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # InteractiveProgramming This is the base repo for the interactive programming project for Software Design, Spring 2018 at Olin College. + +Install PyGame: + $ apt-get build-dep python-pygame + $ apt-get install mercurial python-dev python-numpy ffmpeg libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev + $ pip install pygame + +Install OpenCV: + $ pip install opencv-python diff --git a/contours.py b/contours.py new file mode 100644 index 00000000..6c3c11da --- /dev/null +++ b/contours.py @@ -0,0 +1,25 @@ +import numpy as np +import cv2 + +cap = cv2.VideoCapture(0) + +while(True): + # Capture frame-by-frame + ret, frame = cap.read() + + imgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + ret, thresh = cv2.threshold(imgray, 127, 255, 0) + im2, contours, hierachy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) + cv2.drawContours(imgray, contours, -1, (0,255,0), 3) + + + cv2.imshow('frame', imgray) + + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + +# When everything done, release the capture +cap.release() +cv2.destroyAllWindows() diff --git a/handgesture.py b/handgesture.py new file mode 100644 index 00000000..2d93cb6f --- /dev/null +++ b/handgesture.py @@ -0,0 +1,79 @@ +import numpy as np +from collections import deque +import cv2 + + +cap = cv2.VideoCapture(0) + +while True: + # Capture frame-by-frame + ret, frame = cap.read() + + # Convert to HSV + hsv_scale = cv2.cvtColor(frame.copy(), cv2.COLOR_BGR2HSV) + + + # defining range of blue + lower_threshold_blue = np.array([110,50,50]) + upper_threshold_blue = np.array([130,255,255]) + + # creating the threshold + # binary + mask = cv2.inRange(hsv_scale, lower_threshold_blue, upper_threshold_blue) + mask = cv2.erode(mask, None, iterations=2) + mask = cv2.dilate(mask, None, iterations=2) + + + # blue moment tracking + contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] + center = None + blue_coordinates = [] + + if len(contours) > 0: + + c = max(contours, key=cv2.contourArea) + ((x,y), radius) = cv2.minEnclosingCircle(c) + M = cv2.moments(c) + center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"])) + cv2.circle(frame, (int(x), int(y)), int(radius), (0,255,255), 2) + cv2.circle(frame, center, 5, (0, 0, 255), -1) + + + # definng range of red + lower_threshold_red = np.array([0,100,100]) + upper_threshold_red = np.array([179,255,255]) + + mask2 = cv2.inRange(hsv_scale, lower_threshold_red, upper_threshold_red) + mask2 = cv2.erode(mask2, None, iterations=2) + mask2 = cv2.dilate(mask2, None, iterations=2) + + # blue moment tracking + contours2 = cv2.findContours(mask2.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] + center2 = None + + if len(contours2) > 0: + + c = max(contours2, key=cv2.contourArea) + ((x,y), radius) = cv2.minEnclosingCircle(c) + M = cv2.moments(c) + center2 = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"])) + + cv2.circle(frame, (int(x), int(y)), int(radius), (0,255,255), 2) + cv2.circle(frame, center2, 5, (0, 0, 255), -1) + + + # blue + res = cv2.bitwise_and(frame,frame,mask=mask) + + + # Display the resulting frame + cv2.imshow('frame', frame) + cv2.imshow('mask', mask) + cv2.imshow('mask2', mask2) + cv2.imshow('res', res) + if cv2.waitKey(1) & 0xFF == ord('q'): + break + +# When everything done, release the capture +cap.release() +cv2.destroyAllWindows() diff --git a/pong.py b/pong.py new file mode 100644 index 00000000..6145464a --- /dev/null +++ b/pong.py @@ -0,0 +1,237 @@ +import pygame +from pygame.locals import * +import time +import os +from random import * +import math +import sys + + +class PyGameWindowView(object): + """ A view of the Pong game rendered in a PyGame Window""" + def __init__(self, model, size): + """ Initialize the PyGame window of the game """ + self.model = model + self.screen = pygame.display.set_mode(size) + + def draw(self): + """Draw the current game state to the screen""" + self.screen.fill(pygame.Color(135, 206, 250)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle1.x, + self.model.paddle1.y, + self.model.paddle1.width, + self.model.paddle1.height)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle2.x, + self.model.paddle2.y, + self.model.paddle2.width, + self.model.paddle2.height)) + + pygame.draw.circle(self.screen, + pygame.Color(255,255,102), + (self.model.ball.x, + self.model.ball.y), + self.model.ball.radius) + + pygame.display.update() + + +class PongModel(object): + """Encodes a model of the game state""" + + def __init__(self,size): + self.width = size[0] + self.height = size[1] + self.paddle1 = Paddle(100, 20, 10, self.height) + self.paddle2 = Paddle(100, 20, self.width - 30, self.height / 2) + self.ball = Ball(int(self.width/2), int(self.height/2), int(10), 10) + + def update(self): + """Left Paddle""" + self.paddle1.update() + """Right Paddle""" + self.paddle2.update() + + """Movement of ball when it touches screen boundaries""" + if self.ball.x < 500 or self.ball.x > 0: + self.ball.x = self.ball.x + int(self.ball.vx) + else: + self.ball.x = self.ball.y - int(self.ball.vx) + if self.ball.y < 500 or self.ball.y > 0: + self.ball.y = self.ball.y + int(self.ball.vy) + else: + self.ball.y = self.ball.y - int(self.ball.vy) + + """Movement of the ball when it touches paddles""" + ballmin = self.ball.y - 5 + balltop = self.ball.y + 5 + paddle1_min = self.paddle1.y - self.paddle1.height + paddle2_min = self.paddle2.y - self.paddle2.height + paddle1_x_min = self.paddle1.x - self.paddle2.width + paddle2_x_min = self.paddle2.x - self.paddle2.width + if int(self.paddle1.x + 20) == self.ball.x: + if self.paddle1.y < balltop < paddle1_min: + self.ball.x = self.ball.x - int(self.ball.vx) + self.ball.y = self.ball.y - int(self.ball.vy) + print('she') + elif self.paddle1.y< ballmin < paddle1_min: + self.ball.x = self.ball.x - int(self.ball.vx) + self.ball.y = self.ball.y - int(self.ball.vy) + print('he') + if int(self.paddle2.x + 20) == self.ball.x: + if self.paddle2.y < ballmin < paddle2_min: + self.ball.x = self.ball.x - int(self.ball.vx) + self.ball.y = self.ball.y - int(self.ball.vy) + print('him') + elif self.paddle2.y< balltop < paddle2_min: + self.ball.x = self.ball.x - int(self.ball.vx) + self.ball.y = self.ball.y - int(self.ball.vy) + print('hers') + # if (self.paddle1.y == self.ball.y) and self.paddle1.x == self.ball.x: + # if ballmin == paddle1_min and self.ball.y == self.paddle1.y and self.paddle1.x == self.ball.x: + # self.ball.x = self.ball.x - int(self.ball.vx) + # self.ball.y = self.ball.y - int(self.ball.vy) + # print('HIT') + # # if self.paddle2.x == self.ball.y: + # if ballmin == paddle2_min and self.ball.y == self.paddle2.y and self.paddle2.x == self.ball.x: + # self.ball.x = self.ball.x + int(self.ball.vx) + # self.ball.y = self.ball.y + int(self.ball.vy) + # print('shs') + + """Boundaries for the ball and paddles""" + if self.paddle1.y > 700: + self.paddle1.y = 700 + if self.paddle1.y < 0: + self.paddle1.y = 0 + if self.paddle2.y > 700: + self.paddle2.y = 700 + if self.paddle2.y < 0: + self.paddle2.y = 0 + if self.ball.y >= 800: + self.ball.vy = -self.ball.vy + if self.ball.y <= 0: + self.ball.vy = -self.ball.vy + if self.ball.x < self.paddle1.x: + pygame.display.quit() + if self.ball.x > self.paddle2.x: + pygame.display.quit() + # if self.ball. + def __str__(self): + output_lines = [] + + output_lines.append(str(self.paddle1)) + output_lines.append(str(self.paddle2)) + output_lines.append(str(self.ball)) + + return "\n".join(output_lines) + +class Ball(pygame.sprite.Sprite): + + def __init__(self, x, y, radius, speed): + + self.x = x + self.y = y + self.radius = radius + self.speed = speed + self.vy = randint(-1, 1) + self.vx = randint(-1, 1) + + + def update(self, ball, paddle1, paddle2, vx, vy): + + if self.ball.x == -1 and self.ball.x == 10: + return -1 + elif self.ball.x == 1 and self.paddle2.width == self.ball.x: + return -1 + else: + return 1 + self.x += self.vx + self.y += self.vy + def __str__(self): + return "Ball x=%f, y=%f, radius=%f" % (self.x, self.y, self.radius) + + +class Paddle(pygame.sprite.Sprite): + """Encodes the state of the paddle 1 in the game""" + + def __init__(self, height, width, x, y): + """Initalize a paddle with the sepcified height, width, and position (x,y) """ + + self.height = height + self.width = width + self.x = x + self.y = y + self.vy = 0.0 + + def update(self): + """update the state of the paddle""" + + self.y += self.vy + + def __str__(self): + return "Paddle height=%f, width=%f, x=%f, y=%f" % (self.height, self.width, self.x, self.y) + + +class PyGameMouseController(object): + + def __init__(self, model): + self.model = model + + def handle_event(self, event): + if event.type == MOUSEMOTION: + self.model.paddle1.y = event.pos[1] - self.model.paddle1.height/2.0 + + +class PyGameKeyboardController(object): + + def __init__(self,event): + self.model = model + + def handle_event(self,event): + + if event.type != KEYDOWN: + return + if event.key == pygame.K_UP: + self.model.paddle2.vy += -2.0 + else: + self.model.paddle2.vy = 0.0 + if event.key == pygame.K_DOWN: + self.model.paddle2.vy += 2.0 + + + + + +if __name__ == '__main__': + pygame.init() + + FPS = 200 + size = (1800, 800) + model = PongModel(size) + view = PyGameWindowView(model, size) + + controller1 = PyGameMouseController(model) + controller2 = PyGameKeyboardController(model) + + fps_clock = pygame.time.Clock() + + running = True + while running: + for event in pygame.event.get(): + if event.type == QUIT: + running = False + controller1.handle_event(event) + controller2.handle_event(event) + # ball = pygame.draw.circle + # # ball = Ball(int((size[0])/2), int(size[1]/2), int(10), 10) + # # view.screen.blit(ball, (0, 0)) + + model.update() + view.draw() + time.sleep(.001) + fps_clock.tick(FPS) + + pygame.quit() diff --git a/pong2.py b/pong2.py new file mode 100644 index 00000000..e4eda054 --- /dev/null +++ b/pong2.py @@ -0,0 +1,195 @@ +import pygame +from pygame.locals import * +import time +import numpy as np +import cv2 + + + +class PyGameWindowView(object): + """ A view of the Pong game rendered in a PyGame Window""" + def __init__(self, model, size): + """ Initialize the PyGame window of the game """ + self.model = model + self.screen = pygame.display.set_mode(size) + + def draw(self): + """Draw the current game state to the screen""" + self.screen.fill(pygame.Color(135, 206, 250)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle1.x, + self.model.paddle1.y, + self.model.paddle1.width, + self.model.paddle1.height)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle2.x, + self.model.paddle2.y, + self.model.paddle2.width, + self.model.paddle2.height)) + + pygame.draw.circle(self.screen, + pygame.Color(255,255,102), + (self.model.ball.x, + self.model.ball.y), + self.model.ball.radius) + + pygame.display.update() + + +class PongModel(object): + """Encodes a model of the game state""" + + def __init__(self,size): + self.width = size[0] + self.height = size[1] + self.paddle1 = Paddle(100, 20, 10, self.height) + self.paddle2 = Paddle(100, 20, self.width - 30, self.height / 2) + self.ball = Ball(int(self.width/2), int(self.height/2), int(10), 10) + + + def update(self): + + self.paddle1.update() + self.paddle2.update() + + def __str__(self): + output_lines = [] + + output_lines.append(str(self.paddle1)) + output_lines.append(str(self.paddle2)) + + + return "\n".join(output_lines) + +class Ball(object): + + def __init__(self, x, y, radius, speed): + + self.x = x + self.y = y + self.radius = radius + self.speed = speed + self.vy = 0.0 + self.vx = 0.0 + + + def update(self, ball, paddle1, paddle2, vx, vy): + + if self.ball.x == -1 and 10 == self.ball.x: + return -1 + elif self.ball.x == 1 and self.paddle2.width == self.ball.x: + return -1 + else: + return 1 + + + def __str__(self): + return "Ball x=%f, y=%f, radius=%f" % (self.x, self.y, self.radius) + + + +class Paddle(object): + """Encodes the state of the paddle 1 in the game""" + + def __init__(self, height, width, x, y): + """Initalize a paddle with the sepcified height, width, and position (x,y) """ + + self.height = height + self.width = width + self.x = x + self.y = y + self.vy = 0.0 + + def update(self): + """update the state of the paddle""" + + self.y += self.vy + + def update_position(self, coordinate): + self.y = coordinate + + def __str__(self): + return "Paddle height=%f, width=%f, x=%f, y=%f" % (self.height, self.width, self.x, self.y) + + +def get_coordinates(cap, lower_threshold, upper_threshold): + + + ret, frame = cap.read() + + hsv_scale = cv2.cvtColor(frame.copy(), cv2.COLOR_BGR2HSV) + + + lower_threshold_array = np.array(lower_threshold) + upper_threshold_array = np.array(upper_threshold) + + # creating the threshold + # binary + mask = cv2.inRange(hsv_scale, lower_threshold_array, upper_threshold_array) + mask = cv2.erode(mask, None, iterations=2) + mask = cv2.dilate(mask, None, iterations=2) + + + # blue moment tracking + contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] + center = None + coordinates = [] + + if len(contours) > 0: + + c = max(contours, key=cv2.contourArea) + ((x,y), radius) = cv2.minEnclosingCircle(c) + M = cv2.moments(c) + center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"])) + cv2.circle(frame, (int(x), int(y)), int(radius), (0,255,255), 2) + cv2.circle(frame, center, 5, (0, 0, 255), -1) + coordinates.append(center[1]) + + return coordinates + + + + +if __name__ == '__main__': + pygame.init() + + FPS = 200 + + size = (1800, 800) + model = PongModel(size) + + view = PyGameWindowView(model, size) + + fps_clock = pygame.time.Clock() + + cap = cv2.VideoCapture(0) + + blue_lower = [110,50,50] + blue_upper = [130,255,255] + + green_lower = [160,100,100] + green_upper = [179,255,255] + + + running = True + while running: + + + + + try: + coordinate1 = get_coordinates(cap, blue_lower, blue_upper)[0] * 2 + coordinate2 = get_coordinates(cap, green_lower, green_upper)[0] * 2 + model.paddle1.update_position(coordinate1) + model.paddle2.update_position(coordinate2) + except IndexError: + pass + + + view.draw() + time.sleep(.001) + fps_clock.tick(FPS) + + pygame.quit() diff --git a/pong3.py b/pong3.py new file mode 100644 index 00000000..e0a27a08 --- /dev/null +++ b/pong3.py @@ -0,0 +1,222 @@ +import pygame +from pygame.locals import * +import time +import os +import random +import math +import sys +import cv2 +import numpy as np + + +class PyGameWindowView(object): + """ A view of the Pong game rendered in a PyGame Window""" + def __init__(self, model, size): + """ Initialize the PyGame window of the game """ + self.model = model + self.screen = pygame.display.set_mode(size) + + def draw(self): + """Draw the current game state to the screen""" + self.screen.fill(pygame.Color(135, 206, 250)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle1.x, + self.model.paddle1.y, + self.model.paddle1.width, + self.model.paddle1.height)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle2.x, + self.model.paddle2.y, + self.model.paddle2.width, + self.model.paddle2.height)) + + pygame.draw.circle(self.screen, + pygame.Color(255,255,102), + (self.model.ball.x, + self.model.ball.y), + self.model.ball.radius) + + pygame.display.update() + + +class PongModel(object): + """Encodes a model of the game state""" + + def __init__(self,size): + self.width = size[0] + self.height = size[1] + self.paddle1 = Paddle(100, 20, 10, self.height) + self.paddle2 = Paddle(100, 20, self.width - 30, self.height / 2) + self.ball = Ball(int(self.width/2), int(self.height/2), int(10), 10) + + def update(self): + """Left Paddle""" + self.paddle1.update() + """Right Paddle""" + self.paddle2.update() + + + """Movement of ball when it touches screen boundaries""" + if self.ball.x < 500 or self.ball.x > 0: + self.ball.x = self.ball.x + int(self.ball.vx) + else: + self.ball.x = self.ball.y - int(self.ball.vx) + if self.ball.y < 500 or self.ball.y > 0: + self.ball.y = self.ball.y + int(self.ball.vy) + else: + self.ball.y = self.ball.y - int(self.ball.vy) + + """Movement of the ball when it touches paddles""" + + + right = self.ball.x + self.ball.radius + left = self.ball.x - self.ball.radius + top = self.ball.y - self.ball.radius + bottom = self.ball.y + self.ball.radius + + + + if right == self.paddle2.x and self.ball.y >= self.paddle2.y and self.ball.y <= self.paddle2.height + self.paddle2.y: + self.ball.vx = self.ball.vx * -1 + + if left == self.paddle1.x + self.paddle1.width and self.ball.y >= self.paddle1.y and self.ball.y <= self.paddle1.height + self.paddle1.y: + self.ball.vx = self.ball.vx * -1 + + + + """Boundaries for the ball and paddles""" + if self.paddle1.y > 700: + self.paddle1.y = 700 + if self.paddle1.y < 0: + self.paddle1.y = 0 + if self.paddle2.y > 700: + self.paddle2.y = 700 + if self.paddle2.y < 0: + self.paddle2.y = 0 + if self.ball.y >= 800: + self.ball.vy = -self.ball.vy + if self.ball.y <= 0: + self.ball.vy = -self.ball.vy + if self.ball.x < self.paddle1.x: + pygame.display.quit() + if self.ball.x > self.paddle2.x: + pygame.display.quit() + # if self.ball. + def __str__(self): + output_lines = [] + + output_lines.append(str(self.paddle1)) + output_lines.append(str(self.paddle2)) + output_lines.append(str(self.ball)) + + return "\n".join(output_lines) + +class Ball(pygame.sprite.Sprite): + + def __init__(self, x, y, radius, speed): + + self.x = x + self.y = y + self.radius = radius + self.speed = speed + self.vy = random.choice([-1,1]) + self.vx = random.choice([-1,1]) + + + # def update(self, ball, paddle1, paddle2, vx, vy): + # + # if self.ball.x == -1 and self.ball.x == 10: + # return -1 + # elif self.ball.x == 1 and self.paddle2.width == self.ball.x: + # return -1 + # else: + # return 1 + # self.x += self.vx + # self.y += self.vy + + def __str__(self): + return "Ball x=%f, y=%f, radius=%f" % (self.x, self.y, self.radius) + + +class Paddle(pygame.sprite.Sprite): + """Encodes the state of the paddle 1 in the game""" + + def __init__(self, height, width, x, y): + """Initalize a paddle with the sepcified height, width, and position (x,y) """ + + self.height = height + self.width = width + self.x = x + self.y = y + self.vy = 0.0 + + def update(self): + """update the state of the paddle""" + + self.y += self.vy + + def update_position(self, coordinate): + self.y = coordinate + + def __str__(self): + return "Paddle height=%f, width=%f, x=%f, y=%f" % (self.height, self.width, self.x, self.y) + +class PyGameMouseController(object): + + def __init__(self, model): + self.model = model + + def handle_event(self, event): + if event.type == MOUSEMOTION: + self.model.paddle1.y = event.pos[1] - self.model.paddle1.height/2.0 + + +class PyGameKeyboardController(object): + + def __init__(self,event): + self.model = model + + def handle_event(self,event): + + if event.type != KEYDOWN: + return + if event.key == pygame.K_UP: + self.model.paddle2.vy += -2.0 + else: + self.model.paddle2.vy = 0.0 + if event.key == pygame.K_DOWN: + self.model.paddle2.vy += 2.0 + + +if __name__ == '__main__': + pygame.init() + + FPS = 200 + size = (1800, 800) + model = PongModel(size) + view = PyGameWindowView(model, size) + + controller1 = PyGameMouseController(model) + controller2 = PyGameKeyboardController(model) + + fps_clock = pygame.time.Clock() + + running = True + while running: + for event in pygame.event.get(): + if event.type == QUIT: + running = False + controller1.handle_event(event) + controller2.handle_event(event) + # ball = pygame.draw.circle + # # ball = Ball(int((size[0])/2), int(size[1]/2), int(10), 10) + # # view.screen.blit(ball, (0, 0)) + + model.update() + view.draw() + time.sleep(.001) + fps_clock.tick(FPS) + + pygame.quit() diff --git a/pong4.py b/pong4.py new file mode 100644 index 00000000..c30b47ab --- /dev/null +++ b/pong4.py @@ -0,0 +1,228 @@ +import pygame +from pygame.locals import * +import time +import os +import random +import math +import sys +import cv2 +import numpy as np + +class PyGameWindowView(object): + """ A view of the Pong game rendered in a PyGame Window""" + def __init__(self, model, size): + """ Initialize the PyGame window of the game """ + self.model = model + self.screen = pygame.display.set_mode(size) + + def draw(self): + """Draw the current game state to the screen""" + self.screen.fill(pygame.Color(135, 206, 250)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle1.x, + self.model.paddle1.y, + self.model.paddle1.width, + self.model.paddle1.height)) + pygame.draw.rect(self.screen, + pygame.Color(255, 127, 80), + pygame.Rect(self.model.paddle2.x, + self.model.paddle2.y, + self.model.paddle2.width, + self.model.paddle2.height)) + + pygame.draw.circle(self.screen, + pygame.Color(255,255,102), + (self.model.ball.x, + self.model.ball.y), + self.model.ball.radius) + + pygame.display.update() + + +class PongModel(object): + """Encodes a model of the game state""" + def __init__(self,size): + self.width = size[0] + self.height = size[1] + self.paddle1 = Paddle(100, 20, 10, self.height) + self.paddle2 = Paddle(100, 20, self.width - 30, self.height / 2) + self.ball = Ball(int(self.width/2), int(self.height/2), int(10), 10) + + def update(self): + """Updates Left Paddle""" + self.paddle1.update() + """Updates Right Paddle""" + self.paddle2.update() + + """Movement of ball when it touches screen boundaries""" + if self.ball.x < 500 or self.ball.x > 0: + self.ball.x = self.ball.x + int(self.ball.vx) + else: + self.ball.x = self.ball.y - int(self.ball.vx) + if self.ball.y < 500 or self.ball.y > 0: + self.ball.y = self.ball.y + int(self.ball.vy) + else: + self.ball.y = self.ball.y - int(self.ball.vy) + + + """Movement of the ball when it touches paddles""" + right = self.ball.x + self.ball.radius + left = self.ball.x - self.ball.radius + top = self.ball.y - self.ball.radius + bottom = self.ball.y + self.ball.radius + + if right == self.paddle2.x and self.ball.y >= self.paddle2.y and self.ball.y <= self.paddle2.height + self.paddle2.y: + self.ball.vx = self.ball.vx * -1 + if left == self.paddle1.x + self.paddle1.width and self.ball.y >= self.paddle1.y and self.ball.y <= self.paddle1.height + self.paddle1.y: + self.ball.vx = self.ball.vx * -1 + + """Boundaries for the ball and paddles""" + if self.paddle1.y > 700: + self.paddle1.y = 700 + if self.paddle1.y < 0: + self.paddle1.y = 0 + if self.paddle2.y > 700: + self.paddle2.y = 700 + if self.paddle2.y < 0: + self.paddle2.y = 0 + if self.ball.y >= 800: + self.ball.vy = -self.ball.vy + if self.ball.y <= 0: + self.ball.vy = -self.ball.vy + if self.ball.x < self.paddle1.x: + pygame.display.quit() + if self.ball.x > self.paddle2.x: + pygame.display.quit() + + def __str__(self): + output_lines = [] + + output_lines.append(str(self.paddle1)) + output_lines.append(str(self.paddle2)) + output_lines.append(str(self.ball)) + + return "\n".join(output_lines) + +class Ball(object): + """Encodes the state of the ball in the game""" + def __init__(self, x, y, radius, speed): + """Initalizes a ball with the specified center (x,y) and radius""" + self.x = x + self.y = y + self.radius = radius + self.speed = speed + self.vy = random.choice([-12,12]) + self.vx = random.choice([-12,12]) + + def update(self, ball, paddle1, paddle2, vx, vy): + """ update the state of the ball""" + if self.ball.x == -1 and self.ball.x == 10: + return -1 + elif self.ball.x == 1 and self.paddle2.width == self.ball.x: + return -1 + else: + return 1 + self.x += self.vx + self.y += self.vy + + def __str__(self): + return "Ball x=%f, y=%f, radius=%f" % (self.x, self.y, self.radius) + + + +class Paddle(pygame.sprite.Sprite): + """Encodes the state of the paddle 1 in the game""" + + def __init__(self, height, width, x, y): + """Initalize a paddle with the sepcified height, width, and position (x,y) """ + + self.height = height + self.width = width + self.x = x + self.y = y + self.vy = 0.0 + + def update(self): + """update the state of the paddle""" + + self.y += self.vy + + def update_position(self, coordinate): + """ update the position of the paddle""" + self.y = coordinate + + def __str__(self): + return "Paddle height=%f, width=%f, x=%f, y=%f" % (self.height, self.width, self.x, self.y) + +def get_coordinates(cap, lower_threshold, upper_threshold): + + + ret, frame = cap.read() + + hsv_scale = cv2.cvtColor(frame.copy(), cv2.COLOR_BGR2HSV) + + + lower_threshold_array = np.array(lower_threshold) + upper_threshold_array = np.array(upper_threshold) + + # creating the threshold + # binary + mask = cv2.inRange(hsv_scale, lower_threshold_array, upper_threshold_array) + mask = cv2.erode(mask, None, iterations=2) + mask = cv2.dilate(mask, None, iterations=2) + + + # blue moment tracking + contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] + center = None + coordinates = [] + + if len(contours) > 0: + + c = max(contours, key=cv2.contourArea) + ((x,y), radius) = cv2.minEnclosingCircle(c) + M = cv2.moments(c) + center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"])) + cv2.circle(frame, (int(x), int(y)), int(radius), (0,255,255), 2) + cv2.circle(frame, center, 5, (0, 0, 255), -1) + coordinates.append(center[1]) + + return coordinates + +if __name__ == '__main__': + pygame.init() + + FPS = 200 + size = (1800, 800) + model = PongModel(size) + view = PyGameWindowView(model, size) + + fps_clock = pygame.time.Clock() + + cap = cv2.VideoCapture(0) + + blue_lower = [110,50,50] + blue_upper = [130,255,255] + + green_lower = [160,100,100] + green_upper = [179,255,255] + + + running = True + while running: + + try: + coordinate1 = get_coordinates(cap, blue_lower, blue_upper)[0] * 1.4 + coordinate2 = get_coordinates(cap, green_lower, green_upper)[0] * 1.4 + model.paddle1.update_position(coordinate1) + model.paddle2.update_position(coordinate2) + except IndexError: + pass + + model.update() + view.draw() + time.sleep(.001) + fps_clock.tick(FPS) + + pygame.quit()