質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.63%

タートルグラフィックスを用いて文字を描画したい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 521

GuMasi

score 57

タートルグラフィックスを用いて文字(名前:apple)を描画したいのですが可能でしょうか?

追記:

from turtle import *

with open("handwriting-apple.txt", encoding="utf-8") as stream:
    write("Apple", None, "center", "serif 64 bold")
    color("red")
    penup()
    pensize(4)

   for line in stream:
        action, *args = line.strip().split(" ")
        print(action, args)
        if action == "setpos":
            x, y = map(int, args)
            setpos(x-480, -y+400)
        elif action == "pendown":
            x, y = map(int, args)
            setpos(x-480, -y+400)
            pendown()
        elif action == "penup":
            penup()

hideturtle()
done()


コード、エラー

追記2:
.pyファイルに記録用のコードを記述し実行後

イメージ説明

追記3: ![イメージ説明]

recordファイル、エラー内容

イメージ説明

replayファイル

追記4:エラーの出力内容、バージョンの確認。

イメージ説明

追記5: 該当部分のコード
   

'''
from turtle import *

with open("handwriting-apple.txt", encoding="utf-8") as stream:
    write("Apple", None, "center", "serif 64 bold")
    color("red")
    penup()
    pensize(4)

    # : キャンバスの絶対座標で記録されてるので、タートル中心の座標に修正(数値は適当)
    for line in stream:
        action, *args = line.strip().split(" ")
        print(action, args)
        if action == "setpos":
            x, y = map(int, args)
            setpos(x-480, -y+400)
        elif action == "pendown":
            x, y = map(int, args)
            setpos(x-480, -y+400)
            pendown()
        elif action == "penup":
            penup()

hideturtle()
done()
'''

# 実行方法: python record_motion.py > handwriting-apple.txt
import sys
sys.stdout = open("motion.log", "w", encoding = "utf-8")
from turtle import *

s = Screen()
t = Turtle()

def onmotion(e):
    print("setpos {} {}".format(e.x, e.y))

def onrelease(e):
    print("penup")
    s.cv.unbind("<Motion>")
    s.cv.unbind("<ButtonRelease-1>")

def onpress(e):
    print("pendown {} {}".format(e.x, e.y))
    s.cv.bind("<Motion>", onmotion)
    s.cv.bind("<ButtonRelease-1>", onrelease)

s.cv.bind("<ButtonPress-1>", onpress)
t.write("Apple", None, "center", "serif 64 bold")
t.hideturtle()
done()

実行結果
イメージ説明

追記:6

setpos数値変更

from turtle import *

with open("motion.log", encoding= "utf-8") as stream:
    write("Apple", None, "center", "serif 64 bold")
    color("red")
    penup()
    pensize(4)

    # XXX: キャンバスの絶対座標で記録されてるので、タートル中心の座標に修正(数値は適当)
    for line in stream:
        action, *args = line.strip().split(" ")
        print(action, args)
        if action == "setpos":
            x, y = map(int, args)
            setpos(x-360, -y+340)
        elif action == "pendown":
            x, y = map(int, args)
            setpos(x-360, -y+340)
            pendown()
        elif action == "penup":
            penup()

hideturtle()
done()

実行結果
イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/06 20:09

    setposの数値を調整しましたところ文字に沿っては描画(上記参照追記6)されてるようなのですが、
    こちらで大丈夫でしょうか?

    キャンセル

  • 2020/04/06 20:18

    お、うまくいきましたね
    ズレに関しては微調整は必要かもしれませんが、
    意図通りの動作です

    キャンセル

  • 2020/04/06 20:26

    ありがとうございます。
    teamikl様のおかげです。

    キャンセル

checkベストアンサー

+1

追記を重ねて読みにくく成ってきたかもしれないので検めて

変更点: 

  • Python 2.x/3.x 両方対応です。
  • リダイレクト~は気にしなくても大丈夫です。普通に実行。
  • 出力される&読み込まれるファイルは"motion.log"としました。

記録用スクリプト

record_motion.py 

# -*- coding: utf-8 -*-

from __future__ import print_function, unicode_literals

## Redirect STDOUT to "motion.log" file
import io, sys
sys.stdout = io.open("motion.log", "w", encoding="utf-8")

from turtle import *

def main():
    s = Screen()
    t = Turtle()

    def onmotion(e):
        print("setpos {} {}".format(e.x, e.y))

    def onrelease(e):
        print("penup")
        s.cv.unbind("<Motion>")
        s.cv.unbind("<ButtonRelease-1>")

    def onpress(e):
        print("pendown {} {}".format(e.x, e.y))
        s.cv.bind("<Motion>", onmotion)
        s.cv.bind("<ButtonRelease-1>", onrelease)

    s.cv.bind("<ButtonPress-1>", onpress)
    t.write("Apple", None, "center", "serif 64 bold")
    t.hideturtle()
    done()

if __name__ == "__main__":
    main()

再生用スクリプト

replay_motion.py

# -*- coding: utf-8 -*-

from turtle import *
import fileinput

def main():
    write("Apple", None, "center", "serif 64 bold")
    color("red")
    penup()
    pensize(4)

    for line in fileinput.input(files=["motion.log"]):
        params = line.strip().split(" ")
        action, args = params[0], params[1:]
        print(action, args)
        if action == "setpos":
            x, y = map(int, args)
            setpos(x-480, -y+400)
        elif action == "pendown":
            x, y = map(int, args)
            setpos(x-480, -y+400)
            pendown()
        elif action == "penup":
            penup()

    hideturtle()
    done()

