turtle.addshape()

2025-06-06

Pythonのturtleモジュールにおけるturtle.addshape()関数は、新しい図形(シェイプ)をタートルグラフィックスに登録するために使用されます。

通常、turtleモジュールを使うと、デフォルトでは矢印や亀の形をしたタートル(描画するカーソル)が表示されます。しかし、addshape()を使うことで、自分で定義した図形や画像ファイルをタートルの形として利用できるようになります。

turtle.addshape()の主な使い方

addshape()には、主に2つの使い方があります。

    • 方法
      addshape(name, shape_data)
    • name: その図形に付ける名前(文字列)。後でこの名前を使って図形を適用します。
    • shape_data: 図形を構成する頂点の座標をタプルのリストとして指定します。各タプルは(x, y)形式で、原点からの相対座標です。タートルはこれらの頂点を結んで図形を描画します。

    • import turtle
      
      # 三角形を定義
      triangle_shape = ((0, 0), (50, 0), (25, 50))
      turtle.addshape("triangle", triangle_shape)
      
      # タートルの形を三角形にする
      t = turtle.Turtle()
      t.shape("triangle")
      t.forward(100)
      turtle.done()
      
  1. 画像ファイル(GIF)を登録する

    • 方法
      addshape(name, image_file_path)
    • name: その画像に付ける名前(文字列)。
    • image_file_path: 利用したいGIF画像のファイルパス(文字列)。Pythonのturtleモジュールは、通常、GIF形式の画像をサポートします。

    • import turtle
      
      # 画像ファイル(例: "my_image.gif")を登録
      # 'my_image.gif'はスクリプトと同じディレクトリにあるか、
      # 正しいパスを指定する必要があります。
      turtle.addshape("my_custom_image", "my_image.gif")
      
      # タートルの形を画像にする
      t = turtle.Turtle()
      t.shape("my_custom_image")
      t.forward(100)
      turtle.done()
      

addshape()のメリット

  • 教育
    プログラミング学習において、より魅力的で分かりやすいグラフィックを作成するのに使えます。
  • ゲームやシミュレーション
    タートルグラフィックスを使った簡単なゲームやシミュレーションで、キャラクターやオブジェクトを独自の画像で表現するのに役立ちます。
  • 視覚的な表現の豊かさ
    デフォルトの形だけでなく、より多様なグラフィック表現が可能になります。


AttributeError: 'Turtle' object has no attribute 'addshape'

エラーの原因
addshape()は、タートルの描画を行う「スクリーン(画面)」に新しい図形を登録するためのメソッドです。個々のタートルオブジェクト(例: t = turtle.Turtle())に対して呼び出すものではありません。

解決策
turtle.Screen()オブジェクト、またはモジュールレベルのturtleオブジェクト(import turtleとした場合のturtle)からaddshape()を呼び出します。

悪い例

import turtle
t = turtle.Turtle()
t.addshape("my_shape", ((0,0),(10,10),(0,10))) # エラーになる!

良い例

import turtle
screen = turtle.Screen() # スクリーンオブジェクトを取得
screen.addshape("my_shape", ((0,0),(10,10),(0,10)))

# またはモジュールレベルで
# turtle.addshape("my_shape", ((0,0),(10,10),(0,10)))

t = turtle.Turtle()
t.shape("my_shape") # 登録したシェイプをタートルに適用
turtle.done()

画像ファイルが見つからない / サポートされていない形式

エラーの原因
addshape()で画像ファイルを指定する場合、以下の問題が考えられます。

  • サポートされていない画像形式
    turtleモジュールはGIF形式の画像のみを直接サポートしています。PNG, JPGなどの他の形式はそのままでは使用できません。
  • ファイルが存在しない、またはパスが間違っている
    指定されたファイルパスに画像ファイルが存在しないか、スペルミスがある。

