デッカチャン ブログ

R-1グランプリで優勝。「デッカチャン」ゲームの作り方解説

今回はこれです。

野田クリスタル

R-1ぐらんぷり2020優勝、野田クリスタルさんが開発した
「ブロックくずして」というゲームについて書いていきます。
デッカチャンを動かしてブロック崩しのボールを避けるという
常人には到底思い浮かばないこのゲームを今回は再現してみます。

いきなりこの狂気に満ち溢れるゲームを作るのは大変なので、
まずは、基礎となるブロック崩しがどのように作成さてているか
理解しましょう。

ここからの内容は「そのままのJavaScriptを使ったブロックくずしゲーム
をpythonのtkinterで書き直したものとなります。
クラス定義等の難しい概念は使われていないので、
プログラミング初心者の方でも内容を理解しやすいと思います。

それでは作成していきます。

1.デッカチャンゲーム画面の作成

まずはゲーム画面を作りましょう。
ゲーム画面は次のコードで作成できます。

ウインドウを作成する基本のテンプレートです。9行目を変更することで
ウインドウのサイズを変更することができます。
このコードを実行すると下の図ようになります。空白のゲーム画面ができました。

2.図形を書くためのキャンバスを作成する

ゲーム画面が作成できましたので、次はボールを表示していきましょう。
ゲーム画面にボールを表示するためには「キャンバス」という部品をウインドウに
追加します。
キャンバスの上には画像や、四角、丸などの図形を書くことができます。
今回はウインドウサイズと同じ大きさで白のキャンバスを設定しました。(15-17行目)
そして中心あたりに円を作成しています。(19-20行目)

実行すると次の様になります。

crate_ovalを使うことで円を書くことができます。
ウインドウには左上を0として、x軸とy軸が設定されています。
xとyを指定することでウィンドウの1点の座標を表すことができます。
create_ovalは2つの座標から得られる四角形の内円を描きます。
図にすると次の様なイメージです。
これで画面上にボールを書くことができました。
次はこのボールを動かしていきましょう。

 

3.デッカチャンゲームの作り方|パラパラ漫画方式でボールを動かす

ゲーム作成において、物体を動かす場合、パラパラ漫画の要領で動かしたい物を
少しづつずらしていきます。
実際のプログラムは次の様に書きます。

やや難しくなってきましたが、ポイントは2つです。

1. create_ovalで円の座標をずらしていく。(25-28行目)
2.root.after(50, game_loop)という部分でgame_loop()関数を定期的に呼び出す(29行目)

1の処理で円を右上に少しずらして描写することができますが、描写を一度しか実行しない場合は
ちょっと動いて止まったままになってしまいます。
そこで、ボールをずらすための処理を定期的に繰り返すために、afterという関数を用いて、
50ミリセカンドごとにgome_loop関数を呼び出しています。
この処理によって、繰り返しボールを描写し、動いている様に見せることができます。

実行してみましょう
・・・・・・・なんか違います。
このようになってしまう原因はボールを描写した軌道が次の描写時に
残ったままになってしまうからです。
円を表示する度に過去の円を消すようにしましょう。(26-27行目)

それでは実行結果を確認しましょう!

無事に左上に向かって動いていく様子が確認できたと思います。
ここからゲームに必要な要素を組み込んでいくのですが、このままだとコードは
複雑になってしまいますので一旦機能ごとに整理しましょう。

4.デッカチャンゲームの作り方|機能ごとに処理を分ける

前回のプログラムの内容は、円を描く機能と画面の更新機能を同時に
書いてしまったため、すこし見辛いコードになっています。
今回は、コードの見通しをよくするためと、今後の機能の追加がしやすい様に
それぞれを関数に分ます。

drawBall関数(35-42行目)とgame_loop関数(45-56行目)でそれぞれの機能を分ました。
また、円の直径をcircleWidth(16行目)、
移動する距離をdx, dy(18-20行目)とすることで円のサイズやボールのスピードの変更
に柔軟に対応できる様に変更しました。次はボールを壁に反射させてみましょう。

5.ボールを壁で反射させる

ボールを反射させる方法はシンプルです。
左右の壁にボールが衝突した場合はx軸の進む方向を反転させます。

上下の壁にボールが衝突した場合はy軸の進む方向を反転させます。

もし斜めに当たってもこの法則は変わりません

こんな感じです。
まとめると、上下の壁に衝突した場合はy方向に-1を掛ける、左右の壁に衝突した場合は
x方向に-1をかければOKです。(57-77行目)

実行してボールがウインドウ内で跳ね返ることが確認できればOKです!
次はボールを跳ね返すパドルを作成します。

6.デッカチャンゲームの作り方|ボールを跳ね返すパドルを作成する。

ボールの反射ができたので、次はボールを跳ね返す板、「パドル」を作成します。
パドルの形は単純な四角形で、create_rectangle関数で2点の座標を通る四角形を描写する
ことができます。内円を書くときに描く四角形がそのまま表示されるということですね。
四角を書くために必要な変数を定義している部分が(32-36行目)
実際にパドルとなる四角を表示する部分が(56-66行目)となります。

実行結果

