Add manual speed setting and write docstrings

This commit is contained in:
Nguyễn Gia Phong 2017-07-14 12:12:17 +07:00
parent 95f2fcd02c
commit 16434909f1
3 changed files with 47 additions and 24 deletions

View File

@ -3,11 +3,12 @@ Slacker
**Slacker** is a clone/parody of the popular arcade game *Stacker*, in which **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 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. Press the spacebar to stop the will move back and forth at varying speeds. Hit the switch (in this game it's
boxes and move on to the next row. Only boxes that have something underneath mapped to either Return or Space) to stop the boxes and move on to the next
them will be stacked. As the tower rises, the game will make your tower row. Only boxes that have something underneath them will be stacked. As the
thinner. You win a minor prize at the 10th level (the blocks change color), and tower rises, the game will make your tower thinner. You win a minor prize at
if you reach the 15th level, you will win the major prize. Good luck! 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 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 prizes are excellent (the one that I played let you choose between an iPod, a
@ -25,12 +26,18 @@ codebase, make it more similar to the arcade game and maybe add more features.
Control Control
------- -------
Space, Return Return, Space
Start playing or place your stacking boxes. Start playing or place your stacking boxes.
Escape, ``q`` Escape, ``q``
Return to intro screen or quit. Return to intro screen or quit.
``1`` to ``9``
Set the speed of the game (default: 5).
``0``
Increase the number of blocks currently moving.
Credits Credits
------- -------

View File

@ -6,7 +6,7 @@ with open('README.txt') as f:
setup( setup(
name='slacker-game', name='slacker-game',
version='1.3.2', version='2.0.0',
description='A clone of the arcade game Stacker', description='A clone of the arcade game Stacker',
long_description=long_description, long_description=long_description,
url='https://github.com/McSinyx/slacker-game', url='https://github.com/McSinyx/slacker-game',

View File

@ -26,18 +26,21 @@ from pygame.locals import *
class SlackerMissedTile: class SlackerMissedTile:
"""SlackerMissedTile(x, y, time) => SlackerMissedTile
Slacker object for storing missed tiles.
"""
def __init__(self, x, y, time): def __init__(self, x, y, time):
#self.x. self.y, self.time = x, y, time self.x, self.y, self.time = x, y, time
self.x = x
self.y = y
self.time = time
def get_time_delta(self): def get_time_delta(self):
"""Return the duration the missed tile has been falling in."""
return (pygame.time.get_ticks() - self.time) / 125.0 return (pygame.time.get_ticks() - self.time) / 125.0
class Slacker: 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 BOARD_SIZE = BOARD_WIDTH, BOARD_HEIGHT = 7, 15
SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 280, 600 SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 280, 600
TILE_SIZE = TILE_WIDTH, TILE_HEIGHT = 40, 40 TILE_SIZE = TILE_WIDTH, TILE_HEIGHT = 40, 40
@ -70,11 +73,13 @@ class Slacker:
self.missed_tiles = [] self.missed_tiles = []
self.screen = pygame.display.set_mode(self.SCREEN_SIZE) self.screen = pygame.display.set_mode(self.SCREEN_SIZE)
self.speed = self.LEVEL_SPEED[0] self.speed = self.LEVEL_SPEED[0]
self.speed_ratio = 1.0
self.width = self.MAX_WIDTH[0] self.width = self.MAX_WIDTH[0]
self.x = randint(0, self.BOARD_WIDTH - self.width) self.x = randint(0, self.BOARD_WIDTH - self.width)
self.y = self.BOARD_HEIGHT - 1 self.y = self.BOARD_HEIGHT - 1
def draw_tile(self, x, y): def draw_tile(self, x, y):
"""Draw the tile at position (x, y)."""
if self.game_state == self.LOSE: if self.game_state == self.LOSE:
if y < self.COLOR_CHANGE_Y: if y < self.COLOR_CHANGE_Y:
color = self.TILE_COLOR_ALT_LOSE color = self.TILE_COLOR_ALT_LOSE
@ -98,11 +103,8 @@ class Slacker:
pygame.draw.rect(self.screen, color, rect) pygame.draw.rect(self.screen, color, rect)
pygame.draw.rect(self.screen, self.BLACK, rect, 2) pygame.draw.rect(self.screen, self.BLACK, rect, 2)
def draw_background(self):
self.screen.blit(self.BG_IMAGES[self.game_state],
(0, 0, self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
def draw_board(self): def draw_board(self):
"""Draw the board and the tiles inside."""
for x in range(self.BOARD_WIDTH): for x in range(self.BOARD_WIDTH):
for y in range(self.BOARD_HEIGHT): for y in range(self.BOARD_HEIGHT):
if self.board[y][x]: self.draw_tile(x, y) if self.board[y][x]: self.draw_tile(x, y)
@ -125,7 +127,13 @@ class Slacker:
self.screen, color, self.screen, color,
pygame.Rect(x + 2, y + 2, self.TILE_WIDTH - 3, self.TILE_HEIGHT - 3)) 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): def update_screen(self):
"""Draw the whole screen and everything inside."""
if self.game_state == self.PLAYING: if self.game_state == self.PLAYING:
self.draw_background() self.draw_background()
self.draw_board() self.draw_board()
@ -138,8 +146,9 @@ class Slacker:
pygame.display.flip() pygame.display.flip()
def update_movement(self): def update_movement(self):
"""Update the direction the blocks are moving in."""
self.time = pygame.time.get_ticks() self.time = pygame.time.get_ticks()
if self.last_time + self.speed <= self.time: if self.last_time + self.speed * self.speed_ratio <= self.time:
if not -self.width < self.x + self.direction < self.BOARD_WIDTH: if not -self.width < self.x + self.direction < self.BOARD_WIDTH:
self.direction *= -1 self.direction *= -1
self.x += self.direction self.x += self.direction
@ -148,6 +157,10 @@ class Slacker:
for x in range(self.BOARD_WIDTH)] for x in range(self.BOARD_WIDTH)]
def key_hit(self): 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: if self.y < self.BOARD_HEIGHT - 1:
for x in range(max(0, self.x), for x in range(max(0, self.x),
min(self.x + self.width, self.BOARD_WIDTH)): min(self.x + self.width, self.BOARD_WIDTH)):
@ -167,26 +180,27 @@ class Slacker:
self.direction = choice([1, -1]) self.direction = choice([1, -1])
self.level += 1 self.level += 1
self.speed = self.LEVEL_SPEED[self.level] 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.x = randint(0, self.BOARD_WIDTH - self.width)
self.y -= 1 self.y -= 1
def main_loop(self): def main_loop(self, loop=True):
keep_running = True """The main loop."""
while keep_running: while loop:
self.update_screen() self.update_screen()
if self.game_state == self.INTRO: if self.game_state == self.INTRO:
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
keep_running = False loop = False
elif event.type == KEYDOWN: elif event.type == KEYDOWN:
if event.key in (K_RETURN, K_SPACE): if event.key in (K_RETURN, K_SPACE):
self.game_state = self.PLAYING self.game_state = self.PLAYING
elif event.key in (K_ESCAPE, K_q): elif event.key in (K_ESCAPE, K_q):
keep_running = False loop = False
elif self.game_state == self.PLAYING: elif self.game_state == self.PLAYING:
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
keep_running = False loop = False
elif event.type == KEYDOWN: elif event.type == KEYDOWN:
if event.key in (K_RETURN, K_SPACE): if event.key in (K_RETURN, K_SPACE):
self.key_hit() self.key_hit()
@ -196,11 +210,13 @@ class Slacker:
elif event.key == K_F1 and self.width < self.BOARD_WIDTH: elif event.key == K_F1 and self.width < self.BOARD_WIDTH:
self.x -= self.direction self.x -= self.direction
self.width += 1 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() self.update_movement()
elif self.game_state in (self.LOSE, self.WIN): elif self.game_state in (self.LOSE, self.WIN):
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
keep_running = False loop = False
elif event.type == KEYDOWN: elif event.type == KEYDOWN:
self.__init__() self.__init__()