text: #!/usr/bin/env python
  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("PyRPG 10 ピクセルベーススクロール")
      # マップチップをロード
      Map.images[0] = load_image("grass.png") # 草地
      Map.images[1] = load_image("water.png")  # 水
      Map.images[2] = load_image("forest.png") # 森
      Map.images[3] = load_image("hill.png")   # 丘
      Map.images[4] = load_image("mountain.png")  # 山
      # マップとプレイヤーを作成
      map = Map("test2")
      player = Player("player", (1,1), DOWN)
      clock = pygame.time.Clock()
      while True:
          clock.tick(60)
          player.update(map)
          offset = calc_offset(player)
          map.draw(screen, offset)
          player.draw(screen, offset)
          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()
  
  def calc_offset(player):
      """オフセットを計算する"""
      offsetx = player.rect.topleft[0] - SCR_RECT.width/2
      offsety = player.rect.topleft[1] - SCR_RECT.height/2
      return offsetx, offsety
  
  def load_image(filename, colorkey=None):
      filename = os.path.join("data", filename)
      try:
          image = pygame.image.load(filename)
      except pygame.error as 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, offset):
          """マップを描画する"""
          offsetx, offsety = offset
          # マップの描画範囲を計算
          startx = int(offsetx / GS)
          endx = int(startx + SCR_RECT.width/GS + 1)
          starty = int(offsety / GS)
          endy = int(starty + SCR_RECT.height/GS + 1)
          # マップの描画
          for y in range(starty, endy):
              for x in range(startx, endx):
                  # マップの範囲外はデフォルトイメージで描画
                  # この条件がないとマップの端に行くとエラー発生
                  if x < 0 or y < 0 or x > self.col-1 or y > self.row-1:
                      screen.blit(self.images[self.default], (x*GS-offsetx,y*GS-offsety))
                  else:
                      screen.blit(self.images[self.map[y][x]], (x*GS-offsetx,y*GS-offsety))
      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 or self.map[y][x] == 4:  # 水と山は移動できない
              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)
          self.default = int(lines[1])  # デフォルト値
          for line in lines[2:]:
              line = line.rstrip()
              self.map.append([int(x) for x in list(line)])
          fp.close()
  
  class Player:
      speed = 4  # 1フレームの移動ピクセル数
      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.vx, self.vy = 0, 0  # 移動速度
          self.moving = False  # 移動中か？
          self.direction = dir
      def update(self, map):
          """プレイヤー状態を更新する。
          mapは移動可能かの判定に必要。"""
          # プレイヤーの移動処理
          if self.moving == True:
              # ピクセル移動中ならマスにきっちり収まるまで移動を続ける
              self.rect.move_ip(self.vx, self.vy)
              if self.rect.left % GS == 0 and self.rect.top % GS == 0:  # マスにおさまったら移動完了
                  self.moving = False
                  self.x = int(self.rect.left / GS)
                  self.y = int(self.rect.top / GS)
          else:
              # キー入力があったら移動を開始する（速度をセットする）
              pressed_keys = pygame.key.get_pressed()
              if pressed_keys[K_DOWN]:
                  self.direction = DOWN  # 移動できるかに関係なく向きは変える
                  if map.is_movable(self.x, self.y+1):
                      self.vx, self.vy = 0, self.speed
                      self.moving = True
              elif pressed_keys[K_LEFT]:
                  self.direction = LEFT
                  if map.is_movable(self.x-1, self.y):
                      self.vx, self.vy = -self.speed, 0
                      self.moving = True
              elif pressed_keys[K_RIGHT]:
                  self.direction = RIGHT
                  if map.is_movable(self.x+1, self.y):
                      self.vx, self.vy = self.speed, 0
                      self.moving = True
              elif pressed_keys[K_UP]:
                  self.direction = UP
                  if map.is_movable(self.x, self.y-1):
                      self.vx, self.vy = 0, -self.speed
                      self.moving = True
          # キャラクターアニメーション（frameに応じて描画イメージを切り替える）
          self.frame += 1
          self.image = self.images[int(self.direction*4+self.frame/self.animcycle%4)]
      def draw(self, screen, offset):
          """オフセットを考慮してプレイヤーを描画"""
          offsetx, offsety = offset
          px = self.rect.topleft[0]
          py = self.rect.topleft[1]
          screen.blit(self.image, (px-offsetx, py-offsety))
  
  if __name__ == "__main__":
      main()
  