if __name__ == "__main__":
    main()

出力されるログファイルのサンプル

motion.log

pendown 393 326
setpos 393 327
setpos 393 329
setpos 393 334
setpos 390 340
setpos 389 344
setpos 388 345
setpos 386 348
setpos 384 352
setpos 383 354
setpos 383 355
setpos 381 358
setpos 380 359
setpos 378 361
setpos 377 363
setpos 375 365
setpos 374 369
setpos 373 373
setpos 371 376
setpos 370 380
setpos 369 381
setpos 369 382
setpos 369 384
setpos 368 386
setpos 368 387
setpos 368 388
penup
pendown 388 337
setpos 389 337
setpos 392 340
setpos 393 343
setpos 395 347
setpos 398 353
setpos 400 358
setpos 403 366
setpos 406 373
setpos 408 377
setpos 410 382
setpos 411 385
setpos 411 386
penup
pendown 378 364
setpos 379 364
setpos 385 365
setpos 392 365
setpos 399 367
setpos 401 367
setpos 402 367
penup

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

タートルが文字の線に沿って動き描画するアニメーションを期待されているのでしょうか? (hand-writing animation)
それとも、単に画面上に文字が表示されていればいいのか、どちらでしょう。
どちらも可能ですが、やりたいことの詳細によっては手間が変わってきます。

後者は単純に turtleモジュールにあるwrite() メソッドで文字をオブジェクトとして描画できます。
前者は、まずタートルがどのように動くかの情報を作る必要があります。

  1. 動きのデータを生成するプログラムを作成
  2. 例) 画面に Apple の文字を描画して、文字に沿ってマウスを動かした時の座標を記録
    (ペンタブ等使えばもう少し綺麗に書けるかも・・)
  3. 座標データを読み込み描画アニメーションとして再生するプログラムを作成

追記: 記録~再生の手順
イメージ説明

イメージ説明

イメージ説明

他にも、文字を綺麗に表示したい場合は、フォントのデータから情報を得る等
色々と凝る必要がありますが、大枠は大体このような感じです。


記録用(record_motion.py) リダイレクト付きで実行してください

# -*- coding: utf-8 -*-
# 実行方法: python record_motion.py > motion.log
from turtle import *

# リダイレクトがうまくいかない場合以下の2行を有効にしてみてください
# import sys
# sys.stdout = open("motion.log", "w", encoding="utf-8")

s = Screen()
t = Turtle()

def onmotion(e):
    print("setpos {} {}".format(e.x, e.y))

def onrelease(e):
    print("penup")
    s.cv.unbind("<Motion>")
    s.cv.unbind("<ButtonRelease-1>")

def onpress(e):
    print("pendown {} {}".format(e.x, e.y))
    s.cv.bind("<Motion>", onmotion)
    s.cv.bind("<ButtonRelease-1>", onrelease)

s.cv.bind("<ButtonPress-1>", onpress)
t.write("Apple", None, "center", "serif 64 bold")
t.hideturtle()
done()

再生用(replay_motion.py)

# -*- coding: utf-8 -*-

from turtle import *

with open("motion.log", encoding="utf-8") as stream:
    write("Apple", None, "center", "serif 64 bold")
    color("red")
    penup()
    pensize(4)

    # XXX: キャンバスの絶対座標で記録されてるので、タートル中心の座標に修正(数値は適当)
    for line in stream:
        action, *args = line.strip().split(" ")
        print(action, args)
        if action == "setpos":
            x, y = map(int, args)
            setpos(x-480, -y+400)
        elif action == "pendown":
            x, y = map(int, args)
            setpos(x-480, -y+400)
            pendown()
        elif action == "penup":
            penup()

hideturtle()
done()

motion.log の出力例

pendown 390 332
setpos 390 333
setpos 390 334
setpos 390 335
setpos 390 337
:
:
:


このような感じに、マウスをドラッグ中に通った座標が記録されます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/27 19:34

    回答いただきましてありがとうございます。

    >タートルが文字の線に沿って動き描画するアニメーションを期待されているのでしょうか? (hand-writing animation)それとも、単に画面上に文字が表示されていればいいのか、どちらでしょう。

    >>後者の単に画面上に表示されますのをイメージしていました。

    コードのfrom turtle import *のアスタリスクについてなのですが、importのよこのアスタリスクはどのような意味なのでしょうか?

    後、同様にコードを実行しましたのですが私の環境ではエラー(質問追記:上記参照)になってしまいます。

    キャンセル

  • 2020/03/27 20:40

    モジュールの提供する定数・関数をすべてインポートするという意味になります。
    (__all__ が定義されていればその名前のみをインポート)
    Pythonではあまり推奨されない方法ですが、
    turtle しか使わない状況では毎回モジュール名を付けるのが
    冗長になりがちなので、このようにしてます。

    エラーについては、まず「記録用」のスクリプトで
    テキストファイルを生成されるのを想定してます。
    コメントの指示通りの手順で実行して下さい。
    (ファイル名が間違えていたので修正します)

    文字表示だけなら、上記のスクリプトは忘れてしまって大丈夫。
    write() の部分のみです。
    ‘‘‘
    from turtle import *
    write("apple")
    ‘‘‘

    キャンセル

  • 2020/03/28 21:49

    >turtle しか使わない状況では毎回モジュール名を付けるのが
    冗長になりがちなので、このようにしてます。

    >>そうなのですね。

    > コメントの指示通りの手順で実行して下さい。
    (ファイル名が間違えていたので修正します)

    >>ありがとうございます、試みてみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る