Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d494b89
Project Proposal
Mar 6, 2018
8f3b2ff
Crashed after touching bomb
Mar 9, 2018
8f0056b
March 09
jgadasu Mar 9, 2018
d975d02
Add Main2.py
Mar 9, 2018
37c3411
image Controlled
Mar 9, 2018
f45f928
Update Main2.py
Enmoren Mar 9, 2018
f282769
Delete Main2.py
Enmoren Mar 9, 2018
ce7cd4b
Camera Control
Mar 9, 2018
db0c793
Camera Control
Mar 9, 2018
cf19c6e
Delete InteractiveProgramming.iml
jgadasu Mar 9, 2018
3a2050e
Delete misc.xml
jgadasu Mar 9, 2018
4a3ed64
Delete modules.xml
jgadasu Mar 9, 2018
9f14eb1
Delete vcs.xml
jgadasu Mar 9, 2018
544ef63
Delete workspace.xml
jgadasu Mar 9, 2018
5ef80a2
Add Main3
Mar 9, 2018
01ce8f5
Main4-Model with only 1 bomb
Mar 11, 2018
68600b2
Add shaky bomb and User.update
Mar 11, 2018
1131d06
Finish Bomb User class, working on Lives.update
Mar 11, 2018
10f6a92
Fixed Lives bug, working on ploting gameover
Mar 11, 2018
8ea0ba0
Finish everything except the scores of smile face
Mar 12, 2018
ed3ac13
Add smile and score, still need to change character
Mar 13, 2018
674ea39
Finishedgit add -A!
Mar 15, 2018
3aa6938
Clean unecessary files and rename main file
Mar 15, 2018
9bb7e13
Minor change for debugging purpose
jgadasu Mar 15, 2018
dbe2904
WE ARE DONEgit add -A!
Mar 16, 2018
67d6d1a
Readme
Mar 16, 2018
c972dd1
Project Reflection
jgadasu Mar 16, 2018
5c00d34
Readme2
Mar 16, 2018
95ba757
Readme2
Mar 16, 2018
847fe94
ReadME
jgadasu Mar 16, 2018
de8009d
Project Reflection
jgadasu Mar 16, 2018
47fdaba
Update README.md
Enmoren Mar 16, 2018
5bed263
add image
Mar 16, 2018
9e49632
Update Project Reflection Writeup.md
Enmoren Mar 16, 2018
8c5edd7
add image
Mar 16, 2018
79a8b04
Delete Project Reflection.docx
Enmoren Mar 16, 2018
6d899d9
Update Project Reflection Writeup.md
Enmoren Mar 16, 2018
4f29d34
Update README.md
Enmoren Mar 16, 2018
ccf1335
Update README.md
Enmoren Mar 16, 2018
88f2376
Update README.md
Enmoren Mar 16, 2018
ebab17a
Update Project Reflection Writeup.md
Enmoren Mar 16, 2018
7f8a9dc
Update README.md
Enmoren Mar 16, 2018
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
12 changes: 12 additions & 0 deletions .idea/InteractiveProgramming.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

495 changes: 495 additions & 0 deletions .idea/workspace.xml

Large diffs are not rendered by default.

Binary file added Car.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
272 changes: 272 additions & 0 deletions Game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
import pygame
import time
import random
import cv2
import numpy as np


class PyGameWindowView(object):
""" Provides a view of the Dodgy Game model in a pygame
window """
def __init__(self, model, size):
""" Initialize the view with a reference to the model and the
specified game screen dimensions (represented as a tuple
containing the width and height """
self.model = model
self.size = size
self.screen = pygame.display.set_mode(size)
self.bombflag = True
self.bombflag2 = True
self.font = "arial"
self.font_size = 40
self.score_str = "Score: "


def draw(self):
""" Draw the current game state to the screen """
# Draw the background color
self.screen.fill(pygame.Color(123, 221, 15))

