Initiall development.

This commit is contained in:
Bradley Cornford
2017-07-18 14:05:00 +01:00
commit 53216391dc
24 changed files with 1319 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
# general things to ignore
build/
dist/
*.egg-info/
*.egg
*.py[cod]
__pycache__/
*.so
*~
# due to using tox and pytest
.tox
.cache
# editor ignores
.idea
# package ignores
sensehatsnake/config.py
data/database.json
+13
View File
@@ -0,0 +1,13 @@
language: python
env:
- TOXENV=py27
- TOXENV=py33
- TOXENV=py34
install: pip install tox
script: tox
notifications:
email: false
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Bradley Cornford <me@bradleycornford.co.uk>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+5
View File
@@ -0,0 +1,5 @@
# Include the license file
include LICENSE.txt
# Include the data files
recursive-include data *
+43
View File
@@ -0,0 +1,43 @@
# Raspberry Pi Python sense hat snake
A project to create a Snake game on a Raspberry Pi using a Sense Hat.
## Requirements
This package requires the following system packages to be installed:
- python-pip
- python-dev
## Installation
Begin by installing this packages requirements:
pip install -e .
Finally copy the example configuration file `example.config.py`, and save it as `config.py`
cp sensehatsnake/example.config.py sensehatsnake/config.py
## Configuration
You can now configure Sense-Hat-Snake in a few simple steps. Open `sensehatsnake/config.py` and update the options as needed.
- `columns` - The number of columns the board has.
- `rows` - The number of rows the board has.
- `fps` - The games frames per second.
- `countdown` - The game countdown in seconds.
- `interval` - The game tick interval in milliseconds.
- `score_increment` - The number to increment score by in game.
- `level_increment` - The score when to increment the level by in game.
- `interval_increment` - The number to reduce the game tick interval by in milliseconds.
## Usage
It's really as simple as running the main file
sudo python sensehatsnake/main.py
### License
Sense-Hat-Snake is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
+1
View File
@@ -0,0 +1 @@
{"_default": {"1": {"score": 0}, "2": {"score": 0}, "3": {"score": 1}, "4": {"score": 0}, "5": {"score": 0}, "6": {"score": 0}, "7": {"score": 0}, "8": {"score": 0}}}
View File
+10
View File
@@ -0,0 +1,10 @@
game = {
'columns': 8,
'rows': 8,
'fps': 30,
'countdown': 5,
'interval': 800,
'score_increment': 1,
'level_increment': 8,
'interval_increment': 50
}
View File
+75
View File
@@ -0,0 +1,75 @@
from __future__ import print_function
class Apple:
COORDINATES = None
X = None
Y = None
def __init__(self, coordinates, x=0, y=0):
print("[Apple][info] Initialising Apple")
self.COORDINATES = coordinates
self.X = x
self.Y = y
def set_coordinates(self, coordinates):
print("[Apple][info] Setting Apple coordinates")
self.COORDINATES = coordinates
def set_x(self, x):
print("[Apple][info] Setting Apple X position")
self.X = x
def set_y(self, y):
print("[Apple][info] Setting Apple Y position")
self.Y = y
def set_position(self, coordinates):
print("[Apple][info] Setting Apple X, Y position")
x, y = coordinates
self.X = x
self.Y = y
def coordinates(self):
print("[Apple][info] Getting Apple coordinates")
return self.COORDINATES
def x(self):
print("[Apple][info] Getting Apple X position")
return self.X
def y(self):
print("[Apple][info] Getting Apple Y position")
return self.Y
def position(self):
print("[Apple][info] Getting Apple X, Y position")
return (self.X, self.Y)
def clear(self):
print("[Apple][info] Clearing Apple")
self.COORDINATES = None
self.X = None
self.Y = None
def cleanup(self):
print("[Apple][info] Apple clean up")
self.clear()
def __exit__(self):
print("[Apple][info] Apple exit")
self.cleanup()
+68
View File
@@ -0,0 +1,68 @@
from __future__ import print_function
class Board:
COLUMNS = None
ROWS = None
COORDINATES = None
def __init__(self, columns, rows):
print("[Board][info] Initialising Board")
self.COLUMNS = columns
self.ROWS = rows
self.__generate()
def __generate(self):
self.COORDINATES = [
[0 for x in xrange(self.COLUMNS)]
for y in xrange(self.ROWS)
]
def columns(self):
print("[Board][info] Getting Board columns")
return self.COLUMNS
def rows(self):
print("[Board][info] Getting Board rows")
return self.ROWS
def coordinates(self):
print("[Board][info] Getting Board coordinates")
return self.COORDINATES
def check_collision(self, snake, offset):
print("[Board][info] Checking for Snake collision")
offset_x, offset_y = offset
if 0 > offset_x or offset_x > self.ROWS - 1 or 0 > offset_y or offset_y > self.COLUMNS - 1:
return True
else:
for segment in snake.segments():
if segment[0] == offset_x and segment[1] == offset_y:
return True
return False
def clear(self):
print("[Board][info] Clearing board")
self.COORDINATES = None
self.COLUMNS = None
self.ROWS = None
def cleanup(self):
print("[Board][info] Board clean up")
self.clear()
def __exit__(self):
print("[Board][info] Board exit")
self.cleanup()
+500
View File
@@ -0,0 +1,500 @@
from __future__ import print_function
from board import Board
from apple import Apple
from mock import MagicMock, patch
from random import randint
from snake import Snake
from tinydb import TinyDB, Query
import math
import pygame
import sys
try:
from sense_hat import SenseHat
except ImportError:
print("[Game][error] An error occurred importing 'sense_hat.SenseHat'")
mock = MagicMock()
mock.clear.return_value = True
mock.set_pixel.return_value = True
mock.show_message.return_value = True
with patch.dict('sys.modules', {'sense_hat': mock, 'sense_hat.SenseHat': mock.RTIMU}):
from sense_hat import SenseHat
class Game:
BLOCK_SIZE = 36
COLUMNS = 8
ROWS = 8
FPS = None
COLORS = [
# 0 - Black
(0, 0, 0),
# 1 - Green
(0, 255, 0),
# 2 - Red
(255, 0, 0),
# 3 - Purple
(128, 0, 128),
# 4 - Blue
(0, 0, 255),
# 5 - Orange
(255, 165, 0),
# 6 - Cyan
(0, 255, 255),
# 7 - Yellow
(255, 255, 0),
# 8 - Dark Grey
(35, 35, 35),
# 9 - White
(255, 255, 255)
]
SHAPES = [
# Snake
[
[1],
],
# Apple
[
[2]
],
]
WIDTH = None
HEIGHT = None
COUNTDOWN = None
SCORE_INCREMENT = None
SCORE = 0
APPLES = 0
INTERVAL = None
INTERVAL_INCREMENT = None
LEVEL = 1
LEVEL_INCREMENT = None
PAUSED = False
GAMEOVER = False
BACKGROUND_GRID = None
SNAKE_MOVED = True
pygame = None
pygame_font = None
pygame_screen = None
sensehat = None
db = None
board = None
snake = None
apple = None
def __init__(self, columns, rows, fps, countdown, interval, score_increment, level_increment, interval_increment, pygame_instance=None):
self.COLUMNS = columns
self.ROWS = rows
self.FPS = fps
self.COUNTDOWN = countdown
self.INTERVAL = interval
self.SCORE_INCREMENT = score_increment
self.LEVEL_INCREMENT = level_increment
self.INTERVAL_INCREMENT = interval_increment
if pygame_instance is None:
self.pygame = pygame
else:
self.pygame = pygame_instance
self.sensehat = SenseHat()
self.db = TinyDB('data/database.json')
try:
self.WIDTH = self.BLOCK_SIZE * self.COLUMNS + 150
self.HEIGHT = self.BLOCK_SIZE * self.ROWS
self.BACKGROUND_GRID = [
[8 if x % 2 == y % 2 else 0 for x in xrange(self.COLUMNS)]
for y in xrange(self.ROWS)
]
self.pygame.init()
self.pygame.key.set_repeat(0, 0)
self.pygame_font = self.pygame.font.Font(self.pygame.font.get_default_font(), 12)
self.pygame_screen = self.pygame.display.set_mode((self.WIDTH, self.HEIGHT), 0, 24)
self.pygame.event.set_blocked(self.pygame.MOUSEMOTION)
self.board = Board(self.COLUMNS, self.ROWS)
self.__generate_snake()
self.__generate_apple()
except AttributeError:
print("[Game][error] An error occurred initialising game")
def start(self, run_once=False):
print("[Game][info] Starting game")
try:
pygame_wait = True
while pygame_wait:
for event in self.pygame.event.get():
if event.type == self.pygame.KEYDOWN:
if event.key == self.pygame.K_RETURN:
pygame_wait = False
elif event.key == self.pygame.K_ESCAPE:
self.quit()
self.pygame_screen.fill(self.COLORS[0])
self.__display_message("Press to start")
self.pygame.display.update()
self.sensehat.clear()
except AttributeError:
print("[Game][error] An error occurred starting game")
self.__countdown()
self.__loop()
self.finish()
if run_once is not True:
self.start()
def __countdown(self):
print("[Game][info] Starting game countdown")
try:
seconds = 0
while True:
self.pygame_screen.fill(self.COLORS[0])
remaining = (self.COUNTDOWN - seconds)
if seconds > self.COUNTDOWN:
break
if seconds == self.COUNTDOWN:
self.__display_message("Go!")
else:
self.__display_message("%d!" % remaining)
seconds += 1
self.sensehat.clear()
self.pygame.display.update()
self.pygame.time.wait(1000)
self.pygame_screen.fill(self.COLORS[0])
self.sensehat.clear()
except AttributeError:
print("[Game][error] An error occurred starting game countdown")
def __loop(self):
print("[Game][info] Starting game loop")
try:
self.pygame.time.set_timer(pygame.USEREVENT + 1, self.INTERVAL)
key_actions = {
'ESCAPE': lambda: self.quit(),
'LEFT': lambda: self.__direction_left(),
'RIGHT': lambda: self.__direction_right(),
'DOWN': lambda: self.__direction_down(),
'UP': lambda: self.__direction_up(),
'p': lambda: self.toggle_pause(),
}
pygame_clock = self.pygame.time.Clock()
while not self.GAMEOVER:
self.sensehat.clear()
self.pygame_screen.fill(self.COLORS[0])
if self.PAUSED:
self.__display_message("Paused")
else:
self.__draw_line(
((self.BLOCK_SIZE * self.COLUMNS) + 1, 0),
((self.BLOCK_SIZE * self.COLUMNS) + 1, (self.HEIGHT - 1)),
self.COLORS[9]
)
self.__display_message(
"Score: %d\n\nLevel: %d\n\nApples: %d" % (self.SCORE, self.LEVEL, self.APPLES),
((self.BLOCK_SIZE * self.COLUMNS) + self.BLOCK_SIZE, 2),
self.COLORS[9],
self.COLORS[0],
False
)
self.__draw_matrix(self.BACKGROUND_GRID, (0, 0), None, False)
self.__draw_matrix(self.board.coordinates(), (0, 0), None, False)
self.__draw_matrix(self.snake.coordinates(self.COLUMNS, self.ROWS), (0, 0))
self.__draw_matrix(self.apple.coordinates(), (self.apple.x(), self.apple.y()))
self.pygame.display.update()
for event in self.pygame.event.get():
if event.type == self.pygame.USEREVENT + 1:
self.__move()
elif event.type == self.pygame.QUIT:
self.quit()
elif event.type == self.pygame.KEYDOWN:
for key in key_actions:
if event.key == eval("self.pygame.K_" + key):
key_actions[key]()
pygame_clock.tick(self.FPS)
except AttributeError:
print("[Game][error] An error occurred during game loop")
def __generate_snake(self):
print("[Game][info] Generating snake")
self.snake = Snake(self.SHAPES[0], int(math.floor(self.COLUMNS / 2)), int(math.floor(self.ROWS / 2)))
def __generate_apple(self):
print("[Game][info] Generating apple")
apple_collision = True
offset_x, offset_y = (0, 0)
while apple_collision:
offset_x = randint(0, self.ROWS - 1)
offset_y = randint(0, self.COLUMNS - 1)
apple_collision = self.board.check_collision(self.snake, (offset_x, offset_y))
self.apple = Apple(self.SHAPES[1], offset_x, offset_y)
def __display_message(self, message, coordinates=None, color=COLORS[9], background_color=COLORS[0], sensehat=True):
print("[Game][info] Displaying message")
if sensehat:
self.sensehat.show_message(message, text_colour=color, scroll_speed=0.05)
for i, line in enumerate(message.splitlines()):
message_image = self.pygame_font.render(line, False, color, background_color)
if coordinates is not None:
position_x, position_y = coordinates
else:
message_image_center_x, message_image_center_y = message_image.get_size()
message_image_center_x //= 2
message_image_center_y //= 2
position_x = self.WIDTH // 2 - message_image_center_x
position_y = self.HEIGHT // 2 - message_image_center_y
self.pygame_screen.blit(
message_image,
(position_x, position_y + i * 22)
)
def __draw_line(self, start_position, end_position, color=COLORS[9], sensehat=True):
print("[Game][info] Drawing line")
if sensehat:
start_x, start_y = start_position
end_x, end_y = start_position
for i in xrange(start_y, end_y):
for j in xrange(start_x, end_x):
if start_x == end_x or start_y == end_y:
self.sensehat.set_pixel(j, i, color)
self.pygame.draw.line(self.pygame_screen, color, start_position, end_position)
def __draw_matrix(self, matrix, offset, color=None, sensehat=True):
print("[Game][info] Drawing matrix")
offset_x, offset_y = offset
for y, row in enumerate(matrix):
for x, val in enumerate(row):
if val:
if color is None:
shape_color = self.COLORS[val]
else:
shape_color = color
if sensehat:
self.sensehat.set_pixel((offset_x + x), (offset_y + y), shape_color)
self.pygame.draw.rect(
self.pygame_screen,
shape_color,
self.pygame.Rect((offset_x + x) * self.BLOCK_SIZE, (offset_y + y) * self.BLOCK_SIZE, self.BLOCK_SIZE, self.BLOCK_SIZE),
0
)
def __count_clear_apples(self, apples):
print("[Game][info] Counting cleared apples")
if apples > 0:
self.APPLES += apples
self.SCORE += self.SCORE_INCREMENT * self.LEVEL
if self.APPLES >= self.LEVEL * self.LEVEL_INCREMENT:
self.LEVEL += 1
delay = self.INTERVAL - self.INTERVAL_INCREMENT * (self.LEVEL - 1)
delay = 100 if delay < 100 else delay
self.pygame.time.set_timer(self.pygame.USEREVENT + 1, delay)
def __move(self):
print("[Game][info] Moving snake %s" % (self.snake.direction()))
if not self.GAMEOVER and not self.PAUSED:
new_x, new_y = self.snake.head()
if self.snake.direction() == self.snake.DIRECTION_UP:
new_y = self.snake.y() - 1
elif self.snake.direction() == self.snake.DIRECTION_DOWN:
new_y = self.snake.y() + 1
elif self.snake.direction() == self.snake.DIRECTION_LEFT:
new_x = self.snake.x() - 1
elif self.snake.direction() == self.snake.DIRECTION_RIGHT:
new_x = self.snake.x() + 1
if self.board.check_collision(self.snake, (new_x, new_y)):
self.GAMEOVER = True
return False
tail_x, tail_y = self.snake.tail()
self.snake.set_position((new_x, new_y))
cleared_apples = 0
if new_x == self.apple.x() and new_y == self.apple.y():
self.snake.add_segment((tail_x, tail_y))
cleared_apples += 1
self.__generate_apple()
self.__count_clear_apples(cleared_apples)
self.SNAKE_MOVED = True
return True
def __direction_up(self):
print("[Game][info] Event direction up")
if self.snake.direction() != self.snake.DIRECTION_DOWN and self.SNAKE_MOVED is True:
self.snake.set_direction(self.snake.DIRECTION_UP)
self.SNAKE_MOVED = False
def __direction_down(self):
print("[Game][info] Event direction down")
if self.snake.direction() != self.snake.DIRECTION_UP and self.SNAKE_MOVED is True:
self.snake.set_direction(self.snake.DIRECTION_DOWN)
self.SNAKE_MOVED = False
def __direction_left(self):
print("[Game][info] Event direction left")
if self.snake.direction() != self.snake.DIRECTION_RIGHT and self.SNAKE_MOVED is True:
self.snake.set_direction(self.snake.DIRECTION_LEFT)
self.SNAKE_MOVED = False
def __direction_right(self):
print("[Game][info] Event direction right")
if self.snake.direction() != self.snake.DIRECTION_LEFT and self.SNAKE_MOVED is True:
self.snake.set_direction(self.snake.DIRECTION_RIGHT)
self.SNAKE_MOVED = False
def toggle_pause(self):
print("[Game][info] Toggling paused state")
self.PAUSED = not self.PAUSED
def get_score(self):
print("[Game][info] Calculating score")
return self.SCORE
def print_score(self, high_score=False):
print("[Game][info] Printing score")
score = self.get_score()
try:
self.sensehat.clear()
self.pygame_screen.fill(self.COLORS[0])
if high_score:
self.__display_message("Game Over!\n\nHigh score: %d" % score)
self.pygame.display.update()
else:
self.__display_message("Game Over!\n\nYour score: %d!" % self.get_score())
self.pygame.display.update()
self.pygame.time.wait(3000)
except AttributeError:
print("[Game][error] An error occurred printing score")
def finish(self):
print("[Game][info] Finishing game")
score = self.get_score()
self.pygame.display.update()
if self.db.contains(Query().score >= score):
self.print_score()
else:
self.print_score(True)
self.db.insert({'score': score})
self.reset()
def quit(self):
print("[Game][info] Quitting game")
self.pygame_screen.fill(self.COLORS[0])
self.sensehat.clear()
self.__display_message("Exiting...")
self.pygame.display.update()
sys.exit()
def reset(self):
print("[Game][info] Resetting game")
self.PAUSED = False
self.GAMEOVER = False
self.SCORE = 0
self.APPLES = 0
self.LEVEL = 1
self.SNAKE_MOVED = True
self.board = Board(self.COLUMNS, self.ROWS)
self.snake = None
self.apple = None
self.__generate_snake()
self.__generate_apple()
self.sensehat.clear()
self.pygame.time.set_timer(pygame.USEREVENT + 1, 0)
self.pygame.display.update()
def cleanup(self):
print("[Game][info] Game clean up")
try:
self.sensehat.clear()
self.pygame_screen.fill(self.COLORS[0])
self.pygame.display.update()
self.pygame.quit()
except AttributeError:
print("[Game][error] An error occurred cleaning up")
def __exit__(self):
print("[Game][info] Game exit")
self.cleanup()
+165
View File
@@ -0,0 +1,165 @@
class Snake:
COORDINATES = None
SEGMENTS = None
X = None
Y = None
DIRECTION = None
DIRECTION_UP = 'up'
DIRECTION_DOWN = 'down'
DIRECTION_LEFT = 'left'
DIRECTION_RIGHT = 'right'
def __init__(self, coordinates, x=0, y=0, direction=DIRECTION_LEFT):
print("[Snake][info] Initialising Snake")
self.COORDINATES = coordinates
self.SEGMENTS = []
self.add_segment((x, y))
self.X = x
self.Y = y
self.DIRECTION = direction
def set_coordinates(self, coordinates):
print("[Snake][info] Setting Snake coordinates")
self.COORDINATES = coordinates
def set_direction(self, direction):
print("[Snake][info] Setting Snake direction")
self.DIRECTION = direction
def set_x(self, x):
print("[Snake][info] Setting Snake X position")
if self.length() > 1:
self.remove_segment(-1)
self.add_segment((x, self.SEGMENTS[0][1]), 0)
else:
self.SEGMENTS[0] = (x, self.SEGMENTS[0][1])
self.X = x
def set_y(self, y):
print("[Snake][info] Setting Snake Y position")
if self.length() > 1:
self.remove_segment(-1)
self.add_segment((self.SEGMENTS[0][0], y), 0)
else:
self.SEGMENTS[0] = (self.SEGMENTS[0][0], y)
self.Y = y
def set_position(self, coordinates):
print("[Snake][info] Setting Snake X, Y position")
x, y = coordinates
if self.length() > 1:
self.remove_segment(-1)
self.add_segment(coordinates, 0)
else:
self.SEGMENTS[0] = coordinates
self.X = x
self.Y = y
def add_segment(self, coordinates, position=-1):
print("[Snake][info] Creating Snake segment at index %d" % (position))
self.SEGMENTS.insert(position if position != -1 else len(self.SEGMENTS), coordinates)
def remove_segment(self, position=-1):
print("[Snake][info] Removing Snake segment at index %d" % (position))
self.SEGMENTS.pop(position)
def coordinates(self, columns=0, rows=0):
print("[Snake][info] Getting Snake coordinates")
if columns == 0 and rows == 0:
return self.COORDINATES
coordinates = [
[False for x in xrange(columns)]
for y in xrange(rows)
]
for segment in self.SEGMENTS:
coordinates[segment[1]][segment[0]] = self.COORDINATES[0][0]
return coordinates
def direction(self):
print("[Snake][info] Getting Snake direction")
return self.DIRECTION
def x(self):
print("[Snake][info] Getting Snake X position")
return self.X
def y(self):
print("[Snake][info] Getting Snake Y position")
return self.Y
def position(self):
print("[Snake][info] Getting Snake X,Y position")
return (self.X, self.Y)
def segments(self):
print("[Snake][info] Getting all Snake segments")
return self.SEGMENTS
def head(self):
print("[Snake][info] Getting Snake head")
return self.SEGMENTS[0]
def body(self):
print("[Snake][info] Getting Snake body")
if len(self.SEGMENTS) < 2:
return None
return self.SEGMENTS[1:]
def tail(self):
print("[Snake][info] Getting Snake tail")
return self.SEGMENTS[-1]
def length(self):
print("[Snake][info] Getting Snake length")
return len(self.SEGMENTS)
def clear(self):
print("[Snake][info] Clearing Snake")
self.COORDINATES = None
self.SEGMENTS = None
self.X = None
self.Y = None
self.DIRECTION = None
def cleanup(self):
print("[Snake][info] Snake clean up")
self.clear()
def __exit__(self):
print("[Snake][info] Snake exit")
self.cleanup()
+25
View File
@@ -0,0 +1,25 @@
from __future__ import print_function
from lib.game import Game
import atexit
import config
def main():
game = Game(
config.game['columns'],
config.game['rows'],
config.game['fps'],
config.game['countdown'],
config.game['interval'],
config.game['score_increment'],
config.game['level_increment'],
config.game['interval_increment'],
)
game.start()
atexit.register(game.__exit__)
if __name__ == '__main__':
main()
+2
View File
@@ -0,0 +1,2 @@
[bdist_wheel]
universal=1
+60
View File
@@ -0,0 +1,60 @@
from setuptools import setup, find_packages
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
setup(
name='sense-hat-snake',
version='1.0.0',
description='Raspberry Pi Python sense hat snake',
long_description=long_description,
url='https://github.com/bradcornford/Sense-Hat-Snake',
author='Bradley Cornford',
author_email='me@bradleycornford.co.uk',
license='MIT',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
keywords='sense hat snake raspberry pi',
packages=find_packages(exclude=['contrib', 'docs', 'test']),
install_requires=['pygame', 'sense-hat', 'tinydb', 'mock'],
extras_require={
'dev': ['check-manifest'],
'test': ['coverage'],
},
package_data={},
data_files=[],
entry_points={
'console_scripts': []
},
)
View File
View File
+56
View File
@@ -0,0 +1,56 @@
from __future__ import print_function
from sensehatsnake.lib.apple import Apple
import unittest
class AppleTestCase(unittest.TestCase):
COORDINATES = [
[1]
]
apple = None
def setUp(self):
self.apple = Apple(self.COORDINATES)
def test__init__(self):
self.assertIsInstance(self.apple, Apple)
def test_set_coordinates(self):
self.assertIs(self.apple.set_coordinates([[0]]), None)
self.assertEquals(self.apple.coordinates(), [[0]])
def test_set_x(self):
self.assertIs(self.apple.set_x(1), None)
self.assertEquals(self.apple.x(), 1)
def test_set_y(self):
self.assertIs(self.apple.set_y(1), None)
self.assertEquals(self.apple.y(), 1)
def test_set_position(self):
self.assertIs(self.apple.set_position((1, 1)), None)
self.assertEquals(self.apple.x(), 1)
self.assertEquals(self.apple.y(), 1)
def test_coordinates(self):
self.assertEquals(self.apple.coordinates(), self.COORDINATES)
def test_x(self):
self.assertEquals(self.apple.x(), 0)
def test_y(self):
self.assertEquals(self.apple.y(), 0)
def test_position(self):
self.assertEquals(self.apple.position(), (0, 0))
def test_cleanup(self):
self.assertIs(self.apple.cleanup(), None)
def test__exit__(self):
self.assertIs(self.apple.__exit__(), None)
if __name__ == '__main__':
unittest.main()
+43
View File
@@ -0,0 +1,43 @@
from __future__ import print_function
from sensehatsnake.lib.board import Board
from sensehatsnake.lib.snake import Snake
import unittest
class BoardTestCase(unittest.TestCase):
COLUMNS = 2
ROWS = 2
board = None
def setUp(self):
self.board = Board(self.COLUMNS, self.ROWS)
def test__init__(self):
self.assertIsInstance(self.board, Board)
def test_columns(self):
self.assertEquals(self.board.columns(), self.COLUMNS)
def test_rows(self):
self.assertEquals(self.board.rows(), self.ROWS)
def test_coordinates(self):
self.assertEquals(self.board.coordinates(), [[0, 0], [0, 0]])
def test_check_collision(self):
snake = Snake([[1]])
self.assertIs(self.board.check_collision(snake, (snake.x(), snake.y())), True)
def test_clear(self):
self.assertIs(self.board.clear(), None)
def test_cleanup(self):
self.assertIs(self.board.cleanup(), None)
def test__exit__(self):
self.assertIs(self.board.__exit__(), None)
if __name__ == '__main__':
unittest.main()
+93
View File
@@ -0,0 +1,93 @@
from __future__ import print_function
from sensehatsnake.lib.game import Game
from mock import MagicMock
import unittest
class GameTestCase(unittest.TestCase):
COLUMNS = 2
ROWS = 2
FPS = 1
COUNTDOWN = 0
INTERVAL = 0
SCORE_INCREMENT = 1
LEVEL_INCREMENT = 1
INTERVAL_INCREMENT = 0
game = None
def setUp(self):
mock = MagicMock()
keypress_event_mock = MagicMock()
keypress_event_mock.type = 1
keypress_event_mock.key = 1
userevent_event_mock = MagicMock()
userevent_event_mock.type = 3
mock.get_size.return_value = (0, 0)
mock.get.return_value = [keypress_event_mock, userevent_event_mock]
mock.get_ticks.side_effect = [0, 6000, 0, 5000]
mock.Font.return_value = mock
mock.render.return_value = mock
mock.KEYDOWN = 1
mock.K_RETURN = 1
mock.USEREVENT = 2
mock.font = mock
mock.display = mock
mock.event = mock
mock.time = mock
self.game = Game(
self.COLUMNS,
self.ROWS,
self.FPS,
self.COUNTDOWN,
self.INTERVAL,
self.SCORE_INCREMENT,
self.LEVEL_INCREMENT,
self.INTERVAL_INCREMENT,
mock
)
def test__init__(self):
self.assertIsInstance(self.game, Game)
def test_start(self):
self.assertIs(self.game.start(True), None)
def test_toggle_pause(self):
self.assertIs(self.game.toggle_pause(), None)
self.assertEqual(self.game.PAUSED, True)
self.assertIs(self.game.toggle_pause(), None)
self.assertEqual(self.game.PAUSED, False)
def test_get_score(self):
self.assertIs(self.game.get_score(), 0)
def test_print_score(self):
self.assertIs(self.game.print_score(), None)
def test_finish(self):
self.assertIs(self.game.finish(), None)
def test_quit(self):
with self.assertRaises(SystemExit):
self.assertIs(self.game.quit(), None)
def test_reset(self):
self.assertIs(self.game.reset(), None)
def test_cleanup(self):
self.assertIs(self.game.cleanup(), None)
def test__exit__(self):
self.assertIs(self.game.__exit__(), None)
if __name__ == '__main__':
unittest.main()
+90
View File
@@ -0,0 +1,90 @@
from __future__ import print_function
from sensehatsnake.lib.snake import Snake
import unittest
class SnakeTestCase(unittest.TestCase):
COORDINATES = [
[1]
]
COLUMNS = 2
ROWS = 2
snake = None
def setUp(self):
self.snake = Snake(self.COORDINATES)
def test__init__(self):
self.assertIsInstance(self.snake, Snake)
def test_set_coordinates(self):
self.assertIs(self.snake.set_coordinates([[0]]), None)
self.assertEquals(self.snake.coordinates(), [[0]])
def test_set_direction(self):
self.assertIs(self.snake.set_direction(self.snake.DIRECTION_UP), None)
self.assertEquals(self.snake.direction(), self.snake.DIRECTION_UP)
def test_set_x(self):
self.assertIs(self.snake.set_x(1), None)
self.assertEquals(self.snake.x(), 1)
def test_set_y(self):
self.assertIs(self.snake.set_y(1), None)
self.assertEquals(self.snake.y(), 1)
def test_set_position(self):
self.assertIs(self.snake.set_position((1, 1)), None)
self.assertEquals(self.snake.x(), 1)
self.assertEquals(self.snake.y(), 1)
def test_add_segment(self):
self.assertIs(self.snake.add_segment((1, 1)), None)
self.assertEquals(self.snake.length(), 2)
def test_remove_segment(self):
self.assertIs(self.snake.remove_segment(), None)
self.assertEquals(self.snake.length(), 0)
def test_coordinates(self):
self.assertEquals(self.snake.coordinates(), self.COORDINATES)
self.assertEquals(self.snake.coordinates(self.COLUMNS, self.ROWS), [[self.COORDINATES[0][0], False], [False, False]])
def test_direction(self):
self.assertEquals(self.snake.direction(), self.snake.DIRECTION_LEFT)
def test_x(self):
self.assertEquals(self.snake.x(), 0)
def test_y(self):
self.assertEquals(self.snake.y(), 0)
def test_position(self):
self.assertEquals(self.snake.position(), (0, 0))
def test_segments(self):
self.assertEquals(self.snake.segments(), [(0, 0)])
def test_head(self):
self.assertEquals(self.snake.head(), (0, 0))
def test_body(self):
self.assertEquals(self.snake.body(), None)
def test_tail(self):
self.assertEquals(self.snake.tail(), (0, 0))
def test_length(self):
self.assertEquals(self.snake.length(), 1)
def test_cleanup(self):
self.assertIs(self.snake.cleanup(), None)
def test__exit__(self):
self.assertIs(self.snake.__exit__(), None)
if __name__ == '__main__':
unittest.main()
+8
View File
@@ -0,0 +1,8 @@
from __future__ import print_function
import sensehatsnake.main
import unittest
class MainTestCase(unittest.TestCase):
def test__init__(self):
self.assertTrue("main" in dir(sensehatsnake.main))
+21
View File
@@ -0,0 +1,21 @@
[tox]
envlist = py{27,33,34}
[testenv]
basepython =
py27: python2.7
py33: python3.3
py34: python3.4
deps =
check-manifest
readme_renderer
flake8
pytest
commands =
check-manifest --ignore tox.ini,tests*
python setup.py check -m -r -s
flake8 .
py.test tests
[flake8]
exclude = .tox,*.egg,build,data
select = E,W,F