風船割りゲーム



講師から一言
カーソル移動のロジックを使ってシューティングゲームを作る発想が素晴らしいです。カーソルと風船が重なった瞬間にマウスをクリックすることで風船を割る点に苦労の後がみられます。
今のロジックでは当たり判定が甘いですが、知っている知識をすべて使って当たり判定を作っている点をとても高く評価します。
三角関数を使うことで当たり判定の精度を高めることができるので数学の勉強も合わせてやっていきましょう。

Pythonで記述したコード
import tkinter
import random
import pygame
#変数定義
m_x=0
m_y=0
m_c=0
paint_count=0
score = 0
timer = 30

#画面作成
root = tkinter.Tk()
root.title("風船割りゲーム")
root.geometry("800x600")
root.resizable(False,False)
canvas = tkinter.Canvas(root,width=800,height=600)
canvas.pack()

#画像
背景= tkinter.PhotoImage(file="image\背景.png")
照準= tkinter.PhotoImage(file="image\照準.png")
風船= tkinter.PhotoImage(file="image\風船.png")
風船1= tkinter.PhotoImage(file="image\風船1.png")
風船2= tkinter.PhotoImage(file="image\風船2.png")
着弾_blue= tkinter.PhotoImage(file="image\着弾_blue.png")
着弾_green= tkinter.PhotoImage(file="image\着弾_green.png")
着弾_orange= tkinter.PhotoImage(file="image\着弾_orange.png")
着弾_red= tkinter.PhotoImage(file="image\着弾_red.png")
着弾_yellow= tkinter.PhotoImage(file="image\着弾_yellow.png")
破裂= tkinter.PhotoImage(file="image\破裂.png")
ゲームオーバー= tkinter.PhotoImage(file="image\ゲームオーバー.png")

#効果音
pygame.init()
pygame.mixer.init()
効果音_爆発=pygame.mixer.Sound("sound\爆発.mp3")
効果音_着弾=pygame.mixer.Sound("sound\着弾.mp3")
効果音_バックミュージック=pygame.mixer.Sound("sound\バックミュージック.wav")

#画像リスト
着弾_list = [着弾_blue,着弾_green,着弾_orange,着弾_red,着弾_yellow]

#画像配置
canvas.create_image(400,300,image=背景)
canvas.create_image(200,500,image=風船,tag="風船タグ")
canvas.create_image(400,500,image=風船1,tag="風船タグ1")
canvas.create_image(600,500,image=風船2,tag="風船タグ2")

#ラベル作成
#スコア
label_score = tkinter.Label(root,text="スコア0点",font=("system",24),bg="orange",fg="white")
label_score.place(x=1,y=1)
#タイマー
label_timer = tkinter.Label(root,text = "スタート",font=("system",24),bg="blue",fg="White")
label_timer.place(x=650,y=1)

#関数設定
def mouse_move(e):
    global m_x,m_y
    m_x = e.x
    m_y = e.y

def mouse_press(e):
    global m_c
    m_c = 1

def mouse_release(e):
    global m_c
    m_c = 0

def timer_setup():
    global timer,stop
    timer = timer - 1    
    label_timer["text"]="残り"+str(timer)+"秒"
    root.after(1000,timer_setup)

def game_main_風船():
    if canvas.coords("風船タグ")>[200,-70]:
        canvas.move("風船タグ",0,-30)
        if canvas.coords("風船タグ")==[200,-70]:
            canvas.delete("風船タグ")
            canvas.create_image(200,500,image=風船,tag="風船タグ")

    if canvas.coords("風船タグ1")>[400,-70]:
        canvas.move("風船タグ1",0,-20)
        if canvas.coords("風船タグ1")==[400,-20]:
            canvas.delete("風船タグ1")
            canvas.create_image(400,500,image=風船1,tag="風船タグ1")

    if canvas.coords("風船タグ2")>[600,-70]:
        canvas.move("風船タグ2",0,-50)
        if canvas.coords("風船タグ2")==[600,-100]:
            canvas.delete("風船タグ2")
            canvas.create_image(600,500,image=風船2,tag="風船タグ2")
            
    root.after(230,game_main_風船)