解決策

  • 画像形式の確認と変換

    • 使用したい画像がGIF形式であることを確認します。
    • もしPNGやJPGなどの他の形式であれば、オンラインツールや画像編集ソフトウェア(例: GIMP, Photoshop)を使ってGIF形式に変換します。
    • より高度な方法として、Pillow (PIL) などのライブラリを使用して、実行時に画像をGIFに変換してからaddshapeに渡すことも可能ですが、これは初心者向けではありません。
    • 画像ファイルがPythonスクリプトと同じディレクトリにあることを確認します。
    • 異なるディレクトリにある場合は、絶対パス(例: C:/Users/YourName/images/my_image.gif)または相対パス(例: images/my_image.gif)を正しく指定します。
    • Windowsの場合、パスの区切り文字に\を使う場合はエスケープするか、rプレフィックスを付ける(例: r"C:\Users\...")か、/に置き換える(C:/Users/...)必要があります。


import turtle

# 良い例: スクリプトと同じディレクトリに'my_image.gif'がある場合
screen = turtle.Screen()
screen.addshape("my_custom_image", "my_image.gif")
t = turtle.Turtle()
t.shape("my_custom_image")
turtle.done()

# 悪い例: ファイルが存在しない、またはパスが間違っている場合
# screen.addshape("non_existent_image", "non_existent.gif") # FileNotFoundErrorが発生する可能性

# 悪い例: PNGファイルを直接指定した場合
# screen.addshape("png_image", "my_image.png") # サポートされていない形式でエラーになるか、表示されない

多角形の座標形式が正しくない

エラーの原因
カスタムな多角形を定義する際、shape_dataの形式が間違っているとエラーになります。shape_dataは、座標のタプルを要素とするタプルのリストである必要があります。


((x1, y1), (x2, y2), (x3, y3))

よくある間違い

  • 単一のタプルで複数の座標を定義している: ((0,0,10,10))
  • 座標がタプルになっていない: (0,0,10,10)
  • タプルではなくリストを使っている: [[0,0],[10,10]] (厳密にはエラーにはならないが、推奨されない)

悪い例

import turtle
screen = turtle.Screen()

# 座標の形式が間違っている
# screen.addshape("bad_shape", (0, 0, 10, 10)) # エラー

# 座標がタプルになっていない
# screen.addshape("bad_shape", [[0,0],[10,10]]) # 厳密にはエラーではないが、ドキュメントの推奨形式ではない

良い例

import turtle
screen = turtle.Screen()

# 正しい多角形の定義 (タプルのタプル)
screen.addshape("my_triangle", ((0, 0), (50, 0), (25, 50)))

t = turtle.Turtle()
t.shape("my_triangle")
turtle.done()

既に登録されている名前を使用しようとした

エラーの原因
addshape()で登録する図形名(name引数)はユニークである必要があります。同じ名前で異なる図形を再度登録しようとすると、エラーになるか、意図しない上書きが発生する可能性があります。

解決策
別の名前を使用するか、既存の図形を上書きする意図がある場合は、そのことを認識して行います。通常、同じ名前で何度も登録することは稀です。


import turtle
screen = turtle.Screen()

screen.addshape("square", ((0,0),(10,0),(10,10),(0,10)))
# screen.addshape("square", ((0,0),(20,0),(20,20),(0,20))) # 同じ名前で別の図形を登録しようとすると問題になる可能性
                                                         # この場合、新しい定義が前のものを上書きします。
                                                         # エラーにはなりませんが、意図しない挙動になることがあります。

# 登録済みの名前を再利用するより、異なる名前を使うべき
screen.addshape("larger_square", ((0,0),(20,0),(20,20),(0,20)))

t = turtle.Turtle()
t.shape("square")
# t.shape("larger_square")
turtle.done()

エラーの原因
これはaddshape()に直接関連するエラーではありませんが、turtleグラフィックス全般でよくある問題です。プログラムが終了すると、タートルのウィンドウもすぐに閉じてしまい、せっかく描画したものが確認できないことがあります。

解決策
プログラムの最後にturtle.done()またはturtle.mainloop()screen = turtle.Screen()を使っている場合)を追加して、ウィンドウが開いたままになるようにします。ユーザーが手動でウィンドウを閉じるまで待機します。

悪い例

import turtle
screen = turtle.Screen()
screen.addshape("my_shape", ((0,0),(10,10),(0,10)))
t = turtle.Turtle()
t.shape("my_shape")
# プログラムがすぐに終了し、ウィンドウが閉じてしまう

良い例

import turtle
screen = turtle.Screen()
screen.addshape("my_shape", ((0,0),(10,10),(0,10)))
t = turtle.Turtle()
t.shape("my_shape")
turtle.done() # これによりウィンドウが閉じずに残る


カスタムな多角形を登録する例(三角形)

この例では、頂点の座標を指定してオリジナルの三角形のシェイプを作成し、タートルに適用します。

import turtle

# 1. スクリーンオブジェクトの取得(addshapeはスクリーンに対して呼び出す)
screen = turtle.Screen()
screen.setup(width=600, height=400) # ウィンドウサイズを設定
screen.bgcolor("lightblue")         # 背景色を設定

# 2. 三角形の頂点座標を定義
# (0,0)を基準とした相対座標で定義します。
# 例: (0,0)から右に50、上には動かない -> (50,0)
#     そこから(0,0)を基準に右に25、上に50 -> (25,50)
triangle_vertices = ((0, 0), (50, 0), (25, 50))

# 3. addshape()を使って新しいシェイプを登録
# 第一引数はシェイプの名前、第二引数は頂点座標のタプル
screen.addshape("my_triangle", triangle_vertices)
print("「my_triangle」シェイプが登録されました。")

# 4. タートルオブジェクトを作成
t = turtle.Turtle()
t.speed(1) # タートルの描画速度(1:最も遅い)
t.color("red") # タートルの色

# 5. shape()メソッドで登録したシェイプをタートルに適用
t.shape("my_triangle")
print("タートルの形が「my_triangle」に変更されました。")

# 6. タートルを動かして描画
t.penup() # ペンを上げる(描画しない)
t.goto(-100, 50)
t.pendown() # ペンを下げる(描画する)

t.forward(100)
t.left(90)
t.forward(100)

# 7. クリックでウィンドウを閉じるように設定
screen.exitonclick()
print("プログラムが終了しました。")

解説

  • t.shape("my_triangle"): 作成したタートルtの形を、先ほど登録したmy_triangleに変更します。
  • screen.addshape("my_triangle", triangle_vertices): my_triangleという名前で、triangle_verticesで定義された形状を登録します。
  • triangle_vertices: シェイプの形状を定義するタプルのタプルです。各インナーのタプルは(x, y)座標を表し、タートルの中心を基準とした相対座標です。
  • screen = turtle.Screen(): addshapeメソッドは個々のタートルオブジェクトではなく、turtle.Screen()(描画スクリーン)に関連付けられています。そのため、まずスクリーンオブジェクトを取得します。

GIF画像をタートルのシェイプとして使用する例

この例では、既存のGIF画像ファイルをタートルの形として読み込み、利用します。

準備

このコードを実行する前に、my_image.gifというGIF画像ファイルをPythonスクリプトと同じディレクトリに用意してください。どんなGIF画像でも構いません。

import turtle
import os # ファイルパス操作のためにosモジュールをインポート

# 1. スクリーンオブジェクトの取得
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.bgcolor("lightgreen")

# 2. GIF画像のファイルパスを定義
# スクリプトと同じディレクトリにあると仮定
image_file = "my_image.gif"

# ファイルが存在するか確認(エラー回避のため)
if not os.path.exists(image_file):
    print(f"エラー: 画像ファイル '{image_file}' が見つかりません。")
    print("スクリプトと同じディレクトリにGIF画像を置いてください。")
    # プログラムを終了するか、エラー処理を行う
    exit()

