4

I am programming in python 3.2.2 turtle. I am able to make the turtle follow my cursor when I clack but now I have trouble changing the appearance of the turtle. In my code you will see a tank, and I want the image of the tank to be my turtle.

Here is my code:

#importing modules
from turtle import Turtle
from turtle import *

#Setting up variables
unVar1 = 25
unVar2 = 100
unVar3 = 90
unVar4 = 150
unVar5 = -30
unVar6 = 75
unVar7 = 50
screen = Screen() # create the screen

#first part in making the turtle move
turtle = Turtle()
t = Turtle() # create the first turtle
t2 = Turtle() # create the second turtle
screen.onscreenclick(turtle.goto) # set up the callback for moving the first turtle

#defining shapes and objects
def drawSquare(t , xPrime, yPrime, sideLength):
    t.up()
    t.hideturtle()
    t.goto(xPrime, yPrime)
    t.setheading(270)
    t.down()
    for count in range(4):
        t.forward(sideLength)
        t.left(90)
    t.end_fill()
def drawRectangle(t, x2, y2, sideLength1, sideLength2):
    t.up()
    t.hideturtle()
    t.goto(x2, y2)
    t.setheading(270)
    t.down()
    for count in range(2):
        t.forward(sideLength1)
        t.left(90)
        t.forward(sideLength2)
        t.left(90)
    t.end_fill()
def drawTank():
    t.pencolor("black")
    t.fillcolor("gray")
    t.begin_fill()
    tire1 = drawRectangle(t, int("10"), unVar1, unVar6, int("30")) #Tire
    t.begin_fill()
    tire2 = drawRectangle(t, int("110"), unVar1, unVar6, int("30"))    #Tire
    t.begin_fill()
    tire3 = drawRectangle(t, int("110"), unVar2, unVar6, int("30"))  #Tire
    t.begin_fill()
    tire4 = drawRectangle(t, int("10"), unVar2, unVar6, int("30"))   #Tire
    t.pencolor("gray")
    t.fillcolor("black")
    t.begin_fill()
    bodyTank = drawRectangle(t, int("20"), unVar3, int("130"), int("110")) 
    t.begin_fill()
    gunTank = drawRectangle(t, int("65"), unVar4, int("100"), int("20"))   #Gun
    t.begin_fill()
    exhaustTank = drawRectangle(t, int("50"), unVar5, int("20"), int("10"))   
    t.fillcolor("red")
    t.begin_fill()
    turretTank = drawSquare(t, int("50"), unVar7, int("50"))  #Turret
    t.end_fill()
drawTank()
screen.mainloop() # start everything running
kederrac
  • 15,339
  • 4
  • 25
  • 45
bertrand
  • 111
  • 2
  • 10

2 Answers2

2

You can create a tank cursor with the code you have, you just need to rearrange it. The drawing functions need to create polygons rather than draw directly to the screen. The following will create your tank cursor and drive it around the screen a bit. See the comments on tankCursor() about how you can also used fixed polygons instead -- you don't have to make a bitmap image to do this:

import turtle

unVar1 = 25
unVar2 = 100
unVar3 = 90
unVar4 = 150
unVar5 = -30
unVar6 = 75
unVar7 = 50

def polySquare(t, x, y, length):
    t.goto(x, y)
    t.setheading(270)

    t.begin_poly()

    for count in range(4):
        t.forward(length)
        t.left(90)

    t.end_poly()

    return t.get_poly()

def polyRectangle(t, x, y, length1, length2):
    t.goto(x, y)
    t.setheading(270)

    t.begin_poly()

    for count in range(2):
        t.forward(length1)
        t.left(90)
        t.forward(length2)
        t.left(90)

    t.end_poly()

    return t.get_poly()

