Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a8ad293
v.0.0.1
jonathankohlmeier Oct 18, 2016
44448af
v.0.0.2
jonathankohlmeier Oct 19, 2016
a4b5f6f
v.0.0.3
jonathankohlmeier Oct 19, 2016
88685c7
adding pngs
jonathankohlmeier Oct 19, 2016
7640ce8
github fix lock & task list
jonathankohlmeier Oct 20, 2016
7960cdb
Prabha added to Task List
pdublish Oct 20, 2016
49a661d
Updating the color
pdublish Oct 20, 2016
0e1b80c
exit window fix
jonathankohlmeier Oct 20, 2016
a50bd2e
exit window fix
jonathankohlmeier Oct 20, 2016
8f309f1
version v.0.1.0
jonathankohlmeier Oct 22, 2016
9700fc0
version v.0.1.0
jonathankohlmeier Oct 22, 2016
def28e9
Prabha add
pdublish Oct 27, 2016
e25d97e
Add files via upload
pdublish Oct 27, 2016
8397f51
Updated
pdublish Oct 27, 2016
a073d52
Prabha adding
pdublish Oct 27, 2016
04c1ad8
Adding comments and adding food and rainbow images
pdublish Oct 28, 2016
0cf8a71
updated working code
jonathankohlmeier Oct 30, 2016
86b07d3
starting mvc
jonathankohlmeier Oct 30, 2016
7bf8462
How to run our game
agrant4 Oct 31, 2016
a2b0bdb
Game Directions
agrant4 Oct 31, 2016
0efdd27
Directions to play our game
agrant4 Oct 31, 2016
3b8c660
Add files via upload
agrant4 Oct 31, 2016
50de69c
Updated instructions to match file name
agrant4 Oct 31, 2016
be2c863
added game.py, fixed merge
agrant4 Oct 31, 2016
c096d97
turing in final code
jonathankohlmeier Oct 31, 2016
c827264
cleaning up folder
jonathankohlmeier Oct 31, 2016
bfc9041
cleaning up folder
jonathankohlmeier Oct 31, 2016
9ae0a0f
adding notes to code
jonathankohlmeier Oct 31, 2016
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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# InteractiveProgramming
Prabha Dublish, Alex Grant, Jonathan Kohlmeier

This is the base repo for the interactive programming project for Software Design, Fall 2016 at Olin College.
Unicorn Squad

To play this game you must run the game.py file. In order to move the unicorn, press the arrow keys. If you run into yourself or naviagte outside of the game window, the game will end.

This file is not a good project README.
Replace the contents of this file before you submit your project.
Binary file added food.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
291 changes: 291 additions & 0 deletions game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
import sys
import pygame
import random

class GameManager(object): #*args, **kwargs
def __init__(self, **kwargs):
# Initliizlies PyGame Window & Gameover Font
pygame.display.init()
pygame.font.init()

# Defineing Color RGB Values for GUI elements
self.white = (255, 255, 255)
self.black = (0, 0,0 )
self.red = (255, 0, 0)
self.green = (0, 255, 0)
self.blue = (0, 0, 255)
self.brick = (144, 69, 53)
self.sky_blue= (52, 152, 219)

self.display_width = kwargs.pop('display_width')
self.display_height = kwargs.pop('display_height')
#set game display size and color
self.game_display = pygame.display.set_mode((self.display_width,self.display_height))
self.game_display.fill(self.sky_blue)
#set caption for the game
if 'caption' in kwargs:
pygame.display.set_caption(caption)
else:
pygame.display.set_caption('Unicorn Squad')
#Set fps
self.clock = pygame.time.Clock()
if 'FPS' in kwargs:
self.FPS = kwargs.pop('FPS')
else:
self.FPS = 10

self.font = pygame.font.SysFont(None, 55)
#game exit
def game_did_quit(self):
gameExit = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
return gameExit

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I miss my guess, this doesn't actually wind up getting called?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yep -- y'all check for pygame.QUIT, alongside checking for "q" and such, in the game loop. Calling pygame.event.get() outside of the game loop can cause some issues, so this function is probably not a good idea to use.


def add_icon(self,icon,location):
self.game_display.blit(icon,location)
#set starting spot to center
def get_center(self):
return (self.display_width/2, self.display_height/2)
#identify if unicorn intersects carrot.
def did_collide(self,obj1, obj2):
if obj1.x > obj2.x and obj1.x < obj2.x + obj2.image_width or obj1.x + obj1.image_width > obj2.x and obj1.x + obj1.image_width < obj2.x + obj2.image_width:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun fact - if statements can be split up amongst multiple lines for ease of use/reading/debugging! Nothing wrong with what you did here, of course - just an option.

if obj1.y > obj2.y and obj1.y < obj2.y + obj2.image_height:
return True
elif obj1.y + obj1.image_height > obj2.y and obj1.y + obj1.image_height < obj2.y + obj2.image_height:
return True
return False

#display_width,display_height, caption='Unicorn Squad', FPS=10

class SnakeGame(GameManager):
def __init__(self,**kwargs):
super(SnakeGame,self).__init__(**kwargs)

def is_game_over(self,snake):
if snake.x >= self.display_width or snake.x < 0 or snake.y >= self.display_height or snake.y < 0:
return True
return False

def fill_blue(self):
self.game_display.fill(self.sky_blue)

# Initliazes text object
def text_objects(self, text, color):
textSurface = self.font.render(text, True, color)
return textSurface, textSurface.get_rect()

# Defines display message with color variable
def message_to_screen(self, msg, color, y_displace=0):
textSurf, textRect = self.text_objects(msg,color)
textRect.center = (self.display_width / 2), (self.display_height / 2) + y_displace
self.game_display.blit(textSurf, textRect)
#places score on bottom right corner
def score_to_screen(self, msg, color):
textSurf, textRect = self.text_objects(msg, color)
textRect = (self.display_width - 50), (self.display_height - 50)
self.game_display.blit(textSurf, textRect)

class Image(object):
def __init__(self,**kwargs):
self.start_pos = kwargs.pop('start_pos') #(x,y)
self.icon = pygame.image.load(kwargs.pop('icon'))
self.icon = pygame.transform.scale(self.icon, (kwargs.pop('image_width'), kwargs.pop('image_height')))
self.x = self.start_pos[0]
self.y = self.start_pos[1]
if 'image_width' in kwargs:
self.image_width = kwargs.pop('image_width')
else:
self.image_width = 50
if 'image_height' in kwargs:
self.image_height = kwargs.pop('image_height')
else:
self.image_height = 50


#start_pos=(0,0),icon='food.png', image_width=50, image_height=50

#init "food" image
class Carrot(Image):
def __init__(self,**kwargs):
super(Carrot,self).__init__(**kwargs)

def set_random_location(self,display_width,display_height):
self.x = round(random.randrange(0, display_width-self.image_width))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many snake games avoid allowing targets to spawn "inside" the snake itself. Could be interesting to think about how one would go about doing that!

self.y = round(random.randrange(0, display_height-self.image_height))
self.start_pos = (self.x,self.y)
#init rainbow image
class Rainbow(Image):
def __init__(self, **kwargs):
super(Rainbow,self).__init__(**kwargs)

