Snake Game
The Controls
The controls are fairly simple:
Left => Left Key Right => Right Key Up => Up Key Down => Down Key Play Again => Key "Y" Quit Game => Key "N"
import sys, os, pygame, random, math | |
pygame.init() | |
pygame.display.set_caption("Snake") | |
pygame.font.init() | |
random.seed() | |
SPEED=0.36 | |
SNAKE_SIZE=9 | |
APPLE_SIZE=SNAKE_SIZE | |
SEPARATION=10 | |
SCREEN_HEIGHT=600 | |
SCREEN_WIDTH=800 | |
FPS=25 | |
KEY={'UP':1, 'DOWN':2, 'LEFT':3, 'RIGHT':4} | |
apples=[] | |
screen=pygame.display.set_mode([SCREEN_WIDTH,\ | |
SCREEN_HEIGHT]) | |
score_font=pygame.font.Font(None, 38) | |
score_numb_font=pygame.font.Font(None, 28) | |
game_over_font=pygame.font.Font(None, 46) | |
play_again_font=score_numb_font | |
score_msg=score_font.render('Score: ', 1,\ | |
pygame.Color('green')) | |
score_msg_size=score_font.size('Score') | |
background_color=pygame.Color(74, 74, 74) | |
black = pygame.Color(0, 0, 0) | |
gameClock=pygame.time.Clock() | |
def isCollided(posA, As, posB, Bs): | |
if (posA.x<posB.x+Bs and \ | |
posA.x+As>posB.x and \ | |
posA.y<posB.y+Bs and posA.y+As>posB.y): | |
return True | |
return False | |
def terminate(): | |
pygame.quit() | |
sys.exit() | |
def endGame(): | |
message=game_over_font.render("Game Over", 1,\ | |
pygame.Color("white")) | |
message_play_again=play_again_font.render(\ | |
"Play Again? Y/N",1,pygame.Color("green")) | |
screen.blit(message,(320,240)) | |
screen.blit(message_play_again,(320+12,240+40)) | |
pygame.display.flip() | |
pygame.display.update() | |
myKey=getKey() | |
while(myKey!="exit"): | |
if myKey=="yes": | |
main() | |
elif myKey=="no": | |
terminate() | |
myKey = getKey() | |
gameClock.tick(FPS) | |
def checkLimits(snake): | |
if snake.x>SCREEN_WIDTH: | |
snake.x=SNAKE_SIZE | |
elif snake.x<0: | |
snake.x=SCREEN_WIDTH-SNAKE_SIZE | |
elif snake.y>SCREEN_HEIGHT: | |
snake.y=SNAKE_SIZE | |
elif snake.y<0: | |
snake.y=SCREEN_HEIGHT-SNAKE_SIZE | |
class Apple(object): | |
def __init__(self, x, y, state): | |
self.x=x | |
self.y=y | |
self.state=state | |
self.color=pygame.color.Color('red') | |
def draw(self, win): | |
pygame.draw.rect(win, self.color, (self.x, self.y,\ | |
APPLE_SIZE,\ | |
APPLE_SIZE), 0) | |
class Segment(object): | |
def __init__(self, x, y): | |
self.x=x | |
self.y=y | |
self.direction=KEY['UP'] | |
self.color='white' | |
class Snake(object): | |
def __init__(self, x, y): | |
self.x=x | |
self.y=y | |
self.direction=KEY['UP'] | |
self.stack=[] | |
self.stack.append(self) | |
blackBox=Segment(self.x, self.y+SEPARATION) | |
blackBox.direction=KEY['UP'] | |
blackBox.color='NULL' | |
self.stack.append(blackBox) | |
def move(self): | |
last_element=len(self.stack)-1 | |
while last_element!=0: | |
self.stack[last_element].direction=self.stack[\ | |
last_element-1].direction | |
self.stack[last_element].x=self.stack[\ | |
last_element-1].x | |
self.stack[last_element].y=self.stack[\ | |
last_element-1].y | |
last_element-=1 | |
if len(self.stack)<2: | |
last_segment=self | |
else: | |
last_segment=self.stack.pop(last_element) | |
last_segment.direction=self.stack[0].direction | |
if self.stack[0].direction==KEY["UP"]: | |
last_segment.y=self.stack[0].y-(SPEED * FPS) | |
elif self.stack[0].direction==KEY["DOWN"]: | |
last_segment.y=self.stack[0].y+(SPEED * FPS) | |
elif self.stack[0].direction==KEY["LEFT"]: | |
last_segment.x=self.stack[0].x-(SPEED * FPS) | |
elif self.stack[0].direction==KEY["RIGHT"]: | |
last_segment.x=self.stack[0].x+(SPEED * FPS) | |
self.stack.insert(0, last_segment) | |
def getHead(self): | |
return self.stack[0] | |
def grow(self): | |
last_element=len(self.stack)-1 | |
self.stack[last_element].direction=self.stack[\ | |
last_element].direction | |
if self.stack[last_element].direction==KEY["UP"]: | |
newSegment=Segment(self.stack[last_element].x,\ | |
self.stack[last_element].y+\ | |
SNAKE_SIZE) | |
blackBox=Segment(newSegment.x,\ | |
newSegment.y-SEPARATION) | |
elif self.stack[last_element].direction==\ | |
KEY["DOWN"]: | |
newSegment=Segment(self.stack[last_element].x,\ | |
self.stack[last_element].y+\ | |
SNAKE_SIZE) | |
blackBox=Segment(newSegment.x, newSegment.y+\ | |
SEPARATION) | |
elif self.stack[last_element].direction==\ | |
KEY["LEFT"]: | |
newSegment=Segment(self.stack[last_element].x-\ | |
SNAKE_SIZE,\ | |
self.stack[last_element].y) | |
blackBox=Segment(newSegment.x-SEPARATION,\ | |
newSegment.y) | |
elif self.stack[last_element].direction==\ | |
KEY["RIGHT"]: | |
newSegment=Segment(self.stack[last_element].x+\ | |
SNAKE_SIZE,\ | |
self.stack[last_element].y) | |
blackBox=Segment(newSegment.x+SEPARATION,\ | |
newSegment.y) | |
blackBox.color='NULL' | |
self.stack.append(newSegment) | |
self.stack.append(blackBox) | |
def setDirection(self, direction): | |
if self.direction==KEY["RIGHT"] and direction==KEY["LEFT"]\ | |
or self.direction==KEY["LEFT"] and\ | |
direction==KEY["RIGHT"]: | |
pass | |
elif self.direction==KEY["UP"] and\ | |
direction==KEY["DOWN"] or\ | |
self.direction==KEY["DOWN"] and\ | |
direction==KEY["UP"]: | |
pass | |
else: | |
self.direction=direction | |
def get_rect(self): | |
rect=(self.x, self.y) | |
return rect | |
def getX(self): | |
return self.x | |
def getY(self): | |
return self.y | |
def setX(self, x): | |
self.x=x | |
def setY(self, y): | |
self.y=y | |
def isCrashed(self): | |
counter=1 | |
while counter<len(self.stack)-1: | |
if isCollided(self.stack[0],\ | |
SNAKE_SIZE,\ | |
self.stack[counter],\ | |
SNAKE_SIZE)and self.stack[\ | |
counter].color!="NULL": | |
return True | |
counter+=1 | |
return False | |
def draw(self, win): | |
pygame.draw.rect(win, pygame.color.Color('yellow'),\ | |
(self.stack[0].x,self.stack[0].y,\ | |
SNAKE_SIZE,SNAKE_SIZE),0) | |
counter=1 | |
while counter<len(self.stack): | |
if self.stack[counter].color=='NULL': | |
counter+=1 | |
continue | |
pygame.draw.rect(win, \ | |
pygame.color.Color('white'), \ | |
(self.stack[counter].x,\ | |
self.stack[counter].y,\ | |
SNAKE_SIZE,SNAKE_SIZE),0) | |
counter+=1 | |
def getKey(): | |
for event in pygame.event.get(): | |
if event.type==pygame.KEYDOWN: | |
if event.key==pygame.K_UP: | |
return KEY["UP"] | |
elif event.key==pygame.K_DOWN: | |
return KEY["DOWN"] | |
elif event.key==pygame.K_LEFT: | |
return KEY["LEFT"] | |
elif event.key==pygame.K_RIGHT: | |
return KEY["RIGHT"] | |
elif event.key==pygame.K_ESCAPE: | |
return "exit" | |
elif event.key==pygame.K_y: | |
return "yes" | |
elif event.key==pygame.K_n: | |
pygame.quit() | |
if event.type==pygame.QUIT: | |
terminate() | |
def respawnApples(apple,index,sx,sy): | |
radius=math.sqrt((SCREEN_WIDTH/2*SCREEN_WIDTH/2+\ | |
SCREEN_HEIGHT/2*SCREEN_HEIGHT/2))/2 | |
del apples[:] | |
angle=999 | |
while(angle>radius): | |
angle=random.uniform(0,800)*math.pi*2 | |
x=SCREEN_WIDTH/2 + radius * math.cos(angle) | |
y=SCREEN_HEIGHT/2 + radius * math.sin(angle) | |
if(x==sx and y==sy): | |
continue | |
newApple=Apple(x,y,1) | |
apples.append(newApple) | |
def endGame(): | |
message=game_over_font.render("Game Over",\ | |
1,\ | |
pygame.Color("white")) | |
message_play_again = play_again_font.render(\ | |
"Play Again? Y/N",1,pygame.Color("green")) | |
screen.blit(message, (320, 240)) | |
screen.blit(message_play_again, (320+12, 240+40)) | |
pygame.display.flip() | |
pygame.display.update() | |
myKey = getKey() | |
while myKey != "exit": | |
if myKey == "yes" : | |
main() | |
elif myKey == "no": | |
break | |
myKey = getKey() | |
gameClock.tick(FPS) | |
sys.exit() | |
def drawScore(score): | |
score_numb=score_numb_font.render(str(score), 1,\ | |
pygame.Color('red')) | |
screen.blit(score_msg, (SCREEN_WIDTH-\ | |
score_msg_size[0]-60,10)) | |
screen.blit(score_numb, (SCREEN_WIDTH-45, 14)) | |
def drawGameTime(gameTime): | |
game_time=score_font.render('Time: ', 1,\ | |
pygame.Color('red')) | |
game_time_numb = score_numb_font.render(str(\ | |
gameTime/1000), 1, pygame.Color("red")) | |
screen.blit(game_time, (30, 10)) | |
screen.blit(game_time_numb, (105, 14)) | |
def main(): | |
score=0 | |
snake=Snake(SCREEN_WIDTH/2,SCREEN_HEIGHT/2) | |
snake.setDirection(KEY["UP"]) | |
snake.move() | |
start_segments=3 | |
while start_segments>0: | |
snake.grow() | |
snake.move() | |
start_segments-=1 | |
max_apples=1 | |
eaten_apple=False | |
apple=Apple(random.randint(60,SCREEN_WIDTH),\ | |
random.randint(60,SCREEN_HEIGHT),1) | |
apples.append(apple) | |
respawnApples(apple, max_apples, snake.x, snake.y) | |
startTime=pygame.time.get_ticks() | |
endgame=0 | |
while endgame!=1: | |
gameClock.tick(FPS) | |
keyPress=getKey() | |
if keyPress=='exit': | |
endgame=1 | |
checkLimits(snake) | |
if snake.isCrashed(): | |
endGame() | |
for myApple in apples: | |
if myApple.state==1: | |
if isCollided(snake.getHead(),\ | |
SNAKE_SIZE, myApple,\ | |
APPLE_SIZE): | |
snake.grow() | |
myApple.state=0 | |
score+=1 | |
eaten_apple=True | |
if keyPress: | |
snake.setDirection(keyPress) | |
snake.move() | |
if eaten_apple: | |
eaten_apple=False | |
respawnApples(apples, 0, snake.getHead().x,\ | |
snake.getHead().y) | |
screen.fill(background_color) | |
for apple in apples: | |
if apple.state==1: | |
apple.draw(screen) | |
snake.draw(screen) | |
drawScore(score) | |
gameTime=pygame.time.get_ticks()-startTime | |
drawGameTime(gameTime) | |
pygame.display.flip() | |
pygame.display.update() | |
try: | |
main() | |
except: | |
pass |