Tkinterを使ってサンタになりきる

令和元年が早くも終わりそうになってます。今年は芸能人の結婚ラッシュが目立ちましたね。
私も先日親友からいきなり結婚を報告されました。~~ついこの前まで六花ちゃんの足太くて良いよねとか言ってたじゃん…~~Twitterで愚痴ったら知らない外国人が慰めてくれました。さっそく留学経験が生きて良かったです。

そして世間はクリスマス。数多くのお父さんお母さん達がサンタになることでしょう。今年結婚した方々も将来子供が生まれればサンタになるはずです。

しかし人生1度きりの子育て、多くの新婚夫婦がどうサンタになればいいか悩んでいるのではないでしょうか。
そんな方々のためにサンタの予行演習が出来るゲームを作りました。

ということで[Make IT AdventCalendar2019](https://qiita.com/advent-calendar/2019/make_it)、22日目の記事を書かせていただきます。

# はじめに

今回ゲーム制作にあたって利用したのはTkinterになります。
基本的なコードは[12歳からはじめるゼロからのPythonゲームプログラミング教室](https://www.amazon.co.jp/dp/B0758BJWV6/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)に載っていますので、追加した要素を主に記述していこうかと思います。この本の良いところとして、理解に詰まったときに「自分が12歳以下である」ことを実感できる点があります。若いって良いね。


# タイトル画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316279/5c93ed54-c62f-9b50-4cd3-0b47340db76f.png)

タイトルに他意はありません。デトロイトに住む一人の男がサンタになるまでの物語です。今年のFrostbiteも楽しみですね。

```python:Santagame.py
 
# タイトル作成
frame = tkinter.Frame(width=960, height=640)
frame.place(x=10, y=10)
title = tkinter.Canvas(frame, width=960, height=640)
title.place(x=0, y=0)
title.create_rectangle(0, 0, 960, 640, fill="black")
title_label_up = tkinter.Label(frame, width=0, height=0, text=" ", font=("Arial Black", 70),                           fg="white", bg="black")
title_label_down = tkinter.Label(frame, width=0, height=0, text=" ", font=("Arial", 20),                                fg="white", bg="black")
press_any_key = tkinter.Label(frame, width=0, height=0, text=" ", font=("Arial", 25),                              fg="white", bg="black")
title_label_up["text"] = "DETROIT"
title_label_down["text"] = "B   E   C   O   M   E       S   A   N   T   A"
press_any_key["text"] = "-  Press any key to start  -"
title_label_up.place(x=240, y=220)
title_label_down.place(x=230, y=340)
press_any_key.place(x=280, y=480)

# タイトル消去
def forget_title(event):
    frame.destroy()

# title消去
root.bind("<Any-KeyPress>", forget_title)


```

コードに関してはFrameとCanvasとLabelをつくる、基本的な形になっています。
キーバインドを使い、いずれかのキーを押すことで消えます。

# プレイ画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316279/56ffcdb5-ea99-82df-a837-d996652061cb.png)



矢印キーでサンタを操作します。

基本的なルールとして、おもちゃと斧を手に入れて家を目指します。斧もしくはお金を持っておもちゃ屋に行くことでおもちゃを手に入れることが出来ます。斧のみしか持っていない場合、強盗扱いとなり一部の敵の攻撃力が上がるので注意を。しかし斧を持つと自分自身の攻撃力も上がります。

雪上で斧を振り回す姿はさながら竃門炭治郎。生殺与奪の権を相手に渡してはいけません。殺られる前に殺る、そんな社会の厳しさを子供に教えることもできるゲームに仕上がりました。

# 戦闘画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316279/dc4a9636-3078-fc1f-a014-78850006aa20.png)

暴力と狂気が渦巻くデトロイト（偏見）、敵は国家権力と反社会勢力です。
主人公もサンタになる前はただの赤い服を着た不審者です。職務質問されても仕方ないでしょう。
無料素材に拘るばかりに世界観が崩れてしまいました。でも異世界転生って多分こんな感じ。

陰キャの天敵ヤクザはお金を持っていたらカツアゲしてきます。やられる前に殺りましょう。
強盗した後だと警察官は発砲してきます。殺られる前に殺りましょう。

斧を持っていた場合は戦闘後に血痕が残ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316279/6729933c-520b-98c2-eeb6-e0a9933f43a3.png)

戦闘で負けると洋・和の2種類のbad end画面がランダムで出てきます。


# 実装出来なかった機能
## サンタ画像のgifアニメ表示

Tkinterでそのままgifを使うと1フレーム目しか表示されないので、ループさせたりafter()使ったり試行錯誤するも撃沈。
妥協案として歩くたびに画像が変わる仕組みに。

```Python:SantaGame.py
global santa_i
canvas.create_image(santa_x * 64 + 31, santa_y * 64 + 31,
                        image=santaImages[santa_direction][santa_i], tag="santa")
santa_i += 1
if santa_i > 3:
    santa_i = 0
```

## Tkinterのウィンドウ内での動画の再生

こちらもafter()なり使うも撃沈。
妥協案で別ウィンドウで再生し、終了後ウィンドウを閉じる仕組みに。

```python:SantaGame.py
fps = 250

if cap.isOpened() == False:
    print("Error!")

while cap.isOpened():

    ret, ending = cap.read()

    if ret == True:

        time.sleep(1/fps)
        cv2.imshow('ending', ending)

        if cv2.waitKey(1) & 0xFF == ord('q'):

             break

        else:
            break

cap.release()
cv2.destroyAllWindows()

```

## 戦闘時のキーのunbind
サンタの移動について、当初は矢印ボタンをクリックすることで動かしていましたが、あまりにもダサいのでキーバインドすることに。
しかし戦闘時にunbindしてしまうと戦闘終了後までに再びbindするタイミングが見つからず…。

スタイリッシュ（仮）を取るか機能性をとるか悩んだ結果、バグと共存することを選びました。言うなればこのバグは禰豆子みたいなものです。~~善良なバグと悪いバグの区別もつかないならエンジニアなんてやめてしまえ~~
なのでみなさん戦闘中は矢印キー押さないで下さいね。

# おわりに
遊びたい方は[こちら](https://github.com/feketerigo222/Santa-Game)からダウンロード後、SantaGame.pyを起動してください。

明日は@fumihumiが担当します。