9回目:pygameでゲームを作成する|マップファイルの作成

主人公のかに歩きを治すということで、次のコードを作成しました。

 

かに歩きから普通の歩き方へ


# -*- coding utf-8 -*-
import pygame 
from pygame.locals import*
import sys 

rect=Rect(0,0,640,480)
TATE,YOKO=15,20
GS =32 
DOWN,LEFT,RIGHT,UP=0,1,2,3	#4パターンに分ける

map=[	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
	[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]

def img(filename):
 image=pygame.image.load(filename).convert_alpha()
 return image

def split(image):
 imageList=[]
 for i in range(0,128,GS):
  for ix in range(0,96,GS):
   surface=pygame.Surface((GS,GS))
   surface.blit(image,(0,0),(ix,i,GS,GS))
   surface.set_colorkey(000000)
   surface.convert_alpha()
   imageList.append(surface)
 return imageList

def draw(screen,MapImg):
 for i in range(TATE):
  for ix in range(YOKO):
   if map[i][ix]==0:
    screen.blit(MapImg,(ix*GS,i*GS))

def main():
 pygame.init()
 screen=pygame.display.set_mode(rect.size)
 pygame.display.set_caption("移動")
 playerList=split(img("c.png"))
 MapImg=img("d.png")

 x,y=0,0
 Muki=DOWN
 anime=24
 frame=0
 
 clock=pygame.time.Clock()
 
 while(1):
  clock.tick(60)
  frame+=1
  player=playerList[Muki*3+frame//anime%3]	#Muki*4は縦の列を表している
  print(Muki*4)
  draw(screen,MapImg)

  pressed_keys = pygame.key.get_pressed()
  if pressed_keys[K_LEFT]:
    Muki=LEFT
    x-=1
  if pressed_keys[K_RIGHT]:
    Muki=RIGHT
    x+=1
  if pressed_keys[K_UP]:
    Muki=UP
    y-=1
  if pressed_keys[K_DOWN]:
    Muki=DOWN
    y+=1
 
  screen.blit(player,(x*GS,y*GS))
  pygame.display.update()

  for event in pygame.event.get():
   if event.type==QUIT:
    sys.exit()

if __name__=="__main__":
 main()

以前はimageListを3つしか作成していませんでした。([0],[1],[2])

しかし上下左右方向の動きを格納するので

([0],[1],[2],
[3],[4],[5],
[6],[7],[8],
[9],[10],[11])

という感じに格納する必要があります。

呼び出し方は、Muki*3+frame//anime%3です。

DOWN,LEFT,RIGHT,UP=0,1,2,3と代入しているので、仮にUPを入力したとすると、Mukiに3が代入されて計算されます。(3*3+frame//24%3 = [9]か[10]か[11]のどれか)

マップ情報を他のファイルに格納する

いちいち、.pyの中にマップを書くとかなり大変で、非効率的です。

ということで、外部ファイルに移すということをします。

マップファイルの作成


15 20
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000

これがファイルです。拡張子は「.map」。

文字コードはutf-8のほうがいいです。

ソースコード



# -*- coding utf-8 -*-
import pygame 
from pygame.locals import*
import sys 
import codecs

rect=Rect(0,0,640,480)
GS =32 
DOWN,LEFT,RIGHT,UP=0,1,2,3	#4パターンに分ける

class Map:
    def __init__(self, name):
        self.name = name
        self.TATE = -1  # 行数
        self.YOKO = -1  # 列数
        self.map = []  # マップデータ(2次元リスト)

    def load(self):
        file =self.name
        fp = codecs.open(file,"r",'utf-8-sig')	#ファイルオープン utf-8で設定している人はこの方法で開くほうがいい
        lines = fp.readlines()		 # ファイル全体を行単位で読み込む
        TATE, YOKO = lines[0].split()  		# 行数と列数
        self.TATE, self.YOKO = int(TATE), int(YOKO)  # int型に変換
        for line in lines[1:]:		# マップデータを読み込む 0は抜かして1から
            line = line.rstrip()  	# 改行除去
            self.map.append([int(x) for x in list(line)])	#横の数の分[]に格納、それをさらにmapに格納
        fp.close()
        return self.map,self.TATE,self.YOKO #マップ情報と縦と横を返す



def img(filename):
 image=pygame.image.load(filename).convert_alpha()
 return image

def split(image):
 imageList=[]
 for i in range(0,128,GS):
  for ix in range(0,96,GS):
   surface=pygame.Surface((GS,GS))
   surface.blit(image,(0,0),(ix,i,GS,GS))
   surface.set_colorkey(000000)
   surface.convert_alpha()
   imageList.append(surface)
 return imageList

def draw(screen,MapImg,map,TATE,YOKO):
 for i in range(TATE):
  for ix in range(YOKO):
   if map[i][ix]==0:
    screen.blit(MapImg,(ix*GS,i*GS))

def main():
 pygame.init()
 screen=pygame.display.set_mode(rect.size)
 pygame.display.set_caption("移動")
 playerList=split(img("c.png"))
 MapImg=img("d.png")
 map,TATE,YOKO = Map("test.map").load()
 
 x,y=0,0
 Muki=DOWN
 anime=24
 frame=0
 
 clock=pygame.time.Clock()
 
 while(1):
  clock.tick(60)
  frame+=1
  player=playerList[Muki*3+frame//anime%3]	#Muki*4は縦の列を表している
  draw(screen,MapImg,map,TATE,YOKO)

  pressed_keys = pygame.key.get_pressed()
  if pressed_keys[K_LEFT]:
    Muki=LEFT
    x-=1
  if pressed_keys[K_RIGHT]:
    Muki=RIGHT
    x+=1
  if pressed_keys[K_UP]:
    Muki=UP
    y-=1
  if pressed_keys[K_DOWN]:
    Muki=DOWN
    y+=1
 
  screen.blit(player,(x*GS,y*GS))
  pygame.display.update()

  for event in pygame.event.get():
   if event.type==QUIT:
    sys.exit()

if __name__=="__main__":
 main()

 

マップ作製の部分を抜き出すとこちらです。

 


class Map:
    def __init__(self, name):
        self.name = name
        self.TATE = -1  # 行数
        self.YOKO = -1  # 列数
        self.map = []  # マップデータ(2次元リスト)

    def load(self):
        file =self.name
        fp = codecs.open(file,"r",'utf-8-sig')	#ファイルオープン utf-8で設定している人はこの方法で開くほうがいい
        lines = fp.readlines()		 # ファイル全体を行単位で読み込む
        TATE, YOKO = lines[0].split()  		# 行数と列数
        self.TATE, self.YOKO = int(TATE), int(YOKO)  # int型に変換
        for line in lines[1:]:		# マップデータを読み込む 0は抜かして1から
            line = line.rstrip()  	# 改行除去
            self.map.append([int(x) for x in list(line)])	#横の数の分[]に格納、それをさらにmapに格納
        fp.close()
        return self.map,self.TATE,self.YOKO #マップ情報と縦と横を返す

 

utf-8のファイルを普通にオープンすると不都合があったので、このオープンの仕方にしました。

 

load()でたくさんのreturn値がでてしまったので、もっとスマートな書き方を覚えたいです。(私の実力ではこれが限界でした。)

 

まとめ

まだまだ、オブジェクト指向のプログラミングに慣れていない状態ですのでこのプログラムでも相当悩みました。

 

まあ、悩んでいる時間も面白いのですが早くすらすらと打てるようになりたいと感じました。

 

クラスとメゾットの考え方はかなり難しいですが、少しずつ慣れていけたらと思います。