# 3. addshape()を使ってGIF画像を登録
# 第一引数はシェイプの名前、第二引数は画像ファイルのパス
screen.addshape("my_custom_image", image_file)
print(f"画像ファイル '{image_file}' を「my_custom_image」シェイプとして登録しました。")

# 4. タートルオブジェクトを作成
t = turtle.Turtle()
t.speed(1)
t.penup() # 画像シェイプの場合は通常、ペンを上げてから移動すると良い

# 5. shape()メソッドで登録した画像シェイプをタートルに適用
t.shape("my_custom_image")
print("タートルの形が画像に変更されました。")

# 6. タートルを移動させて描画
t.goto(-150, 0)
t.pendown() # ペンを下ろす(もし画像が描画するものなら)
t.forward(300)

t.penup()
t.goto(0, 100)
t.write("Look! This turtle is an image!", align="center", font=("Arial", 16, "normal"))

# 7. クリックでウィンドウを閉じるように設定
screen.exitonclick()
print("プログラムが終了しました。")

解説

  • screen.addshape("my_custom_image", image_file): my_custom_imageという名前で、指定されたGIF画像を登録します。
  • os.path.exists(image_file): ファイルが存在するかどうかを確認する基本的なチェックです。ファイルが見つからないというエラーを避けるために役立ちます。
  • image_file = "my_image.gif": 使用するGIF画像ファイルの名前を指定します。スクリプトと同じディレクトリにある場合、ファイル名だけで十分です。

この例では、複数のカスタムシェイプを登録し、プログラムの途中でタートルの形を切り替えます。

import turtle
import time # 時間を待つためにインポート

screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.bgcolor("whitesmoke")

# 1. シェイプの定義
# 三角形
triangle_shape = ((0, 0), (50, 0), (25, 50))
screen.addshape("triangle_up", triangle_shape)

# 四角形
square_shape = ((0, 0), (40, 0), (40, 40), (0, 40))
screen.addshape("square_block", square_shape)

# 星形 (簡易版)
# 複数の頂点で星形を表現
star_shape = (
    (0, 20), (5, 5), (20, 5), (8, -5), (15, -20),
    (0, -10), (-15, -20), (-8, -5), (-20, 5), (-5, 5)
)
screen.addshape("star_shape", star_shape)

print("複数のカスタムシェイプが登録されました。")

# 2. タートルオブジェクトを作成
t = turtle.Turtle()
t.speed(2)
t.penup()
t.goto(-200, 0) # 初期位置

# 3. シェイプを切り替えながら描画
t.shape("triangle_up")
t.color("blue")
t.stamp() # 現在のタートルの形をスタンプ

t.forward(100)
t.shape("square_block")
t.color("green")
t.stamp()

t.forward(100)
t.shape("star_shape")
t.color("purple")
t.stamp()

# 形を変えて動かす
t.goto(0, -100)
t.shape("triangle_up")
t.color("orange")
t.pendown()
t.circle(50) # 円を描く

t.penup()
t.goto(150, -100)
t.shape("square_block")
t.color("darkred")
t.write("Shapes!", align="center", font=("Arial", 20, "bold"))


print("タートルの形を切り替えながら描画しました。")

screen.exitonclick()
print("プログラムが終了しました。")
  • t.stamp()を使って、タートルの現在の形をその場に「スタンプ」として残すこともできます。
  • t.shape()を呼び出すことで、タートルの形をプログラムの任意の時点で変更できます。
  • この例では、複数のaddshape()呼び出しを使って、異なる名前で複数のカスタムシェイプを登録しています。


主な代替方法としては、以下の2つが挙げられます。

  1. タートルのペンを使って直接図形を描画する (Pen drawing)
  2. turtle.register_shape() を使用する (実質的に addshape() と同じ)

それぞれについて詳しく説明します。

タートルのペンを使って直接図形を描画する (Pen drawing)

これは、addshape()でカスタムシェイプを登録する代わりに、タートル自身のペン機能を使って、必要な形を描画する方法です。タートルの形を直接変更するわけではありませんが、視覚的には同様の効果を得られます。

