Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math
- import random
- import pygame
- import tkinter as tk
- from tkinter import messagebox
- pygame.init()
- #dimensions of the screen
- n_units = 20 #Numbers of blocks in one line/column of the grid
- dim = 500 #Dimension of the screen (lenght of a side of the square window)
- unit_lenght = dim/n_units
- counter = 0
- boom = False
- # Defines a block in the game (snake is composed of block and fruit/other objects are blocks)
- # Has a move method and draw methods which are called in the update_screen function
- class block():
- counter = 0
- def __init__(self,start,dir_x=1,dir_y=0,color=(255,228,196)):
- self.pos = start #initial position given when an object is created
- self.dir_x = 1
- self.dir_y = 0
- self.color = color #Default color = color of the snake
- #moves the block in (dirx,diry) direction
- def move(self, dir_x, dir_y):
- self.dir_x = dir_x
- self.dir_y = dir_y
- self.pos = (self.pos[0] + self.dir_x, self.pos[1] + self.dir_y) #New position
- #draws the block on the screen
- def draw(self, screen, head=False):
- i = self.pos[0]
- j = self.pos[1]
- #Drawing function
- pygame.draw.rect(screen, self.color, (i*unit_lenght+1,j*unit_lenght+1, unit_lenght-2, unit_lenght-2))
- #Draws eyes of the snake
- if head:
- centre = unit_lenght/2
- radius = 3
- circleMiddle = (int(i*unit_lenght+centre-radius),int(j*unit_lenght+8))
- circleMiddle2 = (int(i*unit_lenght + unit_lenght -radius*2),int(j*unit_lenght+8))
- pygame.draw.circle(screen, (0,0,0), circleMiddle, radius)
- pygame.draw.circle(screen, (0,0,0), circleMiddle2, radius)
- #Class snakes:
- #Attributes: body (list of blocks),
- class snake():
- body = [] # contains blocks
- # Dictionnary with two keys CoordX, CoordY with corresponding values dir_x, dir_Y
- turns = {} #Contains the values of the last block move
- last_key = [0,0,0,0] #Left, right, up, down
- def __init__(self, color, pos):
- self.color = color
- self.head = block(pos)
- self.body.append(self.head) #add a block for the head in body
- self.dir_x = 0 #initial direction
- self.dir_y = 0 #initial direction
- #Moves all the blocks in body
- def move(self):
- #Loop through each frame
- for event in pygame.event.get():
- if event.type == pygame.QUIT: #If the user leaves the window
- pygame.quit() #Quit the game
- keys = pygame.key.get_pressed() #Get the state of all keyboard buttons (if pushed = True)
- for key in keys:
- #Test the 4 buttons UP,Down,Left,Right and fill turns with the associates values
- #that indicate in which direction the snake moves
- if keys[pygame.K_LEFT]: # Players hit left arrow
- #Forbid the snake to turn in the opposite direction it is in
- if self.last_key == [0,1,0,0]: # Is moves to the right
- self.dir_x = 1
- self.dir_y = 0
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y] # Continues to the right
- self.last_key = [0,1,0,0]
- else: # Else goes left
- self.dir_x = -1 # Indicates that the snake will move left
- self.dir_y = 0
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y] #Stores in turns the values and keys
- self.last_key = [1,0,0,0]
- elif keys[pygame.K_RIGHT]: #Right arrow
- if self.last_key == [1,0,0,0]:
- self.dir_x = -1 # Indicates that the snake will move left
- self.dir_y = 0
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y] #Stores in turns the values and keys
- self.last_key = [1,0,0,0]
- else:
- self.dir_x = 1
- self.dir_y = 0
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y]
- self.last_key = [0,1,0,0]
- elif keys[pygame.K_UP]: # Up arrow
- if self.last_key == [0,0,0,1]:
- self.dir_x = 0
- self.dir_y = 1
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y]
- self.last_key = [0,0,0,1]
- else:
- self.dir_x = 0
- self.dir_y = -1
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y]
- self.last_key = [0,0,1,0]
- elif keys[pygame.K_DOWN]: #Down arrow
- if self.last_key == [0,0,1,0]:
- self.dir_x = 0
- self.dir_y = -1
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y]
- self.last_key = [0,0,1,0]
- else:
- self.dir_x = 0
- self.dir_y = 1
- self.turns[self.head.pos[:]] = [self.dir_x, self.dir_y]
- self.last_key = [0,0,0,1]
- #Loop through all the blocks in body to move them one by one
- #by calling the block.move() method
- for i, block in enumerate(self.body):
- position = block.pos[:] #Get the position of the block on the screen
- #If the player pressed a key, call block.move with the values associated to the block's coordinates in turns
- if position in self.turns:
- turn = self.turns[position]
- block.move(turn[0],turn[1])
- if i == len(self.body)-1: # If this is the last block, clear turns
- self.turns.pop(position)
- #Will move the snake if the player didn't hit a button
- else:
- #Deals with the snake hitting a border of the screen
- if block.dir_x == -1 and block.pos[0] <= 0: block.pos = (n_units-1, block.pos[1])
- elif block.dir_x == 1 and block.pos[0] >= n_units-1: block.pos = (0,block.pos[1])
- elif block.dir_y == 1 and block.pos[1] >= n_units-1: block.pos = (block.pos[0], 0)
- elif block.dir_y == -1 and block.pos[1] <= 0: block.pos = (block.pos[0], n_units-1)
- # No border case
- else: block.move(block.dir_x,block.dir_y)
- #Reset to the initial parameters (to restart the game)
- def reset(self, pos):
- self.head = block(pos)
- self.body = []
- self.body.append(self.head)
- self.turns = {}
- self.dir_x = 0
- self.dir_y = 1
- #Add a block at the back of the snake
- def add_block(self):
- tail = self.body[-1] #Last block of the body
- dx, dy = tail.dir_x, tail.dir_y
- #Detects the direction in wich the snake is to fill the body with a block in the right position
- if dx == 1 and dy == 0:
- self.body.append(block((tail.pos[0]-1,tail.pos[1])))
- elif dx == -1 and dy == 0:
- self.body.append(block((tail.pos[0]+1,tail.pos[1])))
- elif dx == 0 and dy == 1:
- self.body.append(block((tail.pos[0],tail.pos[1]-1)))
- elif dx == 0 and dy == -1:
- self.body.append(block((tail.pos[0],tail.pos[1]+1)))
- #Gives the direction to the block
- self.body[-1].dir_x = dx
- self.body[-1].dir_y = dy
- #Calls the draw function from block
- def draw(self, screen):
- for i, c in enumerate(self.body):
- if i ==0:
- c.draw(screen, True)
- else:
- c.draw(screen)
- #Function called each loop to draw the elements and the screen
- def draw_frame(screen, Snake, Fruit, Mine, Animation1, Animation2):
- global counter, boom
- screen.fill((250, 250,250)) #Color of the screen
- Snake.draw(screen) #Draw the snake
- screen.blit(Animation2[len(Snake.body)%9], (Fruit.pos[0]*unit_lenght, Fruit.pos[1]*unit_lenght)) #Draw the fruit
- if boom == True:
- screen.blit(Animation1[counter//3], (Mine.pos[0]*unit_lenght, Mine.pos[1]*unit_lenght))
- counter += 1
- if counter >= 27:
- counter = 0
- boom = False
- else:
- screen.blit(Animation1[counter//3],(Mine.pos[0]*unit_lenght, Mine.pos[1]*unit_lenght))
- pygame.display.update()
- #Function that creates a fruit
- #(it only returns 2 randoms numbers as coordinates and check that they are not on the snake)
- def randomSnack(snake): # give the snake to get its position
- positions = snake.body #snake position
- while True:
- x = random.randrange(n_units)
- y = random.randrange(n_units)
- if len(list(filter(lambda z:z.pos == (x,y), positions))) > 0: #check if the fruit is not on a block of the snake
- continue
- else:
- break
- return (x,y)
- def mine(snake, randomsnack):
- position_S = snake.body
- position_snack = randomsnack.pos
- while True:
- x = random.randrange(n_units)
- y = random.randrange(n_units)
- if len(list(filter(lambda z:z.pos == (x,y), position_S))) > 0 or position_snack == (x,y): #check if the fruit is not on a block of the snake
- continue
- else:
- break
- return (x,y)
- def message_box(subject, content):
- root = tk.Tk()
- root.attributes("-topmost", True)
- root.withdraw()
- messagebox.showinfo(subject, content)
- try:
- root.destroy()
- except:
- pass
- def main():
- global boom
- win = pygame.display.set_mode((dim, dim))
- s = snake((255,0,0), (10,10))
- fruit = block(randomSnack(s), color=(255,0,0))
- bomb = block(mine(s, fruit), color = (0,0,255))
- #myfont = pygame.font.SysFont("monospace", 16)
- flag = True
- clock = pygame.time.Clock()
- mine_animation = [pygame.image.load('mine1.png'), pygame.image.load('mine2.png'), pygame.image.load('Mine3.png'),
- pygame.image.load('Mine4.png'), pygame.image.load('Mine5.png'), pygame.image.load('Mine6.png'),
- pygame.image.load('Mine7.png'), pygame.image.load('Mine8.png'), pygame.image.load('Mine9.png')]
- fruit_animation = [pygame.image.load('Fruit1.png'), pygame.image.load('Fruit2.png'), pygame.image.load('Fruit3.png'),
- pygame.image.load('Fruit4.png'), pygame.image.load('Fruit5.png'), pygame.image.load('Fruit6.png'),
- pygame.image.load('Fruit7.png'), pygame.image.load('Fruit8.png'), pygame.image.load('Fruit9.png')]
- Boom_sound = pygame.mixer.Sound('Bomb+1.wav')
- eat_sound = pygame.mixer.Sound('Slurp+6.wav')
- music = pygame.mixer.Sound('music.wav')
- music.play(-1)
- while flag:
- pygame.time.delay(50)
- clock.tick(10)
- s.move()
- if s.body[0].pos == fruit.pos:
- s.add_block()
- eat_sound.play(0)
- fruit = block(randomSnack(s), color=(255,0,0))
- for x in range(len(s.body)):
- if s.body[x].pos in list(map(lambda z:z.pos,s.body[x+1:])):
- print('Score: ', len(s.body))
- message_box('Score', len(s.body))
- s.reset((10,10))
- break
- elif s.body[0].pos == bomb.pos:
- if len(s.body) < 4:
- message_box('Score', len(s.body))
- s.reset((10,10))
- break
- Boom_sound.play(0)
- s.body.pop(-1)
- s.body.pop(-1)
- s.body.pop(-1)
- boom = True
- break
- print(counter)
- if counter == 26:
- bomb = block(mine(s, fruit), color = (0,0,255))
- draw_frame(win, s, fruit, bomb, mine_animation, fruit_animation)
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement