根據前面慢屏幕亂跑的小球,改編一個彈球遊戲,下面加一個球拍,當球碰到拍子的時候彈回去
版本一
目前這個實現的功能是:加入了一拍子,可以用鍵盤來左右控制移動
#########################
#之前做的畫面沒有互動,這次加入一個球拍,使之能把下落的球給擋回去,目前功能加入了一拍子,可以用鍵盤來左右控制移動
######################
from tkinter import *
import random
import time
#
#創建一個類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
class Ball:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#來回反彈
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函數來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
#獲取X軸座標
self.canvas_width = self.canvas.winfo_width()
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#獲取某個對象在畫布的座標,返回一個數組(兩個座標,左上角的座標和右下角的兩個座標)
pos = self.canvas.coords(self.id)
#打印獲取的座標
print(pos)
#如果最上面的縱軸座標在頂上,則往下移動一個像素
if pos[1] <= 0:
self.y = 1
#如果最下面的縱軸座標在底上,則向上移動
if pos[3] > self.canvas_height:
self.y = -1
#寬度控制#
#如果在左邊框了,那麼向右邊移動3像素
if pos[0] <= 0:
self.x = 3
#如果到右邊框了,左移動3像素
if pos[2] > self.canvas_width:
self.x = -3
#
#創建一個球拍類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
#這個函數綁定一個事件,來實現小球用鍵盤來控制左右移動,當移動到邊界的時候要停止移動
def draw(self,event):
pos = self.canvas.coords(self.id)
if event.keysym == 'Left':
if pos[0] <= 0:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,-100,0)
if event.keysym == 'Right':
if pos[2] >= self.canvas_width:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,100,0)
#創建畫布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 畫布之外沒有邊框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
#創建對象
ball = Ball(canvas,'red')
paddle = Paddle(canvas,'blue')
#一直保持循環
while 1:
ball.draw()
#給球拍綁定事件
canvas.bind_all('<KeyPress-Left>',paddle.draw)
canvas.bind_all('<KeyPress-Right>',paddle.draw)
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.01)
版本2
這個可用用鍵盤來回移動球拍,並且如果球碰到球拍會給它彈回去
#########################
#之前做的畫面沒有互動,這次加入一個球拍,使之能把下落的球給擋回去
######################
from tkinter import *
import random
import time
#
#創建一個類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
class Ball:
#這個地方要獲取paddle的數據,所以要把paddle對象作爲一個參數傳遞進來
def __init__(self,canvas,paddle,color):
self.canvas = canvas
self.paddle = paddle
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#來回反彈
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函數來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
#獲取X軸座標
self.canvas_width = self.canvas.winfo_width()
#fun:判斷是否擊中球拍的函數,擊中返回True,不然返回false
#函數的擦數要獲取球拍的位置,然後和小球的位置來判斷
def hit_paddle(self,pos):
paddle_pos = canvas.coords(self.paddle.id)
#這個地方來講一下判斷規則,現在我們獲取了兩個球和拍子兩個對象在畫布中的座標,通過對座標來判斷是否撞拍
#先判斷橫座標:如果小球的最左邊pos[0]的值大於等於拍子最左邊的值,且球最右邊的座標的值pos[2]小於拍子最右邊的值,那麼橫向是命中的
if pos[0] >= paddle_pos[0] and pos[2] <= paddle_pos[2]:
#縱向判斷:小球的最下邊的值位於球拍的pos[3]上底和下底之間,則縱向命中
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
else:
return False
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#獲取某個對象在畫布的座標,返回一個數組(兩個座標,左上角的座標和右下角的兩個座標)
pos = self.canvas.coords(self.id)
##縱軸控制##
#如果最上面的縱軸座標在頂上,則往下移動一個像素
if pos[1] <= 0:
self.y = 1
#如果最下面的縱軸座標在底上,則向上移動
if pos[3] > self.canvas_height:
self.y = -1
#這兒加入球拍的位置,如果到了球拍的底部也要彈回去,通過加入一個函數來判斷,在draw之前
if self.hit_paddle(pos) == True:
self.y = -1
##寬度控制##
#如果在左邊框了,那麼向右邊移動3像素
if pos[0] <= 0:
self.x = 3
#如果到右邊框了,左移動3像素
if pos[2] > self.canvas_width:
self.x = -3
#
#創建一個球拍類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
#這個函數綁定一個事件,來實現小球用鍵盤來控制左右移動,當移動到邊界的時候要停止移動
def draw(self,event):
pos = self.canvas.coords(self.id)
if event.keysym == 'Left':
if pos[0] <= 0:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,-100,0)
if event.keysym == 'Right':
if pos[2] >= self.canvas_width:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,100,0)
#創建畫布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 畫布之外沒有邊框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
#創建對象
paddle = Paddle(canvas,'blue')
ball = Ball(canvas,paddle,'red')
#一直保持循環
while 1:
ball.draw()
#給球拍綁定事件
canvas.bind_all('<KeyPress-Left>',paddle.draw)
canvas.bind_all('<KeyPress-Right>',paddle.draw)
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.01)
繼續進行優化
加入計分功能和如果錯過三次則自動停止功能
#########################
#之前做的畫面沒有互動,這次加入一個球拍,使之能把下落的球給擋回去
######################
from tkinter import *
import random
import time
#創建畫布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 畫布之外沒有邊框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
#
#創建一個類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
class Ball:
#這個地方要獲取paddle的數據,所以要把paddle對象作爲一個參數傳遞進來
def __init__(self,canvas,paddle,color):
self.canvas = canvas
self.paddle = paddle
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#來回反彈
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函數來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
#獲取X軸座標
self.canvas_width = self.canvas.winfo_width()
#剛開始沒有接觸到底部
self.hit_bottom_count = 0
#fun:判斷是否擊中球拍的函數,擊中返回True,不然返回false
#函數的擦數要獲取球拍的位置,然後和小球的位置來判斷
def hit_paddle(self,pos):
paddle_pos = canvas.coords(self.paddle.id)
#這個地方來講一下判斷規則,現在我們獲取了兩個球和拍子兩個對象在畫布中的座標,通過對座標來判斷是否撞拍
#先判斷橫座標:如果小球的最左邊pos[0]的值大於等於拍子最左邊的值,且球最右邊的座標的值pos[2]小於拍子最右邊的值,那麼橫向是命中的
if pos[0] >= paddle_pos[0] and pos[2] <= paddle_pos[2]:
#縱向判斷:小球的最下邊的值位於球拍的pos[3]上底和下底之間,則縱向命中
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
else:
return False
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#獲取某個對象在畫布的座標,返回一個數組(兩個座標,左上角的座標和右下角的兩個座標)
pos = self.canvas.coords(self.id)
##縱軸控制##
#如果最上面的縱軸座標在頂上,則往下移動一個像素
if pos[1] <= 0:
self.y = 1
#如果最下面的縱軸座標在底上,則向上移動
#if pos[3] > self.canvas_height:
#self.y = -1
if pos[3] >= self.canvas_height:
self.hit_bottom_count = self.hit_bottom_count + 1
self.y = -1
#這兒加入球拍的位置,如果到了球拍的底部也要彈回去,通過加入一個函數來判斷,在draw之前
if self.hit_paddle(pos) == True:
self.y = -1
##寬度控制##
#如果在左邊框了,那麼向右邊移動3像素
if pos[0] <= 0:
self.x = 3
#如果到右邊框了,左移動3像素
if pos[2] > self.canvas_width:
self.x = -3
#
#創建一個球拍類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
#這個函數綁定一個事件,來實現小球用鍵盤來控制左右移動,當移動到邊界的時候要停止移動
def draw(self,event):
pos = self.canvas.coords(self.id)
if event.keysym == 'Left':
if pos[0] <= 0:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,-100,0)
if event.keysym == 'Right':
if pos[2] >= self.canvas_width:
self.canvas.move(self.id,0,0)
else:
self.canvas.move(self.id,100,0)
print(event.keysym)
def main():
#創建對象
paddle = Paddle(canvas,'blue')
ball = Ball(canvas,paddle,'red')
#一直保持循環
while 1:
#用一個變量來判斷是否曾接觸過底部,默認沒接觸過
if True == True:
if ball.hit_bottom_count <= 1 :
#點擊球拍開始
is_begin = True
ball.draw()
#給球拍綁定事件
canvas.bind_all('<KeyPress-Left>',paddle.draw)
canvas.bind_all('<KeyPress-Right>',paddle.draw)
else:
#遊戲結束後,閃爍遊戲結束提示
for i in range(1,20):
time.sleep(0.5)
endmsg=canvas.create_text(250,200,text = 'Game Over!',font =('Times',50),fill = 'red')
tk.update()
time.sleep(0.5)
canvas.itemconfig(endmsg,state = 'hidden')
tk.update()
tk.update_idletasks()
break
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.005)
if __name__ == "__main__":
main()
繼續進行功能擴展
加入如下功能:
- 點擊球拍開始遊戲
- 計分功能
- 加速功能
- 結束提醒功能
'''
#########################
#之前做的畫面沒有互動,這次加入一個球拍,使之能把下落的球給擋回去,同時較少main處的代碼,儘量都放到類中來實現,以符合高內聚低耦合原則
######################
'''
from tkinter import *
import random
import time
#創建畫布
tk = Tk()
tk.title("Game_ball")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
#bd=0,highlightthickness=0 畫布之外沒有邊框
canvas = Canvas(tk,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
'''
#
#創建一個類,這個類含有如下參數:畫布,被擊中的球拍paddle,球的顏色,擊中次數score
#
'''
class Ball:
#這個地方要獲取paddle的數據,所以要把paddle對象作爲一個參數傳遞進來
def __init__(self,canvas,paddle,color,score):
self.canvas = canvas
self.paddle = paddle
self.score = score
self.id = canvas.create_oval(10,10,25,25,fill=color)
self.canvas.move(self.id,245,100)
#來回反彈
#--self.x = 0
#--self.y = -1
starts = [-3,-2,-1,1,2,3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#winfo_height()函數來獲取畫布當前的高度,賦值給對象變量
self.canvas_height = self.canvas.winfo_height()
#獲取X軸座標
self.canvas_width = self.canvas.winfo_width()
#剛開始沒有接觸到底部
self.hit_bottom_count = 0
#fun:判斷是否擊中球拍的函數,擊中返回True,不然返回false
#函數的擦數要獲取球拍的位置,然後和小球的位置來判斷
def hit_paddle(self,pos):
paddle_pos = canvas.coords(self.paddle.id)
#這個地方來講一下判斷規則,現在我們獲取了兩個球和拍子兩個對象在畫布中的座標,通過對座標來判斷是否撞拍
#先判斷橫座標:如果小球的最左邊pos[0]的值大於等於拍子最左邊的值,且球最右邊的座標的值pos[2]小於拍子最右邊的值,那麼橫向是命中的
if pos[0] >= paddle_pos[0] and pos[2] <= paddle_pos[2]:
#縱向判斷:小球的最下邊的值位於球拍的pos[3]上底和下底之間,則縱向命中
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
#此處調用的score類的getScore函數得分,把計算得分的功能讓得分類來實現,通過對象引用獲取某個對象的得分,就相當於球這個對象有了分的屬性
self.score.getScore()
return True
else:
return False
def draw(self):
self.canvas.move(self.id,self.x,self.y)
#獲取某個對象在畫布的座標,返回一個數組(兩個座標,左上角的座標和右下角的兩個座標)
pos = self.canvas.coords(self.id)
##縱軸控制##
#如果最上面的縱軸座標在頂上,則往下移動一個像素
if pos[1] <= 0:
self.y = 1
#如果最下面的縱軸座標在底上,則向上移動
#if pos[3] > self.canvas_height:
#self.y = -1
if pos[3] >= self.canvas_height:
self.hit_bottom_count = self.hit_bottom_count + 1
self.y = -1
#這兒加入球拍的位置,如果到了球拍的底部也要彈回去,通過加入一個函數來判斷,在draw之前
if self.hit_paddle(pos) == True:
self.y = -1
##寬度控制##
#如果在左邊框了,那麼向右邊移動3像素
if pos[0] <= 0:
self.x = 3
#如果到右邊框了,左移動3像素
if pos[2] > self.canvas_width:
self.x = -3
'''
#
#創建一個球拍類,這個類含有兩個參數,一個是畫布,一個是球的顏色
#
'''
class Paddle:
def __init__(self,canvas,color):
self.canvas = canvas
self.id = self.canvas.create_rectangle(0,0,100,10,fill = color)
self.canvas.move(self.id,200,300)
self.x = 0
self.is_start = False
self.canvas_width = self.canvas.winfo_width()
self.canvas.bind_all('<KeyPress-Left>',self.turn_left)
self.canvas.bind_all('<KeyPress-Right>',self.turn_right)
self.canvas.bind_all('<Button-1>',self.start_game)
#這個函數綁定一個事件,來實現小球用鍵盤來控制左右移動,當移動到邊界的時候要停止移動
#應該把檢測是否過線的判斷放在這個地方,因爲只有按鍵的時候才觸發判斷,
def draw(self):
self.canvas.move(self.id,self.x,0)
pos = self.canvas.coords(self.id)
if pos[0] <= 0 :
self.x = 0
elif pos[2] >= self.canvas_width:
self.x = 0
def turn_left(self,evt):
self.x = -3
return self.x
def turn_right(self,evt):
self.x = 3
return self.x
def start_game(self,evt):
self.is_start = True
return self.is_start
'''
#
##得分類,有2個屬性,畫布和顏色;一個方法,得分方法
#
'''
class Score:
def __init__(self,canvas,color):
self.score = 0
self.canvas = canvas
self.id = canvas.create_text(450,10,fill = color,text= self.score,)
def getScore(self):
self.score += 1
#改變得分
self.canvas.itemconfig(self.id,text = self.score)
def main():
#創建對象
score = Score(canvas,'green')
paddle = Paddle(canvas,'blue')
ball = Ball(canvas,paddle,'red',score)
endmsg=canvas.create_text(250,200,text = 'Game Over!',font =('Times',50),fill = 'red',state = 'hidden')
#ball2 = Ball(canvas,paddle,'green')
#一直保持循環
while 1:
#用一個變量來判斷是否曾接觸過底部,默認沒接觸過
if ball.hit_bottom_count <= 4 and paddle.is_start == True:
#點擊球拍開始
#is_begin = True
ball.draw()
#ball2.draw()
paddle.draw()
if ball.hit_bottom_count > 4:
canvas.itemconfig(endmsg,state='normal')
#快速刷新屏幕
tk.update_idletasks()
tk.update()
time.sleep(0.005)
if __name__ == "__main__":
main()