前回ではフィールドの表示を行った、
今回はテトリミノを配置してみる。
Tiled で編集
前回のようにTiledでデータを作っていく
出来上がったファイル
mino_block.tmx
mino_block.tmx
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="28" height="16" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="mino_block.tsx"/>
<layer id="1" name="mino_block" width="28" height="16">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,2,2,0,0,0,3,3,0,4,0,0,0,0,0,5,0,0,6,0,0,7,7,0,8,8,8,8,
0,0,2,2,0,3,3,0,0,4,4,4,0,5,5,5,0,6,6,6,0,7,7,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,
0,0,0,2,0,0,3,0,0,0,4,4,0,0,5,0,0,0,6,0,0,7,7,0,0,0,8,0,
0,0,2,2,0,0,3,3,0,0,4,0,0,0,5,0,0,0,6,6,0,7,7,0,0,0,8,0,
0,0,2,0,0,0,0,3,0,0,4,0,0,0,5,5,0,0,6,0,0,0,0,0,0,0,8,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,0,0,0,0,0,
0,2,2,0,0,0,3,3,0,4,4,4,0,5,5,5,0,6,6,6,0,7,7,0,8,8,8,8,
0,0,2,2,0,3,3,0,0,0,0,4,0,5,0,0,0,0,6,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,
0,0,2,0,0,3,0,0,0,0,4,0,0,5,5,0,0,0,6,0,0,7,7,0,0,8,0,0,
0,2,2,0,0,3,3,0,0,0,4,0,0,0,5,0,0,6,6,0,0,7,7,0,0,8,0,0,
0,2,0,0,0,0,3,0,0,4,4,0,0,0,5,0,0,0,6,0,0,0,0,0,0,8,0,0
</data>
</layer>
</map>
読み込んで加工
作成したtmxファイルを読み込んでみる
mino.py
from enum import Enum, auto
import pytmx
# tmx ファイルからミノを構成するブロックの配置を定義する
def get_mino_data(t, size=4):
tmx_data = pytmx.TiledMap('mino_block.tmx')
shapes = [[] for _ in range(4)]
tile = 0
for r in range(4):
for y in range(size):
for x in range(size):
gid = tmx_data.get_tile_gid(size*t+x, size*(r%4)+y, 0)
if gid != 0:
tile = gid
shapes[r].append((x,y))
return tile, shapes
# ミノの形を定義する列挙型
class minotype(Enum):
Z = 'Z', auto(), *get_mino_data(0)
S = 'S', auto(), *get_mino_data(1)
J = 'J', auto(), *get_mino_data(2)
L = 'L', auto(), *get_mino_data(3)
T = 'T', auto(), *get_mino_data(4)
O = 'O', auto(), *get_mino_data(5)
I = 'I', auto(), *get_mino_data(6)
def __init__(self, name, value, tile, shape):
self._name = name
self._value_ = value
self.tile = tile
self.shape = tuple(tuple(s) for s in shape)
@classmethod
def values(cls):
# Order dictionary -> list
return list(cls.__members__.values())
def main():
for mino in minotype.values():
print(mino.name, mino.value, mino.tile, mino.shape)
if __name__ == '__main__':
main()
とりあえず実行してみた結果はこんな感じ
Z 1 1 (((1, 1), (2, 1), (2, 2), (3, 2)), ((3, 1), (2, 2), (3, 2), (2, 3)), ((1, 2), (2, 2), (2, 3), (3, 3)), ((2, 1), (1, 2), (2, 2), (1, 3)))
S 2 2 (((2, 1), (3, 1), (1, 2), (2, 2)), ((2, 1), (2, 2), (3, 2), (3, 3)), ((2, 2), (3, 2), (1, 3), (2, 3)), ((1, 1), (1, 2), (2, 2), (2, 3)))
J 3 3 (((1, 1), (1, 2), (2, 2), (3, 2)), ((2, 1), (3, 1), (2, 2), (2, 3)), ((1, 2), (2, 2), (3, 2), (3, 3)), ((2, 1), (2, 2), (1, 3), (2, 3)))
L 4 4 (((3, 1), (1, 2), (2, 2), (3, 2)), ((2, 1), (2, 2), (2, 3), (3, 3)), ((1, 2), (2, 2), (3, 2), (1, 3)), ((1, 1), (2, 1), (2, 2), (2, 3)))
T 5 5 (((1, 1), (2, 1), (3, 1), (2, 2)), ((2, 1), (1, 2), (2, 2), (2, 3)), ((2, 1), (1, 2), (2, 2), (3, 2)), ((2, 1), (2, 2), (3, 2), (2, 3)))
O 6 6 (((1, 1), (2, 1), (1, 2), (2, 2)), ((1, 1), (2, 1), (1, 2), (2, 2)), ((1, 1), (2, 1), (1, 2), (2, 2)), ((1, 1), (2, 1), (1, 2), (2, 2)))
I 7 7 (((0, 1), (1, 1), (2, 1), (3, 1)), ((2, 0), (2, 1), (2, 2), (2, 3)), ((0, 2), (1, 2), (2, 2), (3, 2)), ((1, 0), (1, 1), (1, 2), (1, 3)))
問題なく読み込んでいるようだ
フィールドに配置
前回作ったプログラムに追記してミノを表示してみる。
main.py
import pygame
from pytmx import util_pygame as tmx_util
from mino import minotype
TILE_SIZE = 32
MATRIX_SIZE = (20,10)
MATRIX_POS = (11,1)
class Game:
# 番兵用に連想配列でラクする
matrix = {
i:{
j:0 for j in range(-1,11)
} for i in range(-20,21)
}
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((1024, 768))
def draw_tile(self, tmx, x, y, t):
tile_image = tmx.get_tile_image_by_gid(t)
if tile_image:
self.screen.blit(tile_image, (x * TILE_SIZE, y * TILE_SIZE))
def run(self):
clock = pygame.time.Clock()
running = True
self.tmx_data = tmx_util.load_pygame('field.tmx')
self.mino_block = tmx_util.load_pygame('mino_block.tmx')
# 番兵を設置
for i in range(-20,21):
self.matrix[i][-1] = 1
self.matrix[i][10] = 1
for i in range(-1,11):
self.matrix[20][i] = 1
# test code: 各種ミノを設置
for i, m in enumerate(minotype.values()):
for x,y in m.shape[0]:
self.matrix[i*3+y-1][2+x] = m.tile
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
self.screen.fill((0, 0, 0))
for layer in self.tmx_data.layers:
if layer.name == "mainfield":
for x, y, gid in layer.iter_data():
self.draw_tile(self.tmx_data, x, y, gid)
x, y = MATRIX_POS
for i in range(-1, MATRIX_SIZE[0]):
for j in range(MATRIX_SIZE[1]):
self.draw_tile(self.mino_block, x+j, y+i, self.matrix[i][j])
pygame.display.flip()
clock.tick(60)
pygame.quit()
if __name__ == "__main__":
game = Game()
game.run()
無事にテトリミノを配置できているようだ。
まとめ
- ブロックを配置したマップから、各種テトリミノを定義した
- 定義したテトリミノをフィールドに配置してみた