237 lines
6.2 KiB
Python
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
|