-1

"q" is to move so when you press "q" you move in the direction of your mouse and when you press "q" again you stop. When you click your mouse the ship will shoot a bullet but it will pause for a second. Is there a way to make it not pause. Also can you make the triangle a rocket picture? Or the background picture a space.

The code:

from turtle import Screen, Turtle, Vec2D, Turtle
import turtle
import time

screen = turtle.Screen()
screen.title("Test")
screen.setup(width=1000, height=650)

ship = turtle.Turtle()
ship.shape("triangle")
ship.turtlesize(3)
ship.speed('fast')
ship.penup()

bullet = turtle.Turtle()
bullet.shape("circle")
bullet.speed('fast')
bullet.color("green")
bullet.penup()
bullet.hideturtle()
bullet.goto(-525, -350)
bullet.hideturtle()
bullet.turtlesize(0.5)

shot=0

coin=-1
def onmove(self, fun, add=None):
    if fun is None:
        self.cv.unbind('<Motion>')
    else:
        def eventfun(event):
            fun(Vec2D(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale))

        self.cv.bind('<Motion>', eventfun, add)

def goto_handler(position):
    global target
    onmove(screen, None)
    target = position
    onmove(screen, goto_handler)

def move():
    global shot
    if -350<bullet.ycor() and bullet.ycor()<350 and -525<bullet.xcor() and bullet.xcor()<525:
        bullet.forward(15)
    ship.setheading(ship.towards(target))
    if coin==1:
        ship.forward(5)
    if shot==1:
        bullet.hideturtle()
        bullet.goto(ship.xcor(), ship.ycor())
        bullet.setheading(ship.heading())
        bullet.forward(15)
        bullet.showturtle()
        shot=0

    if -275>ship.ycor() or ship.ycor()>275 or -450>ship.xcor() or ship.xcor()>450:
        ship.backward(5)
    screen.ontimer(move, 50)


def shoot(x, y):
    global shot
    if not(-350<bullet.ycor() and bullet.ycor()<350 and -525<bullet.xcor() and bullet.xcor()<525):
        shot=1
def forward():
    global coin
    coin=-coin

target = (0, 0)

onmove(screen, goto_handler)

move()

screen.onscreenclick(shoot)
screen.onkeypress(forward, "q")
screen.listen()
screen.mainloop()

1 Answers1

1

I've tried to optimize your code a bit below, making the bullet react faster when fired. I made space square, instead of rectangular, so there isn't a longer delay before refiring in some directions than in others. I've also parameterized it so you can pick a different size space and it should adjust. I eliminated the shot variable and use the turtle's visibility state instead:

from turtle import Screen, Turtle, Vec2D

SPACE = 825

CURSOR_SIZE = 20
BULLET_SIZE = 10
BULLET_BOUNDS = SPACE/2 + BULLET_SIZE/2

SHIP_SIZE = 60
SHIP_BOUNDS = SPACE/2 - SHIP_SIZE/2

def onmove(self, fun, add=None):
    if fun is None:
        self.cv.unbind('<Motion>')
    else:
        def eventfun(event):
            fun(Vec2D(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale))

        self.cv.bind('<Motion>', eventfun, add)

def goto_handler(position):
    global target

    onmove(screen, None)
    target = position
    onmove(screen, goto_handler)

def move():
    x, y = bullet.position()

    if -BULLET_BOUNDS < x < BULLET_BOUNDS and -BULLET_BOUNDS < y < BULLET_BOUNDS:
        bullet.forward(15)
    else:
        bullet.hideturtle()

    ship.setheading(ship.towards(target))

    if coin:
        x, y = ship.position()

        if -SHIP_BOUNDS < x < SHIP_BOUNDS and -SHIP_BOUNDS < y < SHIP_BOUNDS:
            pass
        else:
            ship.setheading(ship.towards((0, 0)))

        ship.forward(5)

    screen.ontimer(move, 50)

def shoot(x, y):

    screen.onscreenclick(None)

    if not bullet.isvisible():
        bullet.goto(ship.position())
        bullet.setheading(ship.heading())
        bullet.showturtle()
        bullet.forward(30)

    screen.onscreenclick(shoot)

def forward():
    global coin

    coin = not coin

screen = Screen()
screen.setup(width=SPACE, height=SPACE)

ship = Turtle("triangle")
ship.turtlesize(SHIP_SIZE / CURSOR_SIZE)
ship.speed('fastest')
ship.penup()

bullet = Turtle("circle", visible=False)
bullet.turtlesize(BULLET_SIZE / CURSOR_SIZE)
bullet.speed('fastest')
bullet.color("green")
bullet.penup()

coin = False
target = (0, 0)

onmove(screen, goto_handler)

move()

screen.onscreenclick(shoot)
screen.onkeypress(forward, "q")
screen.listen()
screen.mainloop()

To set a background, find a space image in GIF format (but not an animated one) of a size larger than you need. Edit it down to size and use screen.bgpic("space.gif") to make it the background.

To use a ship image is a harder problem. Setting a turtle to use a GIF image is straightforward but the image won't turn with the turtle. That takes more images, more code and more time. I'd stick with your triangle cursor over an image-based spaceship.

Alternatively, you can draw a spaceship in turtle using multiple colored polygons and set that as your cursor -- it should correclty turn with the cursor. See this example involving a tank-shaped cursor.

cdlane
  • 40,441
  • 5
  • 32
  • 81