0
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

テトリス風落ち物パズルを作る part02 ミノ配置

Last updated at Posted at 2024-06-12

前回ではフィールドの表示を行った、
今回はテトリミノを配置してみる。

Tiled で編集

前回のようにTiledでデータを作っていく

image.png

出来上がったファイル

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()


実行してみた結果はこんな感じ
image.png

無事にテトリミノを配置できているようだ。

まとめ

  • ブロックを配置したマップから、各種テトリミノを定義した
  • 定義したテトリミノをフィールドに配置してみた

次回:テトリス風落ち物パズルを作る part03 キー入力・落下処理 #Python - Qiita

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0