パドルが無事に表示されました!
しかし、これでは何も動かないので、
パドルを動かす処理を書いていきましょう。

7.パドルを動かす

それでは先ほど書いたパドルを動かしていきます。
考え方はボールを動かしたときと同じです。
少しずつ動かしながら画面を切り替えれば、
パラパラ漫画のように動き出します。
ボールの時と違うのは

「キーを押した時にパドルを動かす」

ということです。
pythonではキーを押した時と離した時に特定の
関数を呼び出すことができます。これを利用して、
左矢印キーと右矢印キーが押された場合のみ
座標を変更できる様にします。
もちろん画面外にパドルが出ていってしまうことを防ぐため、
if文で画面の幅からはみ出す場合は、移動する処理を無効にする
制限を持たせます。

実際のプログラムでは以下のようになります。
左右のボタンを押したかどうかの判断結果を保存する変数の定義(38-41行目)
キーを押したときに呼び出される関数(63-81行目)
左右のキーに関数を割り当てる処理(83-87行目)
パドルの移動制限(98-106行)

次はゲームオーバーの作成です。

8.デッカチャンゲーム|ゲームオーバーの作成

通常のブロック崩しゲームはパドルでボールを捉えたときは反射させ、
受け止められなかったときにゲームオーバになります。
この機能は「ブロックくずして」には必要ないのですが、
確認のため、ゲームオーバーの機能をつけておきましょう。
内容は単純です。先ほどまで下の壁に当たった場合は反射させていましたが、
その部分をゲームオーバーに変更するだけです。
次はパドルの上にボタンが衝突した際の反射処理ですが、少し複雑です。
ボールの移動先にパドルが存在する場合はy方向の動きを反転すればOKなのですが、
パソコンは座標でしか判定できないため、座標でボールの位置とパドルの位置関係を
精査してあげる必要があります。(121-131行目)
この方法は後の壊されるブロックでも同じことをするので覚えておきましょう。

9.ブロックの作成

続いてブロック崩しのブロックを作成します。
ブロックはcreate_rectangleを使用して画面に表示していきますが、
数が多いため、リストを利用します。
各ブロックの座標をディクショナリの型で定義し、
繰り返し処理でブロックを表示していきます。

プログラムでは下記の位置にコードを追加しています。
ブロックを作成するのに利用する変数の定義(43-60行目)
繰り返し処理でブロックを画面上に表示する処理(92-109行目)

実行してみると次のようになります。
ボールがブロックを貫通していきます。
上で追加した処理はブロックを表示しているだけなので、当然です!
次はブロックにぶつかったらブロックを消して反射させてみましょう。

10.ブロックとボールが衝突したときの処理

ボールがブロックと衝突して反射する処理はボールがパドルに衝突した時の処理と同じです。
パドルとブロックで異なる部分は、ブロックはボールがぶつかったら「消える」ということです。
「消える」ということは、「非表示にする」ということで対応できるため、ボールがブロックと
衝突した場合は非表示にできる様にプログラムを修正します。

ちょっと難しいですが、ブロックを作成する際に、
各ブロックに初期値1のstatusという変数を持たせてます。(59行目)
そして、ブロックとボールが衝突した際にstatusを0にしています。(105-112行目)
drawBlock関数ではif文を用いてstatusが1のブロックのみ表示する様に
処理をしているのでブロックが消えたように見せることができます。(115-126行目)
次はスコアの追加です。

11.デッカチャンゲームの作り方|スコア表示

スコアはブロックを消したときに追加される様にします。
16-17行目:スコアの変数を追加します。
74-77行目:スコアを表示するための関数drawScoreを定義します
117行目:ブロックとボールが衝突した場合スコアを10増やします

これは簡単ですね!
ここまでが基礎的なブロック崩しの作成方法です。
続いて「ブロックくずして」の要素を入れていきます。

12.「ブロックくずして」に必要な物

それでは「ブロックくずして」に必要なものを追加していきます。

12-1.パドルがボールを自動的に追いかける処理

これは単純です、ブロック崩しではパドルを左右のキーで動かしていましたが
「ブロックくずして」パドルは自動でボールを追従する必要があるため、
ボールのx座標とパドルのx座標を同期させてしまえばOKです!
下記プログラム(307-308行目)

12-2.デッカチャンの顔を動かす

パドルの代わりにデッカチャンの顔を動かすので、パドルの処理を
デッカチャンに当てはめればOKなのですが、左右だけでなく、上下にも
動かさなければならないため、y軸方向の処理を追加します。
下記プログラム(86-90, 67-77, 130-132, 234-241, 261-304行目)

12-3.ボールとデッカチャンが衝突したら顔を大きくする

ブロックと同じ様に座標でデッカチャンとボールの衝突をチェックし
ボールとデッカチャンが衝突した場合は画像の拡大率を変更します。
ここで衝突数もカウントし、衝突回数が3回を超えた場合に
ゲームオーバーとします。
下記プログラム(91, 165-182,  346-368行目)

ブロック崩しに上記の機能を入れたプログラムがこちらです。

実行結果

python環境と顔の画像があればコピペで動くので是非一度試してみてください!
友達の顔入れたらウケるかも?