2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tkinterでフィールドマップをつくる

Last updated at Posted at 2024-03-01

はじめに

image.png

Tkinterで、フィールマップをマップチップを用いて作成する方法について解説します。

マップチップとは

マップチップとは、ドット絵で画像を作成する際、画像サイズの小さい最小単位の部品をパズルのように組み合わせて画像を製作する手法、またその最小単位の部品のこと。

容量が今のゲームよりもはるかに少なかった2Dゲームの時代、いかに少ないファイルサイズで効率よく街やフィールドのマップを作るかということに苦心していた頃に使われていた手法であり、ハードの進歩により必須となる局面は減ったとはいえ今でも現役の手法であり、特に2Dの自作ゲームを製作する際に重要なテクニックとして重用されている。

ファミコンなどの旧時代のグラフィック画像を例に見ると、樹木やレンガ、海の波の模様や屋根瓦といった背景の模様などを1マスの小さな単位として扱い、一定の規則に従った配列の繰り返しで構成することで描画していることがよくわかる。
(ピクシブ百科事典より)

なぜマップチップを使うのか

マップを効率的に開発できる
特に大きなゲームの場合、大量のマップが必要になります。マップを一枚の画像にしたものを何十枚用意するより、マップチップを使いまわす方が効率的に開発できます。
容量を削減できる
マップチップを使用することで、同じチップを繰り返し利用することができるので、容量の削減につながります。
一貫性を確保できる
マップチップを使用することで、ゲーム内のグラフィックスやデザインの一貫性を保つことができます。同じセットのチップを使用することで、ゲーム内のすべての場所が統一感を持ち、プレイヤーの没入感が向上します。
修正が容易である
マップチップを使用することで、マップを修正したり拡張したりするのが容易になります。単一のチップを修正することで、ゲーム内の複数の場所に変更が反映されます。

作ってみる

画像を表示する

Tkinterで画像を表示するには、create_imageメゾットを使用します。

canvas.create_image(x, y, anchor, image)
変数名 説明 デフォルト値 備考
x 画像の位置 (X座標) int 0 基準点の座標
y 画像の位置 (Y座標) int 0 基準点の座標
anchor 画像の基準点 str "center" "center", "nw", "n", "ne", "e", "se", "s", "sw", "w" から選択
image 表示する画像 PhotoImage None PhotoImage オブジェクト

以下のサイトに詳しく説明があります。

imageにはPhotoImage オブジェクトを指定する必要があります。PhotoImage オブジェクトは以下で作成できます。

img = tk.PhotoImage(file=xxx.png)

ファイルを直接指定するだけではないことに注意してください。

サンプルコード

画像を表示するサンプルコード
import tkinter as tk

# ウィンドウの作成
root = tk.Tk()
root.title("画像を表示するサンプルコード")

# 画像の読み込み
image_path = "picture.png"
img = tk.PhotoImage(file=image_path)

# キャンバスの作成
canvas = tk.Canvas(root, width=img.width(), height=img.height())
canvas.pack()

# 画像をキャンバスに表示
canvas.create_image(0, 0, anchor=tk.NW, image=img)

# ウィンドウの表示
root.mainloop()

pytonファイルと同じフォルダ内picture.pngという名前の画像を置いてください。名前が一致していればなんでも良いですが、今回は以下の画像を使用しました。
picture.png

実行結果

image.png

画像を拡大して表示する

あまりにも小さいのでこの画像を拡大して表示してみます。整数倍の拡大であれば簡単にできます。

img = img.zoom(x, y)
変数名 説明 備考
x x方向の拡大率 int
y y方向の拡大率 int 未指定の場合はxと同じ値になる

逆に縮小したい場合はimg.subsample()を利用すると整数倍で縮小できます。

サンプルコード

画像を拡大表示するサンプルコード
import tkinter as tk

# ウィンドウの作成
root = tk.Tk()
root.title("画像を拡大表示するサンプルコード")

# 画像の読み込み
image_path = "picture.png"
img = tk.PhotoImage(file=image_path)
# 画像を4倍に拡大する
img = img.zoom(4)

# キャンバスの作成
canvas = tk.Canvas(root, width=img.width(), height=img.height())
canvas.pack()

# 画像をキャンバスに表示
canvas.create_image(0, 0, anchor=tk.NW, image=img)

# ウィンドウの表示
root.mainloop()

実行結果

image.png

一枚の画像から切り取って表示する

以下のタイルセット(マップチップを1枚のシートにしたもの)から、欲しい部分を切り取って表示します。ファイル名はmapchip.pngとしています。
mapchip.png

画像の切り取りにはPillow(PIL)が必要です。コマンドプロンプトで以下のコマンドを入力してインストールしてください。

$ pip install Pillow

cropメゾットを使用することで画像を切り取って表示できます。

img = img.crop((left, top, right, bottom))
変数名 説明
left 切り取る領域の左端の座標 int
top 切り取る領域の上端の座標 int
right 切り取る領域の右端の座標 int
bottom 切り取る領域の下端の座標 int

img.crop(left, top, right, bottom)ではなくimg.crop((left, top, right, bottom))であることに注意してください。あくまで4要素のタプルを1つ与えています。

サンプルコード

画像を切り取って表示するサンプルコード
import tkinter as tk
from PIL import Image, ImageTk

# 定数
MAGNIFICATION = 16 #拡大率
CHIP_WIDTH = 16 #マップチップの幅
CHIP_HEIGHT = 16 #マップチップの高さ

# ウィンドウの作成
root = tk.Tk()
root.title("画像を切り取り表示するサンプルコード")

# 画像の読み込み
image_path = "mapchip.png"
img = Image.open(image_path)

# 画像のサイズを取得
img_width = img.width
img_height = img.height

# 画像の拡大
img = img.resize((img_width * MAGNIFICATION, img_height * MAGNIFICATION))

# 画像のサイズを再取得
img_width = img.width
img_height = img.height

# 画像を切り取って表示(今回は左から2番目)
i = 2 # 左から何番目
j = 1 # 上から何番目
chip = img.crop((CHIP_WIDTH * MAGNIFICATION * (i - 1), CHIP_HEIGHT * MAGNIFICATION * (j - 1), CHIP_WIDTH * MAGNIFICATION * i, CHIP_HEIGHT * MAGNIFICATION * j))
chip = ImageTk.PhotoImage(chip)

# キャンバスの作成
canvas = tk.Canvas(root, width=chip.width(), height=chip.height())
canvas.pack()

# 画像をキャンバスに表示
canvas.create_image(0, 0, anchor=tk.NW, image=chip)

# ウィンドウの表示
root.mainloop()

実行結果

image.png

マップを表示する

以上を組み合わせてマップを表示する簡単なプログラムを作成しました。

サンプルコード

マップを表示するサンプルコード
import tkinter as tk
from PIL import Image, ImageTk

# 定数
MAGNIFICATION = 4 #拡大率
CHIP_WIDTH = 16 #マップチップの幅
CHIP_HEIGHT = 16 #マップチップの高さ

# マップ
MAP = [
    [3,3,3,3,3,3],
    [3,3,4,4,3,3],
    [3,4,1,1,1,3],
    [3,4,1,1,1,3],
    [3,3,3,4,3,3],
    [3,3,3,3,3,3],
]

# マップの要素数
MAP_WIDTH = len(MAP[0])
MAP_HEIGHT = len(MAP)

# ウィンドウの作成
root = tk.Tk()
root.title("マップを表示するサンプルコード")

# 画像の読み込み
image_path = "mapchip.png"
img = Image.open(image_path)

# 画像のサイズを取得
img_width = img.width
img_height = img.height

# 画像の拡大
img = img.resize((img_width * MAGNIFICATION, img_height * MAGNIFICATION))

# 画像のサイズを再取得
img_width = img.width
img_height = img.height

#画像にマップチップが縦横何枚あるかを取得
img_width_in_chips = img_width // (CHIP_WIDTH * MAGNIFICATION)
img_height_in_chips = img_height // (CHIP_HEIGHT * MAGNIFICATION)

# 画像を切り取って配列に格納
chips = [ImageTk.PhotoImage(img.crop((CHIP_WIDTH * MAGNIFICATION * (i % img_width_in_chips), CHIP_HEIGHT * MAGNIFICATION * (i // img_width_in_chips), CHIP_WIDTH * MAGNIFICATION * (i % img_width_in_chips + 1), CHIP_HEIGHT * MAGNIFICATION * ((i // img_width_in_chips) + 1)))) for i in range(img_width_in_chips * img_height_in_chips)]


# キャンバスの作成
canvas = tk.Canvas(root, width=CHIP_WIDTH * MAGNIFICATION * MAP_WIDTH, height=CHIP_WIDTH * MAGNIFICATION * MAP_HEIGHT)
canvas.pack()

# マップをキャンバスに表示
for i in range(MAP_HEIGHT):
    for j in range(MAP_WIDTH):
        canvas.create_image(CHIP_WIDTH * MAGNIFICATION * j, CHIP_HEIGHT * MAGNIFICATION * i, anchor=tk.NW, image=chips[MAP[i][j]])

# ウィンドウの表示
root.mainloop()

実行結果

image.png

まとめ

Tkinterでフィールドマップを表示する方法について解説しました。PILを用いて画像を切り取り、並べて配置することでマップを表示できました。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?