python 實現(xiàn)彈球游戲的示例代碼
更新時間:2020年11月17日 17:03:31 作者:cunxi1992
這篇文章主要介紹了python 實現(xiàn)彈球小游戲,幫助大家更好的理解和學習python,感興趣的朋友可以了解下
運行效果

實現(xiàn)代碼
# -*- coding: utf-8 -*-
import tkinter as tkinter
import tkinter.messagebox as mb
import random,time
class Ball():
'''
創(chuàng)建Ball類,初始化對象,即創(chuàng)建對象設置屬性,
init函數(shù)是在對象被創(chuàng)建的同時就設置屬性的一種方法,Python會在創(chuàng)建新對象時自動調用這個函數(shù)。
'''
def __init__(self,canvas,paddle,score,color,init_x=100,init_y=100):
'''
Ball類初始化屬性
:param canvas:畫布
:param paddle:球拍
:param score:得分
:param color:小球的顏色
:param init_x:小球球的初始橫坐標,有默認值,可不傳
:param init_y:小球球的初始縱坐標,有默認值,可不傳
'''
self.canvas = canvas
self.paddle = paddle
self.score = score
self.color = color
# 保存tkinter畫小球返回的id,為后期移動屏幕上的小球做準備,
# 參數(shù)分別表示為:(10,10)表示左上角x,y坐標,(30,30)表示右下角x,y坐標,即創(chuàng)建一個直徑為20的圓
# fill為小球的填充色
self.id = canvas.create_oval(10,10,30,30,fill=self.color)
# 將小球移動到初始位置,初始位置可通過傳參進行更改,有默認值
self.canvas.move(self.id,init_x,init_y)
# 給一串x分量的起始值(x和y代表橫坐標和縱坐標的分量)
starts = [-3,-2,-1,1,2,3]
# shuffle() 方法將序列的所有元素隨機排序
random.shuffle(starts)
# 隨機混排序,賦值給對象變量x,讓它起始的時候獲得隨機分量值,引起球每次起始角度都不同
self.x = starts[0]
# 對象變量y就是垂直分量移動的初始值,等價于上下移動,值代表移動多少像素點
self.y = -3
# winfo_height()函數(shù)來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
# winfo_width()函數(shù)來獲取畫布當前的寬度,賦值給對象變量
self.canvas_width = self.canvas.winfo_width()
# 小球是否碰觸到畫布底部,初始值為False,即沒有碰到
self.hit_bottom = False
def draw(self):
'''
該函數(shù)用于讓小球水平和垂直運動,在運動的過程中,判斷是否得分、游戲是否結束
'''
# 讓小球可以水平和垂直運動
self.canvas.move(self.id,self.x,self.y)
# coords函數(shù)通過id返回畫布球的坐標列表(兩個坐標,左上角的坐標和右下角的兩個坐標)
position = self.canvas.coords(self.id)
# 判斷小球是否撞到畫布頂部或者底部,保證小球反彈回去,不消失
if position[1] <= 0: # 如果小球的左上角y坐標小于0,則向下移動3個像素
self.y = 3
if position[3] >= self.canvas_height: # 如果小球的右下角y坐標大于畫布寬度,則表示小球碰到了畫布底部,游戲結束
self.hit_bottom = True
if self.hit_paddle(position) == True: # 判斷 球 是否碰到了 球拍,如果碰到了則使小球回彈
self.y = -3
if position[0] <= 0: # 如果小球的左上角x坐標 小于等于0,則向右移動3個像素
self.x = 3
if position[2] >= self.canvas_width: # 如果小球的右下角x坐標 大于等于畫布寬度,則向左移動3個像素
self.x = -3
def hit_paddle(self,position):
'''
該函數(shù)用于判斷 球 是否碰到了 球拍,如果碰到了則使小球回彈,否則游戲結束
:param position:小球的坐標
'''
# 獲取球拍在畫布的坐標,返回一個數(shù)組(兩個坐標,左上角的坐標和右下角的兩個坐標)
paddle_position = self.canvas.coords(self.paddle.id)
print ('paddle_position:',paddle_position[0],paddle_position[1],paddle_position[2],paddle_position[3])
# 如果小球的右下角x坐標 大于等于 球拍左上角x坐標,且小球左上角x坐標 小于等于 球拍右下角x坐標
if position[2] >= paddle_position[0] and position[0] <= paddle_position[2]:
# 如果小球右下角y坐標 大于等于 球拍左上角y坐標,且小球右下角y坐標 小于等于 球拍右下角坐標
if position[3] >= paddle_position[1] and position[3] <= paddle_position[3]:
# 橫坐標 等于
self.x += self.paddle.x
colors = ['red','green']
# shuffle() 方法將序列的所有元素隨機排序,以便隨機獲得小球顏色
random.shuffle(colors)
self.color= colors[0]
#
self.canvas.itemconfig(self.id,fill=colors[0])
# 計算得分并展示,且同時將小球的顏色、關卡顏色同步
self.score.hit(ball_color = self.color)
self.canvas.itemconfig(self.paddle.id,fill=self.color)
# 增加或減少球拍的寬度
self.adjust_paddle(paddle_position)
return True
return False
def adjust_paddle(self,paddle_position):
'''
該函數(shù)用于增加或減少球拍的寬度
:paddle_position:球拍的位置坐標
'''
# 球拍每次的增量大小
paddle_grow_length = 30
# 球拍的寬度 = 球拍的右下角x坐標 - 球拍的左上角x坐標
paddle_width = paddle_position[2] - paddle_position[0]
if self.color == 'red': # 如果當前球的顏色為紅色
if paddle_width > 30: # 如果球拍的寬度大于60
if paddle_position[2] >= self.canvas_width: # 如果球拍右下角的x坐標 大于等于 畫布寬度
# 球拍右下角x坐標 = 球拍右下角x坐標 - 增量值
paddle_position[2] = paddle_position[2] - paddle_grow_length
else:
# 球拍的左上角x坐標 = 球拍的左上角x坐標 + 增量值
paddle_position[0] = paddle_position[0] + paddle_grow_length
elif self.color == 'green': # 如果當前球的顏色為綠色
if paddle_width < 300: # 如果球拍的寬度小于300
if paddle_position[2] >= self.canvas_width: # 如果球拍的右下角x坐標 大于等于 畫布寬度
# 球拍左上角x坐標 - 增量值
paddle_position[0] = paddle_position[0] - paddle_grow_length
else:
# 球拍右下角x坐標 + 增量值
paddle_position[2]=paddle_position[2]+paddle_grow_length
class Paddle:
'''
球拍類
'''
def __init__(self,canvas,color):
'''
:param canvas:畫布
:param color:球拍的顏色
'''
self.canvas = canvas
# winfo_width()函數(shù)來獲取畫布當前的寬度,賦值給對象變量
self.canvas_width = self.canvas.winfo_width()
# winfo_height()函數(shù)來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
# 保存tkinter畫球拍時返回的id,為后期移動屏幕上的球拍做準備,
# create_rectangle 畫矩形,fill為球拍的顏色
self.id = canvas.create_rectangle(0,0,180,15,fill=color)
# 將球拍移動至初始位置
self.canvas.move(self.id,200,self.canvas_height*0.75)
# 設置對象變量x,初始值為0.也就是球拍先不移動
self.x = 0
# 游戲是否開始,默認為Flase,即 不開始
self.started = False
# 是否繼續(xù)游戲,默認值為 否
self.continue_game = False
# 初始化時將事件‘按下左鍵'和函數(shù)向左移動綁定
self.canvas.bind_all('<KeyPress-Left>',self.turn_left)
# 初始化時將事件‘按下右鍵'和函數(shù)向右移動綁定
self.canvas.bind_all('<KeyPress-Right>',self.turn_right)
# 初始化時將事件‘按下Enter鍵'和函數(shù)繼續(xù)游戲綁定
self.canvas.bind_all('<KeyPress-Enter>',self.continue_game)
# 按任意鍵開始游戲
self.canvas.bind_all('<Button-1>',self.start_game)
# 初始化時將事件‘按下space鍵'和函數(shù)暫停游戲綁定
self.canvas.bind_all('<space>',self.pause_game)
def turn_left(self,event):
'''
該函數(shù)用于向左移動時,
'''
# 獲取球拍的位置坐標
position = self.canvas.coords(self.id)
# 如果球拍的左上角x坐標 小于 0
if position[0] <= 0:
# 則再次按向左移動時,移動距離為0
self.x = 0
else:
# 每次向左移動3個像素
self.x = -3
def turn_right(self,event):
# 獲取球拍的位置坐標
position = self.canvas.coords(self.id)
# 如果球拍的右下角x坐標 大于等于 畫布寬度
if position[2] >= self.canvas_width:
# 則再次按向右移動時,移動距離為0
self.x = 0
else:
# 每次向右移動3個像素
self.x = 3
def start_game(self,evt):
self.started = True
def pause_game(self,evt):
if self.started:
self.started=False
else:
self.started=True
def draw(self):
'''
該函數(shù)用于移動球拍
'''
# 球拍類可以水平移動
self.canvas.move(self.id,self.x,0)
# 獲取球拍的位置坐標
position = self.canvas.coords(self.id)
# 如果球拍左上角x坐標小于等于0,則停止移動
if position[0] <= 0:
self.x = 0
# 如果球拍右下角x坐標大于等于0,則停止移動
elif position[2] >= self.canvas_width:
self.x = 0
class Score():
'''
得分類
'''
def __init__(self,canvas,color):
'''
初始化得分類
:param canvas:畫布
:param color:得分文本的顏色
'''
# 初始化得分為0
self.score = 0
# 把參數(shù)canvas賦值給對象變量canvas
self.canvas = canvas
# winfo_width()函數(shù)來獲取畫布當前的寬度,賦值給對象變量
self.canvas_width = self.canvas.winfo_width()
# winfo_height()函數(shù)來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
# 創(chuàng)建文本控件,用戶保存用戶保存得分
self.id = canvas.create_text(self.canvas_width-150,10,text='score:0',fill=color,font=(None, 18, "bold"))
# 用戶保存游戲的關卡顏色
self.note = canvas.create_text(self.canvas_width-70,10,text='--',fill='red',font=(None, 18, "bold"))
def hit(self,ball_color='grey'):
'''
該函數(shù)用于將計算得分并展示,且同時將小球的顏色、關卡顏色同步
:param ball_color:小球的顏色,默認為'grey'
'''
# 得分遞增
self.score += 1
# 將得分展示在文本控件中
self.canvas.itemconfig(self.id,text='score:{}'.format(self.score))
# 將小球的顏色同步至游戲關卡的顏色
if ball_color == 'red':
self.canvas.itemconfig(self.note,text='{}-'.format('W'),fill='red')
elif ball_color=='green':
self.canvas.itemconfig(self.note,text='{}+'.format('W'),fill='green')
else:
self.canvas.itemconfig(self.note,text='--',fill='grey')
def main():
# tkinter.Tk()類創(chuàng)建一個tk對象,它就是一個基本窗口,可以在其上增加其他東西
tk = tkinter.Tk()
# call back for Quit
def callback():
'''
該函數(shù)用于,當點擊窗口 關閉 按鈕時,展示一個消息提示框,詢問是否要關閉,
點擊 是,則退出窗口
'''
if mb.askokcancel("Quit", "Do you really wish to quit?"):
# Ball.flag = False
tk.destroy()
# 使用protocol將 WM_DELETE_WINDOW 與 callback 綁定,程序在退出時打印 'WM_DELETE_WINDOW'
tk.protocol("WM_DELETE_WINDOW", callback)
# 畫布的寬
canvas_width = 600
# 畫布的高
canvas_hight = 500
# 窗口標題
tk.title("Ball Game V1.2")
# 窗口不可被拉伸,(0,0)的意思是“窗口的大小在水平方向上和垂直方向上都不能改變”
tk.resizable(0,0)
# 調用wm_attributes,將窗口始終放到所有其他窗口之前(-topmost),將1改為0畫布窗口不在其他窗口之前
tk.wm_attributes("-topmost",1)
# 創(chuàng)建畫布,bd=0,highlightthickness=0 作用是畫布之外沒有邊框,可以使游戲屏幕看上去更加美觀。最后一個bd是畫布的背景色。
canvas = tkinter.Canvas(tk,width=canvas_width,height=canvas_hight,bd=0,highlightthickness=0,bg='#00ffff')
# 按照上面一行指定的寬度高度參數(shù)調整其自身大小
canvas.pack()
# update強制更新屏幕,實時更新畫布
tk.update()
# 創(chuàng)建得分類,得分控件的顏色為紅色
score = Score(canvas,'red')
# 創(chuàng)建 球拍類,
paddle = Paddle(canvas,"red")
# 創(chuàng)建 小球類,小球的默認顏色為灰色
ball = Ball(canvas,paddle,score,"grey")
# 游戲結束時的提示
game_over_text = canvas.create_text(canvas_width/2,canvas_hight/2,text='Game over',state='hidden',fill='red',font=(None, 18, "bold"))
# 游戲開始時的提示
introduce = 'Welcome to Ball GameV1.2:\nClick Any Key--Start\nStop--Enter\nContinue-Enter\n'
game_start_text = canvas.create_text(canvas_width/2,canvas_hight/2,text=introduce,state='normal',fill='magenta',font=(None, 18, "bold"))
# 主循環(huán),讓tkinter不停地重畫屏幕
while True:
# 如果小球沒有碰到了底部,且 游戲尚未開始
if (ball.hit_bottom == False) and ball.paddle.started:
canvas.itemconfig(game_start_text,state='hidden')
ball.draw()
paddle.draw()
# 如果小球碰到了底部,則游戲結束
if ball.hit_bottom == True:
time.sleep(0.1)
canvas.itemconfig(game_over_text,state='normal')
# 不停的刷新畫布
tk.update_idletasks()
# 強制更新屏幕
tk.update()
time.sleep(0.01)
if __name__=='__main__':
main()
以上就是python 實現(xiàn)彈球小游戲的詳細內容,更多關于python 彈球游戲的資料請關注腳本之家其它相關文章!
相關文章
對python中的for循環(huán)和range內置函數(shù)詳解
下面小編就為大家分享一篇對python中的for循環(huán)和range內置函數(shù)詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04
Numpy 數(shù)組操作之元素添加、刪除和修改的實現(xiàn)
本文主要介紹了Numpy 數(shù)組操作之元素添加、刪除和修改的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-03-03
PyQt5 QSerialPort子線程操作的實現(xiàn)
這篇文章主要介紹了PyQt5 QSerialPort子線程操作的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04

