Refine packaging and remove background images

This commit is contained in:
Nguyễn Gia Phong 2017-07-16 16:11:28 +07:00
parent 16434909f1
commit 6334aed1ba
19 changed files with 358 additions and 242 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
MANIFEST
build
slacker_game.egg-info
dist

1
MANIFEST.in Normal file
View File

@ -0,0 +1 @@
include LICENSE README.rst

View File

@ -3,12 +3,11 @@ Slacker
**Slacker** is a clone/parody of the popular arcade game *Stacker*, in which
you must stack blocks to the top of the screen in order to win the game. Boxes
will move back and forth at varying speeds. Hit the switch (in this game it's
mapped to either Return or Space) to stop the boxes and move on to the next
row. Only boxes that have something underneath them will be stacked. As the
tower rises, the game will make your tower thinner. You win a minor prize at
the 10th level (the blocks change color), and if you reach the 15th level, you
will win the major prize. Good luck!
will move back and forth at varying speeds. Press Space to stop the boxes and
move on to the next row. Only boxes that have something underneath them will be
stacked. As the tower rises, the game will make your tower thinner. You win a
minor prize at the 10th level (the blocks change color), and if you reach the
15th level, you will win the major prize. Good luck!
In the arcade version, credits are expensive (often $1 per play), but the
prizes are excellent (the one that I played let you choose between an iPod, a
@ -19,14 +18,15 @@ win a good prize. Despite the hard nature of the game, I hope will enjoy it,
and if you wind up practicing with the game and getting so good that you win an
extra iPod, I wouldn't mind if you sent it my way. :)
This game was originally made by Clint and Jennifer Herron (see credits). They
wrote the above description, too. I (McSinyx) fork the game to improve the
codebase, make it more similar to the arcade game and maybe add more features.
This game and the above description was originally written by Clint and
Jennifer Herron (see credits). I (McSinyx) fork the game to improve the
codebase, make it more similar to the arcade game and hopefully add more
features.
Control
-------
Return, Space
Space
Start playing or place your stacking boxes.
Escape, ``q``

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup
with open('README.txt') as f:
with open('README.rst') as f:
long_description = f.read()
setup(
@ -17,7 +18,6 @@ setup(
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: MacOS X',
'Environment :: MacOS X',
'Environment :: Win32 (MS Windows)',
'Environment :: X11 Applications',
'Intended Audience :: End Users/Desktop',
@ -27,6 +27,7 @@ setup(
'Programming Language :: Python',
'Topic :: Games/Entertainment :: Arcade'],
keywords='stacker arcade-game pygame-application',
packages=['slacker_game'],
install_requires=['pygame'],
data_files=[('data/*', ['slacker-game'])],
scripts=['slacker-game'])
package_data={'slacker_game': ['*.png', 'VT323-Regular.ttf']},
entry_points={'gui_scripts': ['slacker-game = slacker_game:main']})

View File

@ -1,228 +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 <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2007 Clint Herron
# Copyright (C) 2017 Nguyễn Gia Phong
from math import sin
from random import choice, randint
import pygame
from pygame.locals import *
class SlackerMissedTile:
"""SlackerMissedTile(x, y, time) => SlackerMissedTile
Slacker object for storing missed tiles.
"""
def __init__(self, x, y, time):
self.x, self.y, self.time = x, y, time
def get_time_delta(self):
"""Return the duration the missed tile has been falling in."""
return (pygame.time.get_ticks() - self.time) / 125.0
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 = TILE_WIDTH, TILE_HEIGHT = 40, 40
TILE_COLOR = 127, 127, 255
TILE_COLOR_ALT = 255, 127, 127
TILE_COLOR_LOSE = 64, 64, 128
TILE_COLOR_ALT_LOSE = 127, 64, 64
BLACK = 0, 0, 0
LEVEL_SPEED = 80, 80, 75, 75, 70, 70, 65, 60, 55, 50, 45, 40, 35, 30, 32
MAX_WIDTH = (3,)*4 + (2,)*4 + (1,)*7
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)
BG_IMAGES = [pygame.image.load('data/_{}.png'.format(i))
for i in ('intro', 'game', 'lose', 'win')]
BG_IMAGES[WIN].set_colorkey(BLACK)
BG_IMAGES[LOSE].set_colorkey(BLACK)
def __init__(self):
self.board = [[False] * self.BOARD_WIDTH for _ in range(self.BOARD_HEIGHT)]
self.direction = choice([1, -1])
self.game_state = self.INTRO
self.level = 0
self.last_time = 0
self.missed_tiles = []
self.screen = pygame.display.set_mode(self.SCREEN_SIZE)
self.speed = self.LEVEL_SPEED[0]
self.speed_ratio = 1.0
self.width = self.MAX_WIDTH[0]
self.x = randint(0, self.BOARD_WIDTH - self.width)
self.y = self.BOARD_HEIGHT - 1
def draw_tile(self, x, y):
"""Draw the tile at position (x, y)."""
if self.game_state == self.LOSE:
if y < self.COLOR_CHANGE_Y:
color = self.TILE_COLOR_ALT_LOSE
else:
color = self.TILE_COLOR_LOSE
else:
if y < self.COLOR_CHANGE_Y:
color = self.TILE_COLOR_ALT
else:
color = self.TILE_COLOR
# XOffset is used to draw some wiggle in the tower when you win
if self.game_state == self.WIN:
xoffset = (sin(pygame.time.get_ticks()*0.004 + y*0.5)
* (self.SCREEN_WIDTH / 4))
else:
xoffset = 0
rect = pygame.Rect(x*self.TILE_WIDTH + xoffset, y * self.TILE_HEIGHT,
self.TILE_WIDTH, self.TILE_HEIGHT)
pygame.draw.rect(self.screen, color, rect)
pygame.draw.rect(self.screen, self.BLACK, rect, 2)
def draw_board(self):
"""Draw the board and the tiles inside."""
for x in range(self.BOARD_WIDTH):
for y in range(self.BOARD_HEIGHT):
if self.board[y][x]: self.draw_tile(x, y)
# Draw the missed tiles
for mt in self.missed_tiles:
time_delta = mt.get_time_delta()
x = mt.x * self.TILE_WIDTH
y = mt.y*self.TILE_HEIGHT + time_delta**2
if mt.y < self.COLOR_CHANGE_Y:
color = self.TILE_COLOR_ALT_LOSE
else:
color = self.TILE_COLOR_LOSE
if y > self.SCREEN_HEIGHT:
self.missed_tiles.remove(mt)
else:
pygame.draw.rect(
self.screen, color,
pygame.Rect(x + 2, y + 2, self.TILE_WIDTH - 3, self.TILE_HEIGHT - 3))
def draw_background(self):
"""Draw the background image according to current game_state."""
self.screen.blit(self.BG_IMAGES[self.game_state],
(0, 0, self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
def update_screen(self):
"""Draw the whole screen and everything inside."""
if self.game_state == self.PLAYING:
self.draw_background()
self.draw_board()
elif self.game_state == self.INTRO:
self.draw_background()
elif self.game_state in (self.LOSE, self.WIN):
self.screen.fill(self.BLACK)
self.draw_board()
self.draw_background()
pygame.display.flip()
def update_movement(self):
"""Update the direction the blocks are moving in."""
self.time = pygame.time.get_ticks()
if self.last_time + self.speed * self.speed_ratio <= self.time:
if not -self.width < self.x + self.direction < self.BOARD_WIDTH:
self.direction *= -1
self.x += self.direction
self.last_time = self.time
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 missed block to missed_tiles
self.missed_tiles.append(
SlackerMissedTile(x, self.y, pygame.time.get_ticks()))
self.width = sum(self.board[self.y])
if not self.width:
self.game_state = self.LOSE
elif self.level + 1 == self.WIN_LEVEL:
self.speed, self.game_state = self.WIN_SPEED, self.WIN
else:
self.direction = choice([1, -1])
self.level += 1
self.speed = self.LEVEL_SPEED[self.level]
self.width = min(self.width, self.MAX_WIDTH[self.level])
self.x = randint(0, self.BOARD_WIDTH - self.width)
self.y -= 1
def main_loop(self, loop=True):
"""The main loop."""
while loop:
self.update_screen()
if self.game_state == self.INTRO:
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = False
elif event.type == KEYDOWN:
if event.key in (K_RETURN, K_SPACE):
self.game_state = self.PLAYING
elif event.key in (K_ESCAPE, 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 == KEYDOWN:
if event.key in (K_RETURN, K_SPACE):
self.key_hit()
elif event.key in (K_ESCAPE, K_q):
self.__init__()
# Yes, this is a cheat.
elif event.key == K_F1 and self.width < self.BOARD_WIDTH:
self.x -= self.direction
self.width += 1
elif event.key in range(K_1, K_9 + 1):
self.speed_ratio = (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 == KEYDOWN:
self.__init__()
if __name__ == '__main__':
pygame.init()
slacker = Slacker()
slacker.main_loop()
pygame.display.quit()

92
slacker_game/OFL.txt Normal file
View File

@ -0,0 +1,92 @@
Copyright 2011, The VT323 Project Authors (peter.hull@oikoi.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

1
slacker_game/__init__.py Normal file
View File

@ -0,0 +1 @@
from .slacker import Slacker, main

BIN
slacker_game/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

245
slacker_game/slacker.py Executable file
View File

@ -0,0 +1,245 @@
#!/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 <http://www.gnu.org/licenses/>.
#
# 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
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 = 84 + 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 = 42 + self.y*3 + 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()