このページでは、Python で tkinter を利用した簡単な「横スクロールアクションゲーム」の作り方を解説していきます。
このページは「横スクロールアクションゲームの作り方の解説」の2ページ目となります。
1ページ目は下記ページとなり、1ページ目では作成していくゲームの紹介やクラスの構成等の解説を行なっていますので、まだお読みで無い方は事前に下記ページを読んでいただくことをオススメします。
【Python/tkinter】横スクロールアクションゲームを作る(イントロダクション)また、このページでは上記ページの スクリプトの大枠 で紹介したスクリプトを変更していくことで、主に ウィジェットの作成 と ゲームの背景の表示 の2つを行っていきます。ですので、事前準備としてそのスクリプトを自身の開発環境にコピペしておく必要がありますのでご注意ください。
Contents
ウィジェットの作成
では、まずはウィジェットの作成を行なっていきたいと思います。
このウィジェットの作成機能は、Screen
クラスの createWidgets
メソッドに実装していきます。
作成するウィジェット
今回作成するウィジェットは下記の2つになります。
- キャンバス
- スクロールバー
このページではゲームを作成する上で必要な事のみを解説していきますが、キャンバスに関しては下記ページで、
Tkinterの使い方:キャンバスウィジェットの作り方 Tkinterの使い方:Canvasクラスで図形を描画する Tkinterの使い方:Canvasクラスで描画した図形を操作するスクロールバーに関しては下記ページで詳しく解説していますので、これらのウィジェットについて詳しく知りたい方は別途これらのページを参照していただければと思います。
Tkinterの使い方:スクロールバー(Scrollbar)の使い方スポンサーリンク
Screen
クラスのオブジェクトの生成
キャンバスおよびスクロールバーは「ゲームの画面を表示するためのウィジェット」になりますので、Screen
クラスにこれらのウィジェットを作成させるようにしていきたいと思います。
まずは、その Screen
クラスのオブジェクトを生成するようにしていきます。
Screen
クラスの枠組みだけは既に用意していますので、あとは Game
クラスから Screen
クラスのコンストラクタを実行させるようにすれば、Screen
クラスのオブジェクトの生成は完了します。
具体的には、Game
クラスの __init__
を下記のように変更します。
class Game:
def __init__(self, master):
self.master = master
# ↓これを追加
self.screen = Screen(self.master)
# ↑これを追加
引数の master
はアプリのメインウィンドウとなるウィジェットになります。以降では、この master
上にキャンバスを作成していきます。
キャンバスの作成と配置
続いてキャンバスの作成と配置を行うように Screen
クラスを実装していきます。
キャンバス作成時に必要なパラメータ
キャンバスは tkinter.Canvas
クラスのコンストラクタを実行することで作成できます。今回のような横スクロールゲームを作成する上では、コンストラクタの引数として最低限下記が必要になります。
- 第1引数:親ウィジェット
width
:キャンバスの幅height
:キャンバスの高さscrollregion
:スクロール可能な領域を示す矩形の座標のタプル
特に scrollregion
の詳細については下記ページで解説していますので、詳しく知りたい方は別途下記ページを参照していただければと思います。このページでは必要部分に絞って解説していきます。
上記で指定する width
、height
、scrollregion
の位置関係を図示すると下図のようになります。
要はゲームの本来の画面のサイズは scrollregion
で指定する矩形分となるのですが、表示される領域のサイズがキャンバスのサイズ、すなわち width
と height
の分のみとなります。
今回は横スクロールのゲームになりますので、縦方向にはスクロールは行いません。また、ゲーム開始時点では画面の左端を表示するようにしたいと思います。
この場合、下の図のように scrollregion
には (0, 0, ゲームの画面の幅, height)
を指定すれば良いことになります(下の図の e
が ゲームの画面の幅
となります)。
従って、結局キャンバスを作成する際には、width
と height
および ゲームの画面の幅
のみを決めれば、後の座標は自然と決まることになります。
width
と height
に関しては、あなたご自身の PC の画面のサイズ等を考慮して設定していただければ良いですし、ゲームの画面の幅
に関しては作りたいゲームに合わせて設定すれば良いです。
とりあえずこのページでは、これらのパラメータを下記のように設定してゲームの作成を進めていきたいと思います。
width
:600
height
:400
ゲームの画面の幅
:1500
また、これらの値は後からも参照できるように、Screen
クラスのデータ属性として保持するようにしておきたいと思います。
このために、Screen
クラスの __init__
を下記のように変更します。
class Screen:
def __init__(self, master):
self.master = master
# ↓これを追加
self.view_width = 600
self.view_height = 400
self.game_width = 1500
self.game_height = self.view_height
# ↑これを追加
後から参照しやすいよう、値は view_height
と同じではありますが、データ属性 game_height
も追加しています。
この view_width
と view_height
が表示領域の幅と高さとなり、さらに game_width
と game_height
がゲーム画面の幅と高さとなります。
キャンバスの作成と配置の処理の実装
次は実際にキャンバスの作成と配置の処理を実装していきます。
下記のように Screen
クラスに createWidgets
メソッドを追加し、このメソッドの中で tkinter.Canvas
のコンストラクタの実行処理を記述します。この時、上記で挙げた引数 width
、height
、scrollregion
を指定するようにします。
class Screen:
# ↓これを追加
def createWidgets(self):
self.canvas = tkinter.Canvas(
self.master,
width=self.view_width,
height=self.view_height,
scrollregion= (
0,0,self.game_width,self.game_height
),
highlightthickness=0
)
self.canvas.grid(column=0, row=0)
# ↑これを追加
tkinter.Canvas
のオブジェクトも今後何度も利用するので、tkinter.Canvas
の返却値をデータ属性 self.canvas
に参照させるようにしています。
また、highlightthickness=0
を指定するようにしているのは、キャンバスの図形の位置のズレを解消するためです。詳細は下記ページで解説していますので詳しく知りたい方はこちらを参照していただければと思います。
また、上記の最後に実行している grid
メソッドは、作成したキャンバスを self.master
上(メインウィンドウ上)に配置するための処理になります。これを実行しないと画面上にキャンバスが表示されないので注意してください。
こういった配置を行うメソッドについては下記ページで解説していますので、詳しく知りたい方は別途参照していただければと思います。
Tkinterの使い方:ウィジェットの配置(pack・grid・place)キャンバスの作成と配置の実行
続いては、先程作成した createWidgets
を実行するようにしていきたいと思います。Game
クラスから実行されるようにしても良いのですが、今回は Screen
クラスの __init__
の最後で実行するようにしたいと思います。
具体的には、Screen
クラスの __init__
を下記のように変更します。
class Screen:
def __init__(self, master):
self.master = master
self.view_width = 600
self.view_height = 400
self.game_width = 1500
self.game_height = self.view_height
# ↓これを追加
self.createWidgets()
# ↑これを追加
これにより、Screen
クラスのオブジェクト生成時に createWidgets
メソッドが実行され、キャンバスが作成されるようになります。
変更後のスクリプトを実行すれば、下の図のようなアプリが起動するようになると思います。
といってもキャンバスが真っ白なのでアプリの画面も真っ白です…。ですが、ここまで説明してきた変更を行なっていれば、ゲームの画面を表示させるためのキャンバスの作成自体は行えているはずです。
スクロールバーの作成と配置
次はスクロールバーの作成と配置を行なっていきます。
スクロールバー付きのキャンバスの作り方については下記ページで解説していますので、このページでは詳細な解説は省略させていただこうと思います。
Tkinterの使い方:スクロールバー(Scrollbar)の使い方ただし、上記ページではキャンバスを縦スクロールも横スクロールも行えるようにしていますが、今回は横スクロールのみを行うため、水平方向のスクロールバーのみを作成していきます。
具体的には、先程作成した Screen
クラスの createWidgets
メソッドの後半を下記のように変更します。これにより、スクロールバーの作成と配置およびキャンバスとの連動を行うことができます。
class Screen:
def createWidgets(self):
# 略
self.canvas.grid(column=0, row=0)
# ↓これを追加
xbar = tkinter.Scrollbar(
self.master,
orient=tkinter.HORIZONTAL,
)
xbar.grid(
row=1, column=0,
sticky=tkinter.W + tkinter.E
)
xbar.config(
command=self.canvas.xview
)
self.canvas.config(
xscrollcommand=xbar.set
)
# ↑これを追加
各処理の内容については先程紹介したページで解説していますので、必要に応じて参照していただければと思います。
上記のように createWidgets
メソッドを変更することで、スクリプトを実行すると今度は下の図のようにスクロールバー付きのキャンバスが表示されるようになります。
スクロールバーのスライダーもマウス操作で動かすことも確認できると思いますが、まだキャンバスが真っ白なのでスクロールしていることは実感できないと思います。ですが、次に行うキャンバスへの背景の描画により、画面がスクロールすることを実感できるようになります。
スポンサーリンク
ゲームの背景の表示
次は、Screen
クラスに drawBackground
メソッドを作成することで、背景の表示機能を実現していきます。
背景画像の準備
今回はゲームの背景としては画像を使用したいと思います。つまりキャンバスに画像の描画を行うことでゲームの背景の表示を行ないます。
このためには、まずは描画する背景画像を準備する必要があります。
背景画像なんでも良いのですが、このページでは いらすとや の下記 URL の画像を背景画像として利用していきたいと思います。
http://www.irasutoya.com/2016/01/blog-post_135.html
下の図は上記 URL の画像を転載させていただいたものになります。爽やかな素敵な画像ですね!
転載元:いらすとや
特にゲームの背景として使用したい画像がないのであれば、上の画像を適当なフォルダに保存しておいてください。画像を読み込む際には、この画像を保存した先のファイルパスを指定する必要がありますので、メモしておくと良いと思います。
背景画像の拡大縮小
画像ファイルが準備できれば、あとは背景画像をキャンバスに描画してやれば良いのですが、背景画像とゲーム画面のサイズが合わない場合、余白ができることになってしまいます。
そのため、ゲーム画面のサイズ(scrollregion
で指定した矩形のサイズ)いっぱいに画像を描画ができるよう、事前に拡大縮小を行なってからキャンバスに画像を描画していきたいと思います。
背景画像の拡大縮小の仕方
このページでは単純に、ゲーム画面のサイズに合わせて画像を拡大縮小するようにしたいと思います。
ただし、単純にゲーム画面のサイズに合わせて画像を拡大縮小してしまった場合、背景画像の縦横比が変わってしまって見栄えが悪くなる可能性があるので注意してください。
極端な例を示すと、下の図のように背景画像が横になが〜く拡大縮小される場合があります。
もし画像の縦横比が変わってしまうことが気になる場合、下記ページで画像の縦横比を保ったまま画像の拡大縮小を行い、さらにそれを横方向に何枚も並べることで綺麗に背景を表示する方法の解説を行なっていますので、こちらを参考にしていただければと思います。
【Python/tkinter】横スクロールアクションゲームを作る(カスタマイズ例)背景画像の拡大縮小処理の実装
さて、背景画像の拡大縮小ですが、これは PIL の resize
メソッドにより行うことができます。
この resize
メソッドは、PIL 用の画像オブジェクトからしか実行できないため、まずは PIL の open
関数を利用して背景画像の読み込み& PIL 用の画像オブジェクトの生成を行い、それから resize
メソッドを実行します。
resize
メソッドの引数にはゲーム画面の幅と高さをタプルで指定します。
これによりゲーム画面のサイズに合わせた拡大縮小後の画像を取得できるのですが、PIL 用の画像オブジェクトはキャンバスに描画できません。
そのため、この画像オブジェクトを tkinter 用の画像オブジェクトに変換する必要があります。この変換については下記ページで解説しているので詳しく知りたい方はぜひ読んでいただきたいのですが、結論としては PIL の ImageTk.PhotoImage
クラスのコンストラクタを実行することにより、この変換を実現することができます。
まずはここまで解説した内容の処理を行うメソッドを作成していきましょう。具体的には、Screen
クラスに下記の drawBackground
メソッドを追加します。
class Screen:
# ↓これを追加
def drawBackground(self):
image = Image.open("bg_natural_sougen.jpeg")
size = (self.game_width, self.game_height)
resized_image = image.resize(size)
self.bg_image = ImageTk.PhotoImage(resized_image)
# ↑これを追加
Image.open
関数の引数には、読み込みたい背景画像のファイルパスを指定する必要があります。上記では "bg_natural_sougen.jpeg"
を指定していますが、ご自身が用意した背景画像のファイルパスに応じて変更してください。
また、game_width
と game_height
は キャンバス作成時に必要なパラメータ で追加したデータ属性であり、それぞれゲーム画面の幅と高さを示す値です。これを resize
メソッドの引数に指定していますので、ゲーム画面のサイズに合わせて背景画像が拡大縮小されることになります。
上記の drawBackground
メソッドが実行されれば、データ属性 bg_image
が拡大縮小後の背景画像を参照することになりますので、あとはこの bg_image
をキャンバスに描画すれば背景画像が表示されるようになります。
スポンサーリンク
背景画像の描画
キャンバスへの画像の描画は、tkinter.Canvas
クラスの create_image
メソッドの実行により行うことができます。
描画したい画像は create_image
メソッドのオプション image
で指定します。今回はデータ属性 bg_image
の画像を描画したいので、オプション image=self.bg_image
を指定して create_image
メソッドを実行することになります(image
オプションには tkinter 用の画像オブジェクトを指定する必要があります)。
ということで、先程作成した drawBackground
メソッドの後半でキャンバスの画像の描画を行うようにしていきましょう。具体的には drawBackground
メソッドを下記のように変更します。
class Screen:
def drawBackground(self):
# 略
self.bg_image = ImageTk.PhotoImage(resized_image)
# ↓これを追加
self.canvas.create_image(
0, 0,
anchor=tkinter.NW,
image=self.bg_image
)
# ↑これを追加
上記では、self.canvas
のキャンバスに対して bg_image
の画像の描画を行なっています。anchor
に tkinter.NW
を指定していますので、画像の左上がキャンバスの (0
, 0
) 座標、つまりキャンバスの左上に合わさるように画像が描画されます。
anchor
等の各引数・オプション等の意味は下記ページで解説していますので、詳しく知りたい方は下記ページを参照していただければと思います。
以上により、ゲームの背景の表示を行う drawBackground
メソッドは完成です。
あとは、drawBackground
メソッドを実行するように Screen
クラスの __init__
の最後に下記を追記してやれば、Screen
クラスのオブジェクト生成時に自動的にゲームの背景表示まで行われるようになります。
class Screen:
def __init__(self, master):
# 略
self.createWidgets()
# ↓これを追加
self.drawBackground()
# ↑これを追加
以上の変更を行なった後にスクリプトを起動すれば、下の図のようなアプリが起動するはずです。
背景画像が表示されていること、および、スクロールバーのスライダーの左右への移動に伴って、その背景の表示領域が変化していくことも確認できると思います。
このページで作成したスクリプト
以上で、このページの解説は終了です。
最後に、ここまでの解説を踏まえて作成したスクリプトの全体を下記に掲載しておきます。次のページではこのスクリプトをベースに解説を進めていきたいと思います。
import tkinter
from PIL import Image, ImageTk, ImageOps
import random
# アプリの設定
VIEW_WIDTH = 600
VIEW_HEIGHT = 400
GAME_WIDTH = 1500
BG_IMAGE_PATH = "bg_natural_sougen.jpeg"
class Character:
def __init__(self):
pass
class Player(Character):
def __init__(self):
pass
class Enemy(Character):
def __init__(self):
pass
class CatEnemy(Enemy):
def __init__(self):
pass
class DogEnemy(Enemy):
def __init__(self):
pass
class Goal(Character):
def __init__(self):
pass
class Screen:
def __init__(self, master):
self.master = master
self.view_width = VIEW_WIDTH
self.view_height = VIEW_HEIGHT
self.game_width = GAME_WIDTH
self.game_height = self.view_height
self.createWidgets()
self.drawBackground()
def createWidgets(self):
self.canvas = tkinter.Canvas(
self.master,
width=self.view_width,
height=self.view_height,
scrollregion= (
0,0,self.game_width,self.game_height
),
highlightthickness=0
)
self.canvas.grid(column=0, row=0)
xbar = tkinter.Scrollbar(
self.master,
orient=tkinter.HORIZONTAL,
)
xbar.grid(
row=1, column=0,
sticky=tkinter.W + tkinter.E
)
xbar.config(
command=self.canvas.xview
)
self.canvas.config(
xscrollcommand=xbar.set
)
def drawBackground(self):
image = Image.open(BG_IMAGE_PATH)
size = (self.game_width, self.game_height)
resized_image = image.resize(size)
self.bg_image = ImageTk.PhotoImage(resized_image)
self.canvas.create_image(
0, 0,
anchor=tkinter.NW,
image=self.bg_image
)
class Game:
def __init__(self, master):
self.master = master
self.screen = Screen(self.master)
def main():
app = tkinter.Tk()
game = Game(app)
app.mainloop()
if __name__ == "__main__":
main()
基本的には、ここまで紹介してきたスクリプトと同じなのですが、キャンバスの画面のサイズや背景画像のファイルパスに関してはグローバル変数として定義するようにしています。これは、後から変更しやすい&他のクラスからも参照できるようにするためです。
各グローバル変数の意味合いは下記のようになります。
VIEW_WIDTH
:表示領域の幅(ピクセル数)VIEW_HEIGHT
:表示領域の高さ(ピクセル数)GAME_WIDTH
:ゲーム画面の幅(ピクセル数)BG_IMAGE_PATH
:ゲームの背景となる画像のファイルパス
もし、ここまでの解説の中でこれらを自身の環境に合わせて変更された方は、こちらの定義値も変更しておく必要があるので注意してください。
まとめ
このページでは、横スクロールアクションゲームを作成するにあたって、まずウィジェットの作成とゲームの背景の表示を行いました。
正直まだ全くゲームを作っている感じがしないと思いますが、今回作成したキャンバス上にキャラクターの画像を描画することでゲームを作っていくことになりますので、その土台が出来上がったと考えて良いと思います。
また、tkinter でキャンバスへの画像の描画は様々なアプリ開発で役に立つと思いますので、画像を描画する流れは覚えておくと良いと思います!
次のページでは、キャラクターのクラスを作成し、さらに今回作成したキャンバスを利用してキャラクターの画面上への表示を行なっていきます!
【Python/tkinter】横スクロールアクションゲームを作る(キャラクターの表示)オススメ参考書(PR)
簡単なアプリやゲームを作りながら Python について学びたいという方には、下記の Pythonでつくる ゲーム開発 入門講座 がオススメです!ちなみに私が Python を始めるときに最初に買った書籍です!
下記ようなゲームを作成しながら Python の基本が楽しく学べます!素材もダウンロードして利用できるため、作成したゲームの見た目にも満足できると思います。
- すごろく
- おみくじ
- 迷路ゲーム
- 落ち物パズル
- RPG
また本書籍は下記のような構成になっているため、Python 初心者でも内容を理解しやすいです。
- プログラミング・Python の基礎から解説
- 絵を用いた解説が豊富
- ライブラリの使い方から解説(tkitner と Pygame)
- ソースコードの1行1行に注釈
ゲーム開発は楽しくプログラミングを学べるだけでなく、ゲームで学んだことは他の分野のプログラミングにも活かせるものが多いですし(キーボードの入力受付のイベントや定期的な処理・画像や座標を扱い方等)、逆に他の分野のプログラミングで学んだ知識を活かしやすいことも特徴だと思います(例えばコンピュータの動作に機械学習を取り入れるなど)。
プログラミングを学ぶのにゲーム開発は相性抜群だと思います。
Python の基礎や tkinter・Pygame の使い方をご存知なのであれば、下記の 実践編 をいきなり読むのもアリです。
実践編 では「シューティングゲーム」や「アクションゲーム」「3D カーレース」等のより難易度の高いゲームを作りながらプログラミングの力をつけていくことができます!
また、単にゲームを作るのではなく、対戦相手となるコンピュータの動作のアルゴリズムにも興味のある方は下記の「Pythonで作って学べるゲームのアルゴリズム入門」がオススメです。
この本はゲームのコンピュータ(AI)の動作アルゴリズム(思考ルーチン)に対する入門解説本になります。例えばオセロゲームにおけるコンピュータが、どのような思考によって石を置く場所を決めているか等の基本的な知識を得ることが出来ます。
プログラミングを挫折せずに続けていくためには楽しさを味わいながら学習することが大事ですので、特にゲームに興味のある方は、この辺りの参考書と一緒に Python を学んでいくのがオススメです!