def tankCursor():

    """
    Create the tank cursor.  An alternate solution is to toss the temporary turtle
    and use the commented out polygon assignments instead of the poly* function calls
    """

    temporary = turtle.Turtle()

    screen = turtle.getscreen()

    delay = screen.delay()

    screen.delay(0)

    temporary.hideturtle()
    temporary.penup()

    tank = turtle.Shape("compound")

    # tire1 = ((10, unVar1), (10, unVar1 - unVar6), (10 + 30, unVar1 - unVar6), (10 + 30, unVar1))
    tire1 = polyRectangle(temporary, 10, unVar1, unVar6, 30)  # Tire #1
    tank.addcomponent(tire1, "gray", "black")

    # tire2 = ((110, unVar1), (110, unVar1 - unVar6), (110 + 30, unVar1 - unVar6), (110 + 30, unVar1))
    tire2 = polyRectangle(temporary, 110, unVar1, unVar6, 30)  # Tire #2
    tank.addcomponent(tire2, "gray", "black")

    # tire3 = ((110, unVar2), (110, unVar2 - unVar6), (110 + 30, unVar2 - unVar6), (110 + 30, unVar2))
    tire3 = polyRectangle(temporary, 110, unVar2, unVar6, 30)  # Tire #3
    tank.addcomponent(tire3, "gray", "black")

    # tire4 = ((10, unVar2), (10, unVar2 - unVar6), (10 + 30, unVar2 - unVar6), (10 + 30, unVar2))
    tire4 = polyRectangle(temporary, 10, unVar2, unVar6, 30)  # Tire #4
    tank.addcomponent(tire4, "gray", "black")

    # bodyTank = ((20, unVar3), (20, unVar3 - 130), (20 + 110, unVar3 - 130), (20 + 110, unVar3))
    bodyTank = polyRectangle(temporary, 20, unVar3, 130, 110)
    tank.addcomponent(bodyTank, "black", "gray")

    # gunTank = ((65, unVar4), (65, unVar4 - 100), (65 + 20, unVar4 - 100), (65 + 20, unVar4))
    gunTank = polyRectangle(temporary, 65, unVar4, 100, 20)   # Gun
    tank.addcomponent(gunTank, "black", "gray")

    # exhaustTank = ((50, unVar5), (50, unVar5 - 20), (50 + 10, unVar5 - 20), (50 + 10, unVar5))
    exhaustTank = polyRectangle(temporary, 50, unVar5, 20, 10)
    tank.addcomponent(exhaustTank, "black", "gray")

    # turretTank = ((50, unVar7), (50, unVar7 - 50), (50 + 50, unVar7 - 50), (50 + 50, unVar7))
    turretTank = polySquare(temporary, 50, unVar7, 50)  # Turret
    tank.addcomponent(turretTank, "red", "gray")

    turtle.addshape("tank", shape=tank)

    del temporary

    screen.delay(delay)

tankCursor()  # creates and registers the "tank" cursor shape

turtle.shape("tank")

turtle.up()  # get rid of the ink

# show our tank in motion

turtle.setheading(90)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)
turtle.left(45)
turtle.forward(100)

turtle.done()
cdlane
  • 33,404
  • 4
  • 23
  • 63
1

Since the tank is a shape you created using turtle, you can always simply take a screenshot of your tank and set that screenshot as the shape of the turtle using the turtle module's register_shape and shape functions like so:

turtle.register_shape("INSERT PATH OF SCREENSHOT HERE")
t.shape("INSERT PATH OF SCREENSHOT HERE")

However, if you want to do something harder, you can use the turtle.register_shape() method shown above, but instead of supplying the path of some image, you will instead have to supply a name, and then some coordinates to create the shape. In short, the syntax for that would be:

turtle.register_shape(name, (coordinates))
t.shape(name)

However, that would be very tedious seeing as how complex your tank already is, so I would recommend going on with the method above, where you just take a screenshot of the tank and use that screenshot as a shape for the turtle.

Also, some issues I see with your code:

  1. The following:

    from turtle import Turtle
    from turtle import *
    

    You are importing the turtle module twice. There is no need for that! from turtle import * already imports the Turtle() function, so the first import command is not needed. Therefore, change the import command to just:

    from turtle import *
    # The rest of your code...
    
  2. When the user clicks on the screen to go somewhere, your turtle creates a line wherever it goes. There is a way to avoid this. However, I don't know if you want this, but if you do and decide to keep it, it does result in a lot of the lines going to places they were not supposed to and could eventually start hogging up a lot of memory until your program crashes. So I do recommend taking this step, but whether or not you do is up to you. However, if you do decide to take this step, then to start, define the following function after t2 = Turtle():

    def Go(x, y):
        # Turn the animation completely off
        screen.tracer(0, 0)
        # Pick the pen up so no lines are created as the turtle moves
        turtle.penup()
        # Go to the clicked position on the canvas
        turtle.goto(x, y)
        # Put the pen back down
        turtle.pendown()
        # Turn animation back on
        screen.tracer(1, 1)
    

    And then change:

    screen.onscreenclick(turtle.goto)
    

    To:

    screen.onscreenclick(Go)
    

And that's it! I hope this helps! :)

R. Kap
  • 559
  • 1
  • 8
  • 30