diff --git a/.gitignore b/.gitignore
index 72ab1af..894a44c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,104 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
MANIFEST
-build
-slacker_game.egg-info
-dist
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index fc13dae..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1 +0,0 @@
-include README.rst LICENSE slacker_game/OFL.txt
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..65d1c63
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,33 @@
+[build-system]
+requires = ['flit_core >=2,<3']
+build-backend = 'flit_core.buildapi'
+
+[tool.flit.metadata]
+module = 'slacker_game'
+author = 'Nguyễn Gia Phong'
+author-email = 'mcsinyx@disroot.org'
+home-page = 'https://git.disroot.org/McSinyx/slacker-game'
+requires = ['pygame']
+description-file = 'README.rst'
+classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Environment :: MacOS X',
+ 'Environment :: Win32 (MS Windows)',
+ 'Environment :: X11 Applications',
+ 'Intended Audience :: End Users/Desktop',
+ 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3 :: Only',
+ 'Topic :: Games/Entertainment :: Arcade']
+requires-python = '>=3.6'
+keywords = 'stacker,arcade-game,pygame'
+license = 'GPLv3+'
+
+[tool.flit.entrypoints.gui_scripts]
+slacker-game = 'slacker_game.slacker:main'
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 3c6e79c..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-[bdist_wheel]
-universal=1
diff --git a/setup.py b/setup.py
deleted file mode 100755
index c117d4c..0000000
--- a/setup.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-from setuptools import setup
-
-with open('README.rst') as f:
- long_description = f.read()
-
-setup(
- name='slacker-game',
- version='2.0.2',
- description='A clone of the arcade game Stacker',
- long_description=long_description,
- url='https://github.com/McSinyx/slacker-game',
- author='Clint Herron',
- maintainer='Nguyễn Gia Phong',
- maintainer_email='vn.mcsinyx@gmail.com',
- license='GPLv3+',
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Environment :: MacOS X',
- 'Environment :: Win32 (MS Windows)',
- 'Environment :: X11 Applications',
- 'Intended Audience :: End Users/Desktop',
- 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Topic :: Games/Entertainment :: Arcade'],
- keywords='stacker arcade-game pygame-application',
- packages=['slacker_game'],
- install_requires=['pygame'],
- package_data={'slacker_game': ['VT323-Regular.ttf', 'icon.png']},
- entry_points={'gui_scripts': ['slacker-game = slacker_game:main']})
diff --git a/slacker_game/__init__.py b/slacker_game/__init__.py
index 50e0ec3..3f7ff9a 100644
--- a/slacker_game/__init__.py
+++ b/slacker_game/__init__.py
@@ -1 +1,244 @@
-from .slacker import Slacker, main
+# A clone of the arcade game Stacker
+# Copyright (C) 2007 Clint Herron
+# Copyright (C) 2017, 2020 Nguyễn Gia Phong
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""A clone of the arcade game Stacker"""
+
+__version__ = '2.0.2'
+__all__ = ['Slacker']
+
+from math import cos, pi
+from random import randrange
+
+import pygame
+from pkg_resources import resource_filename
+
+TANGO = {'Butter': ((252, 233, 79), (237, 212, 0), (196, 160, 0)),
+ 'Orange': ((252, 175, 62), (245, 121, 0), (206, 92, 0)),
+ 'Chocolate': ((233, 185, 110), (193, 125, 17), (143, 89, 2)),
+ 'Chameleon': ((138, 226, 52), (115, 210, 22), (78, 154, 6)),
+ 'Sky Blue': ((114, 159, 207), (52, 101, 164), (32, 74, 135)),
+ 'Plum': ((173, 127, 168), (117, 80, 123), (92, 53, 102)),
+ 'Scarlet Red': ((239, 41, 41), (204, 0, 0), (164, 0, 0)),
+ 'Aluminium': ((238, 238, 236), (211, 215, 207), (186, 189, 182),
+ (136, 138, 133), (85, 87, 83), (46, 52, 54))}
+
+
+def data(resource):
+ """Return a true filesystem path for specified resource."""
+ return resource_filename('slacker_game', resource)
+
+
+class SlackerTile:
+ """SlackerTile(x, y) -> SlackerTile
+
+ Slacker object for storing tiles.
+ """
+ SIZE = 40
+ BG = TANGO['Aluminium'][5]
+ MAJOR = 5
+
+ def __init__(self, screen, x, y, state=1, missed_time=None):
+ self.screen, self.x, self.y = screen, x, y
+ if state == Slacker.LOSE:
+ self.dim = 1
+ elif missed_time is None:
+ self.dim = 0
+ else:
+ self.dim = 2
+ self.missed_time = missed_time
+ self.wiggle = state in (Slacker.INTRO, Slacker.WIN)
+
+ def get_xoffset(self, maxoffset, duration=820):
+ """Return the offset on x-axis to make the tile complete an cycle of
+ wiggling oscillation in given duration (in milliseconds).
+ """
+ if self.wiggle:
+ return maxoffset * cos((pygame.time.get_ticks()/float(duration)
+ + self.y/float(Slacker.BOARD_HEIGHT)) * pi)
+ return 0
+
+ def get_yoffset(self):
+ """Return the offset on y-axis when the tile is falling."""
+ if self.missed_time is None:
+ return 0
+ return (pygame.time.get_ticks() - self.missed_time)**2 / 25000.0
+
+ def isfallen(self):
+ """Return if the tile has fallen off the screen."""
+ return self.y + self.get_yoffset() > Slacker.BOARD_HEIGHT
+
+ def draw(self, max_x_offset=2):
+ """Draw the tile."""
+ if self.y < self.MAJOR:
+ color = Slacker.COLOR_MAJOR
+ else:
+ color = Slacker.COLOR_MINOR
+ rect = pygame.Rect((self.x+self.get_xoffset(max_x_offset)) * self.SIZE,
+ (self.y+self.get_yoffset()) * self.SIZE,
+ self.SIZE, self.SIZE)
+ pygame.draw.rect(self.screen, color[self.dim], rect)
+ pygame.draw.rect(self.screen, self.BG, rect, self.SIZE // 11)
+
+
+class Slacker:
+ """This class provides functions to run the game Slacker, a clone of
+ the popular arcade game Stacker.
+ """
+ BOARD_SIZE = BOARD_WIDTH, BOARD_HEIGHT = 7, 15
+ SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 280, 600
+ TILE_SIZE = 40
+
+ COLOR_MAJOR = TANGO['Scarlet Red']
+ COLOR_MINOR = TANGO['Sky Blue']
+ BG_COLOR = TANGO['Aluminium'][5]
+ ICON = pygame.image.load(data('icon.png'))
+
+ MAX_WIDTH = (1,)*7 + (2,)*5 + (3,)*3
+ MAX_SPEED = 70
+ SPEED_DIFF = 5
+ INIT_SPEED = MAX_SPEED + (BOARD_HEIGHT + 1)*SPEED_DIFF
+ COLOR_CHANGE_Y = 5
+ WIN_LEVEL = 15
+ WIN_SPEED = 100
+ INTRO, PLAYING, LOSE, WIN = range(4)
+
+ def __init__(self, restart=False):
+ pygame.init()
+ pygame.display.set_icon(self.ICON)
+ pygame.display.set_caption('Slacker')
+ self.board = [[False]*self.BOARD_WIDTH
+ for _ in range(self.BOARD_HEIGHT)]
+ self.game_state = self.PLAYING if restart else self.INTRO
+ self.falling_tiles = []
+ self.screen = pygame.display.set_mode(self.SCREEN_SIZE)
+ self.speed = self.INIT_SPEED + randrange(5)
+ self.speed_ratio = 1.0
+ self.width = self.MAX_WIDTH[-1]
+ self.y = self.BOARD_HEIGHT - 1
+
+ def draw_text(self, string, height):
+ """Width-fit the string in the screen on the given height."""
+ font = pygame.font.Font(
+ data('VT323-Regular.ttf'),
+ int(self.SCREEN_WIDTH * 2.5 / (len(string) + 1)))
+ text = font.render(string, False, self.COLOR_MINOR[0])
+ self.screen.blit(text, ((self.SCREEN_WIDTH - text.get_width()) // 2,
+ int(self.SCREEN_HEIGHT * height)))
+
+ def intro(self):
+ """Draw the intro screen."""
+ for i in [(2, 2), (3, 2), (4, 2), (1.5, 3), (4.5, 3),
+ (1.5, 4), (2, 5), (3, 5), (4, 5), (4.5, 6),
+ (1.5, 7), (4.5, 7), (2, 8), (3, 8), (4, 8)]:
+ SlackerTile(self.screen, *i, state=self.INTRO).draw(1.5)
+ if pygame.time.get_ticks() // 820 % 2:
+ self.draw_text('Press Spacebar', 0.75)
+
+ def draw_board(self):
+ """Draw the board and the tiles inside."""
+ for y, row in enumerate(self.board):
+ for x, block in enumerate(row):
+ if block:
+ SlackerTile(self.screen, x, y, self.game_state).draw()
+
+ # Draw the falling tiles
+ for ft in self.falling_tiles:
+ if ft.isfallen():
+ self.falling_tiles.remove(ft)
+ else:
+ ft.draw()
+
+ def update_screen(self):
+ """Draw the whole screen and everything inside."""
+ self.screen.fill(self.BG_COLOR)
+ if self.game_state == self.INTRO:
+ self.intro()
+ elif self.game_state in (self.PLAYING, self.LOSE, self.WIN):
+ self.draw_board()
+ pygame.display.flip()
+
+ def update_movement(self):
+ """Update the direction the blocks are moving in."""
+ speed = self.speed * self.speed_ratio
+ positions = self.BOARD_WIDTH + self.width - 2
+ p = int(round(pygame.time.get_ticks() / speed)) % (positions * 2)
+ self.x = (-p % positions if p > positions else p) - self.width + 1
+ self.board[self.y] = [0 <= x - self.x < self.width
+ for x in range(self.BOARD_WIDTH)]
+
+ def key_hit(self):
+ """Process the current position of the blocks relatively to the
+ ones underneath when user hit the switch, then decide if the
+ user will win, lose or go to the next level of the tower.
+ """
+ if self.y < self.BOARD_HEIGHT - 1:
+ for x in range(max(0, self.x),
+ min(self.x + self.width, self.BOARD_WIDTH)):
+ # If there isn't any block underneath
+ if not self.board[self.y + 1][x]:
+ # Get rid of the block not standing on solid ground
+ self.board[self.y][x] = False
+ # Then, add that falling block to falling_tiles
+ self.falling_tiles.append(SlackerTile(
+ self.screen, x, self.y,
+ missed_time=pygame.time.get_ticks()))
+ self.width = sum(self.board[self.y])
+ if not self.width:
+ self.game_state = self.LOSE
+ elif not self.y:
+ self.game_state = self.WIN
+ else:
+ self.y -= 1
+ self.width = min(self.width, self.MAX_WIDTH[self.y])
+ self.speed = self.MAX_SPEED + self.y*self.SPEED_DIFF + randrange(5)
+
+ def main_loop(self, loop=True):
+ """The main loop."""
+ while loop:
+ if self.game_state == self.INTRO:
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ loop = False
+ elif event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_SPACE:
+ self.game_state = self.PLAYING
+ elif event.key in (pygame.K_ESCAPE, pygame.K_q):
+ loop = False
+
+ elif self.game_state == self.PLAYING:
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ loop = False
+ elif event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_SPACE:
+ self.key_hit()
+ elif event.key in (pygame.K_ESCAPE, pygame.K_q):
+ self.__init__()
+ # Yes, this is a cheat.
+ elif event.key == pygame.K_0:
+ self.width += self.width < self.BOARD_WIDTH
+ elif event.key in range(pygame.K_1, pygame.K_9+1):
+ self.speed_ratio = (pygame.K_9-event.key+1) / 5.0
+ self.update_movement()
+
+ elif self.game_state in (self.LOSE, self.WIN):
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ loop = False
+ elif event.type == pygame.KEYDOWN:
+ self.__init__(restart=True)
+ self.update_screen()
diff --git a/slacker_game/__main__.py b/slacker_game/__main__.py
new file mode 100644
index 0000000..6bf40cd
--- /dev/null
+++ b/slacker_game/__main__.py
@@ -0,0 +1,13 @@
+import pygame
+
+from slacker_game import Slacker
+
+
+def main():
+ pygame.init()
+ slacker = Slacker()
+ slacker.main_loop()
+ pygame.display.quit()
+
+
+if __name__ == '__main__': main()
diff --git a/slacker_game/slacker.py b/slacker_game/slacker.py
deleted file mode 100755
index 1d098fc..0000000
--- a/slacker_game/slacker.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# slacker-game - A clone of the arcade game Stacker
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-# Copyright (C) 2007 Clint Herron
-# Copyright (C) 2017 Nguyễn Gia Phong
-
-from math import cos, pi
-from random import randrange
-
-import pygame
-from pkg_resources import resource_filename
-
-TANGO = {'Butter': ((252, 233, 79), (237, 212, 0), (196, 160, 0)),
- 'Orange': ((252, 175, 62), (245, 121, 0), (206, 92, 0)),
- 'Chocolate': ((233, 185, 110), (193, 125, 17), (143, 89, 2)),
- 'Chameleon': ((138, 226, 52), (115, 210, 22), (78, 154, 6)),
- 'Sky Blue': ((114, 159, 207), (52, 101, 164), (32, 74, 135)),
- 'Plum': ((173, 127, 168), (117, 80, 123), (92, 53, 102)),
- 'Scarlet Red': ((239, 41, 41), (204, 0, 0), (164, 0, 0)),
- 'Aluminium': ((238, 238, 236), (211, 215, 207), (186, 189, 182),
- (136, 138, 133), (85, 87, 83), (46, 52, 54))}
-
-
-def data(resource):
- """Return a true filesystem path for specified resource."""
- return resource_filename('slacker_game', resource)
-
-
-class SlackerTile:
- """SlackerTile(x, y) -> SlackerTile
-
- Slacker object for storing tiles.
- """
- SIZE = 40
- BG = TANGO['Aluminium'][5]
- MAJOR = 5
-
- def __init__(self, screen, x, y, state=1, missed_time=None):
- self.screen, self.x, self.y = screen, x, y
- if state == Slacker.LOSE:
- self.dim = 1
- elif missed_time is None:
- self.dim = 0
- else:
- self.dim = 2
- self.missed_time = missed_time
- self.wiggle = state in (Slacker.INTRO, Slacker.WIN)
-
- def get_xoffset(self, maxoffset, duration=820):
- """Return the offset on x-axis to make the tile complete an cycle of
- wiggling oscillation in given duration (in milliseconds).
- """
- if self.wiggle:
- return maxoffset * cos((pygame.time.get_ticks()/float(duration)
- + self.y/float(Slacker.BOARD_HEIGHT)) * pi)
- return 0
-
- def get_yoffset(self):
- """Return the offset on y-axis when the tile is falling."""
- if self.missed_time is None:
- return 0
- return (pygame.time.get_ticks() - self.missed_time)**2 / 25000.0
-
- def isfallen(self):
- """Return if the tile has fallen off the screen."""
- return self.y + self.get_yoffset() > Slacker.BOARD_HEIGHT
-
- def draw(self, max_x_offset=2):
- """Draw the tile."""
- color = (Slacker.COLOR_MAJOR if self.y < self.MAJOR else Slacker.COLOR_MINOR)[self.dim]
- rect = pygame.Rect((self.x+self.get_xoffset(max_x_offset)) * self.SIZE,
- (self.y+self.get_yoffset()) * self.SIZE,
- self.SIZE, self.SIZE)
- pygame.draw.rect(self.screen, color, rect)
- pygame.draw.rect(self.screen, self.BG, rect, self.SIZE // 11)
-
-
-class Slacker:
- """This class provides functions to run the game Slacker, a clone of
- the popular arcade game Stacker.
- """
- BOARD_SIZE = BOARD_WIDTH, BOARD_HEIGHT = 7, 15
- SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 280, 600
- TILE_SIZE = 40
-
- COLOR_MAJOR = TANGO['Scarlet Red']
- COLOR_MINOR = TANGO['Sky Blue']
- BG_COLOR = TANGO['Aluminium'][5]
- ICON = pygame.image.load(data('icon.png'))
-
- MAX_WIDTH = (1,)*7 + (2,)*5 + (3,)*3
- MAX_SPEED = 70
- SPEED_DIFF = 5
- INIT_SPEED = MAX_SPEED + (BOARD_HEIGHT + 1)*SPEED_DIFF
- COLOR_CHANGE_Y = 5 # blocks below which are displayed in the alternate color
- WIN_LEVEL = 15
- WIN_SPEED = 100
- INTRO, PLAYING, LOSE, WIN = range(4)
-
- def __init__(self, restart=False):
- pygame.init()
- pygame.display.set_icon(self.ICON)
- pygame.display.set_caption('Slacker')
- self.board = [[False] * self.BOARD_WIDTH for _ in range(self.BOARD_HEIGHT)]
- self.game_state = self.PLAYING if restart else self.INTRO
- self.falling_tiles = []
- self.screen = pygame.display.set_mode(self.SCREEN_SIZE)
- self.speed = self.INIT_SPEED + randrange(5)
- self.speed_ratio = 1.0
- self.width = self.MAX_WIDTH[-1]
- self.y = self.BOARD_HEIGHT - 1
-
- def draw_text(self, string, height):
- """Width-fit the string in the screen on the given height."""
- font = pygame.font.Font(
- data('VT323-Regular.ttf'),
- int(self.SCREEN_WIDTH * 2.5 / (len(string) + 1)))
- text = font.render(string, False, self.COLOR_MINOR[0])
- self.screen.blit(text, ((self.SCREEN_WIDTH - text.get_width()) // 2,
- int(self.SCREEN_HEIGHT * height)))
-
- def intro(self):
- """Draw the intro screen."""
- for i in [(2, 2), (3, 2), (4, 2), (1.5, 3), (4.5, 3),
- (1.5, 4), (2, 5), (3, 5), (4, 5), (4.5, 6),
- (1.5, 7), (4.5, 7), (2, 8), (3, 8), (4, 8)]:
- SlackerTile(self.screen, *i, state=self.INTRO).draw(1.5)
- if pygame.time.get_ticks() // 820 % 2:
- self.draw_text('Press Spacebar', 0.75)
-
- def draw_board(self):
- """Draw the board and the tiles inside."""
- for y, row in enumerate(self.board):
- for x, block in enumerate(row):
- if block:
- SlackerTile(self.screen, x, y, state=self.game_state).draw()
-
- # Draw the falling tiles
- for ft in self.falling_tiles:
- if ft.isfallen():
- self.falling_tiles.remove(ft)
- else:
- ft.draw()
-
- def update_screen(self):
- """Draw the whole screen and everything inside."""
- self.screen.fill(self.BG_COLOR)
- if self.game_state == self.INTRO:
- self.intro()
- elif self.game_state in (self.PLAYING, self.LOSE, self.WIN):
- self.draw_board()
- pygame.display.flip()
-
- def update_movement(self):
- """Update the direction the blocks are moving in."""
- speed = self.speed * self.speed_ratio
- positions = self.BOARD_WIDTH + self.width - 2
- p = int(round(pygame.time.get_ticks() / speed)) % (positions * 2)
- self.x = (-p % positions if p > positions else p) - self.width + 1
- self.board[self.y] = [0 <= x - self.x < self.width
- for x in range(self.BOARD_WIDTH)]
-
- def key_hit(self):
- """Process the current position of the blocks relatively to the
- ones underneath when user hit the switch, then decide if the
- user will win, lose or go to the next level of the tower.
- """
- if self.y < self.BOARD_HEIGHT - 1:
- for x in range(max(0, self.x),
- min(self.x + self.width, self.BOARD_WIDTH)):
- # If there isn't any block underneath
- if not self.board[self.y + 1][x]:
- # Get rid of the block not standing on solid ground
- self.board[self.y][x] = False
- # Then, add that falling block to falling_tiles
- self.falling_tiles.append(SlackerTile(
- self.screen, x, self.y, missed_time=pygame.time.get_ticks()))
- self.width = sum(self.board[self.y])
- if not self.width:
- self.game_state = self.LOSE
- elif not self.y:
- self.game_state = self.WIN
- else:
- self.y -= 1
- self.width = min(self.width, self.MAX_WIDTH[self.y])
- self.speed = self.MAX_SPEED + self.y*self.SPEED_DIFF + randrange(5)
-
- def main_loop(self, loop=True):
- """The main loop."""
- while loop:
- if self.game_state == self.INTRO:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- loop = False
- elif event.type == pygame.KEYDOWN:
- if event.key == pygame.K_SPACE:
- self.game_state = self.PLAYING
- elif event.key in (pygame.K_ESCAPE, pygame.K_q):
- loop = False
-
- elif self.game_state == self.PLAYING:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- loop = False
- elif event.type == pygame.KEYDOWN:
- if event.key == pygame.K_SPACE:
- self.key_hit()
- elif event.key in (pygame.K_ESCAPE, pygame.K_q):
- self.__init__()
- # Yes, this is a cheat.
- elif event.key == pygame.K_0 and self.width < self.BOARD_WIDTH:
- self.width += 1
- elif event.key in range(pygame.K_1, pygame.K_9 + 1):
- self.speed_ratio = (pygame.K_9 - event.key + 1) / 5.0
- self.update_movement()
-
- elif self.game_state in (self.LOSE, self.WIN):
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- loop = False
- elif event.type == pygame.KEYDOWN:
- self.__init__(restart=True)
- self.update_screen()
-
-
-def main():
- pygame.init()
- slacker = Slacker()
- slacker.main_loop()
- pygame.display.quit()
-
-
-if __name__ == '__main__':
- main()
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..8c37921
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,19 @@
+[tox]
+envlist = py
+minversion = 3.3
+isolated_build = True
+
+[testenv]
+deps =
+ flake8-builtins
+ isort
+commands =
+ flake8
+ isort . --check --diff
+
+[flake8]
+ignore = E226, E701, E704, W503
+
+[isort]
+balanced_wrapping = True
+combine_as_imports = True