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 |