def ending():
    global score
    canvas.delete("all")
    label_timer.place_forget()
    label_score.place_forget()
    canvas.create_image(400,200,image=ゲームオーバー,tag="ゲームオーバー")
    label_score.place(x=100,y=300)
    label_score["bg"]= "black"
    label_score["font"]="system",80
    label_score["text"]="スコア",score,"点"

def バックミュージック():
    効果音_バックミュージック.play()
    root.after(4000,バックミュージック)

def game_main():
    global m_c,paint_count 
    canvas.delete("照準タグ")
    if m_c == 1:
        paint_count= paint_count + random.randint(0,5)
        canvas.delete("着弾タグ")
        canvas.create_image(m_x,m_y,image=着弾_list[paint_count%5],tag="着弾タグ")
        効果音_着弾.play()
        衝突判定()
        衝突判定1()
        paint_count = 0
    else:
        canvas.create_image(m_x,m_y,image=照準,tag="照準タグ")
    if timer== 0:
        ending()
    
    root.after(130,game_main)

def 衝突判定():
    global score,label_score
    #風船タグの衝突判定
    b_x1,b_y1,b_x2,b_y2=canvas.bbox("風船タグ")
    風船位置=b_x1 + b_y1 + b_x2 + b_y2
    p_x1,p_y1,p_x2,p_y2=canvas.bbox("着弾タグ")
    着弾位置=p_x1 + p_y1 + p_x2 + p_y2
    if abs(風船位置-着弾位置) <= 50:
        canvas.create_image(m_x,m_y,image=破裂,tag="破裂タグ")
        canvas.delete("破裂タグ")
        効果音_爆発.play()
        score = score + 1
        label_score["text"]="スコア",score,"点"
        canvas.create_image(m_x,m_y,image=破裂,tag="破裂タグ")
        
def 衝突判定1():
    global score,label_score
    #風船タグ1の衝突判定
    b1_x1,b1_y1,b1_x2,b1_y2=canvas.bbox("風船タグ1")
    風船位置1=b1_x1 + b1_y1 + b1_x2 + b1_y2
    p_x1,p_y1,p_x2,p_y2=canvas.bbox("着弾タグ")
    着弾位置=p_x1 + p_y1 + p_x2 + p_y2
    if abs(風船位置1-着弾位置) <= 50:
        canvas.create_image(m_x,m_y,image=破裂,tag="破裂タグ")
        canvas.delete("破裂タグ")
        効果音_爆発.play()
        score = score + 1
        label_score["text"]="スコア",score,"点"
        canvas.create_image(m_x,m_y,image=破裂,tag="破裂タグ")
        
def 衝突判定2():
    global score,label_score
    #風船タグ1の衝突判定
    b2_x1,b2_y1,b2_x2,b2_y2=canvas.bbox("風船タグ2")
    風船位置2=b2_x1 + b2_y1 + b2_x2 + b2_y2
    p_x1,p_y1,p_x2,p_y2=canvas.bbox("着弾タグ")
    着弾位置=p_x1 + p_y1 + p_x2 + p_y2
    if abs(風船位置2-着弾位置) <= 80:
        canvas.create_image(m_x,m_y,image=破裂,tag="破裂タグ")
        canvas.delete("破裂タグ")
        効果音_爆発.play()
        score = score + 1
        label_score["text"]="スコア",score,"点"
        canvas.create_image(m_x,m_y,image=破裂,tag="破裂タグ")
    
#操作
root.bind("",mouse_move)
root.bind("",mouse_press)
root.bind("",mouse_release)
バックミュージック()
game_main()
game_main_風船()
timer_setup()
#ループ
root.mainloop()