LoginSignup
7
6

More than 3 years have passed since last update.

【Python】Tkinterによる70行で作るGUIアプリ「追いかけっこゲーム」

Last updated at Posted at 2019-05-29

はじめに

こんにちは。
今回は「追いかけっこゲーム」を作っていきたいと思います。
完成するとこんな感じに動きます!

追いかけっこゲーム.gif

赤い円が自分(player)で青い円が敵(enemy)です。
マウスカーソルを操作して、赤い円を動かすことができます。青い円に触れたら止まります。つまりゲームオーバーといった感じです!

環境

  • Windows 10 home
  • Python 3.7.1

numpyを使うので以下のコマンドでインストールしておきましょう。

pip install numpy

「追いかけっこゲーム」の制作

インポート

使うライブラリは以下の2つです。

import tkinter as tk
import numpy as np

ウィンドウの作成

import tkinter as tk
import numpy as np

class Application(tk.Frame):
    def __init__(self,master):
        super().__init__(master)
        self.pack()

        self.width=self.height=500
        master.geometry(str(self.width)+"x"+str(self.height))
        master.title("追いかけっこゲーム")


def main():
    win = tk.Tk()
    app = Application(master = win)
    app.mainloop()


if __name__ == "__main__":

    main()

このプログラムでウィンドウを作っていきます。
サイズは500×500です。タイトル名は追いかけっこゲームです。
詳しくはPythonによるTkinterを使った雛形(クラス化手法)の記事をご参照ください。

敵の動きのベクトル取得に関して

敵の動きのベクトルは以下のenemyVec関数で取得しています。少しややこしい部分なので、解説を入れようと思います。

def enemyVec(self,player,enemy,speed):#敵の動き(x,y)のベクトルを返す
    rad=np.arctan((player.y-enemy.y)/(player.x-enemy.x))#向き(角度の計算)
    if player.x-enemy.x >= 0:
        vx=np.cos(rad)*speed
        vy=np.sin(rad)*speed
    else:
        vx=np.cos(rad)*(-1*speed)
        vy=np.sin(rad)*(-1*speed)
    return [vx,vy]

引数として、playerオブジェクトとenemyオブジェクトを渡しています。それぞれの中心座標を計算で使うためです。ここで、この2つのオブジェクトの向きの計算が少しややこしくなると思います。つまり、2点間の角度の計算です。
2点の座標が分かっているので、ベクトルのx成分とy成分を求めることができます。

(例) A(x1,y1),B(x2,y2)の場合


\vec{AB} =
\begin{matrix}
x2 - x1 \\
y2 - y1 
\end{matrix}

そして、x軸とベクトルがなす角度θを以下のtanの逆関数を使って表すことができます。

θ = \tan^-1(\frac{y}{x})

tanθの範囲が-π/2~π/2なので、playerとenemyのx座標の差の正負で場合分けをし、speedに-1をかけて、方向を変えています。

完成したプログラム

こちらが完成したプログラムになります。

追いかけっこゲーム.py
import tkinter as tk
import numpy as np

class Circle():
    def __init__(self,canvas,x,y,r,color,tag=None):
        self.canvas = canvas
        self.x = x #円の中心のx座標
        self.y = y #円の中心のy座標
        self.r = r #円の半径
        self.color = color
        self.tag = tag

    def createCircle(self):
        self.canvas.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill=self.color,tag=self.tag)

class Application(tk.Frame):
    def __init__(self,master):
        super().__init__(master)
        self.pack()

        self.width=self.height=500
        master.geometry(str(self.width)+"x"+str(self.height))
        master.title("追いかけっこゲーム")

        self.canvas = tk.Canvas(master,width=self.width,height=self.height,bg="black")
        self.canvas.pack()

        self.player = Circle(self.canvas,250,250,30,"red","player") #インスタンスplayerの生成
        self.enemy = Circle(self.canvas,0,0,30,"blue","enemy") #インスタンスenemyの生成

        self.canvas.bind("<Motion>",self.mouseEvent)
        self.master.after(50,self.update)

    def update(self):
        if self.judgeflag(self.player,self.enemy):
            eV = self.enemyVec(self.player,self.enemy,10)
            self.enemy.x += eV[0]
            self.enemy.y += eV[1]
            self.canvas.delete("player")
            self.canvas.delete("enemy")
            self.player.createCircle()
            self.enemy.createCircle()

        self.master.after(50,self.update)

    def enemyVec(self,player,enemy,speed): #敵の動き(x,y)のベクトルを返す
        rad=np.arctan((player.y-enemy.y)/(player.x-enemy.x)) #向き(角度の計算)
        if player.x-enemy.x >= 0:
            vx=np.cos(rad)*speed
            vy=np.sin(rad)*speed
        else:
            vx=np.cos(rad)*(-1*speed)
            vy=np.sin(rad)*(-1*speed)
        return [vx,vy]

    def judgeflag(self,player,enemy): #当たり判定
        if np.sqrt((player.x-enemy.x)**2+(player.y-enemy.y)**2) > player.r+enemy.r: return True
        else: return False

    def mouseEvent(self,event):
        self.player.x = event.x
        self.player.y = event.y

def main():
    win = tk.Tk()
    app = Application(master=win)
    app.mainloop()

if __name__ == "__main__":
    main()

以上で追いかけっこゲームは完成になります。
ここまで読んでいただき、ありがとうございました。

7
6
3

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