特徴

  • 欠点
    • タートル自体の「形」が変わるわけではない。タートルは常にデフォルトの矢印や亀のまま描画する。
    • 複数のタートルが同じカスタム「形」を使う場合に、それぞれのタートルで同じ描画コードを繰り返す必要がある(関数化すれば回避可能)。
    • 複雑な図形やビットマップ画像のような表現は困難。
    • 移動中にタートルの向きに合わせて図形を回転させるのが難しい(手動で回転計算が必要になる)。
  • 利点
    • 外部ファイル(GIF画像)を必要としない。
    • シェイプを登録する手間がない。
    • タートルの移動と連動して、描画中にリアルタイムで図形が形成される様子を見せることができる。
    • begin_fill()end_fill() を使って、描画した図形を塗りつぶすことができる。

コード例

この例では、addshape()で登録する代わりに、タートルが「家」の形を描画します。

import turtle

screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.bgcolor("lightyellow")

t = turtle.Turtle()
t.speed(3)
t.penup() # 描画開始前にペンを上げる
t.goto(-100, -50) # 描画開始位置へ移動
t.pendown() # 描画開始

# 家の形を描画する関数
def draw_house(some_turtle, size):
    some_turtle.color("brown")
    some_turtle.begin_fill() # 塗りつぶし開始

    # 壁
    for _ in range(4):
        some_turtle.forward(size)
        some_turtle.left(90)

    # 屋根
    some_turtle.forward(size) # 屋根の底辺に移動
    some_turtle.left(30)
    some_turtle.forward(size)
    some_turtle.right(60)
    some_turtle.forward(size)
    some_turtle.left(30)

    some_turtle.end_fill() # 塗りつぶし終了
    some_turtle.color("black") # ペンの色を戻す(オプション)

# カスタムシェイプのように家を描画
draw_house(t, 80)

# 別の場所に移動して、別の家を描画
t.penup()
t.goto(100, 0)
t.pendown()
draw_house(t, 50) # 小さい家

turtle.done()

この方法が適している場合

  • 実行時に動的に形状を変化させたい場合(例: サイズや比率を変化させながら描画)。
  • 描画のプロセスを視覚的に見せたい場合(教育目的など)。
  • 描画する図形が比較的シンプルで、タートルの形自体を変更する必要がない場合。

これは代替方法というよりは、turtle.addshape() の別名です。

**turtle.addshape()turtle.register_shape() は全く同じ機能を提供します。**歴史的に、Pythonのturtleモジュールではregister_shape()という名前が使われていましたが、より直感的なaddshape()という別名が追加されました。どちらを使っても結果は同じです。

特徴

  • 欠点
    addshape()と同じ。GIF画像のみサポート。外部ファイルが必要な場合がある。
  • 利点
    addshape()と同じ。つまり、タートルの実際の「形」をカスタムの多角形やGIF画像に変更できる。一度登録すれば、複数のタートルで同じシェイプを簡単に利用できる。

コード例

addshape()を使った最初の例と全く同じコードになりますが、メソッド名がregister_shape()に変わるだけです。

import turtle

screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.bgcolor("lightblue")

triangle_vertices = ((0, 0), (50, 0), (25, 50))

# addshape()の代わりにregister_shape()を使用
screen.register_shape("my_triangle_registered", triangle_vertices)
print("「my_triangle_registered」シェイプが登録されました。")

t = turtle.Turtle()
t.speed(1)
t.color("red")

# 登録したシェイプを適用
t.shape("my_triangle_registered")
print("タートルの形が「my_triangle_registered」に変更されました。")

t.penup()
t.goto(-100, 50)
t.pendown()

t.forward(100)
t.left(90)
t.forward(100)

screen.exitonclick()
print("プログラムが終了しました。")
  • 古いPythonのturtleコードとの互換性を保ちたい場合(ただし、現代のPythonではaddshape()が推奨されます)。
  • addshape()と全く同じ機能が必要な場合。