# Draw two bombs and make a short animation by changing between two picture
self.bomb1 = pygame.transform.scale(
pygame.image.load('bomb1.png'), (125, 125))
self.bomb2 = pygame.transform.scale(
pygame.image.load('bomb2.png'), (125, 125))
if (self.bombflag):
self.screen.blit(self.bomb1, (self.model.bomb.center_x, self.model.bomb.center_y))
self.bombflag = False
else:
self.screen.blit(self.bomb2, (self.model.bomb.center_x, self.model.bomb.center_y))
self.bombflag = True

if (self.bombflag2):
self.screen.blit(self.bomb1, (self.model.bomb2.center_x, self.model.bomb2.center_y))
self.bombflag2 = False
else:
self.screen.blit(self.bomb2, (self.model.bomb2.center_x, self.model.bomb2.center_y))
self.bombflag2 = True

# Draw dropping smile face from the sky
self.smile = pygame.transform.scale(
pygame.image.load('smiley.png'),(70,70))
self.screen.blit(self.smile, (self.model.smile.center_x, self.model.smile.center_y))

# Draw the player into screen by using input from face recognition
self.player = pygame.transform.scale(
pygame.image.load('Car.png'),(100,100))
self.screen.blit(self.player, (self.model.player.center_x, self.model.player.center_y))

# Display score onto the screen
self.myfont = pygame.font.SysFont(self.font, self.font_size, True)
label = self.myfont.render(self.score_str + str(self.model.score), True, (0, 0, 0))
self.screen.blit(label, (self.model.width - 200, 40))

# The Lives left for player on the top left corner
self.skeleton = pygame.transform.scale(
pygame.image.load('skeleton.png'), (60, 60))
for skeleton in self.model.skeletons:
self.screen.blit(self.skeleton, (skeleton.left, skeleton.top))

pygame.display.update()

def gameover(self):
self.end = pygame.transform.scale(
pygame.image.load('gameover.jpg'), (400, 400))
self.endpicturesize = self.end.get_size()
self.screen.blit(self.end, ((self.size[0]-self.endpicturesize[0])/2.0, (self.size[1]-self.endpicturesize[1])/2.0))
pygame.display.update()
time.sleep(1)
cap.release()
cv2.destroyAllWindows()
pygame.display.quit()
pygame.quit()


class Model(object):
'''This class assembles Bomb, Smile, and User into a model.'''
def __init__(self,size):
self.width = size[0]
self.height = size[1]

# Initialize two bombs
self.bomb_init_height = -200
self.bomb_moving_sped = random.randrange(8,15)
self.bomb_moving_sped_fast = random.randrange(15,20)
self.bomb = Bomb(random.randrange(0,self.width), self.bomb_init_height, self.bomb_init_height, self.height,
self.width, self.bomb_moving_sped)
self.bomb2 = Bomb(random.randrange(0, self.width), self.bomb_init_height, self.bomb_init_height, self.height,
self.width, self.bomb_moving_sped_fast)

# Initialize smile face
self.smile_init_height = -200
self.smile_moving_sped = random.randrange(10,20)
# print ("1")
self.smile = Smile(random.randrange(0,self.width), self.smile_init_height, self.smile_init_height, self.height,
self.width, self.smile_moving_sped)

# Initialize player
self.player_init_position = 400
self.player_y_position = 500
self.player = User(self.player_init_position, self.player_y_position,self.width)

# Record score and lives left
self.score = 0
self.lives = 3

# Skeletons array
self.skeletons = []
self.skeleton_width = 50
self.skeleton_space = 10
self.skeleton_left = 30
self.skeleton_top = 30

def update(self):
'''This function updates position changes of every object on the screen.'''
self.bomb.update()
self.bomb2.update()
self.smile.update()
self.player.update()

# If player gets in touch with bomb1
if 460 <= self.bomb.center_y <= 540 and self.player.center_x - 50 <= self.bomb.center_x <= self.player.center_x + 100:
# Decrease the number of lives and remove the touched bomb
self.lives -= 1
self.bomb.center_y = self.width + 100

