ピンボールゲームを実現するためのPythonの楽しい開発を追ってみましょう
ゲーム実行効果
実装プロセス
1. ゲームキャンバスの作成(ボールクラスの作成)
2. いくつかのアクションを追加します (ボールを移動させたり、ボールを前後にバウンドさせたり、ボールの開始方向を変更したり)
3. ラケットを加えてラケットを左右に動かします(円運動)
4. 勝敗の要素を増やす(ボールの位置判断)
ゲームキャンバスを作成する
インポートツールキット tkinter、ランダム、時間
from tkinter import * # 弹球游戏的画布
import random
import time
tk オブジェクトの title 関数を使用し、tk.title("") を通じてウィンドウにタイトル「Pinball Game」を追加します。
サイズ変更可能関数を使用してウィンドウをサイズ変更不可にします。このうち、0,0はウィンドウのサイズを横方向、縦方向に変更できないことを意味します。
Canvas= を使用して Canvas オブジェクトを作成します。
Canvas.pack() 行は、前の行で指定された幅と高さのパラメータに従ってキャンバス自体のサイズを変更するように指示します。
tk.update() は、ゲーム内アニメーション用に tkinter を初期化します。この最後の行がないと、期待どおりの結果が得られません。
tk = Tk()
tk.title("弹球小游戏")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
tk.update()
1. Ball というクラスを作成します。このクラスには 2 つのパラメータがあり、1 つはキャンバス、もう 1 つはボールの色です。
2. キャンバスをオブジェクト変数に保存します。
3. カラーパラメータを塗りつぶし色として使用して、キャンバス上に小さなボールを描画します。
4. 画面上でボールを移動するために使用するため、tkinter がボールを描画するときに返された ID を保存します。
class Ball:
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)
starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
#把y改成-3 ,让小球飞快一点,我们需要再改动几个地方来保证小球不会从屏幕两边消失。
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
#在_init_函数的结尾加上下面的代码来把画布的宽度保存到一个新的对象变量canvas_width 中
self.hit_bottom = False
アニメーション ループを追加する必要があります。「メイン ループ」はプログラムの中心部分であり、一般的に言えば、プログラムの動作のほとんどを制御します。現在のメインループは、tkinter に画面を再描画させるだけです。このループは実行を続け、tkinter による画面の再描画を続けた後、100 分の 1 秒間停止します (プログラムの最後に追加します)。
paddle = Paddle(canvas, 'green') # 创建一个绿色的球拍
ball = Ball(canvas, paddle, 'yellow') # 创建一个黄色的小球
while 1:
if ball.hit_bottom == False:
ball.draw()
paddle.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)
いくつかのアクションを追加する
移動するには 3 つのパラメータを渡します。id は楕円の ID で、x、y です。x は水平に移動しないことを意味し、y は画面上で 1 ピクセル上に移動することを意味します。
この新しいオブジェクト変数を描画関数で使用して、ボールがキャンバスの上部に当たったか下部に当たったかを判断します。
追加したコードは、hit_paddle が true を返した場合、オブジェクト変数を self.y = -3 で -3 に変更し、方向を変更できるようにすることを示しています。
def draw(self):
self.canvas.move(self.id, self.x, self.y)
pos = self.canvas.coords(self.id)
if pos[1] <= 0:
self.y = 3
if pos[3] >= self.canvas_height:
self.hit_bottom = True
if self.hit_paddle(pos) == True:
self.y = -3
if pos[0] <= 0:
self.x = 3
if pos[2] >= self.canvas_width:
self.x = -3
ボールを跳ね返す
跳ねるボールを打つものが何もないと面白くない
これらの新しく追加されたコードは、create_rectangle を呼び出し、長方形を水平方向に 200、300、200 ピクセル、垂直方向に 300 ピクセルの座標に移動した点を除いて、Ball クラスとほぼ同じです。
まず、オブジェクト変数 x を Paddle クラスの _init_ 関数に追加し、キャンバスの幅を保存する変数を追加します。これは、前の Ball クラスで行ったのと同じです。
次の 2 行のコードを使用して、これら 2 つの関数に正しいキーをバインドします。Paddle クラスの数値 tum_left を左矢印キーにバインドします。次に、関数 tum right を右矢印キーにバインドします。
class Paddle:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = 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()
self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
2 つの関数を使用して、左方向 (turn_left) と右方向 (turn_right) に方向を変更します。描画関数の後に追加します。
def turn_left(self, evt):
self.x = -5
def turn_right(self, evt):
self.x = 5
勝敗要因を増やす
今度は、プログラムをただ弾むボールとパドルだけでなく、楽しいゲームに変えてみましょう。ゲームにちょっとした勝利要因を追加する
このループは、ボールが画面の下部に到達したかどうかを常にチェックします (hit_bottom)。if ステートメントに見られるように、ボールがまだ底に到達していないと仮定すると、コードはボールとパドルを動かし続けます。ボールとラケットは、ボールが底に触れない場合にのみ移動します。ボールとラケットの動きが止まったらゲームは終了します。
コード表示(自己収集が必要)
from tkinter import * # 弹球游戏的画布
import random
import time
class Ball:
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)
starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
self.hit_bottom = False
def hit_paddle(self, pos):
paddle_pos = self.canvas.coords(self.paddle.id)
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
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 = 3
if pos[3] >= self.canvas_height:
self.hit_bottom = True
if self.hit_paddle(pos) == True:
self.y = -3
if pos[0] <= 0:
self.x = 3
if pos[2] >= self.canvas_width:
self.x = -3
class Paddle:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = 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()
self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
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 = -5
def turn_right(self, evt):
self.x = 5
class setup:
def setup_game(self):
self.text = self.canvas.create_text(260, 200, text='单击鼠标左键开始游戏', font=('Helvetica', 36))
# 将鼠标左键单击与开始游戏绑定在一起
self.canvas.bind('<Button-1>', lambda start_game: self.start_game())
tk = Tk()
tk.title("弹球小游戏")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
tk.update()
paddle = Paddle(canvas, 'green') # 创建一个绿色的球拍
ball = Ball(canvas, paddle, 'yellow') # 创建一个黄色的小球
while 1:
if ball.hit_bottom == False:
ball.draw()
paddle.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)