slacker-game/lib/main.py

237 lines
6.2 KiB
Python

'''Game main module.
Last Day Game Entry, by Clint Herron
'''
import data
import pygame
from pygame.locals import *
from data import *
from math import sin
BOARD_SIZE = BOARD_WIDTH, BOARD_HEIGHT = 12, 20
SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 240, 400
TILE_SIZE = TILE_WIDTH, TILE_HEIGHT = SCREEN_WIDTH / BOARD_WIDTH, SCREEN_HEIGHT / BOARD_HEIGHT
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, 3, 3, 3, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1)
COLOR_CHANGE_Y = 10 # The block below which are displayed in the alternate color
WIN_LEVEL = 15
current_speed = 50 # Current tile speed in milliseconds
board = []
lose_tiles = []
current_direction = 1
current_x, current_y, current_width = 0, BOARD_HEIGHT - 1, 3
current_level = 0
INTRO = 0
PLAYING = 1
LOSE = 2
WIN = 3
game_state = INTRO
bg_images = ( load_image("intro.png"), load_image("game.png"), load_image("lose.png"), load_image("win.png") )
bg_images[WIN].set_colorkey(BLACK)
bg_images[LOSE].set_colorkey(BLACK)
keep_running = True
def main():
global game_state, current_x, current_y, current_speed, keep_running, current_width, current_level
pygame.init()
screen = pygame.display.set_mode( SCREEN_SIZE )
reset_game()
while(keep_running):
update_movement()
update_board_info()
update_screen(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keep_running = False
elif event.type == KEYDOWN:
if event.key == K_SPACE:
key_hit()
elif event.key == K_ESCAPE:
if game_state == INTRO:
keep_running = False
else:
reset_game()
elif event.key == K_F1: # Yes, this is a cheat.
current_x -= 1
if (current_x < 0): current_x = 0
current_width += 1
if (current_width >= BOARD_WIDTH): current_width = BOARD_WIDTH - 1
pygame.display.quit()
def reset_game():
global game_state, current_x, current_y, current_speed, keep_running, current_width, current_level, lose_tiles
clear_board()
lose_tiles = []
keep_running = True
game_state = INTRO
current_x = 0
current_y = BOARD_HEIGHT - 1
current_level = 0
current_speed = LEVEL_SPEED[current_level]
current_width = MAX_WIDTH[current_level]
def key_hit():
global keep_running, game_state, current_x, current_y, current_width, current_speed, current_level, lose_tiles
if game_state == PLAYING:
if current_y < BOARD_HEIGHT - 1:
for x in range(current_x, current_x + current_width):
if board[x][current_y + 1] == 0: # If they're standing on a block that did not work
current_width -= 1 # Then next time, give them one less block
board[x][current_y] = 0 # Also, get rid of this block that isn't standing on solid ground.
# Then, add a lose tile for that missed block
# Lose tile format is (x, y, color, start time)
lose_tiles.append( (x, current_y,
pygame.time.get_ticks()) )
current_level += 1
check_win_lose()
current_y -= 1
elif game_state == INTRO:
game_state = PLAYING
elif (game_state == LOSE) or (game_state == WIN):
reset_game()
game_state = INTRO
else:
keep_running = False
def check_win_lose():
global game_state, current_width, current_level, current_speed, keep_running, TILE_COLOR
if current_width == 0:
game_state = LOSE
elif current_level == WIN_LEVEL:
current_speed = 100
game_state = WIN
else:
current_speed = LEVEL_SPEED[current_level]
if current_width > MAX_WIDTH[current_level]:
current_width = MAX_WIDTH[current_level]
last_time = 0
def update_movement():
global game_state, last_time, current_x, current_y, current_width, current_speed, current_direction
current_time = pygame.time.get_ticks()
if (last_time + current_speed <= current_time):
if game_state == PLAYING:
new_x = current_x + current_direction
if (new_x < 0) or (new_x + current_width > BOARD_WIDTH):
current_direction = -current_direction
current_x += current_direction
last_time = current_time
def update_screen(screen):
global game_state
if game_state == PLAYING:
draw_background(screen)
draw_board(screen)
elif game_state == INTRO:
draw_background(screen)
pass
elif (game_state == LOSE) or (game_state == WIN):
screen.fill(BLACK)
draw_board(screen)
draw_background(screen)
pygame.display.flip()
def draw_background(screen):
global game_state
screen.blit(bg_images[game_state], (0,0,SCREEN_WIDTH,SCREEN_HEIGHT), (0,0,SCREEN_WIDTH,SCREEN_HEIGHT))
def update_board_info():
global game_state
if game_state == PLAYING:
clear_row(current_y)
fill_current_row()
def draw_board(screen):
for x in range(BOARD_WIDTH):
for y in range(BOARD_HEIGHT):
if board[x][y] == 1:
draw_tile(screen, x, y)
draw_lose_tiles(screen)
def draw_tile(screen, x, y):
xoffset = 0 # XOffset is used to draw some wiggle in the tower when you win
col = TILE_COLOR
if (y < COLOR_CHANGE_Y):
col = TILE_COLOR_ALT
if (game_state == LOSE):
col = TILE_COLOR_LOSE
if (y < COLOR_CHANGE_Y):
col = TILE_COLOR_ALT_LOSE
if game_state == WIN:
xoffset = sin(pygame.time.get_ticks() * 0.004 + y * 0.5) * (SCREEN_WIDTH / 4)
pygame.draw.rect(screen, col, (x * TILE_WIDTH + xoffset, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT))
pygame.draw.rect(screen, BLACK, (x * TILE_WIDTH + xoffset, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT), 2)
# Lose tiles are ones that fall off from the edge when you miss placing them on the proper stack
def draw_lose_tiles(screen):
for lt in lose_tiles:
deltaT = (pygame.time.get_ticks() - lt[2]) * 0.008 # How long it has been falling
x = lt[0] * TILE_WIDTH
y = lt[1] * TILE_HEIGHT + deltaT * deltaT
col = TILE_COLOR_LOSE
if (lt[1] < COLOR_CHANGE_Y):
col = TILE_COLOR_ALT_LOSE
if (y > SCREEN_HEIGHT):
lose_tiles.remove(lt)
else:
pygame.draw.rect(screen, col, (x+2, y+2, TILE_WIDTH-3, TILE_HEIGHT-3))
def clear_board():
global board
board = []
for x in range(BOARD_WIDTH):
board.append([])
for y in range (BOARD_HEIGHT):
board[x].append(0)
def clear_row(y):
for x in range(BOARD_WIDTH):
board[x][y] = 0
def fill_current_row():
global current_x, current_y, current_width
for x in range(current_x, current_x + current_width):
board[x][current_y] = 1