#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame
from pygame.locals import *
import sys
import os

SCR_RECT = Rect(0, 0, 640, 480)
GS = 32
DOWN,LEFT,RIGHT,UP = 0,1,2,3

def main():
    pygame.init()
    screen = pygame.display.set_mode(SCR_RECT.size)
    pygame.display.set_caption(u"PyRPG 08 マップのロード")
    # マップチップをロード
    Map.images[0] = load_image("grass.png")  # 草地
    Map.images[1] = load_image("water.png")  # 水
    # マップとプレイヤー作成
    map = Map("test")
    player = Player("player", (1,1), DOWN)
    clock = pygame.time.Clock()
    while True:
        clock.tick(60)
        player.update()
        map.draw(screen)
        player.draw(screen)
        pygame.display.update()
        for event in pygame.event.get():
            if event.type == QUIT:
                sys.exit()
            if event.type == KEYDOWN and event.key == K_ESCAPE:
                sys.exit()
            # プレイヤーの移動処理
            if event.type == KEYDOWN and event.key == K_DOWN:
                player.move(DOWN, map)
            if event.type == KEYDOWN and event.key == K_LEFT:
                player.move(LEFT, map)
            if event.type == KEYDOWN and event.key == K_RIGHT:
                player.move(RIGHT, map)
            if event.type == KEYDOWN and event.key == K_UP:
                player.move(UP, map)

def load_image(filename, colorkey=None):
    filename = os.path.join("data", filename)
    try:
        image = pygame.image.load(filename)
    except pygame.error, message:
        print "Cannot load image:", filename
        raise SystemExit, message
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image

def split_image(image):
    """128x128のキャラクターイメージを32x32の16枚のイメージに分割
    分割したイメージを格納したリストを返す"""
    imageList = []
    for i in range(0, 128, GS):
        for j in range(0, 128, GS):
            surface = pygame.Surface((GS,GS))
            surface.blit(image, (0,0), (j,i,GS,GS))
            surface.set_colorkey(surface.get_at((0,0)), RLEACCEL)
            surface.convert()
            imageList.append(surface)
    return imageList

class Map:
    images = [None] * 256  # マップチップ(番号->イメージ)
    def __init__(self, name):
        self.name = name
        self.row = -1  # 行数
        self.col = -1  # 列数
        self.map = []  # マップデータ(2次元リスト)
        self.load()
    def draw(self, screen):
        """マップを描画する"""
        for r in range(self.row):
            for c in range(self.col):
                screen.blit(self.images[self.map[r][c]], (c*GS,r*GS))
    def is_movable(self, x, y):
        """(x,y)は移動可能か?"""
        # マップ範囲内か?
        if x < 0 or x > self.col-1 or y < 0 or y > self.row-1:
            return False
        # マップチップは移動可能か?
        if self.map[y][x] == 1:  # 水は移動できない
            return False
        return True
    def load(self):
        """ファイルからマップをロード"""
        file = os.path.join("data", self.name + ".map")
        # テキスト形式のマップを読み込む
        fp = open(file)
        lines = fp.readlines()
        row_str, col_str = lines[0].split()  # 行数と列数
        self.row, self.col = int(row_str), int(col_str)
        for line in lines[1:]:
            line = line.rstrip()
            self.map.append([int(x) for x in list(line)])
        fp.close()

class Player:
    animcycle = 24  # アニメーション速度
    frame = 0
    def __init__(self, name, pos, dir):
        self.name = name  # プレイヤー名(ファイル名と同じ)
        self.images = split_image(load_image("%s.png" % name))
        self.image = self.images[0]  # 描画中のイメージ
        self.x, self.y = pos[0], pos[1]  # 座標(単位:マス)
        self.rect = self.image.get_rect(topleft=(self.x*GS, self.y*GS))
        self.direction = dir
    def update(self):
        # キャラクターアニメーション(frameに応じて描画イメージを切り替える)
        self.frame += 1
        self.image = self.images[self.direction*4+self.frame/self.animcycle%4]
    def move(self, dir, map):
        """プレイヤーを移動"""
        if dir == DOWN:
            self.direction = DOWN
            if map.is_movable(self.x, self.y+1):
                self.y += 1
                self.rect.top += GS
        elif dir == LEFT:
            self.direction = LEFT
            if map.is_movable(self.x-1, self.y):
                self.x -= 1
                self.rect.left -= GS
        elif dir == RIGHT:
            self.direction = RIGHT
            if map.is_movable(self.x+1, self.y):
                self.x += 1
                self.rect.left += GS
        elif dir == UP:
            self.direction = UP
            if map.is_movable(self.x, self.y-1):
                self.y -= 1
                self.rect.top -= GS
    def draw(self, screen):
        screen.blit(self.image, self.rect)

if __name__ == "__main__":
    main()