Question

Hi all I had a question from my class that asked me to create a smiley face using serperate functions for the eyes, mouth and the head. After that they want us to to draw it 10 times over lapping each other slightly and have it tilt to the left by 10 every repetition. I know how to do the for loop, the problem I have is with the tilt.Below is what I have so far. Could you point me in the right direction for the tilt?

import turtle
s=turtle.Screen()
p=turtle.Turtle()

def happymouth(p,x,y):
    p.setheading(-60)
    jump(p,x-60.62,y+65)
    p.circle(70,120)

def eyes(p,x,y):
    jump(p,x+35,y+120)
    p.dot(25)
    jump(p,x-35,y+120)
    p.dot(25)

def jump(p,x,y):
    p.up()
    p.goto(x,y)
    p.down()


def emoticon(p,x,y):
    p=turtle.Turtle()
    s=turtle.Screen()
    p.pensize(3)
    p.setheading(0)
    jump(p,x,y)
    p.circle(100)
    eyes(p,x,y)
    happymouth(p,x,y)
    jump(p,x,y)
Était-ce utile?

La solution

You can do this but it requires you rethink your drawing logic. For the emoticon to hold up under the 10 degree rotations, your positioning of the turtle while drawing the emoticon has to all be relative, not absolute. No turtle.goto(), no jump(turtle, x, y). And then to fit your ten emoticons on the page, you need to make the sizing relative too, not absolute. Here's a rework that does this:

from turtle import Turtle, Screen

def jump(turtle, x, y):
    turtle.up()
    turtle.goto(x, y)
    turtle.down()

def head(turtle, size):
    # to draw circle with current position as center, have to adjust the y position
    turtle.up()
    turtle.right(90)
    turtle.forward(size)
    turtle.left(90)
    turtle.color("black", "yellow")
    turtle.down()

    turtle.begin_fill()
    turtle.circle(size)
    turtle.end_fill()

    # return to the center of the circle
    turtle.up()
    turtle.color("black")
    turtle.left(90)
    turtle.forward(size)
    turtle.right(90)
    turtle.down()

def eyes(turtle, size):
    turtle.up()
    turtle.forward(0.35 * size)
    turtle.left(90)
    turtle.forward(0.2 * size)
    turtle.right(90)
    turtle.down()

    turtle.dot(0.25 * size)

    turtle.up()
    turtle.backward(0.7 * size)
    turtle.down()

    turtle.dot(0.25 * size)

    turtle.up()
    turtle.forward(0.35 * size)
    turtle.right(90)
    turtle.forward(0.2 * size)
    turtle.left(90)
    turtle.down()

def happymouth(turtle, size):
    turtle.up()
    turtle.left(180)
    turtle.forward(0.6 * size)
    turtle.left(90)
    turtle.forward(0.35 * size)
    turtle.left(90)
    turtle.down()

    turtle.right(60)
    turtle.circle(0.7 * size, 120)

    turtle.up()
    turtle.circle(0.7 * size, 240)
    turtle.left(60)
    turtle.forward(0.6 * size)
    turtle.left(90)
    turtle.forward(0.35 * size)
    turtle.right(90)
    turtle.down()

def emoticon(turtle, size):
    turtle.pensize(0.03 * size)
    head(turtle, size)
    eyes(turtle, size)
    happymouth(turtle, size)

screen = Screen()
yertle = Turtle()

width, height = screen.window_width(), screen.window_height()

yertle.setheading(-50)

for xy in range(-5, 5):
    jump(yertle, xy * width / 10, xy * height / 10)

    emoticon(yertle, 60)

    yertle.setheading(yertle.heading() + 10)

screen.exitonclick()

The above code is not optimized as far as drawing -- it always returns to the center to make sure every component is draw relative to it. But it basically works:

enter image description here

There's a completely different way we can solve this problem which allows us to use the absolute turtle.goto() but has it's own difficulties. We can set the turtle itself to be an emoticon and stamp it across the page. This also allows us to ignore the relative sizing since the turtle cursor has its own sizing capability:

from turtle import Turtle, Screen, Shape

def jump(turtle, x, y):
    turtle.up()
    turtle.goto(x, y)
    turtle.down()

def head(turtle, shape, x, y):
    jump(turtle, x, y - 100)
    turtle.begin_poly()
    turtle.circle(100)
    turtle.end_poly()
    shape.addcomponent(turtle.get_poly(), "yellow", "black")

def happymouth(turtle, shape, x, y):
    turtle.setheading(-60)
    jump(turtle, x - 60, y - 35)
    turtle.begin_poly()
    turtle.circle(70, 120)
    turtle.end_poly()
    shape.addcomponent(turtle.get_poly(), "black")
    turtle.setheading(90)

def eyes(turtle, shape, x, y):
    jump(turtle, x + 35, y + 20)
    turtle.begin_poly()
    turtle.circle(13)
    turtle.end_poly()
    shape.addcomponent(turtle.get_poly(), "black")

    jump(turtle, x - 35, y + 20)
    turtle.begin_poly()
    turtle.circle(13)
    turtle.end_poly()
    shape.addcomponent(turtle.get_poly(), "black")

def emoticon(turtle, x, y):
    shape = Shape("compound")

    head(turtle, shape, x, y)
    eyes(turtle, shape, x, y)
    happymouth(turtle, shape, x, y)

    screen.register_shape("emoticon", shape)

screen = Screen()
yertle = Turtle(visible="False")
emoticon(yertle, 0, 0)
yertle.shape("emoticon")

yertle.clear()

yertle.shapesize(0.6, 0.6)

width, height = screen.window_width(), screen.window_height()

yertle.setheading(50)

for xy in range(-5, 5):
    jump(yertle, xy * width / 10, xy * height / 10)

    yertle.stamp()
    yertle.setheading(yertle.heading() + 10)

screen.exitonclick()

Unfortunately, stamps done using turtle.*_poly() can only consist of closed polygons which means the emoticon smile changes somewhat:

enter image description here

Have fun!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top