python遊戲初探:拍子打小球

根據前面慢屏幕亂跑的小球,改編一個彈球遊戲,下面加一個球拍,當球碰到拍子的時候彈回去

版本一

目前這個實現的功能是:加入了一拍子,可以用鍵盤來左右控制移動


#########################
#之前做的畫面沒有互動,這次加入一個球拍,使之能把下落的球給擋回去,目前功能加入了一拍子,可以用鍵盤來左右控制移動
######################
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()

繼續進行功能擴展

加入如下功能:

  1. 點擊球拍開始遊戲
  2. 計分功能
  3. 加速功能
  4. 結束提醒功能
'''
#########################
#之前做的畫面沒有互動,這次加入一個球拍,使之能把下落的球給擋回去,同時較少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()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章