#init unicorn/snake image

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick -- usually, class comments are set inside the class.
e.g.,
class Rainbow(Image):
`''' init rainbow image '''``

class Snake(Image):
def __init__(self,**kwargs):
super(Snake,self).__init__(**kwargs)
self.tail_list = []
self.tail_size = 1
self.direction = "right"
self.delta_y = 0
self.delta_x = 40

#function to add rainbow to tail
def add_to_tail(self):
gameOver = False
snake_head = []
snake_head.append(self.x)
snake_head.append(self.y)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just declare snake_head as [self.x, self.y], rather than appending twice to an empty list.


self.tail_list.append(snake_head)

if len(self.tail_list) > self.tail_size:
del self.tail_list[0]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's often "safer" to use list methods like .pop(0), rather than python's built-in del keyword. If you're working with massive datasets, removing the first element of a list is also not ideal due to the way that python handles lists -- it's not relevant here, since tails won't wind up being hundreds or thousands of items long, but if you're interested in other ways of storing/handling data efficiently I recommend reading about double-ended queues, or deques, e.g. here.


for eachSegment in self.tail_list[:-1]:
if eachSegment == snake_head:
gameOver = True

return gameOver


#function to handle orientation of unicorn depending on which direction it is going

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function comments usually go inside the function itself :D.

def handle_tail(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how getting the icon orientation is "handling tail", but this is a solid way to go about it with the tools in pygame.

if self.direction == "right":
head = self.icon

if self.direction == "left":
head = pygame.transform.flip(self.icon, 1, 0)

if self.direction == "up":
head = pygame.transform.rotate(self.icon, 90)

if self.direction == "down":
head = pygame.transform.rotate(self.icon, 270)

return head

#init movement of unicorn
def process_move(self):
gameExit = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.direction = "left"
self.delta_x = -self.image_width
self.delta_y = 0
elif event.key == pygame.K_RIGHT:
self.direction = "right"
self.delta_x = self.image_width
self.delta_y = 0
elif event.key == pygame.K_UP:
self.direction = "up"
self.delta_y = -self.image_height
self.delta_x = 0
elif event.key == pygame.K_DOWN:
self.direction = "down"
self.delta_y = self.image_height
self.delta_x = 0
return gameExit

def move(self):
self.x += self.delta_x
self.y += self.delta_y
# self.delta_x = 0
# self.delta_y = 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: commented-out code


#manages player score
class Player:
def __init__(self):
self.player_score = 0

def set_score(self,score):
self.player_score = score

def increase_score(self):
self.player_score += 1

def decrease_score(self):
self.player_score -= 1

def reset_score(self):
self.player_score = 0

#main game loop
def run_game(display_width,display_height):
gameExit = False # HItting the close button (closing Window)
gameOver = False # Internal game over view (Hitting the walls or your own tail)
game = SnakeGame(display_width=display_width,display_height=display_height)
player = Player()

snake = Snake(start_pos=game.get_center(),image_height=50,image_width=50, icon="unicorn.png")

carrot = Carrot(icon='food.png',image_height=50,image_width=50, start_pos=(0,0))
carrot.set_random_location(display_width,display_height)

while not gameExit:
while gameOver:
#sets game over screen and options to continue
game.game_display.fill(game.white)
game.message_to_screen("Game Over!", game.red, -50)
game.message_to_screen("Press C to play again, or Q to quit", game.black, 50)
pygame.display.update()

for event in pygame.event.get():
if event.type == pygame.QUIT:
gameOver = False
gameExit = True

# Maps keboard strokes to close game and redo game
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
exit()
if event.key == pygame.K_c:
run_game(display_width,display_height)

gameExit = snake.process_move()


snake.move()

gameOver = game.is_game_over(snake)


#fill blue
game.fill_blue()

game.add_icon(carrot.icon,(carrot.x,carrot.y))

gameOver2 = snake.add_to_tail()
if not gameOver:
gameOver = gameOver2
head = snake.handle_tail() #drawing snake

# defines movement of snake tail
game.game_display.blit(head, (snake.tail_list[-1][0], snake.tail_list[-1][1]))

# defines adding of rainbow image to user sprite
for XnY in snake.tail_list[:-1]:
rainbow = Rainbow(icon="rainbow.png", image_height=50, image_width=50, start_pos=(0,0)).icon
game.game_display.blit(rainbow,(XnY[0], XnY[1]))

game.score_to_screen(str(player.player_score), game.white)

pygame.display.update()

if (game.did_collide(snake,carrot)):
carrot.set_random_location(display_width,display_height)
snake.tail_size += 1
player.increase_score()

game.clock.tick(game.FPS)


pygame.display.quit(str())
pygame.quit()

run_game(800,600)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes, it's useful to add in run_game commands (and other such run commands) in an if __name__ == "__main__" loop, so that if you import functions/objects from here into another file it won't automatically start up a game.

Loading