Skip to content

Instantly share code, notes, and snippets.

@MichaelStett
Last active June 18, 2020 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MichaelStett/62d68d8cab4e55e110621f22e8db208d to your computer and use it in GitHub Desktop.
Save MichaelStett/62d68d8cab4e55e110621f22e8db208d to your computer and use it in GitHub Desktop.
Snake in Python
{
"title": "Snake by Michal Tymejczyk",
"screen": {
"resolution": [
1280,
720
],
"font": null
},
"collisions": {
"snake": true,
"apple": true,
"border": false
},
"colors": {
"snake": [
255,
0,
0
],
"apple": [
0,
255,
0
],
"background": [
255,
255,
255
]
},
"length": 5,
"speed": 15,
"size": 25,
"lag": 1
}
# Based on https://www.pygame.org/project-Snake+in+35+lines-818-.html
import json
import random
import sys
import dotmap
from dotmap import DotMap
import pygame
from pygame.locals import *
from enum import Enum
class Direction(Enum):
DOWN = 0
RIGHT = 1
UP = 2
LEFT = 3
class Game():
class Apple():
__color = (0, 0, 0)
__size = 0
coords = [0, 0]
def __init__(self, color, size, border):
self.__color = color
self.__size = size
self.__limit = border
self.surface = pygame.Surface([self.__size] * 2)
self.surface.fill(self.__color)
self.newPosition()
def newPosition(self):
self.coords[0] = random.randint(0, self.__limit[0] - self.__size * 4)
self.coords[1] = random.randint(0, self.__limit[1] - self.__size * 4)
# -- class Apple --
class Snake():
# private
__length = 0
__color = (0, 0, 0)
__size = 0
__x = []
__y = []
# public
direction = Direction.DOWN
def __init__(self, length, color, size, resolution):
self.__length = length
self.__color = color
self.__size = size
# resolution so snake is centered
self.__x = [resolution[0] * 0.5] * length
for i in range(self.__length):
self.__y.append(resolution[1] * 0.5 - self.__size * i)
self.surface = pygame.Surface([self.__size] * 2)
self.surface.fill(self.__color)
def length(self):
return self.__length
def coords(self, i):
return (self.__x[i], self.__y[i])
def updatePosition(self):
if self.direction == Direction.DOWN: self.update('y', 0, self.__size); return
if self.direction == Direction.RIGHT: self.update('x', 0, self.__size); return
if self.direction == Direction.UP: self.update('y', 0, -self.__size); return
if self.direction == Direction.LEFT: self.update('x', 0, -self.__size); return
def update(self, coord, index, val, byORto = True):
if byORto == True:
if coord == 'x': self.__x[index] += val; return
if coord == 'y': self.__y[index] += val; return
else: # TO VALUE
if coord == 'x': self.__x[index] = val; return
if coord == 'y': self.__y[index] = val; return
print(f"Updated: {coord}[{index}]: {val}")
def move(self):
for i in range(self.length() - 1, 0, -1):
self.update('x', i, self.coords(i - 1)[0], False)
self.update('y', i, self.coords(i - 1)[1], False)
self.updatePosition()
def enlarge(self):
self.__x.append(0)
self.__y.append(0)
self.__length += 1
def isInCollisionWith(self, obj, isBorder = False):
if isBorder is not True:
return (self.__x[0] + self.__size > obj.x and
self.__y[0] + self.__size > obj.y and
self.__x[0] - self.__size < obj.x and
self.__y[0] - self.__size < obj.y)
else:
return (self.__x[0] + self.__size > obj.x or
self.__y[0] + self.__size > obj.y or
self.__x[0] - self.__size < 0 or
self.__y[0] - self.__size < 0)
# -- class Snake --
def __init__(self):
self.loadSettings()
self.border = DotMap({
"x": self.settings.screen.resolution[0],
"y": self.settings.screen.resolution[1]
})
self.snake = self.Snake(self.settings.length,
self.settings.colors.snake,
self.settings.size,
self.settings.screen.resolution)
self.apple = self.Apple(self.settings.colors.apple,
self.settings.size,
self.settings.screen.resolution)
pygame.init()
pygame.display.set_caption(self.settings.title)
self.screen = pygame.display.set_mode(self.settings.screen.resolution)
self.font = pygame.font.Font(self.settings.screen.font, 40)
self.axis = DotMap({
"surface": self.font.render(f"{self.snake.coords(0)}", False, pygame.Color("black")),
"coords": (self.settings.screen.resolution[0] * 0.05, self.settings.screen.resolution[1] * 0.9)
})
self.play()
def loadSettings(self, filename = 'settings.json'):
with open(filename, 'r') as file:
data = json.load(file)
self.settings = DotMap(data)
# TODO: def reset(self): pass
def handle(self, event):
if event.key is K_a:
if self.snake.direction == Direction.DOWN: self.snake.direction = Direction.RIGHT; return
if self.snake.direction == Direction.RIGHT: self.snake.direction = Direction.UP; return
if self.snake.direction == Direction.UP: self.snake.direction = Direction.LEFT; return
if self.snake.direction == Direction.LEFT: self.snake.direction = Direction.DOWN; return
elif event.key is K_d:
if self.snake.direction == Direction.DOWN: self.snake.direction = Direction.LEFT; return
if self.snake.direction == Direction.RIGHT: self.snake.direction = Direction.DOWN; return
if self.snake.direction == Direction.UP: self.snake.direction = Direction.RIGHT; return
if self.snake.direction == Direction.LEFT: self.snake.direction = Direction.UP; return
elif event.key is K_ESCAPE:
sys.exit(0)
def rerender(self):
self.screen.fill(self.settings.colors.background)
self.draw(self.snake)
self.render(self.apple)
self.axis.surface = self.font.render(f"{self.snake.coords(0)}", False, pygame.Color("black"))
self.render(self.axis)
def render(self, obj): # used to render single object
self.screen.blit(obj.surface, obj.coords)
def draw(self, obj): # used to render multiple objects
for i in range(obj.length()):
self.render(DotMap({
"surface": obj.surface,
"coords": obj.coords(i)
}))
def play(self):
while True:
self.rerender()
pygame.time.Clock().tick(self.settings.speed)
for event in pygame.event.get():
if event.type == KEYDOWN:
self.handle(event)
if self.settings.collisions.snake is True:
for i in range(self.snake.length() - 1, 0, -1):
if self.snake.isInCollisionWith(DotMap({"x": self.snake.coords(i)[0], "y": self.snake.coords(i)[1]})):
sys.exit(1)
# collisions with apple
# if self.settings.collisions.apple == True and self.snake.isInCollisionWith(self.apple):
if self.settings.collisions.apple is True:
if self.snake.isInCollisionWith(DotMap({"x": self.apple.coords[0], "y": self.apple.coords[1]})):
self.snake.enlarge()
self.apple.newPosition()
if self.settings.collisions.border is True and self.snake.isInCollisionWith(self.border, isBorder=True) is True:
sys.exit(1)
self.snake.move()
pygame.display.update()
pygame.time.wait(self.settings.lag)
# -- class Game --
Game()
# Based on https://www.pygame.org/project-Snake+in+35+lines-818-.html
import json
import random
import sys
from abc import ABC
import pygame
from pygame.locals import *
from dotmap import DotMap
Settings = DotMap(json.loads('settings.json'));
class Element(ABC):
size = 0
def __init__(self, size, color):
self.size = size
pygame.Surface((size, size)).fill(color)
class Apple(Element):
def __init__(self, size, color):
super().__init__(size, color)
def NewPosition(self):
self.x = random.randint(0, Settings["screenSize"][0] - self.size * 4)
self.y = random.randint(0, Settings["screenSize"][1] - self.size * 4)
class Snake(Element):
def __init__(self, size, color):
super().__init__(size, color)
# local method variables
width = Settings["screenSize"][0]
height = Settings["screenSize"][1]
self.x = [width / 2] * 5
self.y = [height / 2 - size * 0,
height / 2 - size * 1,
height / 2 - size * 2,
height / 2 - size * 3,
height / 2 - size * 4]
self.direction = 0
class Game:
# Init snake and apple
snake = Snake(15, Settings["color"]["snake"])
apple = Apple(15, Settings["color"]["apple"])
score = 0
i = 0
def __init__(self):
pygame.init()
pygame.display.set_caption()
self.screen = pygame.display.set_mode((Settings["screenSize"][0], Settings["screenSize"][1]))
def collide(self, x1, x2, y1, y2, _x):
return x1 + _x > x2 and x1 < x2 + _x and y1 + _x > y2 and y1 < y2 + _x
def Play(self):
while True:
pygame.time.Clock().tick(speed)
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT or event.key == K_a:
if dirs == 0:
dirs = 1
elif dirs == 1:
dirs = 2
elif dirs == 2:
dirs = 3
elif dirs == 3:
dirs = 0
elif event.key == K_RIGHT or event.key == K_d:
if dirs == 0:
dirs = 3
elif dirs == 1:
dirs = 0
elif dirs == 2:
dirs = 1
elif dirs == 3:
dirs = 2
elif event.key == K_ESCAPE:
sys.exit(0)
elif event.key == K_SPACE:
dirs = 4
i = len(snake.x) - 1
if Collisions["snake"]:
while i >= 2:
if collide(snake.x[0], snake.x[i], snake.y[0], snake.y[i], Element.Size):
Restart()
i -= 1
if Collisions["apple"]:
if collide(snake.x[0], apple.x, snake.y[0], apple.y, Element.Size):
score += 1
snake.x.append(700)
snake.y.append(700)
apple.NewPosition()
i = len(snake.x) - 1
while i >= 1:
snake.x[i] = snake.x[i - 1]
snake.y[i] = snake.y[i - 1]
i -= 1
if Collisions["border"]:
if snake.x[0] < Element.Size or snake.x[0] > ScreenSize[0] - Element.Size or snake.y[0] < Element.Size or snake.y[0] > ScreenSize[1] - Element.Size:
Restart()
if snake.direction == 0:
snake.y[0] += Element.Size
elif snake.direction == 1:
snake.x[0] += Element.Size
elif snake.direction == 2:
snake.y[0] -= Element.Size
elif snake.direction == 3:
snake.x[0] -= Element.Size
elif snake.direction == 4:
pygame.time.wait()
screen.fill()
for i in range(0, len(snake.x)):
screen.blit(snake.surface, (snake.x[i], snake.y[i]))
screen.blit(apple.surface, (apple.x, apple.y))
Render(Renders["score"], (ScreenSize[0] / 2, 10))
Render(Renders["possition"], (ScreenSize[0] * 0.05, ScreenSize[1] * 0.9))
pygame.display.update()
def Restart():
Render("Your score was: " + Renders["score"],
(ScreenSize[0] / 3, ScreenSize[1] / 2))
Render(Renders["restart"], (ScreenSize[0] / 3, ScreenSize[1] / 3))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_SPACE:
main()
elif event.key == K_ESCAPE:
sys.exit(0)
def Render(string, position):
screen.blit(
pygame.font.SysFont(Font, Element.Size * 1.5, True).render(string, False, (0, 0, 0)), position)
def main():
Game()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment