クラスを使ったプログラミング
今回のテーマは、クラスを利用したプログラミング。
シューティングゲームを作りながら、Pythonのクラスについて理解が深まるような動画にしよう。
ということで・・・。
出現するたくさんのエイリアン。うん・・・エイリアンクラスを用意して・・・と。
あと・・・ユーザークラスと、ミサイルクラスと。
ミサイルクラスは、自分のミサイルと、エイリアンのミサイルとで、継承を使おうかしら?
まぁ・・・。
そんな感じで、一応少しだけ考えちゃいるんですわ。・・・はい。
詳しくは動画を見ていただくとして、ココには今回の動画で書いたコードを掲載しておきますね。
【前編】クラスの解説とユーザー系プログラミングまで
【後編】ゆるインベーダー仕上げ
今回のゲームでは、画像ファイル(png)をコード内で読み込んでいます。下のコードをコピペなどで試す際には、以下のpngファイル3つをダウンロードし、Pythonファイルと同一ディレクトリ(フォルダ内)に置いて実行してください。
ファイル名「ユーザー」star.png/「エイリアン」alien.png/「ボス」boss.png
尚、動画前編で解説していますが、このコード実行には外部モジュール「Pillow」のインストールが必要です。
import tkinter as tk
import random
from PIL import ImageTk
########## スタークラス ####################
class Star:
def __init__(self, x, y):
self.x = x
self.y = y
self.draw()
self.action()
def draw(self):
self.disp = can.create_image(self.x, self.y, image=starImg)
def action(self):
can.tag_bind(self.disp, "<Button1-Motion>", self.move)
can.tag_bind(self.disp, "<Button-3>", self.bang)
def move(self, event):
if event.x<30 or event.x>770 or event.y>470 or event.y<300 :
return
can.coords(self.disp, event.x, event.y)
self.x = event.x
self.y = event.y
def bang(self, event):
Bullet(event.x, event.y, -10, "orange")
########## エイリアンクラス ####################
class Alien:
def __init__(self):
self.x = 30
self.y = 30
self.moveX = 20
self.draw()
self.move()
def draw(self):
self.disp = can.create_image(self.x, self.y, image=alienImg)
def move(self):
if self.x<0 or self.x>800 :
self.moveX *= -1
self.y += 50
self.x += self.moveX
can.coords(self.disp, self.x, self.y)
r = random.randint(0, 30)
if r==0 :
self.bang()
self.loop = win.after(100, self.move)
self.judge()
def judge(self):
if ((self.x-star.x)**2+(self.y-star.y)**2)<2500 or self.y>470 :
can.delete(self.disp)
win.after_cancel(self.loop)
gameOver()
def bang(self):
AlienBullet(self.x, self.y, 10, "blue")
########## ボスクラス ####################
class Boss():
def __init__(self):
self.life = 100
self.x = 0
self.y = 0
self.moveX = 20
def draw(self):
self.disp = can.create_image(self.x, self.y, image=bossImg)
self.dispLife = can.create_rectangle(self.x-30, self.y, self.x-30+self.life*0.8, self.y+10, fill="lime", outline="lime")
def move(self):
if self.x<100 or self.x>700 :
self.moveX *= -1
self.x += self.moveX
can.coords(self.disp, self.x, self.y)
can.coords(self.dispLife, self.x-30, self.y, self.x-30+self.life*0.8, self.y+10)
r = random.randint(0, 4)
if r==0 :
self.bang()
self.loop = win.after(100, self.move)
def bang(self):
AlienBullet(self.x, self.y, 10, "red")
########## 弾丸クラス ####################
class Bullet:
def __init__(self, x, y, moveY, color):
self.x = x
self.y = y
self.moveY = moveY
self.color = color
self.draw()
self.move()
def draw(self):
self.disp = can.create_oval(self.x-6, self.y-10, self.x+6, self.y+10, fill=self.color)
def move(self):
if self.y<0 or self.y>500 :
can.delete(self.disp)
return
can.move(self.disp, 0, self.moveY)
self.y += self.moveY
win.after(20, self.move)
self.judge()
def judge(self):
for alien in arrayAlien :
if ((self.x-alien.x)**2+(self.y-alien.y)**2)<600 :
can.delete(alien.disp)
win.after_cancel(alien.loop)
arrayAlien.pop(arrayAlien.index(alien))
if ((self.x-boss.x)**2+(self.y-boss.y)**2)<3000 :
boss.life -= 1
can.delete(self.disp)
if boss.life<0 :
can.delete(boss.disp, boss.dispLife)
can.delete(self.disp)
win.after_cancel(boss.loop)
gameClear()
########## エイリアン弾丸クラス ####################
class AlienBullet(Bullet):
def judge(self):
if ((self.x-star.x)**2+(self.y-star.y)**2)<600 :
can.delete(star.disp)
gameOver()
########## ゲームオーバー&クリア ####################
def gameOver():
can.create_text(400, 250, text="YOU LOSE!", fill="red", font=("", 100))
can.delete(star.disp)
def gameClear():
can.create_text(400, 250, text="YOU WIN!", fill="lime", font=("", 100))
########## メイン ####################
#ウィンドウ設定
win = tk.Tk()
win.title("ゆるインベーダー")
win.geometry("800x500+120+100")
#キャンバス
can = tk.Canvas(win, width=800, height=500, bg="cyan")
can.pack()
#画像の変換
starImg = ImageTk.PhotoImage(file="star.png")
alienImg = ImageTk.PhotoImage(file="alien.png")
bossImg = ImageTk.PhotoImage(file="boss.png")
#スターをインスタンス化
star = Star(375, 450)
#エイリアンをインスタンス化
arrayAlien = []
i = 0
def createAlien():
global i
i += 1
alien = Alien()
arrayAlien.append(alien)
createAlienLoop = win.after(500, createAlien)
if i==30 :
win.after_cancel(createAlienLoop)
createAlien()
#ボスをインスタンス化
boss = Boss()
#ボス出現のタイミング
def timing():
timingLoop = win.after(1000, timing)
if len(arrayAlien)==0 :
boss.x = 400
boss.y = 100
boss.draw()
boss.move()
win.after_cancel(timingLoop)
timing()
win.mainloop()