# If player gets in touch with bomb2
if 460 <= self.bomb2.center_y <= 540 and self.player.center_x - 50 <= self.bomb2.center_x <= self.player.center_x + 100:
# Decrease the number of lives and remove the touched bomb
self.lives -= 1
self.bomb2.center_y = self.width + 100

# If player gets in touch with smile face
if 460 <= self.smile.center_y <= 540 and self.player.center_x - 50 <= self.smile.center_x <= self.player.center_x + 100:
# Decrease the number of lives and remove the touched bomb
self.score +=1
# print (self.score)
self.smile.center_y = self.width + 100

# Update skeletons' coordinates
self.skeletons = []
for x in range(self.skeleton_left,
self.skeleton_left + (self.skeleton_width + self.skeleton_space) * self.lives,
self.skeleton_width + self.skeleton_space):
self.skeletons.append(Lives(x, self.skeleton_top))


class Bomb(object):
""" Represents a bomb in dodging game """
def __init__(self, center_x, center_y, start_y, display_width, display_height, moving_speed):
""" Create a bomb object with the specified geometry """
self.center_x = center_x
self.center_y = center_y
self.start_y = start_y
self.display_width = display_width
self.display_height = display_height
self.moving_speed = moving_speed

def update(self):
# update the position of bomb each time
self.center_y += self.moving_speed
# if the bomb achieve the bottom of the screen
if self.center_y >self.display_height:
self.center_y = self.start_y
self.center_x = random.randrange(0, self.display_width)


class Smile(object):
""" Represents a smile face in dodging game """
def __init__(self, center_x, center_y, start_y, display_width, display_height, moving_speed):
""" Create a bomb object with the specified geometry """
self.center_x = center_x
self.center_y = center_y
self.start_y = start_y
self.display_width = display_width
self.display_height = display_height
self.moving_speed = moving_speed

def update(self):
# update the position of smile each time
self.center_y += self.moving_speed
# if the bomb achieve the bottom of the screen
if self.center_y > self.display_height:
self.center_y = self.start_y
self.center_x = random.randrange(0, self.display_width)


class User(object):
''' Represents the player in dodging game '''

def __init__(self, center_x, center_y, display_width):
""" Create a ball object with the specified geometry """
self.center_x = center_x
self.center_y = center_y
self.display_width = display_width
self.center_x = self.display_width * 0.5 - 50

def update(self):
'''Update player's position in x-axis by using OpenCV'''
self.ret, frame = cap.read()
self.faces = face_cascade.detectMultiScale(frame, scaleFactor=1.2, minSize=(20, 20))

# Recognize player's face from computer's camera
for (x, y, w, h) in self.faces:
cv2.circle(frame, (int(w / 2 + x),int( h / 2 + y)), 10, (255, 255, 255), -1)

# Transform coordinates from OpenCV to screen
temp = (float)(x) / (400) * self.display_width

# Reflect coordinates back
temp = self.display_width - temp

# Decrease sensitivity of facial recognition
if abs(self.center_x-temp)> 15:
self.center_x = temp

# If the player's coordinate go out of bounds
if self.center_x >700:
self.center_x =700

# cv2.imshow('frame', frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
pygame.quit()
cap.release()
cv2.destroyAllWindows()


class Lives(object):
'''The number of lives the player has. Starts with 3 lives.'''

def __init__(self, left, top ):
self.left = left
self.top = top


if __name__ == '__main__':

# Initialize computer vision
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
kernel = np.ones((40, 21), 'uint8')
cap = cv2.VideoCapture(0)

# Initialize PyGame display
pygame.init()
pygame.display.set_caption('Dodge Ball')
size = (800, 600)

# Initialize model
model = Model(size)
view = PyGameWindowView(model, size)

running = True
while running:
# Keep drawing and updating objects on the screen
model.update()
view.draw()

