This is the full (non-optimized) version of my snake program. You can find the minified version of the code here.
from time import * from math import floor from random import randint from kandinsky import * from ion import * INTERVAL = 0.16 OUTLINE = True BG_COLOR = (0, 0, 0) SNAKE_COLOR = (0, 255, 0) APPLE_COLOR = (255, 0, 0) BOTTOM_COLOR = (50, 50, 50) SCORE_COLOR = (255, 255, 255) SQUARE_SIZE = 16 SCREEN_W=320 SCREEN_H=192 W=floor(SCREEN_W/SQUARE_SIZE) H=floor(SCREEN_H/SQUARE_SIZE) class Player: def __init__(self, x, y, length, axis, dir): self.axis = axis # 0 = X axis | 1 = Y axis self.dir = dir # 1 = right/down | -1 = left/up self.positions = [] for i in range(length): pos = [x, y] pos[self.axis] += (length-1-i) * -dir self.positions.append(pos) def get_positions(self): return self.positions def set_heading(self, axis, dir): if axis == self.axis: return False self.axis = axis self.dir = dir return True def move(self): length = len(self.positions) for i in range(length-1): self.positions[i] = self.positions[i+1].copy() self.positions[-1][self.axis] += self.dir def grow(self): self.positions.insert(0, self.positions[0]) class Food: def __init__(self, w, h): self.w = w self.h = h def get_pos(self): return self.pos def spawn(self, snake_positions): self.pos = [randint(0, self.w-1), randint(0, self.h-1)] if self.pos in snake_positions: self.spawn(snake_positions) def draw_rect(x, y, w, h, color): fill_rect(x, y, w, 1, color) fill_rect(x, y, 1, h, color) fill_rect(x, y+h, w, -1, color) fill_rect(x+w, y, -1, h, color) def draw_square(xy, color): fill_rect(xy[0]*SQUARE_SIZE, xy[1]*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE, color) if OUTLINE: draw_rect(xy[0]*SQUARE_SIZE, xy[1]*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE, BG_COLOR) def display_score(n): fill_rect(0, SCREEN_H, SCREEN_W, 222-SCREEN_H, BOTTOM_COLOR) draw_string("Score: " + str(n), 5, SCREEN_H+5, SCORE_COLOR, BOTTOM_COLOR) score = 0 while True: snake = Player(4, floor(H/2), 4, 0, 1) apple = Food(W, H) apple.spawn(snake.get_positions()) fill_rect(0, 0, SCREEN_W, SCREEN_H, BG_COLOR) draw_square(apple.get_pos(), APPLE_COLOR) for pos in snake.get_positions(): draw_square(pos, SNAKE_COLOR) display_score(score) draw_string("Press OK to start! ", 130, SCREEN_H+5, SCORE_COLOR, BOTTOM_COLOR) while keydown(KEY_OK) or keydown(KEY_EXE): pass while not (keydown(KEY_OK) or keydown(KEY_EXE)): pass score = 0 display_score(score) first_frame = True just_ate_apple = False while True: # display new frame changes if not first_frame and not just_ate_apple: draw_square(lastTailPos, BG_COLOR) draw_square(snake.get_positions()[-1], SNAKE_COLOR) lastTailPos = snake.get_positions()[0] just_ate_apple = False turned = False time = monotonic() while(monotonic()-time < INTERVAL): if keydown(KEY_RIGHT) and not turned: turned = snake.set_heading(0, 1) if keydown(KEY_LEFT) and not turned: turned = snake.set_heading(0, -1) if keydown(KEY_DOWN) and not turned: turned = snake.set_heading(1, 1) if keydown(KEY_UP) and not turned: turned = snake.set_heading(1, -1) # eat food if snake.get_positions()[-1] == apple.get_pos(): snake.grow() apple.spawn(snake.get_positions()) draw_square(apple.get_pos(), APPLE_COLOR) score += 1 display_score(score) just_ate_apple = True # move snake.move() # game over self_eating = snake.get_positions().count(snake.get_positions()[-1]) > 1 out_of_bounds = (snake.get_positions()[-1][0] < 0) or (snake.get_positions()[-1][0] >= W) or (snake.get_positions()[-1][1] < 0) or (snake.get_positions()[-1][1] >= H) if self_eating or out_of_bounds: break first_frame = False for i in range(4): draw_string("Game Over" + "."*i, 190, SCREEN_H+5, SCORE_COLOR, BOTTOM_COLOR) sleep(0.5)