Python プログラムで動かすフェアリーチェスアプリ開発、連載第 7 回です。
で駒を乗せるための盤面が準備できました。今回は、盤面に配置する駒の画像を準備して読み込んで画面に表示していきたいと思います。
画像を準備
こちらの画像を使わせていただいています。
→ Clker-Free-Vector-ImagesによるPixabayからの画像
こちらをダウンロードして、画像編集ソフト(私は GIMP を使っています)で各 100x100 のサイズのものを白黒合わせて 12 枚作りました。
画像の名前は、例えば白のクイーンなら WQ.png、黒のナイトなら BN.png というように、
色と棋譜における駒を表す記号をもとにしています。
当初この画像ファイルは、メインのプログラムと同一階層に新たなフォルダをつくってその下に配置していました。
▼ chess├─ main.py├─ pieces.py├▼ img│├─ BB.png│├─ ...│└─ WR.png
今はコードが増えたので、 Python ファイルをまとめるフォルダを作り、次のような構成になっています。
▼ chess├▼ codes│├─ main.py│└─ pieces.py├▼ img│├▼ B││├─ BB.png││├─ ...││└─ BR.png│├▼ W││├─ WB.png...
ここでは後者の構成に基づいてコードを書いていきます。
画像の読み込みと設定
を使って画像を処理します。
pip でインストールします。
pip install Pillow
テクスチャの設定
ところで、画像の表示にはテクスチャマッピングというものを使っています。
テクスチャとは画像を貼り付ける板みたいなもので、板の角の座標と画像の角の座標を対応させることで、
板を移動させたり回転させたりしても画像が動いているように見えるという感じですね。
それでテクスチャの設定が必要なのですが、正直言って何をやっているかよくわかっていません。笑
こちらの記事とか読むとなんとなくわかるかも。
utils.py1from PIL import Image2...345def set_img(name, path, imgID):6'''画像の設定: name.pngを読み込む78Parameters9----------10name : str11画像のファイル名.12path : str > 'W', 'B'13画像があるフォルダ名.14imgID : int15指定する画像ID.16'''17img = Image.open(f'../img/{path}/{name}.png') # 画像を読み込む18w, h = img.size # 画像の横幅、縦幅19glBindTexture(GL_TEXTURE_2D, imgID) # imgID のテクスチャを有効化する20# 画像とテクスチャを関連づける21glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,22GL_RGBA, GL_UNSIGNED_BYTE, img.tobytes())23# テクスチャの設定24glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)25glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)262728def draw_img(x, y, imgID):29'''画像を描画する3031Parameters32----------33x, y : float34描画する座標.35imgID : int36画像ID.37'''38glPushMatrix() # 変形範囲の開始39glBindTexture(GL_TEXTURE_2D, imgID) # imgID のテクスチャを有効化する40glTranslate(x, y, 0) # 平行移動41glColor(1, 1, 1) # 色指定4243# テクスチャ座標を指定する44glBegin(GL_QUADS)45glTexCoord(0.0, 1.0)46glVertex(-1.0 / 2, -1.0 / 2)47glTexCoord(1.0, 1.0)48glVertex(1.0 / 2, -1.0 / 2)49glTexCoord(1.0, 0.0)50glVertex(1.0 / 2, 1.0 / 2)51glTexCoord(0.0, 0.0)52glVertex(-1.0 / 2, 1.0 / 2)53glEnd()5455glPopMatrix() # 変形範囲の終了565758def draw_pieces(gameboard, imgID_dict, size=8):59'''駒を描画する6061Parematers62----------63gameboard : dict > {(int, int): obj, ...}64盤面.65imgID : int66画像ID.67size : int, default 868盤面の大きさ.69'''70glEnable(GL_TEXTURE_2D) # テクスチャマッピングを有効化71for i in range(size):72for j in range(size):73piece = gameboard.get((i, j)) # (i, j)にある駒オブジェクトを取得74if piece:75draw_img(i, j, imgID_dict[piece.name])76glDisable(GL_TEXTURE_2D) # テクスチャマッピングを無効化
テクスチャは整数の番号で管理されています。
glTexImage2D()
の最後の引数はimg.tobytes()
というふうに、バイトに変換しなければならないようです。
imgID_dict
は{'WN': 1, 'WR': 2, ...}
みたいな感じの
pieces.py1class Knight(Piece):2abbr = 'N'3def availableMoves(self, x, y, gameboard, Color=None):4...56class Rook(Piece):7abbr = 'R'8def availableMoves(self, x, y, gameboard, Color=None):9...10...1112piece_names = [Knight, Rook, Bishop, Queen, King, Pawn]1314# 画像IDの割り当て15piece_ID = {}16for i, piece in enumerate(piece_names):17piece_ID['W' + piece.abbr] = i + 118piece_ID['B' + piece.abbr] = -(i + 1)
元のコードのuniDict
は、あとからまとめて指定している感じですが、
これから駒が増えていくのに備えて、各駒のクラス内で駒を表す新たな
(`abbr`)を定義しました。uniDict
を使わなくなったので、関係各所で調整を入れつつ、
画像関連の処理も入れ込みます。
main.py1def placePieces(self):2for i in range(0, 8):3self.gameboard[(i, 1)] = Pawn(WHITE, uniDict[WHITE][Pawn], 1)4self.gameboard[(i, 6)] = Pawn(BLACK, uniDict[BLACK][Pawn], -1)5self.gameboard[(i, 1)] = Pawn(WHITE, 'WP', 1)6self.gameboard[(i, 6)] = Pawn(BLACK, 'BP', -1)78placers = [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook]910for i in range(0, 8):11self.gameboard[(i, 0)] = placers[i](WHITE,uniDict[WHITE][placers[i]])12self.gameboard[(i, 7)] = placers[i](BLACK,uniDict[BLACK][placers[i]])13self.gameboard[(i, 0)] = placers[i](WHITE, 'W' + placers[i].abbr)14self.gameboard[(i, 7)] = placers[i](BLACK, 'B' + placers[i].abbr)15...1617def draw(self):18...19draw_pieces(self.gameboard, piece_ID)20...21...2223def glmain(self):24...25# 画像の設定26for name, num in piece_ID.items():27set_img(name, name[0], num)2829glutMainLoop()
これでいったん表示させてみます。
おっと、透過の設定をしなければいけませんね。
透過の設定
一応画像は透過情報も入っているのですが、 OpenGL に透過情報を含めて描画してもらう必要があります。
main.py1def draw(self):2'''描画コールバック'''3glClearColor(0.6, 0.4, 0.2, 1.0)4glClear(GL_COLOR_BUFFER_BIT)5glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # 混合処理の演算方法を指定6glEnable(GL_BLEND) # 混合処理を有効化7...8draw_pieces(self.gameboard, piece_ID)9glDisable(GL_BLEND) # 混合処理を無効化10glutSwapBuffers()
問題なく表示できました!
これで表示はできたわけですが、まだ駒を動かすことができません。
はマウス操作で駒を動かせるようにしたいと思います。この記事がお役に立てたならうれしいです
それでは~