# If player uses all his lives, game is over
if model.lives <= 0:
view.gameover()
running = False
time.sleep(.001)
Binary file added Project Proposal.odt
Binary file not shown.
31 changes: 31 additions & 0 deletions Project Reflection Writeup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# MIni Project Write-up and Reflection

### Project Overview
In Mini Project 4, we explore interactive programming, an instance of interactive computation which accepts input from the user as a program runs, and uses it as a tool in game creation. In this project, our team attempts to implement a game that takes user input from user facial-image data using facial recognition techniques. We created a game where a character, controlled by side-to-side movements of the face, has to get in contact with smiley faces for more points in score and dodge incoming bombs in order to remain in the game.

### Results


We were able to program a game fully-controlled by side-to-side face movements. Using the CV2 package for facial detection, we were able to track the position of the philtrum and nose point. Using the pixel coordinates of the nose point as input, we were able to manipulate our car object along the x-axis making it resemble a facially manipulated game. The team decreased the sensitivity of the facial recognition to reduce the glitchy nature of the car.
We were also able to implement a score mechanism in place to introduce some sense of purpose in the game. Also, with the addition of bomb-art within the game, and necessary model changes, we were able to introduce a crash mechanism for ‘game over’ within the game. By moving the face side-to-side, the user is thus able to control a character (car art also moving side to side) and play our game without user input from the keyboard or mouse. The ‘glitchy’ motion of the bomb was also as a result of a change in the image being blitted onto the screen at a high frequency.
![picture](result1.png)
![picture](result2.png)


### Implementation

Dodgeball game is composed of certain basic classes.
The Bomb class assigns attributes to falling bombs. It generates bomb in random position in its horizontal axis with increasing y coordinate of certain speed. The bomb falls in a constant speed from the top to the bottom of the screen if it does not collide with player controlled character.
The Smile class assigns attributes to falling smiley faces. It works in same way as Bomb class. The Lives class notes the lives a player has for one round of game.
The User class generates player controlled character. Facial recognition is used to grab x coordinate of player’s face through a pre-trained cascade file. One design decision we had here is to decrease the sensitivity of x-coordinate changed on the screen by filtering change of x-coordinate through a threshold value. Hence, the player controlled character can move more smoothly on the screen.
The Model class assembles Bomb, Smile, Lives and User. It builds two bombs and one smiley face and keeps tracking of their positions to check if a collision is happened between objects and player, then reflects the collision in certain attribute (lives and score).
The PygameWindowView draws all those objects created in our Model class.


![picture](class.png)


### Reflection
Initially, our group began designing our software with so many nested functions. One lesson that we learned is that once a code is written without a clear map of Object Oriented Programming relationships and detailed class structure, the code gets pretty messy and it is very time-consuming to rewrite all the code in OOP structure. While our code seemed to work on the surface, it didn’t incorporate Python’s many Object Oriented Programming features. As a result, our team had to redesign and refactor our existing code using Python’s classes, attributes and instances. Refactoring the code was definitely a difficult task.
Merge conflicts were sometimes frustrating, but we used them as an experience to learn more about GIT for version control and collaborative programming. We can definitely improve the conciseness and preciseness of our code. Through this project, we really got our hands on objected-oriented programming.

13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
# InteractiveProgramming
This is the base repo for the interactive programming project for Software Design, Spring 2018 at Olin College.
## Game Instruction
Move your face side-to-side to control the movement of the car character within the game. Score more points by loading the smiley faces in your car trunk. (Just get the car in contact with the smiley face) Remember, you have to avoid the bombs ( PS - things can get quite tricky)
Good luck!! Have FUN!!!

## How to run

1. Install Python3
2. Install Pygame, Numpy and OpenCv
3. Run “Game.py” to play!

### Project Reflection Writeup [a link](https://github.com/Enmoren/InteractiveProgramming/blob/master/Project%20Reflection%20Writeup.md)
Binary file added bomb1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added bomb2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added class.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gameover.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading