タートルグラフィックスで学ぶ Python のキホン 第 11 章
教材コード
第 11 章

文字と姿を切り替えて動かす

線を引くだけが絵ではありません.文字・姿・足跡・塗りで,作品に仕上げます.

ここまで,かめは線を引く道具でした.今回はそれ以外の表現手段を覚えます. 画面に文字を書く,かめの姿を変える, その場に足跡(スタンプ)を押す,図形の内側を塗る. 命令はどれも 1 行で書けるものばかりですが,組み合わせると 「プログラムの出力」ではなく「作品」に見えてきます.

とくに大事なのが write です. 第 12 章でゲームを作るとき,スコアや残り時間を画面に出すのに必ず使います. 数が変わるたびに書き換える方法まで,ここで押さえておきましょう.

この章でできるようになること
  • write で画面に文字を書き,大きさ・書体・そろえ方を指定できる
  • f-string で数と文字をつなげて表示できる
  • clear() して書き直すことで,スコア表示を更新できる
  • shape・shapesize・color でかめの見た目を変えられる
  • stamp・dot・begin_fill で図形を「置く」「塗る」ことができる
  • 姿を順番に切り替えて,ぱらぱら漫画のようなアニメーションが作れる
前の章とのつながり 前の章(第 10 章)は ontimer で動かすことを覚えました. 今回は見せることがテーマです. 最後の節で 2 つを合わせて,「動いて,数字が増えていく画面」を作ります. 前の章と同じく def step(): と global が出てきますが, まだ決まり文句のままで大丈夫です. 仕組みは第 13 章・第 14 章でしっかり習います.

11.1 画面に文字を書く — write

11.1.1 write の基本

write("文字") と書くと,かめが今いる場所に文字が書かれます. ペンが上がっていても下がっていても関係なく書かれますし,かめは動きません.

write1.py
from turtle import *

ht()                    # かめの姿は消しておく

write("こんにちは")

pu()
goto(0, -40)
write("Hello, turtle!")

done()
こんにちはHello, turtle!
図 11.1 write は「今いる場所」に文字を書く.かめは動かないので,次の行を書くには自分で移動する.
ヒント 文字は書いた場所から右へ,上に向かって伸びます. かめの位置が文字の左下だと思ってください. だから 2 行目を書くときは,goto で y を下げてから書きます.

11.1.2 大きさと書体を変える — font

既定の文字はとても小さいので,実際にはほとんどいつも font= を付けて使います.書き方は決まっていて, (書体の名前,大きさ,太さ)の 3 つを丸かっこで並べます.

font の書き方
write("スコア", font=("Arial", 20, "bold"))
#                 ~~~~~~~  ~~  ~~~~~~
#                 書体     大きさ  太さ
書く場所書けるもの説明
書体"Arial" "Times" "Courier" "Georgia" など文字の形.日本語はどの指定でも表示できる書体に置き換わる
大きさ8 16 24 40 …数が大きいほど大きい文字になる.画面いっぱいなら 40〜60 くらい
太さ"normal" "bold" "italic"bold は太字,italic は斜体
write2.py
from turtle import *

ht()
pu()

goto(-240, 60)
write("normal 28", font=("Arial", 28, "normal"))

goto(-240, 10)
write("bold 28", font=("Arial", 28, "bold"))

goto(-240, -40)
pencolor("crimson")
write("bold 44", font=("Arial", 44, "bold"))

done()
normal 28bold 28bold 44
図 11.2 大きさ・太さ・色を変えた文字.色は pencolor で決まる.
文字の色はペンの色 文字の色は write では指定しません. そのときのペンの色(pencolor)で書かれます. 色を変えたいときは,write の前に pencolor("crimson") のように書いてください.

11.1.3 位置をそろえる — align

align= を付けると,かめの位置に対して文字をどうそろえるかを指定できます. "left"(既定・かめの右へ伸びる),"center"(かめを中心に左右へ), "right"(かめの左へ伸びる)の 3 つです.

align.py
from turtle import *

ht()
pensize(2)
pencolor("#c0c6d0")

# 目印の枠と中心線を引く
pu()
goto(-200, -90)
pd()
goto(200, -90)
goto(200, 120)
goto(-200, 120)
goto(-200, -90)
pu()
goto(0, 120)
pd()
goto(0, -90)

pencolor("black")
pu()

goto(0, 70)
write("left", align="left", font=("Arial", 26, "normal"))

goto(0, 10)
write("center", align="center", font=("Arial", 26, "normal"))

goto(0, -50)
write("right", align="right", font=("Arial", 26, "normal"))

done()
leftcenterright
図 11.3 同じ x にいても align で見え方が変わる.得点を右そろえにすると,桁が増えても数字の右端がずれない.
使い分けの目安 題名は "center",得点や残り時間は "right" が定番です. 左そろえのまま数を表示すると,9 → 10 → 100 と 桁が増えるたびに文字がにじり出て,見ていて落ち着きません.

11.1.4 数と文字をつなげる — f-string

表示したいのはたいてい「スコア」ではなく 「スコア: 120」のように,文字と変数の組み合わせです. Python では文字列の前に f を付け, 変数を { } でくくって埋め込みます.これを f-string(エフ文字列)といいます.

f-string の書き方
score = 120

write(f"スコア: {score}")          #  スコア: 120
write(f"あと {60 - 15} 秒")        #  あと 45 秒       (計算も書ける)
write(f"{score} 点 / {200} 点満点")  #  120 点 / 200 点満点
f-string のつまずきどころ
  • 先頭の f を書き忘れると,{score} がそのまま文字として出ます.出力がおかしいときはまずここを疑ってください.
  • { } の中に書くのは変数か式です.{"score"} のようにクォートで囲むと,ただの文字になってしまいます.
  • write("スコア: " + score) はエラーになります.文字と数はそのままではつなげません(str(score) が要ります).f-string ならその手間が要りません.
fstring.py
from turtle import *

ht()
pu()

name = "たろう"
score = 1280
stage = 3

# 目印の枠
goto(-270, -100)
pd()
pensize(2)
pencolor("#c0c6d0")
goto(270, -100)
goto(270, 120)
goto(-270, 120)
goto(-270, -100)
pu()
pencolor("black")

goto(-250, 60)
write(f"プレイヤー: {name}", font=("Arial", 26, "normal"))

goto(-250, 0)
pencolor("crimson")
write(f"スコア: {score}", font=("Arial", 34, "bold"))

goto(-250, -60)
pencolor("navy")
write(f"ステージ {stage} / 全 8 面", font=("Arial", 22, "normal"))

done()
プレイヤー: たろうスコア: 1280ステージ 3 / 全 8 面
図 11.4 変数の中身が文字の中に埋め込まれる.score の値を変えれば表示も変わる.
虫食い虫食い 11-A 名札を作る

名前と学年を画面の中央にそろえて表示します. ____ を埋めてください. 中央ぞろえにするのは align,太字の 40 ポイントにするのは font,変数を埋め込むのは f-string でしたね.

fill9_nametag.py
from turtle import *

ht()
pu()

name = "おのみち はなこ"
grade = 1

goto(0, 20)
pencolor("navy")
write(name, align="____", font=("Arial", ____, "bold"))

goto(0, -40)
pencolor("dimgray")
write(f"情報工学科 {____} 年", align="center", font=("Arial", 22, "normal"))

done()

11.2 書いた文字を書き換える

ここが今回いちばん大事なところです. write で書いた文字は絵の具のように画面に焼き付きます. 同じ場所にもう一度書いても,前の文字は消えません.重なって読めなくなるだけです.

overlap.py
from turtle import *

ht()
pu()
goto(-120, 0)

write("スコア: 0", font=("Arial", 36, "bold"))
write("スコア: 120", font=("Arial", 36, "bold"))    # 上に重なるだけ

done()
スコア: 0スコア: 120
図 11.5 同じ場所に 2 回書いた結果.前の文字は消えない.

11.2.1 clear() して書き直す

書いた文字を 1 つだけ選んで消す命令はありません.そこで clear() で,そのかめが書いたものを消してから,もう一度書く という方法をとります.テレビの画面を毎回描き直すのと同じ考え方です.

rewrite.py
from turtle import *

ht()
pu()

# 1 回目の表示
goto(-120, 0)
write("スコア: 0", font=("Arial", 36, "bold"))

# このかめが書いたものを消す
clear()

# 2 回目の表示
goto(-120, 0)
pencolor("crimson")
write("スコア: 120", font=("Arial", 36, "bold"))

done()
スコア: 120
図 11.6 clear() をはさむと,最後に書いたものだけが残る.
clear() は文字だけを消すのではない clear() は,そのかめが描いた線・文字・はんこをまとめて消します. 同じかめで背景の絵も描いていると,背景まで消えてしまいます. 方法は 2 つです. 1 つは,1 コマぶんの絵を毎回まるごと描き直すと決めてしまうこと. 次の節のプログラムがその形になっています. もう 1 つは,pen = Turtle() のように文字専用のかめを作り, pen.clear() でそのかめが書いた文字だけを消すことです (ほかのかめが描いた背景は残ります).

11.2.2 増えていくスコアを表示する

前の章の ontimer と組み合わせます. 「消す → 数を計算する → 書く」を 0.5 秒ごとに繰り返すと, 数字が増えていく表示になります.これをカウンターといいます.

counter.py
from turtle import *

ht()
score = 0

def step():
    global score

    clear()                 # 前のコマを消す

    pu()
    goto(0, 20)
    pencolor("navy")
    write(f"スコア: {score}", align="center", font=("Arial", 40, "bold"))

    goto(0, -50)
    pencolor("dimgray")
    write("0.5 秒ごとに 10 点ずつ増えます", align="center",
          font=("Arial", 18, "normal"))

    score = score + 10      # 次のコマの準備
    ontimer(step, 500)      # 0.5 秒後にもう一度 step を呼ぶ

step()
done()
global を忘れずに global score は,「この関数の中で使う score は, 関数の外にあるあの score のことだ」という宣言です. これを書かないと,関数の中だけで通用する別の変数ができてしまい, 数がいつまでも増えません.関数の中で外の変数を書き換えるときに必要です. 第 10 章と同じ決まり文句です. 「書き換える外の変数は 1 行目に global で並べる」とだけ覚えておけば, 今回は困りません(仕組みは第 13 章で習います).

やってみよう:ontimer(step, 500) の 500 を 100 にすると どうなるでしょうか.score + 10 を score + 1 にしたら? clear() の行を # でコメントにすると,何が起きるでしょうか.

虫食い虫食い 11-B カウントダウン

10 から 1 ずつ減っていくカウントダウンを作ります. ____ を埋めてください. 毎コマ消すことと,外の変数を書き換える宣言を 忘れないでください.

ヒント 0 になったら「ぼかーん!!」と出して止めます. 止めるには,ontimer を呼ばなければよいだけです.
fill9_countdown.py
from turtle import *

ht()
rest = 10

def step():
    ____ rest

    ____()                 # 前のコマを消す

    pu()
    goto(0, 0)
    if rest > 0:
        pencolor("navy")
        write(f"あと {____}", align="center", font=("Arial", 60, "bold"))
        rest = rest - 1
        ontimer(step, ____)     # 1 秒後
    else:
        pencolor("crimson")
        write("ぼかーん!!", align="center", font=("Arial", 60, "bold"))

step()
done()

11.3 かめの見た目を変える — shape

11.3.1 姿を選ぶ

shape("名前") で,かめの姿を選べます.使える姿は,次の 6 つと, 何も描かない "blank" の 7 種類です(第 8 章).

図 11.7 "classic"(最初の姿)
図 11.8 "turtle"
図 11.9 "arrow"
図 11.10 "circle"
図 11.11 "square"
図 11.12 "triangle"
ヒント このほかに shape("blank") があります.姿が何も描かれなくなるので, ht() と似た働きをします(ただし stamp も押せなくなります).

11.3.2 大きさを変える — shapesize

shapesize(縦, 横) で姿を拡大・縮小します. 1 つ目の数は進む向きに直角な方向(右を向いているときは画面の縦),2 つ目の数は進む向きの方向(右を向いているときは画面の横)の倍率です. shapesize(3) のように 1 つだけ書くと,縦横とも同じ倍率になります.

shapesize.py
from turtle import *

shape("turtle")
color("seagreen")

pu()
goto(-180, 0)
shapesize(1)
stamp()          # 等倍

goto(-60, 0)
shapesize(2)
stamp()          # 2 倍

goto(80, 0)
shapesize(3)
stamp()          # 3 倍

goto(220, 0)
shapesize(1, 4)  # 縦 1 倍・横 4 倍(平たいかめ)
stamp()

ht()
done()
図 11.13 shapesize で大きさが変わる.いちばん右は縦横の倍率を別々にしたもの.

11.3.3 姿の色 — color / fillcolor / pencolor

姿の色は 2 つに分かれています.内側の色が fillcolor,ふちの色が pencolor です. color("赤") と 1 つだけ書くと両方が, color("赤", "白") と 2 つ書くとふち・内側の順に決まります.

shapecolor.py
from turtle import *

shape("circle")
shapesize(3)

pu()
goto(-160, 0)
color("crimson")            # ふちも内側も赤
stamp()

goto(0, 0)
color("crimson", "white")   # ふちは赤・内側は白
stamp()

goto(160, 0)
color("navy", "gold")       # ふちは紺・内側は金
stamp()

ht()
done()
図 11.14 color の引数が 1 つのときと 2 つのときの違い.
注意 color はペンの色も一緒に変えます. 姿だけ赤くしたつもりが線まで赤くなった,というのはよくある勘違いです. 線の色を変えたくないときは fillcolor("red") を使ってください.
虫食い虫食い 11-C 信号機

3 つの丸を横に並べて信号機を作ります. ____ を埋めてください. 丸の姿は "circle",大きさは shapesize で 4 倍, 左の丸の色は "red",置くのは stamp() でしたね.

fill9_signal.py
from turtle import *

bgcolor("#222831")
shape("____")
shapesize(____)

pu()

goto(-110, 0)
color("____")        # 赤
stamp()

goto(0, 0)
color("gold")
____()

goto(110, 0)
color("limegreen")
stamp()

ht()
done()

11.4 足跡を残す — stamp

11.4.1 stamp でその場に姿を押す

stamp() は,今の姿・今の色・今の大きさ・今の向きのまま, その場にはんこを押します.かめ自身は動きません. 線を引かずに形を並べるときにとても便利です.

stamp.py
from turtle import *

shape("turtle")
color("seagreen")
shapesize(1.5)
pu()                    # 線は引かない

goto(-220, -60)

for i in range(8):
    stamp()             # その場に足跡を残す
    fd(56)
    lt(12)              # 少しずつ向きを変える

ht()
done()
図 11.15 pu() で線を消し,stamp だけを並べた.向きも一緒に記録されるので,弧を描いて進む様子が残る.
押したはんこを消す stamp() は押したはんこの番号を返します. sid = stamp() と受け取っておけば, clearstamp(sid) でそのはんこ 1 つだけを消せます. 全部まとめて消すなら clearstamps() です.

11.4.2 clearstamps で消す

clearstamps() ははんこだけを消します. clear() と違って,線や文字は残ります. 動くものは stamp,動かない背景は線で描く,と分けておくと, 毎コマ「はんこだけ消して押し直す」ことができます.

stampmove.py
from turtle import *

# --- 動かない背景(1 回だけ描く)---
pencolor("#c0c6d0")
pensize(3)
pu()
goto(-260, -120)
pd()
goto(260, -120)
pu()

# --- 動く星 ---
star = Turtle()
star.shape("triangle")
star.color("gold")
star.shapesize(2)
star.pu()
star.ht()
star.goto(-240, -80)

def step():
    star.clearstamps()      # 前の足跡だけ消す(線は残る)
    star.fd(12)
    star.lt(3)
    if star.xcor() > 260:
        star.goto(-240, -80)
        star.seth(0)
    star.stamp()
    ontimer(step, 60)

step()
done()

11.4.3 姿を切り替えて「ぱらぱら漫画」にする

なぜ画像を使わないのか もとの教材では,8 枚の絵(man1.gif …… man8.gif)を 順番に切り替えて,人が歩くぱらぱら漫画を作っていました. この教材のランタイムは画像ファイルを表示できませんので, かわりにかめの姿・大きさ・色を順番に切り替えることで同じことをします. こうしておけば,画像ファイルを配る必要がなく,どの環境でもそのまま動きます. 「何コマかを用意して,順番に見せる」という考え方そのものは同じです.

コマの切り替えには,第 7 章で習った余り(%)を使います. i % 4 は 0, 1, 2, 3, 0, 1, 2, 3, … を繰り返すので, 「4 コマぶんの姿」をぐるぐる回せます.

flipbook.py
from turtle import *

ht()
bgcolor("#f6f7fb")
i = 0

man = Turtle()
man.pu()
man.goto(0, 0)
man.color("seagreen")

def step():
    global i

    # --- 1 コマの処理:i に応じて姿を変える ---
    if i % 4 == 0:
        man.shape("turtle")
        man.shapesize(2, 2)
    elif i % 4 == 1:
        man.shape("turtle")
        man.shapesize(2.6, 1.6)
    elif i % 4 == 2:
        man.shape("triangle")
        man.shapesize(2.2, 2.2)
    else:
        man.shape("triangle")
        man.shapesize(1.6, 2.8)

    i = i + 1
    ontimer(step, 150)

step()
done()

動いているものは本のページに載せられないので, 4 コマを止めて並べた図を見てください. うすい枠はどのコマも同じ大きさで描いてあります. このコマを 0.15 秒ずつ順番に見せると,中で何かがもぞもぞ動いて見えます.

① i % 4 が 0
② i % 4 が 1
③ i % 4 が 2
④ i % 4 が 3

1 コマずつ見るとただの図形ですが, 縦長・横長がかわるがわる現れるので, 切り替えると伸び縮みしているように見えます. ぱらぱら漫画は,1 コマだけ見ても何も分からないのが普通です.

やってみよう:コマ数を 4 から 6 に増やしてみましょう (i % 6 にして elif を足します). 色も一緒に変えると,もっと変化が出ます. ontimer の 150 を 400 にすると,動きがどう変わるでしょうか.

点滅させたいときは 点滅も同じやり方でできます. i % 2 == 0 のとき st(), そうでないとき ht() を呼べば,かめが点滅します.

11.4.4 背景を動かして「歩いている」ように見せる

ぱらぱら漫画だけだと,その場で足踏みしているように見えます. ここに背景を足しましょう. 人は画面の真ん中に置いたまま,背景のほうを左へ流すと, 人が右へ歩いているように見えます.

やり方は,11.2.1 でやった「消して書き直す」とまったく同じです. 毎コマ back.clear() で背景のかめが描いたものを消して, 少しだけずらした背景を描き直します. 背景を描いているのは back なので,back に clear() を呼びます. ずれの量を変数 sx で持ち, % を使って端まで行ったら先頭に戻すのがこつです.

scroll.py
from turtle import *

ht()
bgcolor("#eaf4ff")

i = 0            # 何コマ目か
sx = 0           # 背景のずれ

man = Turtle()
man.shape("turtle")
man.color("seagreen")
man.shapesize(2, 2)
man.pu()
man.goto(0, -40)

back = Turtle()  # 背景をかくかめ
back.ht()
back.pu()

def keshiki():
    """地面と木を,sx だけずらして描く"""
    back.pensize(3)
    back.pencolor("#9aa5b1")
    back.pu()
    back.goto(-290, -70)
    back.seth(0)
    back.pd()
    back.fd(580)
    for k in range(4):
        x = (k * 160 + sx) % 640 - 320      # ← 端まで行ったら先頭へ
        back.pu()
        back.goto(x, -70)
        back.seth(90)
        back.pencolor("#8d6e63")
        back.pd()
        back.fd(60)                          # 幹
        back.pu()
        back.dot(50, "#7cb342")              # 葉

def step():
    global i, sx

    back.clear()         # ① 背景のかめが描いた前のコマを消す
    sx = sx - 6          # ② 背景を少し左へずらす
    keshiki()            # ③ 背景を描き直す

    if i % 2 == 0:       # ④ 人の姿を切り替える
        man.shapesize(2.0, 2.0)
    else:
        man.shapesize(2.6, 1.6)

    i = i + 1
    ontimer(step, 120)

step()
done()
① はじめのコマ
② 13 コマ後.木が左へ流れた
③ 27 コマ後.さらに流れた

人の位置は3 コマとも同じです. 動いているのは木だけなのに,人が歩いているように見えます. 横スクロールのゲームは,どれもこの仕掛けでできています.

% で輪にする (k * 160 + sx) % 640 - 320 の % が効かせどころです. sx をどんどん小さくしても, % 640 で 0〜639 に折り返されるので, 木は画面の左端から消えると右端から出てきます. 第 7 章で習った「あまり」が,ここで輪のような動きを作っています.
虫食い虫食い 11-D 信号の色が順に変わる

赤・黄・緑の 3 色を順番に切り替える信号機を作ります. 3 コマを繰り返したいので,3 で割った余りを使います. ____ を埋めてください.

fill9_blink.py
from turtle import *

ht()
bgcolor("#222831")
i = 0

lamp = Turtle()
lamp.shape("circle")
lamp.shapesize(5)
lamp.pu()

def step():
    global i

    if i % ____ == 0:
        lamp.color("red")
    elif i % 3 == ____:
        lamp.color("gold")
    else:
        lamp.color("____")

    i = i + 1
    ontimer(step, 700)

____()
done()

11.5 点を打つ・内側を塗る

11.5.1 dot — 丸い点を打つ

dot(大きさ, 色) は,その場に丸い点を打ちます. stamp と違って向きは関係なく,いつでもまん丸です. 大きさは直径(ピクセル),色は省略するとペンの色になります.

dot.py
from turtle import *

ht()
pu()

goto(-200, 0)
dot(20, "crimson")

goto(-100, 0)
dot(40, "darkorange")

goto(30, 0)
dot(70, "gold")

goto(180, 0)
dot(100, "#4c9f70")     # 16 進数でも指定できる

done()
図 11.16 dot は直径と色を指定して打つ.

11.5.2 begin_fill と end_fill — 内側を塗る

図形の内側を塗るには,描き始める前に begin_fill(), 描き終わったら end_fill() と書きます. この 2 つにはさまれた部分でかめが通った道のりが,1 つの図形として塗られます. 塗る色は fillcolor(または color の 2 つめ)です.

塗りつぶしの型
fillcolor("gold")
begin_fill()
# ← ここで図形を描く
end_fill()
fillshape.py
from turtle import *

ht()
pensize(3)
pu()

# 塗った正方形
goto(-220, -70)
pd()
pencolor("navy")
fillcolor("#8ec5ff")
begin_fill()
for i in range(4):
    fd(120)
    lt(90)
end_fill()

# 塗った星
pu()
goto(20, 40)
pd()
pencolor("darkgoldenrod")
fillcolor("gold")
begin_fill()
for i in range(5):
    fd(150)
    rt(144)
end_fill()

done()
図 11.17 begin_fill と end_fill ではさむと内側が塗られる.星のように交差する図形もきれいに塗れる.
注意 end_fill() を書き忘れるといつまでも塗られません. また,図形が閉じていなくても,始点と終点を結んだものとして塗られます. 思っていない形に塗られたときは,どこで begin_fill したかを 確かめてください.

11.5.3 色の指定 — 名前と #rrggbb

色の指定には 2 とおりあります. 名前で指定する方法と,16 進数で指定する方法です.

書き方例説明
名前"red" "gold" "seagreen" "navy" "hotpink"覚えやすい.よく使う色はだいたい名前がある
#rrggbb"#ff8800" "#222831" "#8ec5ff"赤・緑・青の強さを 00〜ff(0〜255)で並べたもの.細かい色を作れる

#rrggbb は最初とっつきにくいですが,考え方は単純です. #ff0000 は赤だけ全開なので赤,#00ff00 は緑, #0000ff は青.3 つとも同じ値なら灰色で, #000000 が黒,#ffffff が白になります.

図 11.18 赤の強さを変えた(#rr0000)
図 11.19 3 つとも同じ値にすると灰色

11.5.4 背景色を変える — bgcolor

bgcolor("色") で画面全体の背景色を変えられます. 背景を暗くして明るい色で描くと,まるで別の作品のように見えます. プログラムのいちばん最初に書くのが普通です.

bgcolor.py
from turtle import *

bgcolor("#1b2430")      # 濃い紺

ht()
pu()

goto(0, 40)
pencolor("#ffd369")
write("MIDNIGHT", align="center", font=("Arial", 48, "bold"))

goto(0, -20)
pencolor("#eeeeee")
write("背景を変えるだけで雰囲気が変わる", align="center",
      font=("Arial", 20, "normal"))

# 星をちりばめる
goto(-240, 120)
dot(8, "white")
goto(-160, 150)
dot(5, "white")
goto(190, 130)
dot(7, "white")
goto(230, -120)
dot(5, "white")
goto(-210, -130)
dot(6, "white")

done()
MIDNIGHT背景を変えるだけで雰囲気が変わる
図 11.20 bgcolor で背景を変えた画面.
虫食い虫食い 11-E 塗った六角形

オレンジで塗りつぶした正六角形を,濃い背景の上に描きます. ____ を埋めてください. 正六角形の曲がる角度は 360 ÷ 6 でしたね.

fill9_hexfill.py
from turtle import *

____("#2b2b3c")          # 背景を濃くする

ht()
pensize(4)
pencolor("#ffd369")
____("#ff8800")          # 塗る色

pu()
goto(-70, -60)
pd()

____()                   # 塗り始め
for i in range(6):
    fd(120)
    rt(____)
____()                   # 塗り終わり

done()

11.6 組み合わせて作品にする

11.6.1 ポスターを作る

ここまでの命令を全部使うと,1 枚のポスターが作れます. 作るときの順番は,背景 → 帯や飾り → 文字です. 文字を先に書くと,あとから描いた図形に隠れてしまいます.

poster.py
from turtle import *

bgcolor("#10203a")
ht()
pu()

# --- 上の帯を塗る ---
fillcolor("#ffd369")
goto(-290, 60)
begin_fill()
goto(290, 60)
goto(290, 150)
goto(-290, 150)
goto(-290, 60)
end_fill()

# --- 飾りの点 ---
goto(-240, -150)
dot(26, "#ff6b6b")
goto(-180, -150)
dot(26, "#4ecdc4")
goto(-120, -150)
dot(26, "#ffe66d")

# --- 文字 ---
goto(0, 85)
pencolor("#10203a")
write("PROGRAMMING I", align="center", font=("Arial", 42, "bold"))

goto(0, 0)
pencolor("white")
write("文字と図形で表現する", align="center", font=("Arial", 34, "bold"))

goto(0, -60)
pencolor("#9fb3c8")
write("Python とタートル", align="center", font=("Arial", 20, "normal"))

done()
PROGRAMMING I文字と図形で表現するPython とタートル
図 11.21 背景・帯・点・文字を重ねたポスター.描く順番が重なりの順番になる.
ペンを上げたまま塗る 帯は goto を 4 回続けて長方形の道をたどり, begin_fill / end_fill ではさんで塗っています. ペンを上げたままでも塗りは効きます (通った道のりが記録されるため).線を出したくないときに便利です.

11.6.2 スコアボードを作る

第 12 章のゲームで使う形です. 画面の上のほうに情報をまとめて出すとゲームらしく見えます. clear() して書き直す形に最初からしておくと,あとが楽です.

scoreboard.py
from turtle import *

bgcolor("#101820")
ht()

score = 1280
life = 3
stage = 2

def draw_board():
    pu()

    # 左:スコア
    goto(-280, 170)
    pencolor("#ffd369")
    write(f"SCORE  {score}", font=("Arial", 26, "bold"))

    # 中央:ステージ
    goto(0, 170)
    pencolor("#4ecdc4")
    write(f"STAGE {stage}", align="center", font=("Arial", 26, "bold"))

    # 右:残機(右そろえにすると桁が増えてもずれない)
    goto(280, 170)
    pencolor("#ff6b6b")
    write(f"LIFE {life}", align="right", font=("Arial", 26, "bold"))

    # 区切り線
    goto(-290, 155)
    pd()
    pencolor("#33475b")
    pensize(3)
    goto(290, 155)
    pu()

draw_board()

# プレイ画面のつもり
goto(0, -30)
pencolor("#9fb3c8")
write("ここがゲームの画面になる", align="center", font=("Arial", 22, "normal"))

done()
SCORE 1280STAGE 2LIFE 3ここがゲームの画面になる
図 11.22 スコアボード.左・中央・右でそろえ方を変えている.

画面を描く手順に draw_board という名前を付けてあるのが要点です. 第 10 章で覚えた def の決まり文句を,そのまま使っています. こうしておけば,スコアが変わったときに clear() → draw_board() と 2 行書くだけで表示を更新できます. 第 12 章では,まさにこの形でゲームの画面を毎コマ描き直します.

11.7 この章で出てきた命令

命令意味
write(文字)今いる場所に文字を書く
write(文字, align="center")そろえ方を指定する.left/center/right
write(文字, font=("Arial", 20, "bold"))書体・大きさ・太さを指定する
f"スコア: {score}"f-string.{ } の中の変数や式を文字に埋め込む
clear() / t.clear()そのかめが描いた線・文字・はんこを消す(かめの位置は変わらない)
shape("turtle")姿を変える.classic/turtle/circle/square/triangle/arrow/blank
shapesize(縦, 横)姿を拡大・縮小する.1 つだけ書くと縦横とも同じ倍率
color(色)ペンの色と塗りの色をまとめて変える
color(線の色, 塗りの色)2 つ書くと,ふちと内側を別々に指定できる
fillcolor(色)塗りの色だけを変える
stamp()今の姿・色・大きさ・向きで,その場にはんこを押す
clearstamps()押したはんこを全部消す(線と文字は残る)
clearstamp(番号)はんこを 1 つだけ消す
dot(大きさ, 色)その場に丸い点を打つ.大きさは直径
begin_fill()ここから塗る,の合図
end_fill()ここまで塗る,の合図.はさんだ道のりの内側が塗られる
bgcolor(色)画面全体の背景色を変える
ontimer(関数, ミリ秒)指定した時間のあとに関数を 1 回呼ぶ(第 10 章)
画像は使えません この教材では画像ファイル(GIF・JPEG)を貼ることはできません. ブラウザの中だけで動くようにしてあるためです. そのかわり,姿・大きさ・色・塗りを組み合わせれば,かなりの表現ができます. 「絵を用意する」ではなく「形を組み立てる」と考えてください.

演習

「▶ この演習を開く」で右側に読み込み,発展させてください. できあがったら「⤓ 保存」でファイルに保存して,手元に残しておきましょう.

演習演習 11-1 自分の名刺

自分の名刺(または名札)を作ってください.出発点のプログラムには 枠と名前だけが入っています.所属や連絡先を書き足し,飾りを付けて仕上げてください. 枠は左下が (-240, -110),右上が (240, 110) の長方形, 名前は (0, 10) に大きさ 36 で中央そろえに書いてあります.

要件

  • 名前の下の (0, -35) に,所属(大学名・学科名と学年)を大きさ 20 で中央そろえに書く.学年は変数 grade = 1 に入れ,f-string(f"…学科 {grade} 年")で埋め込む.
  • 枠の右下の (225, -90) に,連絡先(メールアドレスなど)を大きさ 16 で右そろえ(align="right")に書く.
  • 枠の左下((-200, -85)・(-170, -85)・(-140, -85) など)に,枠の左下に,dot の飾りを for i in range(kazu): の繰り返しで横に並べる.個数は変数 kazu = 3 に入れ,i 番目の点は (-200 + i * 30, -85) に置く(kazu を 5 に変えるだけで 5 つ並ぶようにする).
  • これもやりましょう:枠の上の部分,左下 (-240, 70)・右上 (240, 110) の長方形を,begin_fill / end_fill で好きな色(例:"#268bd2")に塗って帯にする.文字より先に塗ること(11.6.1 の「背景 → 帯や飾り → 文字」の順).
評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. (0, -35) の所属が大きさ 20 の中央そろえで,学年が f-string({grade})で埋め込まれている
  2. (225, -90) の連絡先が大きさ 16 の右そろえで,枠の右端にそろっている
  3. 飾りの dot を for i in range(kazu): で並べ,位置を式 -200 + i * 30 で決めている(kazu を変えると点の数が変わる)
  4. (-240, 70)〜(240, 110) の帯が begin_fill / end_fill で塗られ,文字が帯に隠れていない

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • 枠の左下の角・幅・高さを変数にし,帯・名前・所属・連絡先の位置をその変数から計算して,名刺全体を 1 か所の変更で動かせるようにする
  • i で飾りの点の色を切り替える(i % 3 で 3 色を順に使う)

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

演習演習 11-2 メダルを作る

dot と write で金メダルを 1 つ描くプログラムを与えます. これを発展させ,金・銀・銅の 3 つのメダルを横に並べてください. ただし,同じ命令を 3 回書き写すのではなく, for i in range(3): の 1 つの繰り返しで描きます.

x 座標は -160 + i * 160,数字は f"{i + 1}" で書けます. 色は if i == 0: のように i で切り替えます.

要件

  • 3 つのメダルを for i in range(3): の 1 つの繰り返しで描く.メダルの中心は (-160 + i * 160, 0).外側は直径 140,内側は直径 110 の dot を重ねる.
  • 色は i で切り替える.金:外 "#d4af37"・内 "#f0d879",銀:外 "#9fa6ad"・内 "#d7dce1",銅:外 "#b06a2c"・内 "#dd9a5c".
  • 数字 1・2・3 を f"{i + 1}" で,中心から 22 下((x, -22))に大きさ 60 の中央そろえで書く.
  • これもやりましょう:メダルの上に,begin_fill / end_fill で塗ったリボン(三角形)を付ける.頂点は (x - 30, 120)・(x + 30, 120)・(x, 60),色は "#c0392b"(x はそのメダルの中心の x 座標).メダル本体より先に塗ると,下の先がメダルに隠れてきれいに見えます.
1
出発点の金メダル
評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. 3 つのメダルを for i in range(3): の1 つの繰り返しで,x = −160・0・160 に描く(同じ命令を 3 回書き写していない)
  2. 数字 1・2・3 を f-string(f"{i + 1}")で,メダルの中央にそろえて書く
  3. i で色を切り替え,指定の色で金・銀・銅が見分けられる
  4. begin_fill / end_fill で塗った赤い三角形のリボンが,3 つのメダルの上にそれぞれ付いている

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • メダルの下に,順位に応じた文字(「優勝」など)を書く
  • メダルの数を変数 kazu にし,間隔を kazu から計算して,4 つ以上にしても画面に収まり重ならないようにする
  • メダルの y 座標を i から式で決め,1 位がいちばん高くなるように並べる

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

演習演習 11-3 はんこで模様を作る

stamp() だけを使って模様を描くプログラムを与えます. これを,形の違うリングを重ねた模様が,はんこ 1 つずつできあがっていく アニメーションにしてください. 第 10 章 10.7.3 の「少しずつ描き足す」と同じく,ontimer で 1 コマにつき 1 つだけはんこを押し,押し終わったら止めます.

出発点の for の繰り返し(金色の三角形 12 個)は,この step() に置き換えます.

要件

  • 押したはんこの数を変数 n(はじめは 0)で数え,step() が呼ばれるたびに中心 (0, 0) から 1 つだけはんこを押す.
  • 次の 3 重のリングにする(全部で 54 個).
    • 外側:n が 0〜23 のとき."triangle",shapesize(1.6),色 "#ffd369",向き n * 15 度,中心から 190 進んだ所
    • 中間:n が 24〜41 のとき."square",shapesize(1.0),色 "#4ecdc4",向き (n - 24) * 20 度,中心から 120 進んだ所
    • 内側:n が 42〜53 のとき."circle",shapesize(0.8),色 "#ff6b6b",向き (n - 42) * 30 度,中心から 55 進んだ所
  • ontimer(step, 60) で 60 ミリ秒ごとに次のはんこを押す.54 個押し終わったら ontimer を呼ばずに止め,ht() でかめを隠す.
  • これもやりましょう:押し終わったら,模様のまん中 (0, -15) にwrite で「完成」と,白("white"),大きさ 24 の太字,中央そろえで書く.
ヒント 向きは seth(角度) で決められます. 毎回 goto(0, 0) で中心に戻ってから seth → fd → stamp の順にすると, リングのどこに押すかを n だけで決められます.
出発点の模様
評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. 三角形 24 個・正方形 18 個・丸 12 個の 3 重のリングが,指定の半径・色・大きさで描かれる
  2. ontimer で 60 ミリ秒ごとに 1 つずつはんこが増え,模様ができあがっていく様子が見える
  3. 54 個押し終わったら ontimer を呼ばずに止まり,かめが隠れる
  4. 押し終わったあと,中央に「完成」が白の太字で書かれる

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • clearstamps() で消して,もう一度最初から押し直す(何度でもくり返す)
  • リングごとの個数を変数にし,向きを 360 / 個数 から求めて,個数を変えてもリングが等間隔に閉じるようにする
  • 押しているあいだ,f-string で「あと {54 - n} 個」を表示する

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

演習演習 11-4 カウントダウンを仕上げる

虫食い 11-B のカウントダウンを,作品として仕上げてください. 出発点のプログラムは,ただ数が減るだけです(10 から 1 秒ごとに 1 ずつ減り,0 で「GO!」).

要件

  • 数字は (0, -50) に大きさ 90 の太字,中央そろえで書く.残りが 4 以上なら白("white"),3 以下なら赤("#ff5252")にする(if で色を切り替える).
  • 数字の後ろに飾りの輪を置く.(0, 0) に直径 240 の dot("#1b2a3d")を打ち,その上に直径 210 の dot(背景と同じ "#101820")を重ねる.毎コマ clear() するので,飾りも毎コマ描き直す.
  • (0, -160) に,残り秒数を f-string で「あと 10 秒」のように,大きさ 26 の太字,色 "#4ecdc4",中央そろえで書く(数字と同じ変数 rest から作り,数字と同じ値で毎コマ変わる).
  • これもやりましょう:0 になって「GO!」("gold")を出すコマでは,bgcolor("#2e7d32") で背景を緑に変え,「あと … 秒」の代わりに「START!」と書く.
ヒント 毎コマ clear() しているので,同じかめで描いた 背景の飾りも毎コマ描き直す必要があります. bgcolor だけは clear() で消えません.
評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. 数字が 10 から 1 秒ごとに減り,3 以下になると赤に変わる(if で色を切り替えている)
  2. 直径 240 と 210 の dot の輪が数字の後ろにあり,毎コマ描き直されて消えずに見えている
  3. (0, -160) の「あと ○ 秒」が f-string({rest})で作られ,大きい数字と同じ値で毎コマ変わる
  4. 0 になると背景が緑に変わり,「GO!」と「START!」が表示されて止まる

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • 最初の秒数と赤にする境目(3)を変数にし,値を変えても色の切り替えと終わり方が正しく動く
  • 残りが少なくなるほど数字を大きくする
  • 文字専用のかめを作り,飾りは 1 回だけ描いて文字だけを pen.clear() で書き直す

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

演習演習 11-5 ぱらぱら漫画

姿を切り替えるアニメーションを作ります. いきなり完成形を目指さず,3 段階に分けて作ってください. 1 段階ごとに必ず実行して,動くことを確かめてから次へ進みます.

  1. 第 1 段階 — コマを 1 つだけ出す.まだ動かしません.好きな姿・大きさ・色のものを,好きな場所に 1 つ出すところまで作ります.
  2. 第 2 段階 — コマを 3 つにする.i % 3 で 3 つの姿を順番に切り替えます.出発点のプログラムがちょうどここです.
  3. 第 3 段階 — コマを 4 つ以上に増やして仕上げる.位置や色も一緒に変えて,作品にします.

仕上げるのは第 3 段階のものです.第 3 段階の要件は次のとおりです.

  • コマを 4 つ以上にする(i % 3 を i % 4 や i % 6 に直す).actor.shape だけでなく actor.shapesize も使って,どの 2 つのコマも見た目が違うようにする.
  • 1 コマは 140 ミリ秒(ontimer(step, 140)).actor は (-200, -60) から始め,1 コマごとに x 座標を 12 ずつ増やして右へ進め,x が 220 を超えたら -220 に戻す.
  • 画面の上の (0, 150) に,題名を大きさ 32 の太字,中央そろえで書く(最初に 1 回だけ).
  • これもやりましょう:画面の下の (0, -200) に,いま何コマ目かを f-string で「コマ 3 / 6」のように表示する(大きさ 18,中央そろえ).題名を消さないように,文字専用のかめ pen = Turtle() を作り,毎コマ pen.clear() してから書き直す(11.2.1).
ヒント 画像ファイルは使えませんが,「何コマかを順番に見せる」という ぱらぱら漫画の考え方は同じです. コマを何枚用意するか,1 コマを何ミリ秒見せるかを変えて, いちばん気持ちよく見える組み合わせを探してください. 11.4.4 のように背景を流すと,さらにアニメーションらしくなります.
評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. コマ数が 4 以上あり,shape と shapesize の組み合わせで,どのコマも見た目が違う
  2. 140 ミリ秒ごとにコマが切り替わり,同時に x が 12 ずつ右へ進み,220 を超えると左端へ戻る
  3. (0, 150) の題名が,最後まで消えずに残っている
  4. (0, -200) の「コマ ○ / ○」が文字専用のかめで毎コマ書き直され,文字が重ならない

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • 11.4.4 のように背景を流す
  • コマに合わせて y 座標も変え,跳ねているように見せる
  • 動く向きに合わせて姿の向きも変える

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

演習演習 11-6 スコアボードつきの画面

第 12 章のゲームの練習です. スコアが自動で増えていくスコアボードを作ってください. 出発点はスコアだけが増える単純なものです ((-280, 170) に「SCORE」,300 ミリ秒ごとに 5 点ずつ増える). 11.6.2 のスコアボードを参考にしてください.

要件

  • 残り時間を変数 rest = 30 で用意し,1 コマ(300 ミリ秒)ごとに 1 ずつ減らす.右端の (280, 170) に f-string で「TIME 30」のように,align="right" で右そろえにして書く.
  • 中央の (0, 170) に,f-string で「STAGE 1」のように中央そろえで書く(文字はすべて大きさ 26 の太字).STAGE は 1 から始めてスコアが 50 点増えるごとに 1 つ進める(スコア 0〜45 なら 1,50〜95 なら 2,100〜145 なら 3,150 なら 4.score // 50 + 1 で求められる).
  • スコアが 100 以上になったら,「SCORE」の文字の色を "#ff5252" に変える.
  • これもやりましょう:rest が 0 になったら ontimer を呼ばずに止め,画面の中央 (0, -20) に「GAME OVER」を大きさ 44 の太字,中央そろえで書く(このときスコアは 150 点になっているはずです).
評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. 「TIME」が 30 から 1 コマごとに減り,(280, 170) に右そろえで表示される
  2. 「STAGE」がスコアから求めた値(score // 50 + 1)で中央に表示され,スコア 50・100・150 で 2・3・4 に進む
  3. スコアが 100 以上になると「SCORE」の色が赤に変わる
  4. TIME が 0 になると止まり,中央に「GAME OVER」が出る(スコアは 150 で止まる)

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • スコアボードを draw_board のような名前の付いた関数にまとめる
  • 1 コマの得点(5)・制限時間(30)・ステージの区切り(50)を変数にし,値を変えても STAGE・色・終わり方が正しく変わる
  • 残り時間が 5 以下になったら TIME の文字を点滅させる

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

自由演習 11-7 自由制作:動くポスター

ここまでの命令を自由に組み合わせて,動くポスターを作ってください. 題材は何でもかまいません.部活の勧誘,好きな食べ物の紹介, 自分の自己紹介 — 何か人に見せたくなるものにしてください.

  • write で題名と説明を出すこと(2 種類以上の大きさ)
  • bgcolor で背景を決めること
  • dot・stamp・begin_fill のうち2 つ以上を使うこと
  • ontimer で,どこかが動くこと(文字が変わる・色が変わる・姿が変わる・位置が変わる,のどれでもよい)
  • 先頭にコメントで,題名・氏名・日付を書くこと
ヒント 動かすところは,1 か所で十分です.たとえば 「題名の色が 1 秒ごとに変わる」だけでも,止まっている絵とは印象がまるで違います. 欲張るより,1 つの動きをていねいに作るほうがよい作品になります.
作品例 たとえば,こんな作りにできます.ねたに困ったら真似してみてください.
  1. 画面に「注目→」という文字と,数字を出す
  2. 1 秒ごとに数字を 10, 9, 8 …… と減らす
  3. 残りが 3 になったら数字を赤にする
  4. 0 になったら絵の見た目をがらりと変え,「ぼかーん!!」と大きく書く

数字を減らすのは演習 11-4,見た目を変えるのは 10.3・11.4 でやったことです. すでに習ったものの組み合わせだけでできています.

評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. write で題名と説明を,2 種類以上の大きさで書く
  2. bgcolor で背景色を決め,dot・stamp・begin_fill のうち 2 つ以上を使う
  3. ontimer で,見た目のどこかが変わり続ける(文字・色・姿・位置のどれか)
  4. 先頭のコメントに,題名・氏名・日付がある

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • 終わりのある動き(カウントダウンが 0 で止まる など)を入れる
  • 文字専用のかめを作り,背景を残したまま文字だけを書き換える
  • f-string で変わる数(残り秒数・回数など)を文字に埋め込んで表示する

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

追加実習:仕組みを確かめてから設計する

得点の値と,画面の文字を分ける

得点表示では,scoreという数値と,画面に書いた文字は別のものです.

scoreへ10を足しただけでは,以前writeした文字が自動で変わるわけではありません.値を更新し,表示用のかめが以前の文字を消し,新しい値を書き直す,という手順が必要です.

データの変更と再描画を分けて理解します.

文字を書くかめを専用にすると,clearで得点だけを消せます.

図形も同じかめで描いていると,得点を書き直すたびに図形まで消えることがあります.背景,動く対象,文字という役割を分けると,更新の範囲を選べます.

表示位置も毎回明示すれば,別の処理がペンを動かした影響を受けにくくなります.

文字の揃え方は,値の桁数が変わると違いが分かります.

左揃えなら左端,中央揃えなら中心,右揃えなら右端を基準にします.9から10へ変わるとき,どこを動かしたくないかを考えて選んでください.

数字が増えたときだけ表示がずれる問題は,計算の不具合ではなく配置の基準の問題かもしれません.

以下は,値を変更してから表示し直す例です.

最終的な文字だけでなく,コンソールのscoreも確認してください.次の演習では初期値9へ1を加えて10を表示します.

桁数が変わる境界を試すことで,1桁だけのテストでは見えない配置の問題を確認できます.

lec08_2_extra_1.py
from turtle import *
label = Turtle()
label.hideturtle()
label.penup()
label.goto(0,100)
score = 0
label.write(score,align="center",font=("Arial",24,"normal"))
score += 10
label.clear()
label.write(score,align="center",font=("Arial",24,"normal"))
print("得点",score)
done()
10
演習設計して確かめる

scoreを9から10へ変更し,表示を右揃えにしてください.値を変更する行と,表示を消して書き直す行を区別して説明します.文字用のかめ以外が描いた線は消さない設計にします.

評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. score を 9 から始めて 1 を足す行と,label.clear() して書き直す行が分かれている
  2. align="right" で書き,9 から 10 に桁が増えても右端がずれない
  3. assert score == 10 で値を確かめている

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • ほかのかめで背景の線を描き,label.clear() のあとも背景が残ることを確かめる
  • 11 → 100 のように,さらに桁が増える場合も試す

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

見た目を変える操作と,位置を変える操作

shapeやshapesizeは,かめの見た目を変える操作です.

見た目の大きさが変わっても,x座標やy座標が同じなら,基準となる位置は変わりません.動いているように見える演出でも,実際には位置の更新なのか,形や大きさの切り替えなのかを分けて考えます.

それぞれを独立に試すと,組み合わせたときの効果を予測しやすくなります.

stampは,その時点の見た目を足跡として残します.

その後かめを移動したり色を変えたりしても,過去のスタンプが自動で同じように変わるわけではありません.現在の個体と,残した描画結果は別です.

文字表示のwriteと同じく,後から値を変えたら既存の画面も自動更新される,という思い込みを避けてください.

hideは現在のかめを隠す操作で,それまでに描いた線やスタンプをすべて消す操作ではありません.

clearやclearstampsとの違いを,具体的な画面で確かめましょう.見えなくしたいものが,現在の姿なのか,過去の足跡なのかによって使う命令が変わります.

名前が似た命令でも,対象を区別して選びます.

以下では違う大きさの姿を3か所に残します.

それぞれのスタンプを描く前に,位置と大きさを設定しています.次の演習では位置を固定し,形だけを変えた場合の違いを観察します.

重なった足跡が残る理由を説明し,1つだけ見せたい場合には何を消す必要があるか考えてください.

lec08_2_extra_2.py
from turtle import *
penup()
shape("turtle")
for i in range(3):
    goto(-100+i*100,0)
    shapesize(i+1)
    stamp()
hideturtle()
done()
演習設計して確かめる

3つのスタンプをすべて同じ位置に置き,大きさ1,2,3で重ねてください.その後clearstampsで足跡を消し,最後の大きさのスタンプだけを残します.現在のかめは隠します.

評価の目安(10 段階)

必須(すべて満たして正しく動けば 8)

  1. 3 つのはんこを同じ位置に大きさ 1・2・3 で重ねて押す
  2. clearstamps() で足跡を消し,最後の大きさのはんこだけを押し直して残す

発展(必須に加えて 1 つ以上で 9,学んだ範囲を大きく超える作り込みで 10)

  • sid = stamp() と clearstamp(sid) で,1 つずつ消す版も作る
  • 消す前と消した後を ontimer で順に見せる

必須が 1〜2 つ足りない → 7 / 動かない・未着手が複数 → 6

まとめ

  • write(文字, align=, font=) で画面に文字を書く.色は pencolor で決まる.
  • f-string(f"スコア: {score}")で,数と文字をつなげて表示する.
  • 書いた文字は消せないので,clear() して書き直す.1 コマぶんをまるごと描き直すのが確実.
  • shape・shapesize・color でかめの見た目を変えられる.姿を順番に切り替えるとぱらぱら漫画になる.
  • stamp は姿のはんこ,dot は丸い点,begin_fill/end_fill は内側の塗りつぶし.
  • 色は名前でも #rrggbb でも指定できる.bgcolor で背景を変えると雰囲気が一変する.
  • 作品を作るときは背景 → 図形 → 文字の順に描く.

次の回はいよいよゲームを作ります. キーボードやマウスで操作して,当たったかどうかを判定する. 第 10 章の ontimer と,今回の write によるスコア表示が, そのまま土台になります. ここまでに習った変数・if・繰り返しを全部つないで,1 本の作品にしましょう.

復習:虫食いで確かめる

コードの ____ を埋めてください.実行前に結果を予測し,実行後に問題文の条件と照合しましょう.assert は条件が成り立つかを調べ,成り立たないとエラーになります.

虫食い虫食い・復習 1 古い得点表示を消す

同じ位置に得点0と得点1を書きます.文字が重ならないよう,古い表示を消す命令を補ってください.

fill_review_lec08_2_1.py
from turtle import *
pen = Turtle()
pen.hideturtle()
pen.write("得点: 0")
pen.____()
pen.write("得点: 1")
done()