# 桌上曲棍球小遊戲教學
---
### 遊戲完成圖

---
## 基本設置
### 視窗中心座標為(0,0)
```python=
import turtle #導入turtle函式庫
wn = turtle.Screen() #宣告一個wn變數為turtle物件中的screen類別
wn.title("桌上曲棍球對戰") #使用turtle函式設定遊戲視窗名字
wn.bgcolor("black") #設定背景顏色
wn.setup(width=800, height=600) #設定視窗寬度(width)、高(height)
wn.tracer(0) #阻止視窗自動更新
```
---
## 握把
```python=
paddle_a = turtle.Turtle() #宣告一個握把物件
paddle_a.speed(0) #改變物件繪圖的速度
paddle_a.shape("square") #預設square形狀為 20*20 像素
paddle_a.color("white") #改變物件的顏色
paddle_a.penup() #使物件移動時不留下痕跡
paddle_a.shapesize(stretch_wid=5, stretch_len=1) #延伸物件大小
paddle_a.goto(-350, 0) #設定物件位置
```
---
### 握把的移動
```python=
def paddle_a_up():
y = paddle_a.ycor() #宣告y變數為a握把的核心y座標
y+=20
paddle_a.sety(y) #將a握把的y核心位置設定到y
```
---
### 製作球
```python=
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.2 #設置球 X 座標移動速度
ball.dy = 0.2 #設置球 Y 座標移動速度
```
---
### 使鍵盤輸入可以被讀取
```python=
wn.listen()#讓視窗開始讀取鍵盤輸入
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
wn.onkeypress(paddle_b_up, "Up")
wn.onkeypress(paddle_b_down, "Down")
```
---
## 計分系統
```python=
# 記分板
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle() #隱藏物件
pen.goto(0, 260)
pen.write("玩家 1: 0 玩家 2: 0",
align="center",
font=("Courier", 24, "normal")) #列印記分板
```
---
## 遊戲主程式
- 把遊戲叫出來
- 邊框的反彈&計分
- 握把碰撞判定
---
### 開啟遊戲
```python=
while 1:
wn.update()#更新視窗
#讓球動起來
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)
```
---
### 邊框的反彈&計分
```python=
#上邊框
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
#下邊框
elif ball.ycor() < -285:
ball.sety(-285)
ball.dy *= -1
```
---
```python=
#左邊框
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear() #清除記分板
pen.write("玩家 1: %d 玩家 2: %d" % (score_a, score_b), align="center", font=("Courier", 24, "normal"))
```
---
```python=
#右邊框
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear() #清除記分板
pen.write("玩家 1: %d 玩家 2: %d" % (score_a, score_b), align="center", font=("Courier", 24, "normal"))
ball.goto(0, 0)
ball.dx *= -1
```
---
### 握把的碰撞判定
```python=
if ball.xcor() < -340 and ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50:
ball.dx *= -1
if ball.xcor() > 340 and ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50:
ball.dx *= -1
```
---
## 完成程式碼
```python=
import turtle
wn = turtle.Screen()
wn.title("Game")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0) # 阻止視窗更新(手動更新可以以更快的方式製作遊戲)
# 分數
score_a = int(0)
score_b = int(0)
# 槓桿 A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square") # basic 20*20 像素
paddle_a.color("white")
paddle_a.penup() # 使其移動時不留下痕跡
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.goto(-350, 0)
# 槓桿 B
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.penup()
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.goto(350, 0)
# 球
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.1 # 設置球 X 座標移動速度
ball.dy = 0.1 # 設置球 Y 座標移動速度
# 記分板
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle() # 隱藏物件
pen.goto(0, 260)
pen.write("玩家 1: 0 玩家 2: 0", align="center",
font=("Courier", 24, "normal")) # 列印記分板
# 函式
def paddle_a_up():
y = paddle_a.ycor()
y += 20
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y -= 20
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
y += 20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
y -= 20
paddle_b.sety(y)
# 鍵盤輸入
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
wn.onkeypress(paddle_b_up, "Up")
wn.onkeypress(paddle_b_down, "Down")
# 遊戲主程式
while 1:
wn.update()
# 讓球動起來
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)
# 讓球反彈
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -285:
ball.sety(-285)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear() # 清除記分板
pen.write("玩家 1: %d 玩家 2: %d" % (score_a, score_b),
align="center", font=("Courier", 24, "normal"))
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear() # 清除記分板
pen.write("玩家 1: %d 玩家 2: %d" % (score_a, score_b),
align="center", font=("Courier", 24, "normal"))
# 槓桿反彈
if ball.xcor() > 340 and ball.xcor() < 360 and (ball.ycor() < paddle_b.ycor() + 40 and ball.ycor() > paddle_b.ycor() - 40):
ball.setx(340)
ball.dx *= -1
if ball.xcor() < -340 and ball.xcor() > -360 and (ball.ycor() < paddle_a.ycor() + 40 and ball.ycor() > paddle_a.ycor() - 40):
ball.setx(-340)
ball.dx *= -1
```
{"metaMigratedAt":"2023-06-17T21:15:55.206Z","metaMigratedFrom":"YAML","title":"桌上曲棍球小遊戲教學","breaks":true,"slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"b405d87d-0698-478c-9009-9939bd969d2c\",\"add\":3169,\"del\":438},{\"id\":\"83f5b3e0-d6bd-4eaf-bceb-fc6a8dfdeecf\",\"add\":1782,\"del\":621},{\"id\":\"4d8ac2d3-29c7-4a8e-a906-e7cdf0999b25\",\"add\":1609,\"del\":180},{\"id\":\"ca056cfc-4faf-46a7-8aa9-ef58b3a12a53\",\"add\":22,\"del\":4}]"}